rsyncがBashスクリプトで「末尾の欠落」について文句を言う


13

スクリーンセッションで、あるサーバーから別のサーバーにファイルをrsyncしようとしています。毎回長いコマンドを書く代わりに、Bashスクリプトを入れることにしました。しかし、実行するとMissing trailing-" in remote-shell command.エラーが発生します。

スクリプトで何がうまくいかないのか疑問に思います。

root@127.0.0.1:~# /raid/data/module/bin/rbk.sh Movies /raid/data/Movies rsync_target/

/raid/data/module/bin/screen -S Movies 

/opt/bin/rsync --rsh="ssh -p 10022 -c des"\
--rsync-path="/opt/bin/rsync" --inplace --progress -a -vv \
/raid/data/Movies sys@192.168.1.15:/raid/data/rsync_target/

Missing trailing-" in remote-shell command.
rsync error: syntax or usage error (code 1) at main.c(361) [sender=3.0.5]

スクリプトは、最初に何を実行するかをエコーし​​てから、コマンドを実行します。以下は私のスクリプトのダンプです:

#!/bin/bash
SCREEN="/raid/data/module/bin/screen"
SCREENOPT="-S"
SCREEN_TITLE=$1

RSYNC="/opt/bin/rsync"
RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"

SOURCE=$2

REMOTE_USER="sys@"
REMOTE_HOST="192.168.1.15"
REMOTE_BASE=":/raid/data/"
REMOTE_TARGET=$3

echo ${SCREEN} ${SCREENOPT} ${SCREEN_TITLE}

echo ${RSYNC} ${RSYNCOPT} ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}
${RSYNC} ${RSYNCOPT} ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}

回答:


23

短い答え:BashFAQ#050を参照してください。

長い答え:あなたが抱えている問題は、変数に引用符を埋め込むことが、あなたが思っているように機能しないことです。具体的には、変数が置き換えられる前に引用符が解析されるため、変数の値に引用符が含まれていると、正しく動作しません。コマンドラインで設定RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" ..."して使用すると${RSYNCOPT}、変数内の引用符は解析されず、通常の文字として扱われます。このように、rsyncのコマンドは、単一のパラメータを受信するのではなく--rsh=ssh -p 10022 -c des、それが受信5: 、--rsh="ssh-p10022-cおよびdes"。--rshコマンドには単一の(一致しない)引用符が含まれているため、エラーが発生します。

何が起こっているのかを確認するset -xには、コマンドを実行する前にシェルに各コマンドを出力させる(実際に何が起こっているのかを確認できるようにする)か、echo ${whatever}(非常に誤解を招く)をに置き換えprintf "%q " ${whatever}; echoます。

これを解決するにはいくつかの方法があります。1つはRSYNCOPT、そもそも変数に(おそらく他のものも)変数を格納しようとしないようにすることです。もう1つはRSYNCOPT、単純な文字列ではなく配列(この混乱のないワード境界を追跡できる)として格納することです。

コマンドを実行する前に印刷するset -xには、rsyncコマンドの前に使用し、後で+ xを設定してオフにするか、printf上記のコマンドのようなものを使用します(コマンドの後に余分なスペースが印刷されることに注意してください。問題)。

array + printfアプローチは次のとおりです。

...
RSYNCOPT=(--rsh="ssh -p 10022 -c des" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv)
...
printf "%q " ${SCREEN} ${SCREENOPT} ${SCREEN_TITLE}
echo

printf "%q " ${RSYNC} "${RSYNCOPT[@]}" ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}
echo
${RSYNC} "${RSYNCOPT[@]}" ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET}

私を正しい方向に向けてくれてありがとう、とにかくあなたが提供したリンクをざっと見て、関数がより読みやすいことを確信しました(または少なくとも適切にフォーマットされたときにそうなります):( run_rsync() { /opt/bin/rsync "--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv" $1 $2 } run_rsync ${SOURCE} ${REMOTE_USER}${REMOTE_HOST}${REMOTE_BASE}${REMOTE_TARGET} これはかなり古いですが、まだ1つです) 「リモートシェルコマンドで "Missing trailing-"」を検索したときの最初のリンクの例)
Francesco Marchetti-Stasi

6

エスケープされた引用符とエスケープされていない引用符の迷路は$RSYNCOPT、私を混乱させます。rsyncやssh、ローカルシェルやリモートシェルが混乱しているのは当然です。

バックスラッシュを追加または削除してこれを機能させる方法はあるかもしれませんが、代わりに次の回避策をお勧めします。

交換:

RSYNCOPT="--rsh=\"ssh -p 10022 -c des\" --rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"

沿って:

export RSYNC_RSH="ssh -p 10022 -c des"
RSYNCOPT="--rsync-path=\"/opt/bin/rsync\" --inplace --progress -a -vv"

私のシステムでスクリプトを少し簡略化したバージョンを試したところ、同じエラーメッセージが表示されました。この回避策で修正されました。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.