Script de bash não substituindo a variável conforme esperado

1

Estou tentando escrever um script de shell que usa um comando chamado jmxquery

Isso é o que funciona na linha de comando:

[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**

Como você pode ver, eu obtenho um JMX OK com detalhes de contagem de threads. Então, estou tentando fazer o mesmo em um script de shell. Eu tenho uma variável definida assim:

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"

Então eu corro:

java -jar ${JAR} -U ${SERVICE_URL} $attr_marksweep_threadcount

Aqui está um trecho da aparência da saída com o 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**

Como você pode ver, é cortado o resto do comando depois do PS.

Como obtenho o script para substituir corretamente?

    
por Aditya K 02.09.2016 / 10:03

2 respostas

1

Quando você faz isso (parafraseando seu exemplo mais curto no comentário):

mkdir "foo bar"
parms="-l 'foo bar'"
ls $parms

A variável parms é divisão de palavras ao longo de qualquer espaço em branco, sem considerar as cotações, torna-se assim -l , 'foo e bar' (três argumentos). O exemplo original teve o mesmo problema com attr_marksweep_threadcount e terminou com um dos argumentos contendo java.lang:type=GarbageCollector,name='PS e o resto da string citada em outro argumento. Eu suponho que seu java não gostou disso.

Se citarmos a variável que contém os parâmetros:

ls "$parms"

Recebemos ls chamado com -l 'foo bar' (um argumento). Citar a variável impede a divisão de palavras (e a globalização de nomes de arquivos), mas aspas dentro da variável não.

É um pouco difícil contornar esse problema com variáveis de shell simples, mas como o Bash tem matrizes , você poderia usar um e colocar cada argumento em um elemento separado da matriz:

array=("-l" "foo bar")
ls "${array[@]}"

"${array[@]}" se expande para o equivalente a todos os membros da matriz, citados individualmente.

Com shells sem array, você precisa usar algumas soluções. Os parâmetros posicionais podem ser expanded com $@ da mesma forma que as matrizes:

set -- "-l" "foo bar"
ls "$@"

Ou, como a divisão de palavras é feita somente ao longo dos caracteres definidos em IFS , podemos dividir o shell em algo diferente de espaço em branco.

IFS=#
parms='-l#foo bar'
ls $parms
# though IFS stays set to the hash sign after this

A saída de bash -x em seu exemplo tenta mostrar o que acontece, mas desde que ele tenta mostrar em aspas simples uma string contendo um aspas simples, a saída é um pouco confusa. Este:  %código% analisa como 'java.lang:type=GarbageCollector,name='\''PS' , 'java.lang:type=GarbageCollector,name=' e \' todos concatenados juntos, ou seja, duas cadeias de caracteres com aspas simples e uma aspa simples entre aspas. Que parece mais bonito entre aspas duplas: 'PS' .

    
por 02.09.2016 / 15:46
0

Tente substituir:

attr_marksweep_threadcount="-O java.lang:type=GarbageCollector,name='PS MarkSweep' -A LastGcInfo -K GcThreadCount"

com:

attr_marksweep_threadcount='-O java.lang:type=GarbageCollector,name="PS MarkSweep" -A LastGcInfo -K GcThreadCount'
    
por 02.09.2016 / 10:55