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.comsh - how do I watch for a process to have died in shell script? - Stack Overflow
how to catch status code of killed process by bash script
unix - How to suppress Terminated message after killing in bash? - Stack Overflow
linux - Shell script process is getting killed automatically - Stack Overflow
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
$
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.
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"
}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.
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
Every process has to have a parent process (to collect exit status, at the very least). see man 2 wait. If a parent process dies, its children are sent a SIGHUP signal (see man 7 signal). SIGHUP is a catchable signal, but if the child doesn't catch it, the default action is to kill the child process.
See man nohup to keep things going.
To execute a background job and keep it running after terminal is closed use:
nohup command &>/dev/null &
Enable core dump in your system, it is the most commonly used method for app crash analysis. I know it is a bit painful to gdb core file, but more or less you can find something out of it. Here is a reference link for you.(http://www.cyberciti.biz/tips/linux-core-dumps.html).
Another way to do this is tracing you script by "strace -p PID-X", note that it will slow down your system, espeically several hours in your case, but it can be the last resort.
Hope above helpful to you.
Better to check all the signals generated and caught by OS at that time by specific script might be one of signal is causing to kill your process.
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.
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."
With standard sh and bash, you can
set -e
It will
$ help set
...
-e Exit immediately if a command exits with a non-zero status.
It also works (from what I could gather) with zsh. It also should work for any Bourne shell descendant.
With csh/tcsh, you have to launch your script with #!/bin/csh -e
May be you could use:
$ <any_command> || exit 1
Your script is run on another shell and uses the -f option (follow) of tail which appends the output as the file grows. In short, the script has no exit point, so it's not supposed to end, even if you desire the script to do so.
tl;dr: create a bash exit hook and kill your background job from there.
Details:
Create a PID file in your
tail/grepscript like so:echo $$ > $HOME/script.pidAdd an exit hook to your login shell by adding something like this to your
$HOME/.bash_profile:function finish { # Your cleanup code here kill -9 `cat $HOME/script.pid` } trap finish EXITProfit.
This will break if you envoke your tail script multiple times. This could be handled by creating a lock file or skipping the script.pid file and crafting a killall <scriptname> inside the trap function.
Does the name of your script include MailSender? Try changing it, if so. Also, use pkill -9, it'll be cleaner:
#!/bin/bash
pkill -9 MailSender
echo starting
./MailSender
pkill will kill anything contained MailSender, maybe your script contain MailSender in its name. Change it.
Use a negative PID which will cause a process group to be killed. The -- tells kill that the rest of the arguments are not option switches so the hyphen (minus) before the PID won't confuse it.
kill -- -12345
Also, -9 is a last resort. Don't use it until you've tried at least -15 (SIGTERM, which is the default) first. This gives a program the chance to do housekeeping before it exits. See When should I use kill -9 or Useless use of kill -9 or kill -9.
killall might give you better results.
Warning: killall behaves differently on the different *nix's. On Linux, it will kill the processes with the titles matching the argument. On Solaris, it will kill EVERY process, not just the ones you specify. So on Solaris, running killall as root will effectively shut down the machine. Make sure you know which behavior the command follows
Processes can call the _exit() system call (on Linux, see also exit_group()) with an integer argument to report an exit code to their parent. Though it's an integer, only the 8 least significant bits are available to the parent (exception to that is when using waitid() or handler on SIGCHLD in the parent to retrieve that code, though not on Linux).
The parent will typically do a wait() or waitpid() to get the status of their child as an integer (though waitid() with somewhat different semantics can be used as well).
On Linux and most Unices, if the process terminated normally, bits 8 to 15 of that status number will contain the exit code as passed to exit(). If not, then the 7 least significant bits (0 to 6) will contain the signal number and bit 7 will be set if a core was dumped.
perl's $? for instance contains that number as set by waitpid():
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Bourne-like shells also make the exit status of the last run command in their own $? special parameter. However, it does not contain directly the number returned by waitpid(), but a transformation on it, and it's different between shells.
What's common between all shells is that $? contains the lowest 8 bits of the exit code (the number passed to exit()) if the process terminated normally.
Where it differs is when the process is terminated by a signal. In all cases, and that's required by POSIX, the number will be greater than 128. POSIX doesn't specify what the value may be. In practice though, in all Bourne-like shells that I know, the lowest 7 bits of $? will contain the signal number. But, where n is the signal number,
in ash, zsh, pdksh, bash, the Bourne shell,
$?is128 + n. What that means is that in those shells, if you get a$?of129, you don't know whether it's because the process exited withexit(129)or whether it was killed by the signal1(HUPon most systems). But the rationale is that shells, when they do exit themselves, by default return the exit status of the last exited command. By making sure$?is never greater than 255, that allows to have a consistent exit status:$ bash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"' bash: line 1: 16720 Terminated sh -c "kill \$\$" 8f # 128 + 15 $ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?" bash: line 1: 16726 Terminated sh -c "kill \$\$" 8f # here that 0x8f is from a exit(143) done by bash. Though it's # not from a killed process, that does tell us that probably # something was killed by a SIGTERMksh93,$?is256 + n. That means that from a value of$?you can differentiate between a killed and non-killed process. Newer versions ofksh, upon exit, if$?was greater than 255, kills itself with the same signal in order to be able to report the same exit status to its parent. While that sounds like a good idea, that means thatkshwill generate an extra core dump (potentially overwriting the other one) if the process was killed by a core generating signal:$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"' ksh: 16828: Terminated 10f # 256 + 15 $ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?" ksh: 16816: Illegal instruction(coredump) Illegal instruction(coredump) 104 # 256 + 15, ksh did indeed kill itself so as to report the same # exit status as sh. Older versions of `ksh93` would have returned # 4 instead.Where you could even say there's a bug is that
ksh93kills itself even if$?comes from areturn 257done by a function:$ ksh -c 'f() { return "$1"; }; f 257; exit' zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit' # ksh kills itself with a SIGHUP so as to report a 257 exit status # to its parentyash.yashoffers a compromise. It returns256 + 128 + n. That means we can also differentiate between a killed process and one that terminated properly. And upon exiting, it will report128 + nwithout having to suicide itself and the side effects it can have.$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"' 18f # 256 + 128 + 15 $ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?" 8f # that's from a exit(143), yash was not killed
To get the signal from the value of $?, the portable way is to use kill -l:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(for portability, you should never use signal numbers, only signal names)
On the non-Bourne fronts:
csh/tcshandfishsame as the Bourne shell except that the status is in$statusinstead of$?(note thatzshalso sets$statusfor compatibility withcsh(in addition to$?)).rc: the exit status is in$statusas well, but when killed by a signal, that variable contains the name of the signal (likesigtermorsigill+coreif a core was generated) instead of a number, which is yet another proof of the good design of that shell.es. the exit status is not a variable. If you care for it, you run the command as:status = <={cmd}
which will return a number or sigterm or sigsegv+core like in rc.
Maybe for completeness, we should mention zsh's $pipestatus and bash's $PIPESTATUS arrays that contain the exit status of the components of the last pipeline.
And also for completeness, when it comes to shell functions and sourced files, by default functions return with the exit status of the last command run, but can also set a return status explicitly with the return builtin. And we see some differences here:
bashandmksh(since R41, a regression^Wchange apparently introduced intentionally) will truncate the number (positive or negative) to 8 bits. So for instancereturn 1234will set$?to210,return -- -1will set$?to 255.zshandpdksh(and derivatives other thanmksh) allow any signed 32 bit decimal integer (-231 to 231-1) (and truncate the number to 32bits).ashandyashallow any positive integer from 0 to 231-1 and return an error for any number out of that.ksh93forreturn 0toreturn 320set$?as is, but for anything else, truncate to 8 bits. Beware as already mentioned that returning a number between 256 and 320 could causekshto kill itself upon exit.rcandesallow returning anything even lists.
Also note that some shells also use special values of $?/$status to report some error conditions that are not the exit status of a process, like 127 or 126 for command not found or not executable (or syntax error in a sourced file)...
When a process exits, it returns an integer value to the operating system. On most unix variants, this value is taken modulo 256: everything but the low-order bits is ignored. The status of a child process is returned to its parent through a 16-bit integer in which
- bits 0–6 (the 7 low-order bits) are the signal number that was used to kill the process, or 0 if the process exited normally;
- bit 7 is set if the process was killed by a signal and dumped core;
- bits 8–15 are the process's exit code if the process exited normally, or 0 if the process was killed by a signal.
The status is returned by the wait system call or one of its siblings. POSIX does not specify the exact encoding of the exit status and signal number; it only provides
- a way to tell whether the exit status corresponds to a signal or to a normal exit;
- a way to access the exit code, if the process exited normally;
- a way to access the signal number, if the process was killed by a signal.
Strictly speaking, there's no exit code when a process is killed by a signal: what there is instead is an exit status.
In a shell script, the exit status of a command is reported via the special variable $?. This variable encodes the exit status in an ambiguous way:
- If the process exited normally then
$?is its exit status. - If the process was killed by a signal then
$?is 128 plus the signal number on most systems. POSIX only mandates that$?is greater than 128 in this case; ksh93 adds 256 instead of 128. I've never seen a unix variant that did anything other than add a constant to the signal number.
Thus in a shell script you cannot tell conclusively whether a command was killed by a signal or exited with a status code greater than 128, except with ksh93. It is very rare for programs to exit with status codes greater than 128, in part because programmers avoid it due to the $? ambiguity.
SIGINT is signal 2 on most unix variants, thus $? is 128+2=130 for a process that was killed by SIGINT. You'll see 129 for SIGHUP, 137 for SIGKILL, etc.