View previous topic :: View next topic |
Author |
Message |
Zucca Moderator


Joined: 14 Jun 2007 Posts: 3965 Location: Rasi, Finland
|
Posted: Wed Mar 05, 2025 5:30 pm Post subject: Complex shell redirections - help |
|
|
I've been developing few scripts to simplify a lot of things on all of my systems.
To avoid bashisms (which I most of the times do) for little more portability, I've tried to find a solution to use exec to redirect stdout and stderr to log. That's pretty easy just by Code: | exec > stdout.log 2> stderr.log | ... for example.
But when it comes to passing these streams to logger, things get orders of magnitude more complex if I want to avoid bashisms.
With bash one can Code: | exec >(logger [arguments]) | , but ~POSIX shells (I tend to target busybox sh and alternatively mksh and dash too) don't support such syntax.
After quite some time (frankly) of digging around the net, I found this: SE - mikeserv: | _log()( p=
mkfifo "${p:=$(mktemp -u)}" &&
printf %s "$p" &&
exec <&- >&- <>/dev/null >&0 &&
{ rm "$p"
logger --priority user."$1" --tag "${0##*/}"
} <"$p" &
) | ... that code is meant to be used as: Code: | exec >"$(_log notice)" 2>"$(_log error)"
| ... for example. Neat really.
I can follow this code at every line except the line with exec.
I cannot decipher what it does.
(I really do understand why novices find it sometimes hard to understand bourne -like shell scripting. :D)
Anyway what I think the exec line does:- <&- >&- closes stdin and stdout
- <>/dev/null connects stdin and stdout to NULL
- >&0 redirects stdout to stdin
... yeaaah... That doesn't make any sens whatsoever to me.
Living something like 20 years on sh and bash and I still stumble upon some "magic" like this which I don't understand.
Anyone to decipher this to me?
And if you have better/alternative, sh prefereably, solutions, speak up? _________________ ..: Zucca :..
My gentoo installs: | init=/sbin/openrc-init
-systemd -logind -elogind seatd |
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
 |
Hu Administrator

Joined: 06 Mar 2007 Posts: 23153
|
Posted: Wed Mar 05, 2025 6:00 pm Post subject: Re: Complex shell redirections - help |
|
|
When in doubt, use strace to see what is done.
Zucca wrote: | Anyway what I think the exec line does:- <&- >&- closes stdin and stdout
- <>/dev/null connects stdin and stdout to NULL
- >&0 redirects stdout to stdin
... yeaaah... That doesn't make any sens whatsoever to me. | Per info bash: info '(bash)Redirections': | The redirection operator
[N]<>WORD
causes the file whose name is the expansion of WORD to be opened for
both reading and writing on file descriptor N | Presumably, this is not a bashism, so we can rely on the documentation for bash to address your question. If so, then your interpretation is slightly incorrect. <>/dev/null opened null onto stdin only, but did so as a read-write descriptor, so that the subsequent >&0 (which sets stdout=stdin) does not lead to weird errors with a stdout that is not writable. To show why this is needed, consider: Code: | $ (exec </dev/null >&0; echo a)
-bash: echo: write error: Bad file descriptor
$ (exec <>/dev/null >&0; echo a)
$ |
Regarding strace: Code: | $ strace -e trace=file,close,dup,dup2,dup3 /bin/busybox sh -c 'exec <&- >&- <>/dev/null >&0'
execve("/bin/busybox", ["/bin/busybox", "sh", "-c", "exec <&- >&- <>/dev/null >&0"], 0x7ffd44f0e498 /* 0 vars */) = 0
readlinkat(AT_FDCWD, "/proc/self/exe", "/bin/busybox", 4096) = 12
newfstatat(AT_FDCWD, "/", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
newfstatat(AT_FDCWD, ".", {st_mode=S_IFDIR|0755, st_size=4096, ...}, 0) = 0
close(0) = 0
close(1) = 0
openat(AT_FDCWD, "/dev/null", O_RDWR|O_CREAT, 0666) = 0
dup2(0, 1) = 1
close(10) = 0
close(11) = 0
+++ exited with 0 +++
| In particular, this shows directly that the <> is a read-write descriptor for /dev/null. |
|
Back to top |
|
 |
Zucca Moderator


Joined: 14 Jun 2007 Posts: 3965 Location: Rasi, Finland
|
Posted: Thu Mar 06, 2025 8:49 am Post subject: |
|
|
Hu,
Thanks again for your input. :)
I really should use strace more often.
Now that the function makes more sense, I'll start crafting and testing my own.
Thanks again! _________________ ..: Zucca :..
My gentoo installs: | init=/sbin/openrc-init
-systemd -logind -elogind seatd |
Quote: | I am NaN! I am a man! |
|
|
Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|