jmxquery라는 명령을 사용하는 쉘 스크립트를 작성하려고 합니다.
이는 명령줄에서 작동합니다.
[root@monitor jmxquery]# java -jar /opt/jmxquery/jmxquery.jar \
-U service:jmx:rmi:///jndi/rmi://tomcat.cyberdyne.corp:1099/jmxrmi \
-O java.lang:type=GarbageCollector,name='PS MarkSweep' \
-A LastGcInfo \
-K GcThreadCount
**JMX OK - LastGcInfo.GcThreadCount=4 | LastGcInfo.GcThreadCount=4**
보시다시피, 스레드 개수 세부정보로 JMX OK를 얻었습니다. 그래서 쉘 스크립트에서 동일한 작업을 수행하려고 합니다. 다음과 같이 정의된 변수가 있습니다.
JAR=/opt/jmxquery/jmxquery.jar
JMXHOST=tomcat.cyberdyne.corp
JMXPORT=1099
SERVICE_URL="service:jmx:rmi:///jndi/rmi://${JMXHOST}:${JMXPORT}/jmxrmi"
attr_marksweep_threadcount="-O java.lang:type=GarbageCollector,name='PS MarkSweep' -A LastGcInfo -K GcThreadCount"
그런 다음 다음을 실행합니다.
java -jar ${JAR} -U ${SERVICE_URL} $attr_marksweep_threadcount
이것은 bash -x 출력의 일부입니다.
+ attr_marksweep_threadcount='-O java.lang:type=GarbageCollector,name='\''PS MarkSweep'\'' -A LastGcInfo -K GcThreadCount'
+ java -jar /opt/jmxquery/jmxquery.jar -U service:jmx:rmi:///jndi/rmi://spotfirewin75.cyberdyne.corp:1099/jmxrmi -O 'java.lang:type=GarbageCollector,name='\''PS' 'MarkSweep'\''' -A LastGcInfo -K GcThreadCount
**JMX CRITICAL - java.lang:type=GarbageCollector,name='PS**
보시다시피 PS 이후의 나머지 명령은 잘렸습니다.
스크립트를 올바르게 바꾸려면 어떻게 해야 합니까?
답변1
이렇게 하면(주석에서 더 짧은 예를 다른 말로 표현):
mkdir "foo bar"
parms="-l 'foo bar'"
ls $parms
변수 parms
는분사공백과 함께 따옴표는 고려되지 않으므로 ,
-l
, 'foo
( bar'
3개의 매개변수)가 됩니다. 원래 예제에는 와 동일한 문제가 있었는데 , 이는 다른 매개변수에서 참조되는 나머지 문자열을 attr_marksweep_threadcount
포함하는 매개변수 중 하나로 끝났습니다 . java.lang:type=GarbageCollector,name='PS
나는 당신의 자바가 이것을 좋아하지 않는다고 가정합니다.
매개변수가 포함된 변수를 참조하는 경우:
ls "$parms"
우리는 (논쟁) ls
불려 졌습니다. -l 'foo bar'
변수를 인용하면 단어 분할(파일 이름에 와일드카드 사용)을 방지할 수 있지만 인용 부호는~에변수는 그렇지 않습니다.
간단한 쉘 변수를 사용하여 이 문제를 해결하는 것은 다소 어렵지만 Bash는정렬, 하나를 사용하고 각 매개변수를 배열의 별도 요소에 넣을 수 있습니다.
array=("-l" "foo bar")
ls "${array[@]}"
"${array[@]}"
모든 배열 멤버와 동등하게 확장됩니다(개별적으로 인용됨).
무제한의 쉘 배열의 경우 몇 가지 해결 방법을 사용해야 합니다. 이것위치 매개변수할 수 있다로 확장됨$@
배열과 유사:
set -- "-l" "foo bar"
ls "$@"
또는 단어 분할은 에 설정된 문자에 따라서만 수행되므로 IFS
공백이 아닌 다른 항목에서 쉘 분할을 만들 수 있습니다.
IFS=#
parms='-l#foo bar'
ls $parms
# though IFS stays set to the hash sign after this
예제의 출력은 bash -x
진행 상황을 표시하려고 시도하지만 작은 따옴표 안에 작은 따옴표가 포함된 문자열을 표시하려고 하므로 출력이 약간 혼란스럽습니다. This: , 및 함께 연결된 모든 항목(작은따옴표로 묶인 두 개의 문자열과 작은따옴표로 묶인 작은따옴표) 'java.lang:type=GarbageCollector,name='\''PS'
으로 해석됩니다 . 큰따옴표를 사용하면 더 좋아 보입니다 .'java.lang:type=GarbageCollector,name='
\'
'PS'
"java.lang:type=GarbageCollector,name='PS"
답변2
교체해 보세요:
attr_marksweep_threadcount="-O java.lang:type=GarbageCollector,name='PS MarkSweep' -A LastGcInfo -K GcThreadCount"
그리고:
attr_marksweep_threadcount='-O java.lang:type=GarbageCollector,name="PS MarkSweep" -A LastGcInfo -K GcThreadCount'