¿Qué hace `<& -`?

20

Copié un fragmento de Bash para poner en segundo plano un comando ssh ejecutado de forma remota:

ssh user@remote <<CMD
some process <&- >log 2>error &
CMD

¿Qué <&-hacer?
Supongo que es lo mismo que< /dev/null

Mi siguiente entendimiento es que los tres descriptores de archivos principales ( stdin, stdout, stderr) deben ser cerradas para impedir:

  1. El trabajo está en segundo plano y la secuencia de comandos sale, ¿conflictiva de alguna manera?
  2. Cuando el terminal se cierra, ¿se cierran todos los procesos que aceptan stdin del terminal?
Eric Francis
fuente
Referencia cruzada obligatoria: consulte ¿Cuáles son los operadores de control y redireccionamiento del shell? - aunque todo lo que dice sobre este operador es que "puede usarse para cerrar o duplicar descriptores de archivos" y debe "ver la sección relevante del manual de su shell".
G-Man dice 'reinstalar a Monica' el
Si recuerdo correctamente, ssh -nNT user@remote 'command'creará una sesión SSH no interactiva. Agregue &al fondo, anteponga nohupal commandpara mantenerlo en funcionamiento si su conexión se corta.
Mark K Cowan
1
@ MarkKCowan man sshsugiere que -N deshabilita la ejecución de un comando remoto por completo, y una prueba rápida lo respalda.
Tom Hunt
Ah sí, usé -nNTR para reenvío de puerto inverso. Ignora el -N y -R entonces :)
Mark K Cowan

Respuestas:

30

<&-no es exactamente lo mismo que < /dev/null. <&-cierra fd 0, mientras que lo < /dev/nullredirige desde el dispositivo /dev/null, que nunca proporciona datos y siempre da EOF en la lectura. La diferencia es principalmente que una read(2)llamada de un FD cerrado (el <&-caso) producirá un error con EBADF, mientras que una llamada de un FD redirigido nulo no devolverá bytes leídos (condición de fin de archivo). Si su programa nunca lee de stdin, la distinción no importa.

Cerrar los FD es una buena práctica si está haciendo algo en segundo plano, ya que un proceso en segundo plano se bloqueará si intenta leer algo de TTY. Sin embargo, este ejemplo no maneja completamente todo lo que debería; idealmente habría una nohupo setsidinvocación en alguna parte, para desasociar completamente el proceso en segundo plano.

Tom Hunt
fuente
Entonces, ¿debería usar nohupademás de cerrar los descriptores de archivo?
Eric Francis
2
El método más completo (que imita la forma en que los programas se demonizan a sí mismos) es algo así setsid some process <&- >path/to/log 2>path/to/error. El método más rápido es algo así nohup some process &.
Tom Hunt
2
@EricFrancis: Usar nohupno tiene sentido aquí. nohupevitar que el proceso reciba HUPseñal cuando se cierra su terminal de control. Pero no tenías ninguna terminal en este caso.
Cuonglm
@TomHunt: el proceso en segundo plano no se bloqueó, la sesión ssh sí.
Cuonglm
2
no es una buena idea cerrar los fds 0, 1 y 2 ... no desea que el próximo fd creado tome uno de esos valores. mejor redirigirlos a / dev / null
Murray Jensen
7

Ver man bash:

  [n]<&word

se utiliza para duplicar descriptores de archivos de entrada. Si se wordexpande a uno o más dígitos, el descriptor de archivo indicado por nse convierte en una copia de ese descriptor de archivo. Si los dígitos word no especifican un descriptor de archivo abierto para la entrada, se produce un error de redireccionamiento. Si la palabra se evalúa como -, el descriptor de archivo nestá cerrado. Si nno se especifica, se utiliza la entrada estándar (descriptor de archivo 0).

choroba
fuente
La definición correcta es que no se especifica lo que sucede cuando se tiene [n]<&wordy la palabra contiene más de un solo dígito.
schily
¿Qué quieres decir? Es el man bashincorrecto?
Eric Francis
@EricFrancis porque no está especificado en el estándar, bashelige implementarlo de una manera sensata (para alguna definición adecuada de "sano"). Otros depósitos pueden o no hacerlo.
muru
@muru La pregunta está etiquetada bash, no posix-shell.
Barmar
@Barmar ok. Entonces...?
muru
7

<&- Cerrar entrada estándar.

La forma general, definida por POSIX , es:

[n]<&word

Su propósito de hacer un descriptor de archivo nes una copia del descriptor de archivo denotado por word. Se supone estándar en si nse omite, y si wordes así -, el descriptor de archivo nse cerrará.

No es lo mismo que </dev/null, ya que en caso de </dev/null, la entrada estándar todavía se abrió y se redirigió a otro lugar.

Debe cerrar todos los descriptores de archivos de los procesos que se adjuntaron al socket ssh, de lo contrario, la sesión ssh no se puede cerrar.

Puede ejecutar el comando en una máquina remota sin adjuntarlo a la sesión ssh, usando screen o tmux :

ssh user@remote 'screen -S test -d -m command'
Cuonglm
fuente
¿Por qué el voto negativo?
Cuonglm