쉘에서 일반적인 커맨드 대체에 대한 예시이다.


$ filename=/home/www/file1

$ firstchar=$(echo $filename | cut -c1)



/를 ^로 변경한다


$ echo $filename | tr "$firstchar" "^"

^users^steve^memos

$ filename=$(echo $filename | tr "$firstchar" "^")    

$ echo $filename

^users^steve^memos

$




커맨드 대체는 중첩될 수 있다.  $()안에 $()을 추가할 수 있는 커맨드 대체이다. 


변수에 첫 번째 문자가 나타날 때마다 다른 문자로 변경하려고 한다고 가정한 예시를 살펴본다.



$ filename=/home/www/file1

$ echo $filename | tr "$(echo $filename | cut -c1)" "^"

^home^www^file1



$ filename=$(echo $filename | tr "$(echo $filename | cut -c1)" "^")

$ echo $filename

^home^www^file1

$

Posted by '김용환'
,



반복적으로 해야 할 작업들이 있다면, xargs -n1을 사용하면 편리한다.


예를 들어, 다음처럼 hosts라는 장비 목록 파일에 장비 정보를 매개변수로 받아 먼가를 처리하는 코드(host.rb)를 사용할  때 xargs -n1을 사용할 수 있다. 



$ cat hosts

a.google.io

b.google.io

c.google.io


$ cat hosts | xargs -n1 ruby host.rb


Posted by '김용환'
,



쉘에서 역 슬래시의 용도를 설명한다.  역 슬래시는 특별한 용도로 쓰인다. 원래의 문자가 가진 의미를 문자로 표현하기 위해 사용된다.


대표적인 예시가 다음과 같다. > 이라는 입력 리디렉션을 다른 문자 >로 바꾸었다. 


$ echo >

-bash: syntax error near unexpected token `newline'

$ echo \>

>




특수 문자를 보여주기 위해 사용된다. 


$ echo "\\"

\



그러나 공백 앞에 쓰일 때는 그냥 문자로 쓰인다. 


$ echo "\ is"

\ is




변수 대체를 막을 수 있다. 

$ echo \$greeting

$greeting




"를 표현하기 위해 \"를 사용한다.

$ greeting=one'

>

> 'two

$ echo "\"$greeting\""

"one


two"





참고로 변수가 멀티 라인 값을 가지면, 따옴표가 없으면 개행 문자를 보여주지 않는다. 큰 따옴표를 사용하면 멀티 라인을 출력한다.


$ greeting=one'

>

> 'two

$ echo $greeting

one two

$ echo "$greeting"

one


two





개행문자 앞에 \을 사용하면 개행문자가 없었던 것처럼 변수에 저장한다. 


$ l=hello\

> world\

> OK


$ echo $l

helloworldOK


$ echo "$l"

helloworldOK

Posted by '김용환'
,


쉘에서 따옴표가 없는 것, 작은 따옴표, 큰 따옴표 사이의 주요 차이점을 확인한다.


작은 따옴표는 쉘에 모든 문자를 무시하도록 알리지만, 

큰 따옴표는 대부분의 문자를 무시하도록 알린다. 


쉘에서 큰 따옴표 안에서 사용되는 다음 세 문자는 무시하지 않는다.

- 달러 기호($)

- 역 따옴표(`)

- 백 슬래시(\)



예시 1)


쉘은 별표를 보고 현재 디렉토리의 모든 파일 이름을 대체한다.


$ files=*

$ echo $files

a aa.txt b bb.txt foo server1.rb webserver1 webserver2



쉘은 작은 따옴표로 묶인 문자를 완전히 홀로 남겨두고 결과적으로 $files를 출력한다. 


$ echo '$files'

$files



쉘은 변수 이름 대체를 큰 따옴표 안에서 수행한다.


$ echo "$files"

*





예시 2)



쉘에서 따옴표를 사용하지 않으면 변수의 개행 문자를 제거할 뿐 아니라 공백이나 탭과 같은 매개변수 구분자도 처리한다


a="Hello

> World"

$ echo $a

Hello World


쉘은 큰 따옴표가 포함된 공백 문자를 남긴다. 


a="Hello

> World"

$ echo "$a"

Hello

World




쉘에서 작은 따옴표를 감추기 위해 큰 따옴표를 사용할 수 있고 그 반대도 사용할 수 있다.


$ a='"Hello" Shell'

$ echo $a

"Hello" Shell

$ b="Hello 'Shell'"

$ echo $b

Hello 'Shell'






Posted by '김용환'
,





$((expression))은 산술 확장(arithmetic expansion)이라 해서 수식을 사용할 수 있다. 


그룹핑을 강제하기 위해 표현식 안에서 괄호를 자유롭게 사용할 수 있다.


