0

I want to run a command every several minutes until I turn it off.

After some searching, I found lots of ways of doing the first half (running a command periodically and indefinitely), what about I want to turn it off?

Edit
By "turn it off" probably I mean "turn it off using another shell command".

Edit
Just to clarify want I really want to do, actually I want to run a Python program P periodically until I give some command to stop it.
And just in case that P happens to be running while I'm giving out the stop command, I want it to finish the current run first, and then not to run ever since.

  • and what exactly would trigger the turn-off ? you can launch a watch loop and 'turn it off' by killing the process, does that suit you ? – mazs Jun 28 '16 at 8:20
  • Is this a command like ls or something that runs quickly, and you want to run it every few seconds? – Kusalananda Jun 28 '16 at 8:29
  • @mazs seems it does, thanks, just how would I know the pid of the watch loop (in order to kill it)? – dontloo Jun 28 '16 at 8:32
  • 1
    I don't get it. In the question you say you want to run a process "periodically and indefinitely" until you terminate it. Then you say you don't want to terminate it. Now you say you have two processes; one runs for a long time (and you don't want to kill it), and the other should run periodically (and you do want to kill it). I think you need to clarify the question and tell us what's really happening and what you want to be doing. (EDIT: I mean update the question. Don't do it in comments.) – Kusalananda Jun 28 '16 at 8:48
  • 1
    @Kusalananda hi sorry for the terrible explanation, I edited the answer a bit, does it seem to make sense now? – dontloo Jun 28 '16 at 9:01
1

You have two options: Modify the Python script, or write a shell script wrapper.

To modify the Python script:

  1. You should loop around what it is you want to be doing.

  2. Install a signal handler to catch the INT signal (sent by Ctrl-C) and TERM signal (sent by plain kill). When the signal is caught, set a variable telling the Python script that it should no longer loop. I'm not familiar enough with with Python to be able to tell you how to do this.

Alternative solution: Shell script wrapper, which does the same as the above, but outside the Python script:

#!/bin/sh

loop_again=1

trap 'loop_again=0;wait' INT TERM

while (( loop_again )); do
    echo "Kill me with 'kill -9 $$'"
    ./python_script &
    echo "Kill the Python script with 'kill $!'"
    wait
done

This wrapper script starts your Python script in the background, and then waits for it to finish. It then restarts it, indefinitely. It also tells you how to terminate it and the Python script in each iteration.

If you kill the script (using plain kill, not kill -9), or press Ctrl-C, the loop_again variable is set to zero (which will cause the loop to terminate at the end of the current iteration), and then it waits for the currently running background process to finish before exiting.

If you kill the wrapper script with kill -9 (which is the same as kill -s KILL, sending a KILL signal that can't be ignored or caught by a signal handler), it will exit, leaving your Python script running in the background until it finishes by itself.

1

You can try using a watch 'loop' to run the program repeatedly and see the result, or a while loop. Obtain the PID of that process with echo $! and use kill to terminate that PID. For example :

while :; do ./test.py; done & echo $! > /tmp/testpy.pid

Use kill to terminate program when you want :

kill -9 `cat /tmp/testpy.pid`
  • 1
    thank you so much, I've tried something similar, I'm not sure but it seems that if the while loop runs indefinitely, the later half echo $! > /tmp/testpy.pid will never gets executed unless the while loop is done. am I making any sense? – dontloo Jun 28 '16 at 9:11
  • 1
    it should work, i tested it on my Ubuntu with a shellscript.....the & will place the while loop in the background and the echo will grab the PID of the last executed process – mazs Jun 28 '16 at 9:32
  • The echo will grab the PID of the first Python script invocation, but not of the subsequent ones. To "exit" the loop, one would have to put it in the foreground with fg and press Ctrl-C. – Kusalananda Jun 28 '16 at 9:41
  • Yeah good to know...you can also try to put the whole while loop in a shellscript – mazs Jun 28 '16 at 9:48
1

You can create a cron job to run your command on regular basis. For example if you want to execute the job on every hour you should create the following cron job:

0 * * * * /path/to/your/command >/dev/null 2>&1

If you want to stop the execution of the job type ps aufx|grep yourcommand|grep -v and kill the pid of it.

  • you can use pkill yourcommand to kill the program. – Archemar Jun 28 '16 at 9:27
  • This would start the Python script even though the last invocation of it hasn't finished running. Also, one would have to remove the crontab entry to stop the subsequent invocations of the script. – Kusalananda Jun 28 '16 at 9:46
-1

You can press CTRL + c or send the SIGTERM signal with kill or killall.

  • This doesn't answer the periodically part. – Archemar Jun 28 '16 at 9:29
  • @Archemar: The Author wrote: After some searching, I found lots of ways of doing the first half (running a command periodically and indefinitely), what about I want to turn it off? – Harald Weber Jun 28 '16 at 14:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.