2015-08-26 4 views
0

Когда я бег моего сценария он не:выполнить команду из сценария оболочки не удается

# sh -x ./rsync.sh 
... 
+ rsync --safe-links --password-file=/etc/rsync.secret -rtvun --include='*.log*.gz' --filter='-! */' --prune-empty-dirs /some/path [email protected]::foo 
Unknown filter rule: `'-!' 
rsync error: syntax or usage error (code 1) at exclude.c(904) [client=3.1.1] 

но когда я копирую & вставить rsync --safe-links .... строки и выполнить его он работает отлично.

rsync.sh:

#!/bin/bash 

rsync_opts="--safe-links --password-file=/etc/rsync.secret -rtvu" 

while read path hostname volume extra_opts; do 
    rsync ${rsync_opts} ${extra_opts} ${path} ${volume}@${hostname}::${volume} 
done < /etc/rsync.paths 

rsync.paths:

/some/path/ hostname foo --include='*.log*.gz' --filter='-! */' --prune-empty-dirs 

ли кто-нибудь знает, почему он не из сценария и отлично работает, когда я запускаю команду вручную? Как я могу это исправить?

UPDATE: Он отлично работает, когда я использую eval "rsync ...", но до сих пор я не знаю, почему он не работает withou ней:/

+2

Я не смог сразу найти хороший дубликат SO, но это [эта проблема] (http://mywiki.wooledge.org/BashFAQ/050). Выходной сигнал 'sh -x' неоднозначен (' touch 'hello world'' и 'touch hello world' оба выводят одно и то же), что заставляет вас думать, что вы выполняете ту же команду, даже если вы этого не делаете. Вместо этого используйте 'bash -x'. –

+0

Если это проблема с неверным истолкованием переменных bash, не следует ли их цитировать? –

ответ

0

Ваша проблема в том, что ваш сценарий читает текст --filter='-! */' --prune-empty-dirs в переменную $extra_opts, который передается буквально команде, включая апострофы. Поэтому он разделяется на следующие аргументы: --filter='-!, */' и --prune-empty-dirs. Когда вы используете eval, то вся строка передается интерпретатору оболочки, который интерпретирует апострофы так, как вы хотите, поэтому он работает.

Кроме того, поскольку ваш сценарий использует bash, его следует отлаживать с помощью bash -x вместо sh -x.

+0

Итак ... может 'echo rsync $ {rsync_opts} ... помощь? Xargs? И если так, безопаснее ли тогда «eval'ing? –

+1

'xargs' не поможет по той же причине, что и исходная команда не работает. Он по-прежнему передает аргументы в буквальном смысле. Если вы хотите интерпретировать укус, который вы получили в качестве ввода в качестве оболочки, единственным вариантом будет 'eval'. В качестве альтернативы вы можете поместить один аргумент в каждую строку входного файла, но тогда вам понадобится более сложный парсер. – petersohn

Смежные вопросы