Bashスクリプトで文字列を実行しようとしています。文字列には変数が含まれています(したがって、状況によっては一部のCLIパラメータを置き換えることができます)。
問題は、インクルード変数を使用すると、--argument=value
すべてがクラッシュしてエラーが発生することです。
Missing trailing-' in remote-shell command.
サンプルコード:
#!/bin/bash
rsync_path="/usr/bin/rsync -azhrP"
rsync_ssh_cmd="--rsh='ssh -o Compression=no'"
`$rsync_path /path/to/file $rsync_ssh_cmd username@localhost:/tmp`
このコードに最後の文字列を入れるとecho
大丈夫です。ただし、スクリプトで文字列を実行しようとすると、期待どおりに実行されません。
解決策が見つかりました。試してみると、すべてが大丈夫でしょう。
eval "my-command-string"
変える
`my-command-string`
または
(my-command-string)
なぜですか?どうすれば使用を避けることができますか(本当にすべきですか?)eval
?
私はbash 4.3.11(1)-release (x86_64-pc-linux-gnu)
(Kubuntu 14.04.3)を使用しています。
答え1
いいえeval
文字列を2回評価する別の方法を見つけて、これを防ぐことができます。何をしても必ず必要です。2つの評価あなたの要求解析を解析する。
私の言葉は:
this is 'a parsed" command string"'
^3として計算性格:
1: this 2: is 3: a parsed" command string"
3の引用符は重要ではありません。まったく問題ではありません。単語の特定の文字。'
元のコマンドラインで使用された構文引用したこれはシェルのパーサーが解釈され分離されるため重要です。言葉。その中にあるものはすべて単語の一部にすぎません。
だから得たいならもっと言葉はaから出てきた。一つ、準備済みつまり、これをシェルへの入力として返す必要があります。これは、シェルが入力時に入力引用符を処理することです。引用符は、意味のある方法で入力をエスケープして区切るために使用されます。 Shellがこのように続くと、無意味でかなり怖いでしょう。最後にみんな入力はゼロと評価されます!
だからあなたは2回目のレビュー。処理しないため、$(
コマンド置換では取得できません。)
入力する、彼らは管理する出力。どんな副作用$
単語拡張これをより多くの世代と同一視することもできます。性格そうではありません。つまり、大地-分かれた。大地- 分割$IFS
して*
ワイルドカードシェルによって実行される後ろに入力する性格解析中にすでに区別されています。
今の全体的な目的eval
はeval
Uat〜のように入力するシェルが入力として受け取った文字列。これは正確にこれは正しいツールですが、必要に応じて他の方法で行うこともできます。
1つの方法は、.
独自の結果を得ることです。
string="printf '<%s>\n' 'these are' 'some words' 'i will evaluate again'"
. /dev/fd/0 <<!
$string
!
この例では、シェル評価する〜のように入力するそれ出力。効果があります:
<these are>
<some words>
<i will evaluate again>
別のシェルを呼び出して出力を入力として評価します。
sh -c "$string"
...結果は同じです。あなたはできます遅延シェルを定義して入力しますalias
。
alias evaled="$string"
evaled
...同じ出力。
最大直接方法は次のとおりです
eval "$string"
効果は他のすべての例とほぼ同じですが、今回は実際にコマンドを使用して行いました。名前付き私がしたいことのために。
eval
人々はそれが何をするのか、なぜそれを使うべきかを理解していなかったので、悪い評価を受けました。問題は、その仕事の効果を理解できない場合、それを使用してはならないということです。迷子になりやすいです。コマンドが評価されます。二重- これは通常よりも多く -一つこれは通常、ほとんどの人がこのサイトを閲覧するのに十分な時間です。
したがってeval
、この場合、目的の操作を実行するにはを使用する必要があります。なぜなら、やりたいことはeval
文字列だからです。私は判断しないなぜeval
もっと良い方法があればいいのですが、文字列が欲しいが、シェル文字列の内容が欲しいときコメントしました。シェル入力としてeval
。
答え2
埋め込み引用符が原因でこの問題が発生します。バッシュFAQ
作業環境は次のとおりです。
#!/bin/bash
rsync_path="/usr/bin/rsync -azhrP"
rsync_ssh_cmd=(--rsh='ssh \-o Compression=no')
`$rsync_path /path/to/file $rsync_ssh_cmd root@localhost:/tmp`
【概念の証拠】
[root@localhost ~]# bash -x /tmp/c.sh
+ rsync_path='/usr/bin/rsync -azhrP'
+ rsync_ssh_cmd=(--rsh='ssh \-o Compression=no')
++ /usr/bin/rsync -azhrP /path/to/file --rsh=ssh '\-o' Compression=no root@localhost:/tmp
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/root/.ssh/id_rsa' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: /root/.ssh/id_rsa
root@localhost's password: