Pasando variables en el comando ssh remoto

99

Quiero poder ejecutar un comando desde mi máquina usando ssh y pasar a través de la variable de entorno $BUILD_NUMBER

Esto es lo que estoy intentando:

ssh pvt@192.168.1.133 '~/tools/myScript.pl $BUILD_NUMBER'

$BUILD_NUMBER se establece en la máquina que realiza la llamada ssh y, dado que la variable no existe en el host remoto, no se detecta.

¿Cómo paso el valor de $BUILD_NUMBER?

Fergal
fuente
1
no relacionado con Hudson, eliminó la etiqueta. (Hudson solo crea la variable)
Peter Schuetze

Respuestas:

188

Si utiliza

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

en vez de

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

su shell interpolará el $BUILD_NUMBERantes de enviar la cadena de comando al host remoto.

sarnold
fuente
8
Si alguien DEBE usar comillas simples para que el comando incluido en las comillas no se evalúe localmente, entonces debe usar "'$ VARIABLE'". Ejemplo: ssh [email protected] '~ / tools / run_pvt.pl "' $ BUILD_NUMBER '"'
dr.doom
3
No sabía que bash reacciona de manera diferente con comillas simples y dobles. ¡Gracias!
silgon
1
los desarrolladores del núcleo de Linux deben arder en el infierno
goldstar
@goldstar, tenga en cuenta que la diferencia entre el comportamiento de comillas simples y comillas dobles en el shell es anterior a Linux por décadas.
sarnold
3
PSA: si su cadena contiene entrada de usuario, esta es una muy mala idea y podría exponerlo a ataques de inyección de código.
Brian McCutchon
27

Las variables entre comillas simples no se evalúan. Utilice comillas dobles:

ssh pvt@192.168.1.133 "~/tools/run_pvt.pl $BUILD_NUMBER"

El shell expandirá las variables entre comillas dobles, pero no entre comillas simples. Esto cambiará a la cadena deseada antes de pasar al sshcomando.

Stephen
fuente
2

(Esta respuesta puede parecer innecesariamente complicada, pero es fácilmente extensible y robusta con respecto a los espacios en blanco y los caracteres especiales, hasta donde yo sé).

Puede alimentar datos directamente a través de la entrada estándar del sshcomando y readdesde la ubicación remota.

En el siguiente ejemplo,

  1. una matriz indexada se llena (por conveniencia) con los nombres de las variables cuyos valores desea recuperar en el lado remoto.
  2. Para cada una de esas variables, le damos a sshuna línea terminada en nulo dando el nombre y valor de la variable.
  3. En el shhcomando en sí, recorremos estas líneas para inicializar las variables requeridas.
# Initialize examples of variables.
# The first one even contains whitespace and a newline.
readonly FOO=$'apjlljs ailsi \n ajlls\t éjij'
readonly BAR=ygnàgyààynygbjrbjrb

# Make a list of what you want to pass through SSH.
# (The “unset” is just in case someone exported
# an associative array with this name.)
unset -v VAR_NAMES
readonly VAR_NAMES=(
    FOO
    BAR
)

for name in "${VAR_NAMES[@]}"
do
    printf '%s %s\0' "$name" "${!name}"
done | ssh user@somehost.com '
    while read -rd '"''"' name value
    do
        export "$name"="$value"
    done

    # Check
    printf "FOO = [%q]; BAR = [%q]\n" "$FOO" "$BAR"
'

Salida:

FOO = [$'apjlljs ailsi \n ajlls\t éjij']; BAR = [ygnàgyààynygbjrbjrb]

Si no los necesita export, debería poder usarlos en declarelugar de export.

Una versión realmente simplificada (si no necesita la extensibilidad, tiene una sola variable para procesar, etc.) se vería así:

$ ssh user@somehost.com 'read foo' <<< "$foo"
Alice M.
fuente
2

La lista de variables de entorno aceptadas en SSHD de forma predeterminada incluye LC_*. Así:

LC_MY_BUILDN="1.2.3" ssh -o "SendEnv LC_MY_BUILDN" ssh-host 'echo $LC_MY_BUILDN'
1.2.3
Alex Stragies
fuente
0

Como se respondió anteriormente, no es necesario establecer la variable de entorno en el host remoto. En su lugar, puede simplemente hacer la meta-expansión en el host local y pasar el valor al host remoto.

ssh pvt@192.168.1.133 '~/tools/run_pvt.pl $BUILD_NUMBER'

Si realmente desea establecer la variable de entorno en el host remoto y usarla, puede usar el envprograma

ssh pvt@192.168.1.133 "env BUILD_NUMBER=$BUILD_NUMBER ~/tools/run_pvt.pl \$BUILD_NUMBER"

En este caso, esto es un poco exagerado, y tenga en cuenta

  • env BUILD_NUMBER=$BUILD_NUMBER ¿La meta expansión en el host local?
  • la BUILD_NUMBERvariable de entorno remoto será utilizada por
    el shell remoto
Gilles Gouaillardet
fuente
0

También es posible pasar variables de entorno explícitamente a través de ssh. Requiere alguna configuración del lado del servidor, por lo que esta no es una respuesta universal.

En mi caso, quería pasar una clave de cifrado del repositorio de respaldo a un comando en el servidor de almacenamiento de respaldo sin tener esa clave almacenada allí, ¡pero tenga en cuenta que cualquier variable de entorno está visible en ps! La solución de pasar la clave en stdin también funcionaría, pero la encontré demasiado engorrosa. En cualquier caso, aquí se explica cómo pasar una variable de entorno a través de ssh:

En el servidor, edite el sshd_configarchivo, por lo general, /etc/ssh/sshd_configy agregue una AcceptEnvdirectiva que coincida con las variables que desea pasar. Ver man sshd_config. En mi caso, quiero pasar variables a borg backup, así que elegí:

AcceptEnv BORG_*

Ahora, en el cliente, use la -o SendEnvopción para enviar variables de entorno. La siguiente línea de comando establece la variable de entorno BORG_SECRETy luego la marca para que se envíe a la máquina cliente (llamada backup). Luego se ejecuta printenvallí y filtra la salida para las variables BORG:

$ BORG_SECRET=magic-happens ssh -o SendEnv=BORG_SECRET backup printenv | egrep BORG
BORG_SECRET=magic-happens
TvE
fuente
Puede "pasar de contrabando" sus variables utilizando la configuración predeterminada del lado del servidor, consulte mi respuesta . La esencia es que la configuración predeterminada de OpenSSHd incluye LC_*variables permitidas para enviar, así que solo use $LC_TvE_foo, o $LC_BORG_SECRET, solo asegúrese de no "colisionar" con una variable incorporada.
Alex Stragies
-2

Escape de la variable para acceder a las variables fuera de la sesión ssh: ssh [email protected] "~ / tools / myScript.pl \ $ BUILD_NUMBER"

Sarah Gruneisen
fuente
2
Esto no logra lo que pide la pregunta.
Patrick Trentin
2
desde el punto de vista del caparazón, '$FOO'es equivalente a "\$FOO". la pregunta era "¿cómo pasar una variable de shell con SSH?". Como ya lo indicó @PatrickTrentin, esta no es una respuesta correcta porque BUILD_NUMBERla variable de entorno no se configura de forma remota.
Gilles Gouaillardet