ulimit -t 1 limits the script's CPU time to 1 second. When the script has consumed all its CPU time it gets killed.

To limit the CPU time of just one command in your script you can use parentheses to start it in a subshell with its own limit, e.g.

(ulimit -t 1; LD_PRELOAD=../../EasySandbox/EasySandbox.so ./a.out < $testin) 
Answer from Florian Diesch on askubuntu.com
Discussions

how to catch status code of killed process by bash script
If you do a wait inside the trap, that will put the exit status (99) in $?. You can still also do the wait outside of the trap, but this one will return 130 (128+2) and not 99. Be aware that if you're calling runbg inside $(), it will run in a subshell. In this case the parent shell won't have the trap installed, and when you press Ctrl-c it will just exit normally. More on reddit.com
🌐 r/bash
8
4
January 17, 2025
sh - how do I watch for a process to have died in shell script? - Stack Overflow
I'm running a shell test program that I can view a progress bar but when I run it I keep getting a unary error . Is kill -0 a way to kill a subprocess in shell ? Or is there another method to tes... More on stackoverflow.com
🌐 stackoverflow.com
unix - How to suppress Terminated message after killing in bash? - Stack Overflow
How can you suppress the Terminated message that comes up after you kill a process in a bash script? I tried set +bm, but that doesn't work. I know another solution involves calling exec 2> /dev/ More on stackoverflow.com
🌐 stackoverflow.com
linux - Shell script process is getting killed automatically - Stack Overflow
I am facing problem with shell script i have ascript which will be running in infinite loop so say its havin PID X.The process is running for 4-5 hours but automatically the process getting killed.... More on stackoverflow.com
🌐 stackoverflow.com
Top answer
1 of 6
15

I would do something like this:

#!/bin/bash
trap : SIGTERM SIGINT

echo $$

find / >/dev/null 2>&1 &
FIND_PID=$!

wait $FIND_PID

if [[ $? -gt 128 ]]
then
    kill $FIND_PID
fi

Some explanation is in order, I guess. Out the gate, we need to change some of the default signal handling. : is a no-op command, since passing an empty string causes the shell to ignore the signal instead of doing something about it (the opposite of what we want to do).

