9

Suppose I run a command in one shell session, for example bash -c 'apt-get update && apt-get upgrade'. 5 minutes later I decide to go outside for a snack, and realize I forgot to add some form of notification mechanism for whether exit was success or failure.

Well, what do I now ? If only I could query from another terminal the exit status of that other command ( or specifically, that PID), maybe I could after all display some sort of pop up. So the question is: how can I query exit status of an already running process from another terminal ?

In other words,

GIVEN that I have a running process in terminal A AND its PID is known

WHEN I execute some command in terminal B

THEN I should be able to know if process in terminal A finishes with exit status 0 or exit status >1.

Sergiy Kolodyazhnyy
  • 105,154
  • 20
  • 279
  • 497
  • So you want something (an alert command reporting the exit code?) to run once a specified, arbitrary process A (given PID) terminates, after attaching a "watcher" to it with command B? We can not assume that A is a background job running in the same shell where you later type B, no? – Byte Commander Sep 03 '18 at 23:29
  • @ByteCommander Correct. It's a foreground job. – Sergiy Kolodyazhnyy Sep 03 '18 at 23:32
  • I don't think it is possible to get a return code from a child of a different shell. You can use wait to get the code of a background process in your current shell, after it terminates, but I could not find anything that would allow querying other shells. Simply monitoring whether a process is still running and raising an alert once it exits is also trivial again, but not finding out its exit code. The only way I could possibly think of would require preparing your shell's PROMPT_COMMAND to store the last exit code in a tempfile or similar accessible location. Would that be an option? – Byte Commander Sep 03 '18 at 23:49
  • @ByteCommander Nope. No preparing terminal A, do everything from terminal B. And trust me, it's possible. – Sergiy Kolodyazhnyy Sep 04 '18 at 00:01
  • 1
    Well, it would be a permanent preparation (editing .bashrc once), but okay. Looking forward to read the answer, if you find one. – Byte Commander Sep 04 '18 at 00:03
  • @ByteCommander I already do, I just wanna see what others come up with. :) – Sergiy Kolodyazhnyy Sep 04 '18 at 00:05
  • @dsstorefile1 I'm not familiar with what TIOCSTI is or with ioctl() syscall, so maybe ? – Sergiy Kolodyazhnyy Sep 04 '18 at 01:03
  • I know you already have an answer but want some comments first....Um go to Terminal A and type echo $? – WinEunuuchs2Unix Sep 04 '18 at 01:17
  • @WinEunuuchs2Unix hehe, would give exit status from within terminal A. I want it from within terminal B. – Sergiy Kolodyazhnyy Sep 04 '18 at 01:26

1 Answers1

9

Use strace as follows:

sudo strace -e trace=none -e signal=none -q -p $PID

Neither system calls nor signals are of interest here, so we tell strace to ignore them with the -e expressions and supress a status message with -q. strace attaches to the process with PID $PID, waits for it to exit normally and outputs its exit status like this:

+++ exited with 0 +++

A simple if expression to call any type of notification could be:

if sudo strace -e trace=none -e signal=none -q -p $PID |& grep -q ' 0 '; then
  echo yeah
else
  echo nope
fi

Example run

# in terminal 1
$ (echo $BASHPID;sleep 10;true)
8807
# in terminal 2
$ if sudo strace -e{trace,signal}=none -qp8807|&grep -q ' 0 ';then echo yeah;else echo nope;fi
yeah

# in terminal 1
$ (echo $BASHPID;sleep 10;false)
12285
# in terminal 2
$ if sudo strace -e{trace,signal}=none -qp12285|&grep -q ' 0 ';then echo yeah;else echo nope;fi
nope

Most of the credit goes to this answer on U&L, please leave an upvote there if you find this useful.

dessert
  • 39,982