Équivalent Dash de l'auto-redirection de la sortie du script

9

Dans Bash, vous pouvez rediriger toutes les futures sorties stdout du script en cours d'exécution . Par exemple, avec ce script,

exec > >(logger -t my-awesome-script)
echo 1
echo 2
echo 3

Cela se terminera dans syslog:

Oct 26 01:03:16 mybox my-awesome-script[72754]: 1
Oct 26 01:03:16 mybox my-awesome-script[72754]: 2
Oct 26 01:03:16 mybox my-awesome-script[72754]: 3

Mais cela est spécifique à Bash et l'exécutif nu avec redirection ne semble pas fonctionner dans Dash.

Syntax error: redirection unexpected

Comment puis-je le faire fonctionner dans Dash, ou éventuellement dans les deux shells?

Alex B
la source
Pourriez-vous clarifier exactement ce dont vous avez besoin? Vous pouvez rediriger avec >dans le tiret. Je me rends compte que vous semblez demander autre chose mais je ne peux pas vraiment dire ce que c'est.
terdon
@terdon J'ai développé l'explication.
Alex B

Réponses:

6

Vous pouvez simplement faire:

{ commands
....
} | logger -t my_awesome_script

Vous pouvez le faire avec n'importe quel shell.

Si vous n'aimez pas son apparence, faites peut-être que le script s'enroule dans une fonction.

#!/bin/sh
run() if     [ "$run" != "$$" ] || return
      then   sh -c 'run=$$ exec "$0" "$@"' "$0" "$@" |
             logger -t my-awesome-script
      fi
#script-body
run "$@" || do stuff
mikeserv
la source
Cette dernière ligne devrait être run ${1+"$@"} || do stuffpour que les arguments soient conservés.
Adam Katz
@AdamKatz - bon point, execpt ${1+"$@"}ne fait rien "$@" . Il a eu d'autres problèmes de toute façon.
mikeserv
"$@"passera ""lorsqu'il n'y a pas d'arguments tandis que ${1+"$@"}passera une chaîne vide lorsqu'il n'y a pas d'arguments. Cela est extrêmement important pour de nombreux programmes, car ils analysent ""comme un argument vide tandis qu'une chaîne vide (sans guillemets) ne serait pas du tout interprétée comme un argument.
Adam Katz
@AdamKatz - un très vieux shell Bourne pourrait (et je ne m'attendrais pas à trouver dashsur un tel système) , mais sinon, il "$@"est unique en ce sens qu'un cas zéro-args ne se substitue pas à un argument nul pour les shells POSIX.
mikeserv
1
@AdamKatz - c'était en fait un bogue même dans l'ancien bsh et n'aurait jamais dû fonctionner comme ça. Il a finalement été corrigé, mais je ne sais pas si cela devrait toujours être nécessaire dans un Solaris 10, par exemple. Vous avez raison d' environ $ * - il ne marche pas présentent les mêmes propriétés soignées de expabsion - son unicité se rapporte onky au contenu des variables de son expansion, mais il sera toujours something.in mon avis, "${@+is especially cool $@}" . Mais pas très différent de l'ancienne ${1+”$@"}solution de contournement après tout. Si vous avez un ksh93:"${1+quoted" not quoted "quoted again}"
mikeserv
5

La substitution de processus est facilement simulée avec des canaux nommés.

mkfifo logger_input
logger -t my_awesome_script < logger_input &
exec > logger_input
echo 1
echo 2
echo 3

En fait, les canaux nommés sont l'un des mécanismes (l'autre étant /dev/fd) avec lesquels la substitution de processus peut être implémentée bash.

chepner
la source
Le plus polyvalent à mon avis: je pourrais utiliser tee pour rediriger vers plusieurs flux de façon transparente. Une seule chose: n'oubliez pas de supprimer le logger_input créé à la fin d'un script.
lauhub
2

Je ne pense pas que ce soit possible en dash. Pour autant que je sache sur sa manpage , il ne prend pas en charge la substitution de processus.

Comme solution de contournement, vous pouvez essayer ce que mikserv a suggéré , ou vous pouvez tout rediriger vers un fichier, puis une fois votre script terminé (probablement dans un script), ajoutez le contenu de ce fichier à l'enregistreur:

$ exec > ~/foo/foo.txt
$ ls
$ echo something
$ cat foo/foo.txt | sudo logger -t my-awesome-script
terdon
la source
En fait, la substitution de processus - ou ce que d'autres shells appellent substitution de processus - est plus facile que les dashautres shells. La substitution de processus équivaut simplement à un argument qui pointe vers un /dev/fd/[num]lien vers un canal anonyme. dashfait ici des documents avec des canaux anonymes plutôt que de créer des fichiers temporaires comme le font la plupart des autres shells. Ce cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\nn'est donc pas seulement équivalent sur le plan fonctionnel, vous pouvez même nommer le fd vous-même. Pourtant, votre point de vue est bien fait sur l'inverse - vous devez ouvrir un nouveau fd avec execet en arrière-plan un processus qui le lit.
mikeserv
2
@mikeserv: Dans quel sens est cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\n"plus facile" que cat <(get output)?
ruakh
@mikeserv: Cela implique de nombreuses règles à retenir; peut-être vous êtes-vous simplement tellement habitué à eux que vous ne le remarquez pas.
ruakh
@ruakh - bien sûr. < >redirections du shell. En gros, si vous n'en faites que deux, vous pouvez également les empiler sur les lignes suivantes. Mais oui, vous avez raison - j'aime ici les documents. Pourtant, autant de choses qui pourraient nécessiter de se souvenir, c'est plus facile quand elles fonctionnent universellement je pense. Là encore, beaucoup de gens n'ont pas beaucoup d'utilité pour les autres obus et cela ne fait donc aucune différence pour eux. Je ne suis tout simplement pas parmi eux.
mikeserv
1
@mikeserv: Pas seulement heredocs, mais aussi /dev/fd/3(sous cette forme précise), et les détails de ce qui arrive aux espaces blancs. . . et d'ailleurs, le fait que toute cette approche fonctionne du tout dans Dash, quand elle ne fonctionne pas dans d'autres shells qui ont tous les composants, signifie que l'approche globale est une règle spéciale à retenir. (Cela me rappelle les tentatives de créer un anglais simplifié avec moins de vocabulaire; ils coupent des mots comme persister , mais ils ignorent les idiomes tout aussi difficiles comme continuer .)
ruakh