Live data from Hacker News

“Exit traps” can make your Bash scripts more robust and reliable (2013)

redsymbol.net

41–50 of 159 posts

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#41
post #33
post #11

I used an exit trap to kill an SSH agent that I am running, and I noticed that dash did not kill if the script was interrupted, but only if it ran to successful completion. I asked on the mailing list if this was expected behavior, and it turns out that POSIX only requires EXIT to run on a clean shutdown; to catch interruptions, add more signals. trap 'eval $(ssh-agent -k)' EXIT INT ABRT KILL TERM

I think you want: trap 'ssh-agent -k' EXIT INT TERM I don't see any reason for the eval as "ssh-agent -k" doesn't return anything useful you want the shell to evaluate.

That's not what the eval is for.

The "ssh-agent -k" command will emit shell commands that the shell must then execute which will kill the agent daemon and unset the socket environment variable.

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#43
I couldn't find a way to have more than one callback per signal, and created a system to have an array of callbacks:

https://github.com/kidd/scripting-field-guide/blob/master/bo...

A nice bonus is that it also keeps the return value of the last non-callback function, so your script behaves better when called from other scripts.

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#44
post #41
post #33

Earlier quoted context omitted.

I think you want: trap 'ssh-agent -k' EXIT INT TERM I don't see any reason for the eval as "ssh-agent -k" doesn't return anything useful you want the shell to evaluate.

That's not what the eval is for. The "ssh-agent -k" command will emit shell commands that the shell must then execute which will kill the agent daemon and unset the socket environment variable.

> The "ssh-agent -k" command will emit shell commands

Does it really? I've executed it here and it just runs kill, doesn't emit any bash. Running just ssh-agent (without any args) does that though, which is what's probably causing the confusion.

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#46
post #34

Earlier quoted context omitted.

SIGABRT would have to come from the process itself; IDK when if ever the shell would do that. And SIGKILL can't be handled, so that is indeed pointless.

POSIX says that "setting a trap for SIGKILL or SIGSTOP produces undefined results", but for signals it describes SIGKILL as "Kill (cannot be caught or ignored)". I'm guessing this is some relic from 80s Unix systems where SIGKILL behaved different, or perhaps just an inconsistency/oversight.

I read that as undefined in terms of how the shell itself handles it, because the OS doesn't care.

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#47
post #41
post #33

Earlier quoted context omitted.

I think you want: trap 'ssh-agent -k' EXIT INT TERM I don't see any reason for the eval as "ssh-agent -k" doesn't return anything useful you want the shell to evaluate.

That's not what the eval is for. The "ssh-agent -k" command will emit shell commands that the shell must then execute which will kill the agent daemon and unset the socket environment variable.

If all you care about is killing it, you don't need to eval the output. The output just unsets two environment variables which only matters in the current shell context.

  $ ssh-agent
  SSH_AUTH_SOCK=/var/folders/8p/_pwq997168s7vdwwdg_qr1j40000gn/T//ssh-DE0IoJfU5rrM/agent.15015; export SSH_AUTH_SOCK;
  SSH_AGENT_PID=15016; export SSH_AGENT_PID;
  echo Agent pid 15016;

  $ SSH_AGENT_PID=15016; export SSH_AGENT_PID;
  $ ssh-agent -k
  unset SSH_AUTH_SOCK;
  unset SSH_AGENT_PID;
  echo Agent pid 15016 killed;
That said, it doesn't hurt to eval it, so I overstated my case in my original comment.

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#48
post #11

I used an exit trap to kill an SSH agent that I am running, and I noticed that dash did not kill if the script was interrupted, but only if it ran to successful completion. I asked on the mailing list if this was expected behavior, and it turns out that POSIX only requires EXIT to run on a clean shutdown; to catch interruptions, add more signals. trap 'eval $(ssh-agent -k)' EXIT INT ABRT KILL TERM

The signals EXIT HUP INT TERM cover everything I've run into (I'm actually using EXIT SIGHUP SIGINT SIGTERM but presumably it's equivalent).

In basic terms for my purposes these respectively account for a clean exit, the terminal emulator being closed, ctrl-c, the kill command (edit: the default SIGTERM kill -15, not the SIGKILL kill -9)

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#49
post #44
post #41

Earlier quoted context omitted.

That's not what the eval is for. The "ssh-agent -k" command will emit shell commands that the shell must then execute which will kill the agent daemon and unset the socket environment variable.

> The "ssh-agent -k" command will emit shell commands Does it really? I've executed it here and it just runs kill, doesn't emit any bash. Running just ssh-agent (without any args) does that though, which is what's probably causing the confusion.

I am on OpenBSD 7.2, and I see:

  $ eval $(ssh-agent)
  Agent pid 56785

  $ ssh-agent -k
  unset SSH_AUTH_SOCK;
  unset SSH_AGENT_PID;
  echo Agent pid 56785 killed;
The correct processing of that output requires an eval.

Did you have any other questions?

Re: “Exit traps” can make your Bash scripts more robust and reliable (2013)

#50
post #15

I like combining this with a bash implementation of an event API ( https://github.com/bashup/events ). This makes it easy/idiomatic, for example, to conditionally add cleanup as you go. Glossing over some complexity, but roughly: add_cleanup(){ event on cleanup "$@" } trap "event emit 'cleanup'" HUP EXIT start_postgres(){ add_cleanup stop_postgres # actually start pg } start_apache(){ add_cleanup stop_apache # actual…

Thank you for sharing - if i understand the code, the queue is serialized into bash variable(s) (arrays)?

I must admit I find the code somewhat painfully terse and hard to read.

Still, interesting idea. I wonder if using a temporary SQLite/Berkeley DB/etc for queue might generalize the idea to a "Unix" event system - allowing other programs and scripts to use it for coordinating? (Like logger(1) does for logging)?

Post reply on HN