Score:0

Run a command in background, but get a non-zero exit code *immediately* when `No such file or directory`

cn flag

I need to run some (unknown) command in the background like this:

nohup some_command &

Since such a command will run and (hopefully) complete in background, I cannot get its exit status immediately; that is OK.

However, I need to get an "error" exit status immediately in case that some_command is not found (i.e., when the error message from bash is No such file or directory or command not found).

What can be the shortest and simplest workaround alternatives that I can use?


Some background information for the questions asked in the comments: This is a GUI "frontend" program that interacts with the user. The user enters some command (for example, gedit some_file) and my GUI program executes this command and immediately goes back to a loop to accept the next command from the user. So, the command entered should run "detached" from the GUI program. However, if the user enters some wrong command (for example, geditxyz) I want to immediately alert the user that the command is not found.

ar flag
Do you need to use both `nohup` in the beginning and `&` in the end? Will it work if you use one or the other?
raj avatar
cn flag
raj
By "get" the exit status, do you mean to get it programmatically (to use later in a script), or to just get it displayed on the terminal? Because in the second case, bash does it by itself if you set `set -b`. Try to type `nohup nonexistent &` and you immediately get the output like `[1]+ Exit 127 nohup nonexistent`.
Score:3
cn flag

Since such a command will run and (hopefully) complete in background, I cannot get its exit status; that is OK.

This statement is incorrect to begin with:

#!/bin/bash
some_command &
pid="$!"
wait -n "$pid"
echo "Status was ${?}."

If you want to be notified immediately, you can use a few signal-based tricks.

Handling of SIGCHLD would be the most obvious option, but (1) its support in Bash is buggy and (2) despite set -b, trap handlers will actually wait for command boundaries.

That said, the next best option (which also interrupts long-runing foreground processing immediately when some_command fails) is (an equivalent of) generating a Ctrl+C for your entire process group. This is delivered and acted upon immediately, the shell itself can handle the signal and continue, if desired, whereas the foreground process will, presumably, exit by default etc.

#!/bin/bash
set -e

handler() {
  echo 'command failure signalled'
  trap - INT
}
trap handler INT

background() {
  local -ir pid="$1"
  shift
  "$@" || kill -INT -- -"$pid"
}
background "$$" some_command &

# long-running foreground task
echo 'before long processing'
sleep 5 || echo 'long processing interrupted'
echo 'after long processing'

Try to replace some_command with (e.g.) sleep 2 to test the “successful” case.

FedKad avatar
cn flag
Thanks for the answer. It is very close to what I need, but still "somewhat complex." Also, I clarified my earlier statement by adding the word **immediately**.
mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.