9

In Bash you can redirect all future stdout output of the currently running script. For example with this script,

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

This will end up in 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

But this is Bash-specific and the naked exec with redirection doesn't seem to work in Dash.

Syntax error: redirection unexpected

How can I make it work in Dash, or possibly in both shells?

  • Could you clarify what you need exactly? You can redirect with > in dash. I realize you seem to be asking for something else but I can't quite tell what it is. – terdon Oct 25 '14 at 13:55
  • @terdon I have expanded the explanation. – Alex B Oct 25 '14 at 14:06
6

You can just do:

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

You can do that with any shell.

If you don't like the way it looks, maybe make the script wrap itself in a function.

#!/bin/sh
run() if     [ "$run" != "$$" ] || return
      then   sh -c 'run=$$ exec "$0" "$@"' "$0" "$@" |
             logger -t my-awesome-script
      fi
#script-body
run "$@" || do stuff
  • That last line should be run ${1+"$@"} || do stuff so that arguments are retained. – Adam Katz Feb 1 '16 at 23:48
  • @AdamKatz - good point, execpt ${1+"$@"} does nothing "$@" doesnt. It had other problems anyway. – mikeserv Feb 1 '16 at 23:56
  • "$@" will pass "" when there are no arguments while ${1+"$@"} will pass an empty string when there are no arguments. This matters tremendously for many programs, as they parse "" as an empty argument while an (unquoted) empty string would not be interpreted as an argument at all. – Adam Katz Feb 2 '16 at 0:42
  • @AdamKatz - a very old Bourne shell might (and i wouldnt expect to find dash on such a system), but otherwise "$@" is unique in that a zero-args case does not substitute to a null argument for POSIX shells. – mikeserv Feb 2 '16 at 0:47
  • 1
    @AdamKatz - it was actually a bug even in the old bsh and should never have worked like that. It was eventually fixed, but i dunno whether or not it should still be necessary in a Solaris 10, for example. Youre right about $* - it doesnt exhibit the same neat properties of expabsion - its uniqueness onky pertains to the variable contents of its expansion, though it will always be something.in my opinion, "${@+is especially cool $@}" . But not practically very different than the old ${1+”$@"} workaround after all. If you have a ksh93: "${1+quoted" not quoted "quoted again}" – mikeserv Feb 2 '16 at 1:32
4

Process substitution is easily simulated with named pipes.

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

In fact, named pipes are one of the mechanisms (the other being /dev/fd) with which process substitution can be implemented in bash.

  • The most versatile in my opinion: I could use tee to redirect to several streams seamlessly. Just one thing: do not forget to delete the created logger_input at the end of a script. – lauhub Jan 15 '15 at 9:43
2

I don't think this is possible in dash. As far as I can tell from its man page, it has no support for process substitution.

As a workaround, you could try what mikserv suggested, or you can redirect everything to a file, and then after your script is finished (presumably this is in a script), add that file's contents to logger:

$ exec > ~/foo/foo.txt
$ ls
$ echo something
$ cat foo/foo.txt | sudo logger -t my-awesome-script
  • In fact, process substitution - or what other shells call process substitution - is easier in dash then other shells. Process substitution just amounts to an argument that points to a /dev/fd/[num] link to an anonymous pipe. dash does here-documents with anonymous pipes rather than genning temp files as most other shells do. So cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\n is not only functionally equivalent, you even get to name the fd yourself. Still, your point is well made about going the other way - you need to open a new fd with exec and background a process that reads it. – mikeserv Oct 25 '14 at 15:03
  • 2
    @mikeserv: In what sense is cat /dev/fd/3 3<<HEREDOC\n$(get output)\nHEREDOC\n "easier" than cat <(get output)? – ruakh Oct 25 '14 at 17:54
  • @mikeserv: It involves plenty of rules to remember; perhaps you have simply grown so used to them that you don't notice. – ruakh Oct 25 '14 at 23:50
  • @ruakh - well, sure. < > shell redirections. basically if you just do two of those you can then pile on the following lines too. But yeah, you have a point - I like here docs. Still, as many things as might require remembering, it's easier when they work universally I think. Then again a lot of people don't have much use for other shells and so it makes no difference to them. I'm just not among them. – mikeserv Oct 26 '14 at 2:22
  • 1
    @mikeserv: Not just heredocs, but also /dev/fd/3 (in that precise form), and the details of what happens to whitespace . . . and for that matter, the fact that this whole approach works at all in Dash, when it doesn't work in other shells that have all of the components, means that the overall approach is a special rule to remember. (This reminds me of attempts to create a simplified English with less vocabulary; they cut out words like persist, but they ignore just-as-difficult idioms like keep on.) – ruakh Oct 26 '14 at 3:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.