linux - variable - stdin bash script




El pseudo-terminal no se asignará porque stdin no es un terminal (7)

Después de leer muchas de estas respuestas, pensé que compartiría mi solución resultante. Todo lo que agregué es /bin/bash antes del heredoc y ya no da el error.

Utilizar esta:

ssh [email protected] /bin/bash <<'ENDSSH'
   hostname
ENDSSH

En lugar de esto (da error):

ssh [email protected] <<'ENDSSH'
   hostname
ENDSSH

O usa esto:

ssh [email protected] /bin/bash < run-command.sh

En lugar de esto (da error):

ssh [email protected] < run-command.sh

EXTRA :

Si aún desea una solicitud interactiva remota, por ejemplo, si el script que está ejecutando de forma remota le solicita una contraseña u otra información, ya que las soluciones anteriores no le permitirán escribir en las solicitudes.

ssh -t [email protected] "$(<run-command.sh)"

Y si también desea registrar toda la sesión en un archivo logfile.log :

ssh -t [email protected] "$(<run-command.sh)" | tee -a logfile.log

Estoy intentando escribir un script de shell que crea algunos directorios en un servidor remoto y luego usa scp para copiar archivos de mi máquina local en el remoto. Esto es lo que tengo hasta ahora:

ssh -t [email protected]<<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 [email protected]:$REL_DIR
scp ./dir2 [email protected]:$REL_DIR

Cada vez que lo ejecuto recibo este mensaje:

Pseudo-terminal will not be allocated because stdin is not a terminal.

Y el guión simplemente cuelga para siempre.

Mi clave pública es de confianza en el servidor y puedo ejecutar todos los comandos fuera de la secuencia de comandos muy bien. ¿Algunas ideas?


El mensaje de advertencia Pseudo-terminal will not be allocated because stdin is not a terminal. es debido al hecho de que no se especifica ningún comando para ssh mientras que la entrada estándar se redirige desde un documento aquí. Debido a la falta de un comando especificado como argumento, ssh primero espera una sesión de inicio de sesión interactiva (lo que requeriría la asignación de una pty en el host remoto) pero luego debe darse cuenta de que su stdin local no es tty / pty. La redirección de la entrada estándar de ssh desde un documento aquí normalmente requiere que se especifique un comando (como /bin/sh ) como un argumento para ssh , y en tal caso, no se asignará ningún pty en el host remoto de forma predeterminada.

Como no hay comandos que ejecutar a través de ssh que requieren la presencia de un tty / pty (como vim o top ), el interruptor -t a ssh es superfluo. Simplemente use ssh -T [email protected] <<EOT ... o ssh [email protected] /bin/bash <<EOT ... y la advertencia desaparecerá.

Si <<EOF no se escapa o no tiene comillas simples (es decir, <<\EOT o <<'EOT' ), las variables dentro del documento aquí serán expandidas por el shell local antes de que se ejecute ssh ... El efecto es que las variables dentro del documento aquí permanecerán vacías porque están definidas solo en el shell remoto.

Por lo tanto, si el shell local debería poder acceder a $REL_DIR y definirlo en el shell remoto, se debe definir $REL_DIR fuera del documento de aquí antes del comando ssh ( versión 1 a continuación); o, si se usa <<\EOT o <<'EOT' , la salida del comando ssh se puede asignar a REL_DIR si la única salida del comando ssh a stdout se genera mediante el echo "$REL_DIR" dentro del único / escapado -cita aquí el documento ( versión 2 abajo).

Una tercera opción sería almacenar el documento aquí en una variable y luego pasar esta variable como un argumento de comando a ssh -t [email protected] "$heredoc" ( versión 3 a continuación).

Y, por último, pero no menos importante, no sería una mala idea comprobar si los directorios en el host remoto se crearon correctamente (ver: verificar si el archivo existe en el host remoto con ssh ).

# version 1

unset DEP_ROOT REL_DIR
DEP_ROOT='/tmp'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR="${DEP_ROOT}/${datestamp}"

ssh localhost /bin/bash <<EOF
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
#echo "$REL_DIR"
exit
EOF

scp -r ./dir1 [email protected]:"$REL_DIR"
scp -r ./dir2 [email protected]:"$REL_DIR"


# version 2

REL_DIR="$(
ssh localhost /bin/bash <<\EOF
DEP_ROOT='/tmp'
datestamp=$(date +%Y%m%d%H%M%S)
REL_DIR="${DEP_ROOT}/${datestamp}"
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
echo "$REL_DIR"
exit
EOF
)"

