Есть несколько проблем с вашим подходом:
Ваше здесь c интерполируется локально . Фактическая команда, которую вы выполняете: for w in var asd dsa 123 ; do echo >&2; echo "123"; done
Это можно увидеть с помощью set -x, чтобы включить локальную трассировку, и запустить s sh с cat вместо оболочки входа в систему:
ssh pi cat << EOF
for w in $(echo "/var/asd/dsa/123" | tr "/" " ") ; do echo $w >&2; echo "123"; done
EOF
+ ssh pi cat
++ echo /var/asd/dsa/123
++ tr / ' '
for w in var asd dsa 123 ; do echo >&2; echo "123"; done
Как видите, echo /var/asd/dsa/123
и tr / ' '
выполняются локально, а $ w интерполируется в пустую строку.
Возможно, вы хотите использовать одинарные кавычки вокруг EOF:
ssh pi cat << 'EOF'
for w in $(echo "/var/asd/dsa/123" | tr "/" " ") ; do echo $w >&2; echo "123"; done
EOF
+ ssh pi cat
for w in $(echo "/var/asd/dsa/123" | tr "/" " ") ; do echo $w >&2; echo "123"; done
Теперь команда поступает правильно.
Примечание: если вы sh, что $(echo "/var/asd/dsa/123" | tr "/" " ")
запускается локально, то вам по крайней мере нужно выйти из $ ш.
ssh pi << EOF
for w in $(echo "/var/asd/dsa/123" | tr "/" " ") ; do echo \$w >&2; echo "123"; done
EOF
Буферизация испортит порядок . Вот почему ваши пустые строки (напечатанные echo >&2
) находятся в конце вашего вывода. Вы можете использовать tee
, чтобы «форсировать» буферизацию строки:
ssh -T pi << 'EOF'
for w in $(echo "/var/asd/dsa/123" | tr "/" " ") ; do echo $w >&2; echo "123"; done
EOF
+ ssh -T pi
Linux mserv 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l
...
123
123
123
123
var
asd
dsa
123
В сравнении:
ssh pi << 'EOF'
for w in $(echo "/var/asd/dsa/123" | tr "/" " ") ; do echo $w >&2; echo "123"; done 2>&1 | tee
EOF
+ ssh pi
Linux mserv 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l
...
var
123
asd
123
dsa
123
123
123
(в первом случае сначала печатается STDIN, затем STDERR, во втором, чередуются строки)
Передача команд в s sh и принудительное выполнение оболочки входа Если вы запускаете команды, отправляя их в stdin из s sh, запускается оболочка входа и распечатайте MOTD (в зависимости от конфигурации сервера) и запустите оболочку входа (которая имеет несколько побочных эффектов).
В моем примере Linux mserv 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l
является частью MOTD. Однако нет необходимости в конвейере, s sh будет запускать последний аргумент через пользовательскую оболочку, без необходимости передавать его в STDIN. Это может быть ограничено значением MAX_ARG_STRLEN (что составляет ~ 128 КБ), но если у вас есть скрипт такого размера, вам, вероятно, следует сначала отправить его на хост.
$ ssh pi '
for w in $(echo "/var/asd/dsa/123" | tr "/" " ")
do
echo $w >&2
echo "123"
done 2>&1 | tee
'
var
123
asd
123
dsa
123
123
123
Примечание: Это может быть ограничено MAX_ARG_STRLEN (что составляет ~ 128 КБ), но если у вас есть скрипт такого размера, вы, вероятно, должны сначала найти его на хосте.
Примечание: pi
- это тестовый сервер, который я использую, замените его соответствующей информацией о подключении.