5 ms·
An annoying thing about bash is that EXIT will also run on SIGINT (^C), which most other shells won't (in my reading it's also not POSIX compliant, although the
by arp242 3y ago
An annoying thing about bash is that EXIT will also run on SIGINT (^C), which most other shells won't (in my reading it's also not POSIX compliant, although the document is a bit vague). Some might argue this is a feature, but IMHO it's a bug – sometimes you really don't want cleanup to happen so people can inspect the contents of temporary files for debugging. Because trap doesn't pass the signal information to the handler it's hard to not do cleanup on SIGINT, so it's certainly less flexible, and it's an annoying incompatibility between bash and any other shell.
Also, zsh has a much nicer mechanism for the common case:
{
echo lol
} always {
# Ensure *all* temporary files are cleaned up.
nohup rm -rf / &
}
- c5c3c9 3y ago[flagged]
- jcotton42 3y ago> Because trap doesn't pass the signal information to the handler it's not hard not to do cleanup on SIGINT Did you mean "it's hard" instead of "it's not hard"?
- arp242 3y agoOops, yes, thanks; seems a "not" got duplicated in editing – still within edit window.
- ggm 3y agoSome temporary file remover. Lol indeed
- arp242 3y ago"Keep non-temporary files intact" was not part of the design document.
- wkat4242 3y ago// Thinks about that type I typed rm -rf /<space>something by mistake. It took a few seconds before I thought... "Why does it take that long for only a handful of files?" I never did that again. Had my DOS filesystem mounted under Linux too (yes that long ago), and I spent a few days guessing the first letter of each deleted file with norton disk doctor or undeleter or something. That was fun (FAT16 filesystems overwrote the first letter of each filename to delete it) At least it wasn't a mistake I made at work on some production thing. Though there is a reason I make all the desktops on windows production servers bright red. One time I was tired and shut down "my laptop" forgetting I was still logged into a remote server 200km away..... :/ Of course the iLO wasn't hooked up but I was extremely happy to find that HP servers listen to wake on LAN even when they're off. Another one for the never again books :P
- pmarreck 3y agoThe nice thing about temp files is that the OS will eventually remove them, even if you don't
- ggm 3y agoOnly if Cron is set up to do it. I have hosts without /tmp and /var/tmp clearance and they have data states which persist across reboot. with UNIX/POSIX systems it pays to say "it depends" often.
- inadequatespace 3y agomacOS does it on reboot, not sure if it inherited this from BSD proper
- arp242 3y agoFreeBSD comes with a "periodic" script to do it daily, but it's not enabled by default. There's this idea that macOS is "based on BSD", but that's not really the case in any meaningful way; it took some components, but the system overall isn't really "based on it" as such.
- pmarreck 3y agoThat's fair, but a storage space specially treated as at least theoretically "ephemeral" should be cleared out on some regular basis before things start depending on it NOT being cleared out. That said, it makes sense that at least some distros would leave a job in place to do so but initially disabled so that the user can decide based on the use-case
- WJW 3y agoAll files are temporary if your timespan is long enough.
- abwizz 3y agomy oldest file (sadly) is only from 2003. how about you?
- WJW 3y agoDifficult to say. The oldest file I could find says it's from 1989, but it got onto my machine a lot later. There's also a lot of "Ship of Theseus" going on, since it's a source code file that has seen lots of revisions over the decades.
- js2 3y ago> Because trap doesn't pass the signal information to the handler You can examine $? on entry to the trap function. On signals, it will be 128 + signal. i.e. on TERM (15) it will be 143. On INT (2) it will be 130. #!/bin/bash skip_exit= on_exit() { code=$? if test $code == 130; then skip_exit=1 fi if test -n "$skip_exit"; then return fi echo "Exiting with: $code" return $code } trap on_exit INT EXIT sleep 2 false With ctrl-c: $ ./foo.sh ^C After 2 seconds: $ ./foo.sh Exiting with: 1 You can also setup separate handlers for each signal and use a sentinel: $ cat foo.sh #!/bin/bash skip_exit= on_int() { echo int skip_exit=1 } on_exit() { test -n "$skip_exit" && return echo exit } trap on_int INT trap on_exit EXIT sleep 2 With ctrl-c: $ ./foo.sh ^Cint After 2 seconds: $ ./foo.sh exit
- arp242 3y agoI mean, it's possible, but it's not exactly pretty, and it won't necessarily work in all POSIX compliant shells either (although I believe it will in most, but I didn't test – things the trap execution order and exact status codes are not exactly defined IIRC).
- usr1106 3y agoFor robust code you should also use set -e. This changes things again. Often a process started by the shell will get the signal, too (depends of course on how it is sent) and exit with a non-zero return value (depends on the process of course). I believe (not at the computer right now) the handler for EXIT is called in that case. Was it so that bash can also trap ERR, but dash cannot? It's not perfectly easy to handle all possible cases, and certainly impossible in a fully portable way.
- tjoff 3y ago> For robust code you should also use set -e. Highly debatable.
- digitalsushi 3y ago
- blibble 3y agoif you're debugging hit ctrl+z and it will suspend the script in place
- archi42 3y agoThanks for pointing this quirk/difference out! I'll keep it in mind. Regarding the expected behaviour: I believe this is largely a matter of preference/philosophy. I have previously used trap handlers in bash scripts explicitly so that the cleanup is run in every case and /tmp is not polluted - even of failures. Reasoning: For automated tasks or people not familiar with Linux/my script, the disk should not be filled up with old garbage data. And for debugging, I usually add a '-d/--debug' option to have more verbose output and disable the cleanup on Ctrl+C (but still cleanup on normal exit). But as I said, I don't believe there is the one true way. So except for pointing out that I had to ensure external cleanup in case the script was run by some auomated tasks in a permanent environment (read: native), I wouldn't seriously complain if I ever used one of your scripts :)
- arp242 3y ago> I have previously used trap handlers in bash scripts explicitly so that the cleanup is run in every case and /tmp is not polluted - even of failures That's perfectly fine – even desirable – behaviour for a whole bunch of use cases. The thing is you can opt-in to that trivially with "trap EXIT INT TERM ABRT", whereas the reverse is harder and much less obvious, so it seems like a better design to me (although a "trap ALWAYS" shortcut would be even better so you don't need to list signals). At this point it's difficult to change due to compatibility as people's bash scripts would break in subtle ways, but it's one of my many annoyances with bash (my view is that people really ought to ditch bash in favour of a better shell – zsh being the most obvious incremental improvement, though far from the only option – but this always proves to be a controversial opinion).