El pseudoterminal no se asignará porque la entrada estándar no es un terminal
Estoy intentando escribir un script de shell que cree algunos directorios en un servidor remoto y luego use scp para copiar archivos desde mi máquina local al control remoto. Esto es lo que tengo hasta ahora:
ssh -t user@server<<EOT
DEP_ROOT='/home/matthewr/releases'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR=$DEP_ROOT"/"$datestamp
if [ ! -d "$DEP_ROOT" ]; then
echo "creating the root directory"
mkdir $DEP_ROOT
fi
mkdir $REL_DIR
exit
EOT
scp ./dir1 user@server:$REL_DIR
scp ./dir2 user@server:$REL_DIR
Cada vez que lo ejecuto me sale este mensaje:
Pseudo-terminal will not be allocated because stdin is not a terminal.
Y el guión simplemente se cuelga para siempre.
Mi clave pública es confiable en el servidor y puedo ejecutar todos los comandos fuera del script sin problemas. ¿Algunas ideas?
Intente ssh -t -t
(o ssh -tt
para abreviar) forzar la asignación de pseudo-tty incluso si la entrada estándar no es una terminal.
Ver también: Terminar la sesión SSH ejecutada por el script bash
Desde la página de manual de ssh:
-T Disable pseudo-tty allocation.
-t Force pseudo-tty allocation. This can be used to execute arbitrary
screen-based programs on a remote machine, which can be very useful,
e.g. when implementing menu services. Multiple -t options force tty
allocation, even if ssh has no local tty.
También con opción -T
de manual.
Deshabilitar la asignación de pseudo-tty
Según la respuesta de Zanco , no está proporcionando un comando remoto ssh
, dada la forma en que el Shell analiza la línea de comando. Para resolver este problema, cambie la sintaxis de su ssh
invocación de comando para que el comando remoto esté compuesto por una cadena de varias líneas sintácticamente correcta.
Hay una variedad de sintaxis que se pueden utilizar. Por ejemplo, dado que los comandos se pueden canalizar a bash
and sh
y probablemente también a otros shells, la solución más sencilla es simplemente combinar ssh
la invocación del 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
Tenga en cuenta que ejecutar lo anterior sin /bin/bash
generará la advertencia Pseudo-terminal will not be allocated because stdin is not a terminal
. También tenga en cuenta que EOT
está entre comillas simples, por lo que bash
reconoce el heredoc como un nowdoc , desactivando la interpolación de variables locales para que el texto del comando se pase tal cual a ssh
.
Si eres fanático de las pipas, puedes reescribir lo anterior de la siguiente manera:
cat <<'EOT' | ssh user@server /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
La misma advertencia /bin/bash
se aplica a lo anterior.
Otro enfoque válido es pasar el comando remoto de varias líneas como una sola cadena, utilizando múltiples capas de bash
interpolación variable de la siguiente manera:
ssh user@server "$( cat <<'EOT'
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT
)"
La solución anterior soluciona este problema de la siguiente manera:
ssh user@server
es analizado por bash y se interpreta como elssh
comando, seguido de un argumentouser@server
que se pasará alssh
comando"
comienza una cadena interpolada, que cuando se complete, comprenderá un argumento que se pasará alssh
comando, que en este caso será interpretado comossh
el comando remoto a ejecutar comouser@server
$(
comienza a ejecutar un comando, y la salida es capturada por la cadena interpolada circundantecat
es un comando para generar el contenido de cualquier archivo que siga. La salida decat
se devolverá a la cadena interpolada de captura.<<
comienza un bash heredoc'EOT'
especifica que el nombre del heredoc es EOT. Las comillas simples'
que rodean a EOT especifican que el heredoc debe analizarse como un nowdoc , que es una forma especial de heredoc en la que bash no interpola el contenido, sino que se transmite en formato literal.Cualquier contenido que se encuentre entre
<<'EOT'
y<newline>EOT<newline>
se agregará a la salida de nowdocEOT
finaliza el nowdoc, lo que da como resultado la creación de un archivo temporal nowdoc y su devolución alcat
comando de llamada.cat
genera el nowdoc y pasa la salida a la cadena interpolada de captura)
concluye el comando a ejecutar"
concluye la captura de la cadena interpolada. El contenido de la cadena interpolada se devolverássh
como un único argumento de línea de comando, quessh
se interpretará como el comando remoto para ejecutar comouser@server
Si necesita evitar el uso de herramientas externas como cat
y no le importa tener dos declaraciones en lugar de una, use el read
heredoc integrado para generar el 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}"