$((expression))에서 사용할 수 있는 연산자는  +, -, *, /, %, **와 같은 기본 문법에 +=, -=, *=, /=, 변수++, 변수--  등 많은 연산자와 숫자, 변수를 사용할 수 있다. 




예시 1) x진수를 10 진수로 


$ echo $((16#100))

256



예시 2) 간단한 산술 확장


$ i=2

$ echo $((i+1))

3



예시 3) 특정 변수에 산술 계산한 다음 다시 해당 변수에 저장


$ i=$(( i * 5 ))

$ echo $i

10



예시 4) 고급 산술 확장


$ i=3

$ j=2

$ echo $((i = i * (j + 1)))

9




예시 5) ++


$ i=10

$ i=$(( ++i ))

$ echo $i

11



예시 6) *=


$ i=5

$ i=$((i*=5))

$ echo $i

25




예시 7) true(1)/false(0) 


$ i=5

$ j=$(( i < 10 ))

$ echo $j

0






유의할 점은 다음과 같다. 


1. (( 다음에 공백이, )) 전에 공백이 있어도 동작한다. 


$ i=$(( i * 5 ))

$ echo $i

50



2. (( 사이에 공백이 있으면 동작하지 않는다. 


$ i=$( (i * 5) )

-bash: i: command not found






Posted by '김용환'
,





쉘에서 여러 진수의 값을 10진수로 변환할 수 있다. 


2진수 

$ echo $((2#1010))

10


4진수

$ echo $((4#1010))

68


16진수 

$ echo $((16#FF))

255



Posted by '김용환'
,



centos 공식 문서 페이지는 다음 링크에 있다.


https://www.centos.org/docs/



하지만, centos 6, 7 공식 문서는 사실 없다.



centos 7에 대한 문서는 위키와 redhat 페이지에 존재한다. 


https://wiki.centos.org/Manuals/ReleaseNotes/CentOS7


https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/7/html/System_Administrators_Guide/



Posted by '김용환'
,



일반적으로 자바 프로세스를 확인하려면, ps 또는 jps를 사용한다. 


$ ps -e | grep java

$ jps



중요한 내용만 보고 싶다면, jps -ml을 사용하여 알 수 있다. 



$ jps -ml | grep 4822

4822 google.server.Server  --http.port=8001




프로세스(process) 이름을 길게 얻으려면 다양한 방밥이 있는데, 간단하게 (efw) 옵션을 주거나 /proc/밑의 cmdline으로 알 수 있다. 


$ ps -efw | grep java

$ cat /proc/${PID}/cmdline



하지만, 너무 classpath가 너무 많아서 command line이 너무 길면 결국 얻어올 수 없다. (커널레벨의 제한이 있다)



command line을 ps또는 /proc/${PID}/cmdline에서 볼 수 있도록 하려면, http://stackoverflow.com/questions/199130/how-do-i-increase-the-proc-pid-cmdline-4096-byte-limit의 내용처럼 PAGE_SIZE를 수정하고 컴파일해야 한다고 한다. 



centos 6,7(kernel 3.12전)에서 적용된 base.c 소스

http://lxr.free-electrons.com/source/fs/proc/base.c?v=2.4.37



하지만, 리눅스 커널 4.2가 설치된 버전에서는 완전한 커맨드를 사용할 수 있다. 

- proc: fix PAGE_SIZE limit of /proc/$PID/cmdline (Alexey Dobriyan) 

https://patchwork.kernel.org/patch/6191541/

http://www.serverphorums.com/read.php?12,1179056

http://lxr.free-electrons.com/source/fs/proc/base.c?v=4.2






* 참고로, 일부 centos 버전에서는 모두 볼 수 있다.

최근에 장비에 2.6.32-642.11.1el6.centos.plus 버전이 깔려 있는데, ps 커맨드 실행시 프로세스 이름을 한 줄로 보여주고 있다. 


$ uname -r

2.6.32-642.11.1.el6.centos.plus.x86_64



http://centos.yourname.nl/centos/6/centosplus/Source/SPackages/에서

http://centos.yourname.nl/centos/6/centosplus/Source/SPackages/kernel-2.6.32-642.11.1.el6.centos.plus.src.rpm를 다운받아 확인한다. 


rpm 를 설치한다. 


$ sudo rpm -ivh kernel-2.6.32-642.11.1.el6.centos.plus.src.rpm



rpmbuild 디렉토리에 SOURCES와 SPECS가 존재한다.  kernel.spec 파일에 패치된 내용이 존재한다. 


./SPECS/kernel.spec:- [fs] proc: fix PAGE_SIZE limit of /proc/$PID/cmdline (Jarod Wilson) [1100069]



커널 소스를 풀어본다. 


$ rpm2cpio kernel-2.6.32-642.11.1.el6.centos.plus.src.rpm | cpio -idmv 


$ tar xvf linux-2.6.32-642.11.1.el6.tar.bz2


$ cd  linux-2.6.32-642.11.1.el6


$ vi ./fs/proc/base.c



바뀐 내용을 확인할 수 있다.



* 소스


다운받은 소스 또는 http://lxr.free-electrons.com/source/fs/proc/base.c?v=4.2#L199를 참조한다.


특별히 볼 소스는 다음과 같다. 

include/linux/mm_types.h에 있는 mm_struct과 base.c를 살펴보면, 프로세스 영역으로 들어가 

 매개변수가 들어가는 공간을 확인한다(len1, len2)

code & data 영역(access_remote_vm)에 들어갈 공간에 데이터가 없다면, 최대 PAGE_SIZE안의 데이터를 매개변수로 받는다. (아마도 PAGE_SIZE보다 작은 매개변수 값들) code 영역에 들어간 공간 정도로 엄청 긴 것은 계속 code &data 영역에서 계속 매개변수를 읽도록 한다. 결국은 매개변수를 다 채워서 리턴하는 코드이다. 








Posted by '김용환'
,


centos 5에서 설치시 rpm is not signed이라는 에러가 발생했다.


$ sudo yum install abc.rpm

Package abc.rpm is not signed



centos 5.8에서 rpm을 지우려면 /etc/yum.conf에서 작업을 진행해야 한다. 


$ cat /etc/yum.conf

gpgcheck=1


gpgcheck의 값을 1로 변경한다.


$ sudo vi /etc/yum.conf

gpgcheck=0




설치는 이상없이 잘 작동된다. 

$ sudo yum install abc.rpm

Posted by '김용환'
,




grafana, telegraf, influxDB로 실시간 모니터링은 구축했지만, jvm 모니터링을 구축한 내용이다.



이전 내용은 http://knight76.tistory.com/entry/grafana를 참조한다.






telegraf를 이용해 자바를 모니터링하는 방법이 있다. 


- 웹 애플리케이션에 jolokia 활용하기 (https://github.com/influxdata/telegraf/tree/master/plugins/inputs/jolokia)

- stats-jvm-profile를 java agent를 사용하는 방법(https://github.com/etsy/statsd-jvm-profiler)


두 방법 모두 javaagent 기반이라 등록/해제 모두 재시작을 해야 한다는 점이 좀 걸렸다. 웹도 아니면 jolokia가 불편하기도 하기도 하다. 더 간단한 방법으로 보고 싶었다. 



jmx를 순수하게 사용하는 방식을 사용했다. 결론은 대만족이다. 

cmdline-jmxclient 0.10.3을 다운받아 jmx 호출을 통해 jvm 메모리 부분을 모니터링하도록 스크립트를 구성했다. 


그리고, influxDB http write api를 이용해서 저장했다. (단순한 질의와 파일을 이용한 bulk 작업이 가능하다)

influxDB 1.1 이전에는 json을 지원했지만, influxDB 1.1부터는 그냥 property와 sql형태만 지원하는 것 같다. 

(참조 : https://docs.influxdata.com/influxdb/v1.1/guides/writing_data/)



crontab에 아래 스크립트(g1, cms 메모리 정보)를 만들어 jvm이 떠 있는 장비로 jmx을 모니터링 정보를 influxDB에 저장하도록 했다. 




<핵심 스크립트>



# timestamp 구성하기 

t="$(date -u +%s)"

oo="000000000"

timestamp=$t$oo

echo $timestamp 


/usr/java/default/bin/java -jar cmdline-jmxclient-0.10.3.jar - abc.google.io:10100 "java.lang:type=MemoryPool,name=G1 Eden Space" "Usage" 2>> /tmp/javalog2

used="$(cat /tmp/javalog2 | grep used | cut -f2 -d" ")"

curl -i -XPOST 'http://influxdb.google.io:8086/write?db=telegraf' -d "javamem,server=abc.google.io,type=g1-eden value=$used $timestamp"




많이 보면 좋긴 하지만, 잘 동작한다고 가정하고 주요 지표만 보도록 했다. 

만약 다른 지표를 추가해 세밀히 볼 수 있을 것이다. 



g1일 때 

"java.lang:type=Memory" "HeapMemoryUsage"

"java.lang:type=MemoryPool,name=G1 Survivor Space"

"java.lang:type=MemoryPool,name=G1 Old Gen"

"java.lang:type=MemoryPool,name=G1 Eden Space"



cms일 때 

"java.lang:type=Memory" "HeapMemoryUsage"

"java.lang:type=MemoryPool,name=Par Eden Space" "Usage"

"java.lang:type=MemoryPool,name=Par Survivor Space" "Usage"

"java.lang:type=MemoryPool,name=CMS Old Gen" "Usage"




기존 grafana에 jvm 모니터링 추가한 내용이다. jvm 서버 재시작 없이 gc 내용을 볼 수 있게 만들었다. 




Posted by '김용환'
,