POSIX command/process substitution
_log()( x=0
while [ -e "${TMPDIR:=/tmp}/$$.$((x+=1))" ]
do continue; done &&
mkfifo -- "$TMPDIR/$$.$x" &&
printf %s\\n "$TMPDIR/$$.$x" || exit
exec >&- >/dev/null
{ rm -- "$TMPDIR/$$.$x"
logger --priority user."$1" --tag "${0##*/}"
} <"$TMPDIR/$$.$x" &
) <&- </dev/null
You should be able to use that like:
exec >"$(_log notice)" 2>"$(_log error)"
Here's a version which makes use of the mktemp
command:
_log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
)
...which does much the same, except that it allows mktemp
to select the filename for you. This works because process substitution is by no means magical and works in a very similar way to command substitution. Instead of replacing the expansion with the value of the command run within it as command substitution does, process substitution replaces it with the name of a filesystem link where the output can be found.
While the POSIX shell does not provide a direct corollary to such a thing, emulating it is very simply done. All you need to do is make a file, print its name to the standard out of a command substitution, and in the background of same run your command which will output to that file. Now you can just redirect into the value of that expansion - exactly as you do with process substitution. And so the POSIX shell provides all of the tools you need of course - all that is required is that you put them to use in a way which suits you.
Both of the above versions ensure that they destroy the filesystem link to the pipes they create/use before ever making use of them. This means there is no cleanup required after the fact, and, more importantly, their streams are only available to the processes which initially open them - and so their filesystem links cannot be used as a means to snoop/hijack your logging activity. To leave their fs-links in the filesystem is a potential security hole.
Another way is to wrap it. It can be done from within the script.
x=${x##*[!0-9]*}
_log(){
logger --priority user."$1" --tag "${0##*/}"
} 2>/dev/null >&2
cd ../"$PPID.$x" 2>/dev/null &&
trap 'rm -rf -- "${TMPDIR:-/tmp}/$PPID.$x"' 0 ||
{ until cd -- "${TMPDIR:=/tmp}/$$.$x"
do mkdir -- "$TMPDIR/$$.$((x+=1))"
done &&
x=$x "$0" "$@" | _log notice
exit
} 2>&1 | _log error
That would basically allow your script to call itself if it hasn't yet and get you a work directory in temp to boot.
mktemp
and other non-standard commands, it could be:_log()( p=; mkfifo "${p:=$(mktemp -u)}"; printf %s "$p"; exec <&- >&- <>/dev/null >&0; { rm "$p"; logger --priority user."$1" --tag "${0##*/}"; } <"$p" &)
. I wrote it using fully portable command language in all ways - with the exception of your own. Also,basename
is not a very useful utility."${0##*/}"
is both more robust and faster. – mikeserv Jul 27 '15 at 18:03.xprofile
has to be executed withsh
. – l0b0 Jul 27 '15 at 18:07sh
and modify$PATH
to match in.xprofile
. Maybe reconsider your edit though -/bin/sh
is, as I think, maybe a little more ambiguous. – mikeserv Jul 27 '15 at 18:09logger
doesn't recognize any options. But, since POSIXlogger
doesn't even have a way to log standard input (only command line arguments), the whole effort comes to pieces without an extended version oflogger
. Perhaps the same effect could be achieved withtee -a
but then we're chest-deep in hypotheticals; I don't personally know any implementations oflogger
that don't accept any options. – Wildcard Jan 22 '16 at 21:40logger
thing - this was just intended to demonstrate a few simply implemented and highly customizable library functions to handle process substitution with little fuss and much speed in tiny POSIX shells so people wouldn't have to turn to giant, buggy sloths likebash
. A lot of my other stuff is written with similar spirit. – mikeserv Jan 22 '16 at 22:00exec
command in the top level actually opens thefifo
for writing before therm
command is run? (Also, is there some edge case breakage that is prevented by closing stdin/stdout before redirecting them from/to/dev/null
?) – Wildcard Mar 14 '16 at 09:01zsh
w/ multios enabled. As for the first part:{ this; can\'t; happen; before; } < this
. Does that help? – mikeserv Mar 15 '16 at 12:53