open and close perl processes with time out cross-platform - windows

How can I launch and end a process after a time out in perl?
I need the script to work in Windows and Unix, what's my best options?
edit: how do I get the process ID for the started process on windows and unix and how do I kill it at the timeout

You can use the operating system to signal an ALRM (alarm), which you can then exit your process on after a set number of seconds.
So for instance, if at the top of your script you put:
alarm 300;
This will cause your process to receive an ALRM signal. This will kill your process immediately, or you can trap it and clean up your process before it dies.
For further reading: http://perldoc.perl.org/functions/alarm.html
You can trap the signal like this:
$SIG{ALRM} = sub {
# Clean up process here and exit
};
In response to your edit "edit: how do I get the process ID for the started process on windows and unix and how do I kill it at the timeout"
The process ID is stored in perl as $$, so:
print 'My process ID is:', $$, "\n";

Related

How can I send a signal without the shell waiting for the currently running program to finish?

If I send a signal using kill, it seems to wait until the current program (in this example sleep 1000) finishes running. When I instead send SIGINT via pressing Ctrl+C in the shell, it receives the interrupt immediately however.
What I want, however, is for the interrupt to be received immediately after sending the signal via kill. Also, why does it behave like I would want it to when I press Ctrl+C?
#!/usr/bin/env sh
int_after_a_while() {
local pid=$1
sleep 2
echo "Attempting to kill $pid with SIGINT"
# Here I want to kill the process immediately, but it waits until sleep finishes
kill -s INT $pid
}
trap "echo Interrupt received!" INT
int_after_a_while $$ &
sleep 1000
I would appreciate any help on this issue. Thanks in advance!
As noted in the referenced answer https://unix.stackexchange.com/questions/282525/why-did-my-trap-not-trigger/282631#282631 the shell will normally wait for a utility to complete before running a trap. Some alternatives are:
Start the long running process in the background, then wait for it using the wait builtin. When a trapped signal is received during such a wait, the wait is interrupted and the trap is taken. Unfortunately, the exit status of wait does not distinguish between the child process exiting on a signal and a trap occurring. For example
sleep 1000 &
p=$!
wait "$p"
Send a signal to the whole process group via kill -s INT 0. The effect is much like if the user had pressed Ctrl+C, but may be more extreme than you want if your script is run from another script.
Use a shell such as zsh or FreeBSD sh that supports set -o trapsasync which allows running traps while waiting for a foreground job.

Bash: Cannot send ctrl+c into started program

I'm trying to write a bash script that starts a program, waits for x seconds and than sends the ctrl+c signal to the program to stop it.
The program is "trace-cmd" (which is a frontend for ftrace) that records/traces data until ctrl+c is pressed.
I already found a solution to get the PID of trace-cmd, and to send the SIGINT signal using kill to it. Yet, somehow it does not work.
This is my command that is executed (all in one line, just formatted for readability):
sudo trace-cmd record -p function -P $PID & echo $! > ./pid_trace.txt &
echo "[+] Stored PID:" $(cat ./pid_trace.txt) &
sleep $seconds; printf "Killing trace-cmd\n"; sudo kill -INT $(cat ./pid_trace.txt)
The 'echo' is just for testing, I used the txt file as I could not assign the $! value to a variable. As far as I understood: the "&" is used so that these commands are executed concurrently and the ";" so that they are executed after each other. So: i should start trace-cmd, store the PID than start the time, and only after the timer is done execute the kill.
When the ctrl+c signal is pressed while executing trace-cmd, a specific output can be seen (basically that the trace is getting stored). Yet, with my bash program I cannot see it. I assume that the kill signal is either not "delivered" or that the SIGINT is not the signal that trace-cmd expects (can a program intercept these signals? or the key-strokes rather)
Any help would be appreciated!
The 'sudo' process does not pass INT signal to it's children. The CTRL/C processing passed the INT signal to all processes running in the foreground for the connected terminal.
Try one of the options:
Consider using regular kill on sudo (NO -INT). This will use TERM signal, which will result in sudo terminating sub processes.
Send the INT signal directly to the frace (pkill -INT trace_cmd)

shell script process termination issue

