Per la risposta di zanco , non stai fornendo un comando remoto a ssh
, dato come la shell analizza la riga di comando. Per risolvere questo problema, modificare la sintassi ssh
dell'invocazione del comando in modo che il comando remoto sia composto da una stringa multilinea sintatticamente corretta.
Esistono varie sintassi che possono essere utilizzate. Ad esempio, poiché i comandi possono essere reindirizzati bash
e sh
, e probabilmente anche altre shell, la soluzione più semplice è semplicemente combinare l' ssh
invocazione della shell con heredocs:
ssh user@server /bin/bash <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
Si noti che l'esecuzione di quanto sopra senza /bin/bash
comporterà l'avviso Pseudo-terminal will not be allocated because stdin is not a terminal
. Nota inoltre che EOT
è racchiuso tra virgolette singole, in modo da bash
riconoscere l'eredoc come un nowdoc , disattivando l'interpolazione della variabile locale in modo che il testo del comando venga passato così com'è ssh
.
Se sei un fan delle pipe, puoi riscrivere quanto sopra come segue:
cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
Lo stesso avvertimento /bin/bash
vale per quanto sopra.
Un altro approccio valido è passare il comando remoto multilinea come una singola stringa, usando più livelli di bash
interpolazione variabile come segue:
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
La soluzione sopra risolve questo problema nel modo seguente:
ssh user@server
viene analizzato da bash e viene interpretato come il ssh
comando, seguito da un argomento user@server
da passare al ssh
comando
"
inizia una stringa interpolata, che una volta completata comprenderà un argomento da passare al ssh
comando, che in questo caso verrà interpretato ssh
come il comando remoto da eseguire comeuser@server
$(
inizia un comando da eseguire, con l'output catturato dalla stringa interpolata circostante
cat
è un comando per generare il contenuto di qualunque file segue. L'output di cat
verrà passato nuovamente nella stringa interpolata di acquisizione
<<
inizia un branco ereditario
'EOT'
specifica che il nome dell'eredità è EOT. Le singole virgolette che '
circondano EOT specificano che l'ereditarietà dovrebbe essere analizzata come nowdoc , che è una forma speciale di ereditarietà in cui i contenuti non vengono interpolati da bash, ma piuttosto trasmessi in formato letterale
Qualsiasi contenuto riscontrato tra <<'EOT'
e <newline>EOT<newline>
verrà aggiunto all'output nowdoc
EOT
termina nowdoc, creando un file temporaneo nowdoc che viene restituito al cat
comando chiamante . cat
genera l'outdoc e restituisce l'output alla stringa interpolata di acquisizione
)
conclude il comando da eseguire
"
conclude la stringa interpolata di acquisizione. Il contenuto della stringa interpolata verrà restituito ssh
come singolo argomento della riga di comando, che ssh
interpreterà come il comando remoto da eseguire comeuser@server
Se devi evitare di usare strumenti esterni come cat
, e non ti dispiace avere due istruzioni invece di una, usa il read
built-in con un heredoc per generare il comando 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…