Bashスクリプトは期待どおりに変数を置き換えません。

Bashスクリプトは期待どおりに変数を置き換えません。

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噴射空白とともに引用符は考慮されないので、、、 (3つのパラメータ)になります-l。元の例には同じ問題がありました。これは、他のパラメータで参照されている残りの文字列を含むパラメータの1つで終わりました。私はあなたのJavaがこれが好きではないと仮定します。'foobar'attr_marksweep_threadcountjava.lang:type=GarbageCollector,name='PS

パラメータを含む変数を参照する場合:

ls "$parms"

私たちは(議論)ls呼ばれました。-l 'foo bar'変数を引用すると、単語の分割(ファイル名にワイルドカードを使用)を防ぐことができますが、引用符は~へ変数はそうではありません。

単純なシェル変数を使用してこの問題を解決するのはやや難しいですが、Bashはソート、1つを使用して、各パラメータを配列の別々の要素に入れることができます。

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: と一緒に連結されたすべての項目 (二重引用符で囲まれた 2 つの文字列と一重引用符で囲まれた単一引用符)'java.lang:type=GarbageCollector,name='\''PS' として解釈されます。二重引用符を使用すると、より良く見えます。'java.lang:type=GarbageCollector,name='\''PS'"java.lang:type=GarbageCollector,name='PS"

おすすめ記事