Во-первых, ссылки на переменные (например, $STATUS
) расширяются локальной оболочкой еще до того, как команда будет отправлена на удаленный компьютер, не говоря уже о выполнении.Чтобы предотвратить это, вам нужно экранировать $
(например, \$STATUS
), чтобы он просто передавался в удаленную систему, а не интерпретировался локально.
Во-вторых, кавычки не вкладываются.Вы пытаетесь вложить двойные кавычки в строку в двойных кавычках, и это не работает;вам нужно избегать внутренних двойных кавычек (как и $
).
Вы можете проверить это, используя echo
вместо ssh
.Обычно это плохой способ сказать, что происходит с командой оболочки, потому что echo
показывает, как выглядят аргументы после , которые они прошли через процесс разбора оболочки.Но в этом случае это именно то, что будет отправлено в удаленную систему, так что это то, что вы хотите.Вот пример:
$ PASSWORD='p4ssw0rd'
$ PASSCONFIRM='p4ssw0rd'
$ echo "printf '%s\n%s' "$PASSWORD" "$PASSCONFIRM" | passwd; STATUS=$?; echo $STATUS; if (( $STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;"
printf '%s\n%s' p4ssw0rd p4ssw0rd | passwd; STATUS=0; echo ; if (( == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;
Обратите внимание на «STATUS=0; echo ; if (( == 0 ))
» - это потому, что все ссылки на переменные ($?
и $STATUS
) были расширены локально, до 0 и «» соответственно.Вот версия с добавленными соответствующими escape-кодами:
$ echo "printf '%s\n%s' \"$PASSWORD\" \"$PASSCONFIRM\" | passwd; STATUS=\$?; echo \$STATUS; if (( \$STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;"
printf '%s\n%s' "p4ssw0rd" "p4ssw0rd" | passwd; STATUS=$?; echo $STATUS; if (( $STATUS == 0 )); then printf 'Password Changed Successfully\n'; else printf 'Password Change Unsuccessful\n'; fi; sleep 1;
Кстати, обратите внимание, что я предполагаю, что PASSWORD
и PASSCONFIRM
являются локальными, а должен быть расширен локально, поэтому я не сделал$
на тех.Но есть потенциальная проблема: если какое-либо значение содержит что-либо, что интерпретируется внутри двойных кавычек, удаленная оболочка будет интерпретировать его.Так, например, если ваш пароль p4$$w0rd
, $$
будет заменен идентификатором процесса удаленной оболочки.Было бы лучше использовать одинарные кавычки вокруг них, но если они содержат одинарные кавычки, возникнет хаос:
$ PASSWORD="p4'\$\$w0rd"
$ echo "$PASSWORD" # show the true password
p4'$$w0rd
$
$ # This will not work right, because of the $$:
$ echo "printf '%s\n%s' \"$PASSWORD\" \"$PASSCONFIRM\" ..."
printf '%s\n%s' "p4'$$w0rd" "p4ssw0rd" ...
$
$ # Neither will this, because of the single-quote:
$ echo "printf '%s\n%s' '$PASSWORD' '$PASSCONFIRM' ..."
printf '%s\n%s' 'p4'$$w0rd' 'p4ssw0rd' ...
$
$ # But this, while messy, will work:
$ ESCAPEDPW=${PASSWORD//\'/\'\\\'\'}
$ ESCAPEDCONFIRM=${PASSCONFIRM//\'/\'\\\'\'}
$ echo "printf '%s\n%s' '$ESCAPEDPW' '$ESCAPEDCONFIRM' ..."
printf '%s\n%s' 'p4'\''$$w0rd' 'p4ssw0rd' ...
... подождите, я слышал, вы говорите, , что будет работать?Да, и вот демонстрация того, что этот бестолковый пароль будет делать в удаленной системе:
$ printf '%s\n%s' 'p4'\''$$w0rd' 'p4ssw0rd'
p4'$$w0rd
p4ssw0rd
(Обратите внимание, что они не совпадают, потому что я не удосужился обновить PASSCONFIRM
.)