/bin/sh -version
GNU sh, version 1.14.7(1)
exitfn () {
# Resore signal handling for SIGINT
echo "exiting with trap" >> /tmp/logfile
rm -f /var/run/lockfile.pid # Growl at user,
exit # then exit script.
}
trap 'exitfn; exit' SIGINT SIGQUIT SIGTERM SIGKILL SIGHUP
The above is my function in shell script.
I want to call it in some special conditions...like
when:
"kill -9" fires on pid of this script
"ctrl + z" press while it is running on -x mode
server reboots while script is executing ..
In short, with any kind of interrupt in script, should do some action
eg. rm -f /var/run/lockfile.pid
but my above function is not working properly; it works only for terminal close or "ctrl + c"
Kindly don't suggest to upgrade "bash / sh" version.
SIGKILL cannot be trapped by the trap command, or by any process. It is a guarenteed kill signal, that by it's definition cannot be trapped. Thus upgrading you sh/bash will not work anyway.
You can't trap kill -9 that's the whole point of it, to destroy processes violently that don't respond to other signals (there's a workaround for this, see below).
The server reboot should first deliver a signal to your script which should be caught with what you have.
As to the CTRL-Z, that also gives you a signal, SIGSTOP from memory, so you may want to add that. Though that wouldn't normally be a reason to shut down your process since it may be then put into the background and restarted (with bg).
As to what do do for those situations where your process dies without a catchable signal (like the -9 case), the program should check for that on startup.
By that, I mean lockfile.pid should store the actual PID of the process that created it (by using echo $$ >/var/run/myprog_lockfile.pid for example) and, if you try to start your program, it should check for the existence of that process.
If the process doesn't exist, or it exists but isn't the right one (based on name usually), your new process should delete the pidfile and carry on as if it was never there. If the old process both exists and is the right one, your new process should log a message and exit.

Can I link a process to a file in bash?

I would like to do the following:
I want to link a process A to a file F, so:
If F dissapears A crashes.
F will only dissapear when A finishes.
Is this possible? Thank you very much.
You should not avoid PIDs. They are process identifiers, and meant to be used.
Bash automatically monitors child processes it starts. The most recent background process id is maintained in $!. Bash also supports job controls using '%n' syntax.
You can trap child procs status changes with trap SIGCHLD, and you can "wait" for one or all child processes to complete with the wait command.
Here is a rough approximation of your two process monitoring, which consists of "job1" and "job2" being started the the sample script:
job1 & # start job1 in background
j1pid=$! # get its process id
job2 & # start job2 in background
j2pid=$1 # get its process id
trap 'err=1' ERR # trap all errors
err=
wait $j1pid # wait for job1 to complete
# at this point job1 could have completed normally,
# or either process could have had an error
trap - ERR # revert to "normal" handling of most errors
# kill the processes nicely, or abruptly
# kill -TERM sends the TERM signal to the process, which it can trap
# and do whatever pre-exit process is needed.
# kill -9 cannot be trapped.
for pid in $j1pid $j2pid ; do
kill -TERM $pid 2>/dev/null || kill -9 $pid
done
You already have a file with almost this property on Linux. If you created a process, the /proc/procNum will exist while the process is alive. As an example, if your process number is 1050, the /proc/1050 will exist until the process die. I do not know if removing this file will kill the process but you can try to tie both together.

shell script to spawn processes, terminate children on SIGTERM

I want to write a shell script that spawns several long-running processes in the background, then hangs around. Upon receiving SIGTERM, I want all the subprocesses to terminate as well.
Basically, I want a "master process".
Here's what I got so far:
#!/bin/sh
sleep 600 &
PID1="$!"
sleep 600 &
PID2="$!"
# supposedly this should kill the child processes on SIGTERM.
trap "kill $PID1 $PID2" SIGTERM
wait
The above script fails with trap: 10: SIGTERM: bad trap.
Edit: I'm using Ubuntu 9.04
This works for me:
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
kill -- -$$ sends a SIGTERM to the whole process group, thus killing also descendants.
Specifying signal EXIT is useful when using set -e (more details here).
Joe's answer put me on the right track.
I also found out I should trap more signals to cover my bases.
Final script looks like this:
#!/bin/sh
sleep 600 &
PID1="$!"
sleep 600 &
PID2="$!"
trap "kill $PID1 $PID2" exit INT TERM
wait
I suspect your /bin/sh is not a Bash (though you tagged the question as 'Bash').
From the message I guess it's a DASH. Check its manual or just fix your shebang if you need to write Bash code.
This script looks correct and works for me as expected.
How do you send the SIGTERM signal to the "master process"?
Maybe you should execute kill -l to check which signals are supported.
As the error message suggests you send signal "10" which your system doesn't seem to recognize.
And next time you should add operating system, shell version, kernel, ... for such a question

Resources