Then, the find command is run in the background (from the script's perspective) and we call the wait builtin for it to finish. Since we gave a real command to trap above, when a signal is handled, wait will exit with a status greater than 128. If the process waited for completes, wait will return the exit status of that process.

Last, if the wait returns that error status, we want to kill the child process. Luckily we saved its PID. The advantage of this approach is that you can log some error message or otherwise identify that a signal caused the script to exit.

As others have mentioned, putting kill -- -$$ as your argument to trap is another option if you don't care about leaving any information around post-exit.

For trap to work the way you want, you do need to pair it up with wait - the bash man page says "If bash is waiting for a command to complete and receives a signal for which a trap has been set, the trap will not be executed until the command completes." wait is the way around this hiccup.

You can extend it to more child processes if you want, as well. I didn't really exhaustively test this one out, but it seems to work here.

$ ./test-k.sh &
[1] 12810
12810
$ kill 12810
$ ps -ef | grep find
$
2 of 6
9

Was looking for an elegant solution to this issue and found the following solution elsewhere.

trap 'kill -HUP 0' EXIT

My own man pages say nothing about what 0 means, but from digging around, it seems to mean the current process group. Since the script get's it's own process group, this ends up sending SIGHUP to all the script's children, foreground and background.

🌐
Reddit
reddit.com › r/bash › how to catch status code of killed process by bash script
r/bash on Reddit: how to catch status code of killed process by bash script
January 17, 2025 -

Edit: thank you guys, your comments were very helpful and help me to solve the problem, the code I used to solve the problem is at the end of the post (*), and for the executed command output "if we consider byeprogram produce some output to stdout" I think to redirect it to a pipe, but it did not work well

Hi every one, I am working on project, and I faced an a issue, the issue is that I cannot catch the exit code "status code" of process that worked in background, take this program as an example, that exits with 99 if it received a sigint, the code:

#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
void bye(){
// exit with code 99 if sigint was received
exit(99);
}
int main(int argc,char** argv){
signal(SIGINT, bye);
while(1){
sleep(1);
}
return 0;
}

then I compiled it using

`gcc example.c -o byeprogram`

in the same directory, I have my bash script:

set -x
__do_before_wait(){
##some commands
return 0
}
__do_after_trap(){
##some commands
return 0
}
runbg() {
local __start_time __finish_time __run_time
__start_time=$(date +%s.%N)
# Run the command in the background
($@) &
__pid=$!
trap '
kill -2 $__pid
echo $?
__finish_time=$(date +%s.%N)
__run_time=$(echo "$__finish_time - $__start_time" | bc -l)
echo "$__run_time"
__do_after_trap || exit 2
' SIGINT
__do_before_wait || exit 1
wait $__pid
## now if you press ctrl+c, it will execute the commands i wrote in trap
}
out=`runbg  /path/to/byeprogram`

my problem is I want to catch or print the code 99, but I cannot, I tried to execute the `byeprogram` from the terminal, and type ctrl+c, and it return 99, how to catch the 99 status code??

*solution:

runbg() {
# print status_code,run_time
# to get the status code use ( | gawk -F, {print $1})
# to get the run time use ( | gawk -F, {print $2})

    __trap_code(){
        kill -2 $__pid
        wait $__pid
        __status_code=$?
        __finish_time=$(date +%s.%N)
        __run_time=$(echo "$__finish_time - $__start_time" | bc -l)
        echo "$__status_code,$__run_time"
        __do_after_trap
        exit 0
    }
    local __start_time __finish_time __run_time
    __start_time=$(date +%s.%N)
    ($@) &
    local __pid=$!
    trap __trap_code SIGINT
    __do_before_wait
    wait $__pid
    __status_code=$?
    __finish_time=$(date +%s.%N)
    __run_time=$(echo "$__finish_time - $__start_time" | bc -l)
    echo "$__status_code,$__run_time"
}
🌐
Stack Overflow
stackoverflow.com › questions › 71578894 › how-do-i-watch-for-a-process-to-have-died-in-shell-script
sh - how do I watch for a process to have died in shell script? - Stack Overflow
To kill a process, one generally use the SIGQUIT/3 (quit program) or SIGKILL/9 (terminate program) ; the process could trap the signal and make a clean exit, or it could ignore the signal so the OS has to terminate it 'quick and dirty'.
Top answer
1 of 12
169

In order to silence the message, you must be redirecting stderr at the time the message is generated. Because the kill command sends a signal and doesn't wait for the target process to respond, redirecting stderr of the kill command does you no good. The bash builtin wait was made specifically for this purpose.

Here is very simple example that kills the most recent background command. (Learn more about $! here.)

kill $!
wait $! 2>/dev/null

Because both kill and wait accept multiple pids, you can also do batch kills. Here is an example that kills all background processes (of the current process/script of course).

kill $(jobs -rp)
wait $(jobs -rp) 2>/dev/null

I was led here from bash: silently kill background function process.

2 of 12
21

The short answer is that you can't. Bash always prints the status of foreground jobs. The monitoring flag only applies for background jobs, and only for interactive shells, not scripts.

see notify_of_job_status() in jobs.c.

As you say, you can redirect so standard error is pointing to /dev/null but then you miss any other error messages. You can make it temporary by doing the redirection in a subshell which runs the script. This leaves the original environment alone.

(script 2> /dev/null)

which will lose all error messages, but just from that script, not from anything else run in that shell.

You can save and restore standard error, by redirecting a new filedescriptor to point there:

exec 3>&2          # 3 is now a copy of 2
exec 2> /dev/null  # 2 now points to /dev/null
script             # run script with redirected stderr
exec 2>&3          # restore stderr to saved
exec 3>&-          # close saved version

But I wouldn't recommend this -- the only upside from the first one is that it saves a sub-shell invocation, while being more complicated and, possibly even altering the behavior of the script, if the script alters file descriptors.


EDIT:

For more appropriate answer check answer given by Mark Edgar

Find elsewhere
Top answer
1 of 3
1

There really are only a couple of possibilities. Assuming you're just running this from the command line, you should see the message ... unless, of course, what you're doing puts the PID of your shell process in PIDS, in which case the kill would kill the (sub) shell running your command before you hit the echo.

Suggestion: echo $PIDS before you call kill and see what's there. In fact, I'd be tempted to comment out the kill and try the command, just to see what happens.

#!/bin/bash
PIDS=$(ps -e | grep $1 |grep -v grep| awk '{print $1}')
echo $PIDS
# kill -s SIGINT $PIDS
echo "Done sendings signal"

Of course, you can always run the script with bash -x to see everything.

2 of 3
0

Your script works. The only reason I can see for the echo not being executed is that some value of $1 and the script file name combine so that your script PID is also gathered, thereby making the script suicide.

The PIDS line spawns a process running ps, grep, another grep -- so you won't find in PIDS the processes running grep, but what about the parent process itself?

Try:

#!/bin/bash
PIDS=$(ps -e | grep $1 |grep -v grep | awk '{print $1}' | grep -v "^$$\$" )
kill -s SIGINT $PIDS
echo "Done sendings signal"

or run the pipes one after the other with suitable safety greps.

Edit: it is evident that the "$1" selection is selecting too much. So I'd rewrite the script like this:

#!/bin/bash
# Gather the output of "ps -e". This will also gather the PIDs of this
# process and of ps process and its subshell.
PSS=$( ps -e )
# Extract PIDs, excluding this one PID and excluding a process called "ps".
# Don't need to expunge 'grep' since no grep was running when getting PSS.
PIDS=$( echo "$PSS" | grep -v "\<ps\>" | grep "$1" | awk '{print $1}' | grep -v "^$$\$" )
if [ -n "$PIDS" ]; then
    kill -s SIGINT $PIDS
else
    echo "No process found matching $1"
fi
echo "Done sending signal."
🌐
GitHub
github.com › facebookresearch › hyperreel › issues › 3
Bash script got killed suddenly · Issue #3 · facebookresearch/hyperreel
January 9, 2023 - Hi, Thanks for the code ! I am trying to run the experiment on the immersive dataset but the script got killed suddenly without any warnings or errors ! I have also properly adjust the data path in the local.yaml file like this: bash scr...
Author   facebookresearch
🌐
ErrorCrate
errorcrate.com › linux › killed
Killed - Linux Error | ErrorCrate
2 weeks ago - The 'Killed' error message is returned by the shell when a process is terminated by the kernel with a SIGKILL (Signal 9) signal. SIGKILL cannot be caught, blocked, or ignored by the application, resulting in an immediate exit. This most commonly happens because the kernel's Out-Of-Memory (OOM) ...
🌐
PerlMonks
perlmonks.org
Why does my script exit with "Killed" - that's all...
isync has asked for the wisdom of the Perl Monks concerning the following question: · www.com | www.net | www.org
🌐
Spiceworks
community.spiceworks.com › software & applications
Shell commands are getting killed - Software & Applications - Spiceworks Community
May 8, 2011 - Hi, We have realy strange phenomenon on our aix 5.3.12 box. We have a ksh script containing simple commands like ‘ls’, ‘mv’ etc. realy nothing complicated. When this script is runing in the background, sometimes (not always) some command are mysteriously getting killed, what we get in the log file is a message like: test.sh [20]: 123456 Killed (where line 20 is: ‘ls abc.txt’) When in the foreground it’s never happend.