scp -r ./dir1 [email protected]:"$REL_DIR"
scp -r ./dir2 [email protected]:"$REL_DIR"


# version 3

heredoc="$(cat <<'EOF'
# -onlcr: prevent the terminal from converting bare line feeds to carriage return/line feed pairs
stty -echo -onlcr
DEP_ROOT='/tmp'
datestamp="$(date +%Y%m%d%H%M%S)"
REL_DIR="${DEP_ROOT}/${datestamp}"
if [ ! -d "$DEP_ROOT" ] && [ ! -e "$DEP_ROOT" ]; then
   echo "creating the root directory" 1>&2
   mkdir "$DEP_ROOT"
fi
mkdir "$REL_DIR"
echo "$REL_DIR"
stty echo onlcr
exit
EOF
)"

REL_DIR="$(ssh -t localhost "$heredoc")"

scp -r ./dir1 [email protected]:"$REL_DIR"
scp -r ./dir2 [email protected]:"$REL_DIR"

Estoy agregando esta respuesta porque resolvió un problema relacionado que tenía con el mismo mensaje de error.

Problema : instalé cygwin en Windows y estaba recibiendo este error: el Pseudo-terminal will not be allocated because stdin is not a terminal

Resolución : Resulta que no había instalado el programa de cliente openssh y las utilidades. Debido a que cygwin estaba usando la implementación de ssh para Windows, no la versión de cygwin. La solución fue instalar el paquete openssh cygwin.


Intente ssh -t -t (o ssh -tt para abreviar) para forzar la asignación pseudo-tty incluso si stdin no es un terminal.

Vea también: Terminar sesión SSH ejecutada por 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.

Según la respuesta de zanco , no está proporcionando un comando remoto a ssh , dado que el shell analiza la línea de comandos. Para resolver este problema, cambie la sintaxis de la invocación de su comando ssh para que el comando remoto se componga de una cadena multilínea sintácticamente correcta.

Hay una variedad de sintaxis que se pueden utilizar. Por ejemplo, dado que los comandos se pueden canalizar a bash y sh , y probablemente también a otros shells, la solución más sencilla es combinar la invocación de shell ssh con heredocs:

ssh [email protected] /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 dará como resultado que el Pseudo-terminal will not be allocated because stdin is not a terminal advertencia Pseudo-terminal will not be allocated because stdin is not a terminal . También tenga en cuenta que EOT está rodeado por 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 como está a ssh .

Si eres fanático de las tuberías, puedes reescribir lo anterior de la siguiente manera:

cat <<'EOT' | ssh [email protected] /bin/bash
echo "These commands will be run on: $( uname -a )"
echo "They are executed by: $( whoami )"
EOT

La misma advertencia sobre /bin/bash aplica a lo anterior.

Otro enfoque válido es pasar el comando remoto multilínea como una sola cadena, utilizando múltiples capas de interpolación de variables bash siguiente manera:

ssh [email protected] "$( 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:

  1. ssh [email protected] se analiza mediante bash, y se interpreta como el comando ssh , seguido de un argumento [email protected] que se pasa al comando ssh

  2. " comienza una cadena interpolada, que cuando se complete, comprenderá un argumento que se pasará al comando ssh , que en este caso será interpretado por ssh como el comando remoto que se ejecutará como [email protected]

  3. $( comienza un comando para ejecutarse, con la salida capturada por la cadena interpolada circundante

  4. cat es un comando para generar el contenido del archivo que sigue. La salida de cat pasará de nuevo a la cadena interpolada de captura

  5. << comienza un bash heredoc

  6. '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 los contenidos no se interpolan con bash, sino que se transmiten en formato literal.

  7. Cualquier contenido que se encuentre entre <<'EOT' y <newline>EOT<newline> se agregará a la salida de nowdoc

  8. EOT termina el nowdoc, lo que da como resultado que se cree un archivo temporal nowdoc y se devuelva al comando cat que realiza la llamada. cat saca el nowdoc y devuelve la salida a la cadena interpolada de captura

  9. ) concluye el comando a ejecutar

  10. " concluye la captura de la cadena interpolada. El contenido de la cadena interpolada se devolverá a ssh como un único argumento de línea de comando, que ssh interpretará como el comando remoto que se ejecutará como [email protected]

Si necesita evitar el uso de herramientas externas como cat , y no le importa tener dos declaraciones en lugar de una, use la read incorporada con un heredoc 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 [email protected] "${SSH_COMMAND}"

También con opción -T desde manual

Deshabilitar la asignación de pseudo-tty


ssh -t foobar @ localhost yourscript.pl





ssh