私のスクリプトには次のものがあります。
sshkey="/Users/me/some path/with spaces/id_rsa"
dstport=...
dstparent=...
dstuserhost=...
rsync -az --delete -e "ssh -i $sshkey -p $dstport" $src $dstuserhost:$dstparent
私がそれを実行すると、私は得ます:
rsync: "/Users/me/some" の link_stat 失敗: 対応するファイルまたはディレクトリなし (2)
答え1
周囲に一重引用符を追加すると、$sshkey
問題が解決します。
rsync -az --delete -e "ssh -i '$sshkey' -p '$dstport'" "$src" "$dstuserhost:$dstparent"
値$sshkey
は二重引用符で囲まれた文字列内にあるため、呼び出し前にインタラクティブシェルによって拡張されますが、単一引用符は、接続を確立するために呼び出しが行われたrsync
ときに文字列がもはや分割されるのを防ぎます。rsync
ssh
$sshkey
それ自体に一重引用符文字が含まれていないとします。
答え2
「内部」引用符を挿入する必要があります。私が言うこと
printf -v rsh_cmd 'ssh -i "%s" -d "%s"' "$sshkey" "$dstport"
...
rsync ... -e "$rsh_cmd"
答え3
-e
このオプションの引数は、シェルのコマンドrsync
ラインではなくrsync
コマンドラインです。rsync
Bourne シェルとは異なる独自のルールを使用して解析されます。
すべてのシェルと同様に、空白文字をパラメータ区切り文字として扱い、Bourneシェルと同様に、一重引用符と二重引用符(バックスラッシュを除く)を引用演算子として扱います。シェル拡張(たとえば$var
、、、、$(cmd)
... *.txt
)~user
は実行されません。
したがって、疑似コマンドラインに任意の引数を含めるには、二重引用符文字自体(一重引用符で囲む)を除いて、引数を二重引用符で囲むか、一重引用符で囲むことができます。一重引用符文字自体の場合(二重引用符で囲む)
たとえば、SSHキーファイルがある場合、パラメータはまたはに/cygdrive/c/John Doe/.ssh/John "Dude" Doe's.rsa
似-e
ている必要があります。'/cygdrive/c/John Doe/.ssh/John "Dude" Doe'"'"'s.rsa'
"/cygdrive/c/John Doe/.ssh/John "'"'"Dude"'"'" Doe's.rsa"
これを行うために専用の関数を定義できます。再同期リファレンス良い:
# ksh93/bash/zsh syntax:
rsync_quote() {
local arg="$1"
arg=${arg//\'/\'\"\'\"\'}
printf "'%s'\n" "$var"
}
rsync -e "ssh -i $(rsync_quote "$sshkey") -p $dstport" ...
別のオプションは、シェルを引数として渡してコマンドラインを解釈する-e
ことです。ssh
これの1つの利点は、シェルが変数拡張を実行できることです。
KEY=$sshkey PORT=$dstport SSH_COMMAND='ssh -i "$KEY" -p "$PORT" "$@"' \
rsync -e "sh -c 'eval \"\$SSH_COMMAND\"' sh" ...
:で実行すると、strace -fe execve -s 999
次のように拡張されることがわかります。
execve("/usr/bin/rsync", ["rsync", "-e", "sh -c 'eval \"$SSH_COMMAND\"' sh", "1/", "localhost:2/"], 0x7ffc03b83678 /* 74 vars */) = 0
strace: Process 7208 attached
[pid 7208] execve("/bin/sh", ["sh", "-c", "eval \"$SSH_COMMAND\"", "sh", "localhost", "rsync", "--server", "-e.LsfxC", ".", "2/"], 0x7ffcc6ad0f28 /* 74 vars */) = 0
[pid 7209] execve("/usr/bin/ssh", ["ssh", "-i", "/cygdrive/c/John Doe/.ssh/John \"Dude\" Doe's.rsa", "-p", "2222", "localhost", "rsync", "--server", "-e.LsfxC", ".", "2/"], 0x5651a0c144a8 /* 74 vars */) = 0