Que fait «<& -»?

20

J'ai copié un extrait de Bash en arrière-plan d'une commande ssh exécutée à distance:

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

Que fait <&--il?
Je suppose que c'est la même chose que< /dev/null

Ma prochaine compréhension est que les trois descripteurs de fichiers principaux ( stdin, stdout, stderr) doivent être fermées pour empêcher:

  1. Le travail est en arrière-plan et le script se termine - en conflit en quelque sorte?
  2. Lorsque le terminal se ferme, tous les processus qui acceptent stdin du terminal sont fermés?
Eric Francis
la source
Renvoi obligatoire: voir Quels sont les opérateurs de contrôle et de redirection du shell? - bien que tout ce qu'il dit à propos de cet opérateur est qu'il "peut être utilisé pour fermer ou dupliquer des descripteurs de fichiers" et vous devriez "voir la section pertinente du manuel de votre shell".
G-Man dit `` Réintègre Monica '' le
Si je me souviens bien, ssh -nNT user@remote 'command'va créer une session SSH non interactive. Ajoutez-le &en arrière-plan, ajoutez-le nohupà commandpour le faire fonctionner si votre connexion est interrompue.
Mark K Cowan,
1
@MarkKCowan man sshsuggère que -N désactive entièrement l'exécution d'une commande à distance, et un test rapide le prend en charge.
Tom Hunt
Ah oui, j'ai utilisé -nNTR pour la redirection de port inverse. Ignorez -N et -R alors :)
Mark K Cowan

Réponses:

30

<&-n'est pas tout à fait la même chose que < /dev/null. <&-ferme fd 0, alors < /dev/nullqu'il le redirige depuis l'appareil /dev/null, qui ne fournit jamais de données et donne toujours EOF en lecture. La différence est principalement qu'un read(2)appel à partir d'un FD fermé (le <&-cas) provoquera une erreur avec EBADF, alors qu'un appel à partir d'un FD redirigé nul ne retournera aucun octet lu (condition de fin de fichier). Si votre programme ne lit jamais depuis stdin, la distinction n'a pas d'importance.

La fermeture des FD est une bonne pratique si vous mettez en arrière-plan quelque chose, car un processus en arrière-plan se bloque s'il essaie de lire quoi que ce soit sur TTY. Cependant, cet exemple ne gère pas tout ce qu'il devrait; dans l'idéal, il y aurait une nohupou une setsidinvocation quelque part, pour dissocier pleinement le processus d'arrière-plan.

Tom Hunt
la source
Je devrais donc utiliser nohupen plus de fermer les descripteurs de fichiers?
Eric Francis
2
La méthode la plus approfondie (qui imite la façon dont les programmes se démonisent) est quelque chose comme setsid some process <&- >path/to/log 2>path/to/error. La méthode la plus rapide ressemble à quelque chose nohup some process &.
Tom Hunt
2
@EricFrancis: Utiliser nohupn'a aucun sens ici. nohupempêcher le processus de recevoir un HUPsignal lorsque sa borne de commande est fermée. Mais vous n'aviez pas de terminal dans ce cas.
cuonglm
@TomHunt: Le processus d'arrière-plan ne s'est pas bloqué, la session ssh l'a fait.
cuonglm
2
ce n'est pas une bonne idée de fermer les fds 0, 1 et 2 ... vous ne voulez pas que le prochain fd créé prenne une de ces valeurs. mieux les rediriger vers / dev / null
Murray Jensen
7

Voir man bash:

  [n]<&word

est utilisé pour dupliquer les descripteurs de fichiers d'entrée. Si se worddéveloppe à un ou plusieurs chiffres, le descripteur de fichier désigné par nest fait pour être une copie de ce descripteur de fichier. Si les chiffres de word ne spécifient pas de descripteur de fichier ouvert pour entrée, une erreur de redirection se produit. Si le mot est évalué à -, le descripteur de fichier nest fermé. Si nn'est pas spécifié, l'entrée standard (descripteur de fichier 0) est utilisée.

choroba
la source
La définition correcte est qu'il n'est pas spécifié ce qui se passe lorsque vous en avez [n]<&wordet que le mot contient plus d'un seul chiffre.
schily
Que voulez-vous dire? Est-ce man bashincorrect?
Eric Francis
@EricFrancis parce qu'il n'est pas spécifié dans la norme, bashchoisit de l'implémenter de manière saine (pour une définition appropriée de "sain"). D'autres obus peuvent le faire ou non.
muru
@muru La question est balisée bash, non posix-shell.
Barmar
@Barmar ok. Donc...?
muru
7

<&- fermer l'entrée standard.

La forme générale, définie par POSIX , est:

[n]<&word

Son but de créer un descripteur de fichier nest une copie du descripteur de fichier désigné par word. L'entrée standard est supposée si nest omise, et si wordc'est le cas -, le descripteur de fichier nsera fermé.

Ce n'est pas la même chose que </dev/null, puisque dans le cas de </dev/null, l'entrée standard est toujours ouverte et a été redirigée vers un autre endroit.

Vous devez fermer tous les descripteurs de fichiers des processus qui ont été attachés au socket ssh, sinon la session ssh ne peut pas se fermer.

Vous pouvez exécuter la commande sur une machine distante sans la rattacher à la session ssh, en utilisant screen ou tmux :

ssh user@remote 'screen -S test -d -m command'
cuonglm
la source
Pourquoi le vote négatif?
cuonglm