Gentoo Forums
Gentoo Forums
Gentoo Forums
Quick Search: in
Complex shell redirections - help
View unanswered posts
View posts from last 24 hours

 
Reply to topic    Gentoo Forums Forum Index Portage & Programming
View previous topic :: View next topic  
Author Message
Zucca
Moderator
Moderator


Joined: 14 Jun 2007
Posts: 3965
Location: Rasi, Finland

PostPosted: Wed Mar 05, 2025 5:30 pm    Post subject: Complex shell redirections - help Reply with quote

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
View user's profile Send private message
Hu
Administrator
Administrator


Joined: 06 Mar 2007
Posts: 23155

PostPosted: Wed Mar 05, 2025 6:00 pm    Post subject: Re: Complex shell redirections - help Reply with quote

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
View user's profile Send private message
Zucca
Moderator
Moderator


Joined: 14 Jun 2007
Posts: 3965
Location: Rasi, Finland

PostPosted: Thu Mar 06, 2025 8:49 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Reply to topic    Gentoo Forums Forum Index Portage & Programming All times are GMT
Page 1 of 1

 
Jump to:  
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