Zgodnie z odpowiedzią zanco nie udostępniasz polecenia zdalnego ssh, biorąc pod uwagę sposób, w jaki powłoka analizuje wiersz poleceń. Aby rozwiązać ten problem, zmień składnię sshwywołania polecenia, tak aby zdalne polecenie składało się z poprawnego pod względem składni, ciągu zawierającego wiele wierszy.
Istnieje wiele różnych składni, których można użyć. Na przykład, ponieważ polecenia mogą być rurami do bashi shi prawdopodobnie inne powłoki zbyt najprostszym rozwiązaniem jest po prostu połączyć sshpowłoki wywołania z heredocs:
ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
Zauważ, że wykonanie powyższego bez /bin/bash spowoduje ostrzeżenie Pseudo-terminal will not be allocated because stdin is not a terminal. Zauważ też, że EOTjest otoczony pojedynczymi cudzysłowami, dzięki czemu bashrozpoznaje heredoc jako nowdoc , wyłączając lokalną interpolację zmiennych, aby tekst polecenia był przekazywany „tak jak jest”ssh .
Jeśli jesteś fanem rur, możesz przepisać powyższe w następujący sposób:
cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
To samo zastrzeżenie /bin/bashdotyczy powyższego.
Innym ważnym podejściem jest przekazanie wieloliniowego zdalnego polecenia jako pojedynczego łańcucha, przy użyciu wielu warstw bashinterpolacji zmiennych w następujący sposób:
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
Powyższe rozwiązanie rozwiązuje ten problem w następujący sposób:
ssh user@serverjest analizowany przez bash i jest interpretowany jako sshpolecenie, a następnie argument user@serverprzekazywany do sshpolecenia
"rozpoczyna interpolowany ciąg, który po zakończeniu będzie zawierać argument, który zostanie przekazany do sshpolecenia, które w tym przypadku będzie interpretowane sshjako zdalne polecenie do wykonania jakouser@server
$( rozpoczyna polecenie do wykonania, a wyjście jest przechwytywane przez otaczający interpolowany ciąg
catto polecenie do wyświetlania zawartości dowolnego pliku, który następuje. Dane wyjściowe catzostaną przekazane z powrotem do przechwyconego interpolowanego ciągu
<<zaczyna bash heredoc
'EOT'określa, że nazwa heredoc to EOT. Pojedyncze cytaty 'otaczające EOT określają, że heredok powinien być analizowany jako nowdoc , co jest specjalną formą heredoc, w której zawartość nie jest interpolowana przez bash, ale raczej przekazywana w formacie dosłownym
Każda treść napotkana między <<'EOT'i <newline>EOT<newline>zostanie dołączona do danych wyjściowych nowdoc
EOTkończy nowdoc, co powoduje utworzenie pliku tymczasowego nowdoc i przekazanie go z powrotem do catkomendy wywołującej . catwysyła nowdoc i przekazuje dane wyjściowe do przechwyconego interpolowanego ciągu
) kończy polecenie do wykonania
"kończy przechwycony interpolowany ciąg. Zawartość interpolowanego ciągu zostanie przekazana z powrotem sshjako pojedynczy argument wiersza poleceń, który sshbędzie interpretowany jako polecenie zdalne do wykonania jakouser@server
Jeśli chcesz uniknąć korzystania z zewnętrznych narzędzi, takich jak cati nie masz nic przeciwko posiadaniu dwóch instrukcji zamiast jednej, użyj readwbudowanego narzędzia heredoc do wygenerowania polecenia SSH:
IFS='' read -r -d '' SSH_COMMAND <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
ssh user@server "${SSH_COMMAND}"
ssh user@server /bin/bash <<EOT…