Running a cron every 30 seconds

孤人 提交于 2019-12-16 20:02:13

问题


Ok so I have a cron that I need to run every 30 seconds.

Here is what I have:

*/30 * * * * /bin/bash -l -c 'cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'''

It runs, but is this running every 30 minutes or 30 seconds?

Also, I have been reading that cron might not be the best tool to use if I run it that often. Is there another better tool that I can use or install on Ubuntu 11.04 that will be a better option? Is there a way to fix the above cron?


回答1:


You have */30 in the minutes specifier - that means every minute but with a step of 30 (in other words, every half hour). Since cron does not go down to sub-minute resolutions, you will need to find another way.

One possibility, though it's a bit of a kludge, is to have two jobs, one offset by 30 seconds:

* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )

Both cron jobs actually run every minute but the latter one will wait half a minute before executing the "meat" of the job, /path/to/executable.

For other (non-cron-based) options, see the other answers here, particularly the ones mentioning fcron and systemd. These are probably preferable assuming your system has the ability to use them (such as installing fcron or having a distro with systemd in it).




回答2:


You can't. Cron has a 60 sec granularity.

* * * * * cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''
* * * * * sleep 30 && cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''



回答3:


Cron's granularity is in minutes and was not designed to wake up every x seconds to run something. Run your repeating task within a loop and it should do what you need:

#!/bin/env bash
while [ true ]; do
 sleep 30
 # do what you need to here
done



回答4:


No need for two cron entries, you can put it into one with:

* * * * * /bin/bash -l -c "/path/to/executable; sleep 30 ; /path/to/executable"

so in your case:

* * * * * /bin/bash -l -c "cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\'' ; sleep 30 ; cd /srv/last_song/releases/20120308133159 && script/rails runner -e production '\''Song.insert_latest'\''"




回答5:


If you are running a recent Linux OS with SystemD, you can use the SystemD Timer unit to run your script at any granularity level you wish (theoretically down to nanoseconds), and - if you wish - much more flexible launching rules than Cron ever allowed. No sleep kludges required

It takes a bit more to set up than a single line in a cron file, but if you need anything better than "Every minute", it is well worth the effort.

The SystemD timer model is basically this: timers are units that start service units when a timer elapses.

So for every script/command that you want to schedule, you must have a service unit and then an additional timer unit. A single timer unit can include multiple schedules, so you normally wouldn't need more than one timer and one service.

Here is a simple example that logs "Hello World" every 10 seconds:

/etc/systemd/system/helloworld.service:

[Unit]
Description=Say Hello
[Service]
ExecStart=/usr/bin/logger -i Hello World

/etc/systemd/system/helloworld.timer:

[Unit]
Description=Say Hello every 10 seconds
[Timer]
OnBootSec=10
OnUnitActiveSec=10
AccuracySec=1ms
[Install]
WantedBy=timers.target

After setting up these units (in /etc/systemd/system, as described above, for a system-wide setting, or at ~/.config/systemd/user for a user-specific setup), you need to enable the timer (not the service though) by running systemctl enable helloworld.timer. If you want to start the timer immediately (instead of waiting for it to start after a reboot), also run systemctl start helloworld.timer.

The [Timer] section fields used here are as follows:

  • OnBootSec - start the service this many seconds after each boot.
  • OnUnitActiveSec - start the service this many seconds after the last time the service was started. This is what causes the timer to repeat itself and behave like a cron job.
  • AccuracySec - sets the accuracy of the timer. Timers are only as accurate as this field sets, and the default is 1 minute (emulates cron). The main reason to not demand the best accuracy is to improve power consumption - if SystemD can schedule the next run to coincide with other events, it needs to wake the CPU less often. The 1ms in the example above is not ideal - I usually set accuracy to 1 (1 second) in my sub-minute scheduled jobs, but that would mean that if you look at the log showing the "Hello World" messages, you'd see that it is often late by 1 second. If you're OK with that, I suggest setting the accuracy to 1 second or more.

As you may have noticed, this timer doesn't mimic Cron all that well - in the sense that the command doesn't start at the beginning of every wall clock period (i.e. it doesn't start on the 10th second on the clock, then the 20th and so on). Instead is just happens when the timer ellapses. If the system booted at 12:05:37, then the next time the command runs will be at 12:05:47, then at 12:05:57, etc. If you are interested in actual wall clock accuracy, then you may want to replace the OnBootSec and OnUnitActiveSec fields and instead set an OnCalendar rule with the schedule that you want (which as far as I understand can't be faster than 1 second, using the calendar format). The above example can also be written as:

OnCalendar=*-*-* *:*:00,10,20,30,40,50

Last note: as you probably guessed, the helloworld.timer unit starts the helloworld.service unit because they have the same name (minus the unit type suffix). This is the default, but you can override that by setting the Unit field for the [Timer] section.

More gory details can be found at:

  • Arch Linux Wiki page about SystemD timers which gives a very good overview of the topic, with examples.
  • man systemd.timer
  • man systemd.time
  • man systemd.service
  • man system.exec



回答6:


You can check out my answer to this similar question

Basically, I've included there a bash script named "runEvery.sh" which you can run with cron every 1 minute and pass as arguments the real command you wish to run and the frequency in seconds in which you want to run it.

something like this

* * * * * ~/bin/runEvery.sh 5 myScript.sh




回答7:


Cron job cannot be used to schedule a job in seconds interval. i.e You cannot schedule a cron job to run every 5 seconds. The alternative is to write a shell script that uses sleep 5 command in it.

Create a shell script every-5-seconds.sh using bash while loop as shown below.

$ cat every-5-seconds.sh
#!/bin/bash
while true
do
 /home/ramesh/backup.sh
 sleep 5
done

Now, execute this shell script in the background using nohup as shown below. This will keep executing the script even after you logout from your session. This will execute your backup.sh shell script every 5 seconds.

$ nohup ./every-5-seconds.sh &



回答8:


Use watch:

$ watch --interval .30 script_to_run_every_30_sec.sh



回答9:


Use fcron (http://fcron.free.fr/) - gives you granularity in seconds and way better and more feature rich than cron (vixie-cron) and stable too. I used to make stupid things like having about 60 php scripts running on one machine in very stupid settings and it still did its job!




回答10:


in dir /etc/cron.d/

new create a file excute_per_30s

* * * * * yourusername  /bin/date >> /home/yourusername/temp/date.txt
* * * * * yourusername sleep 30; /bin/date >> /home/yourusername/temp/date.txt

will run cron every 30 seconds




回答11:


Crontab job can be used to schedule a job in minutes/hours/days, but not in seconds. The alternative :

Create a script to execute every 30 seconds:

#!/bin/bash
# 30sec.sh

for COUNT in `seq 29` ; do
  cp /application/tmp/* /home/test
  sleep 30
done

Use crontab -e and a crontab to execute this script:

* * * * * /home/test/30sec.sh > /dev/null



回答12:


Currently i'm using the below method. Works with no issues.

* * * * * /bin/bash -c ' for i in {1..X}; do YOUR_COMMANDS ; sleep Y ; done '

If you want to run every N seconds then X will be 60/N and Y will be N.

Thank you.




回答13:


Thanks for all the good answers. To make it simple I liked the mixed solution, with the control on crontab and the time division on the script. So this is what I did to run a script every 20 seconds (three times per minute). Crontab line:

 * * * * 1-6 ./a/b/checkAgendaScript >> /home/a/b/cronlogs/checkAgenda.log

Script:

cd /home/a/b/checkAgenda

java -jar checkAgenda.jar
sleep 20
java -jar checkAgenda.jar 
sleep 20
java -jar checkAgenda.jar 



回答14:


write one shell script create .sh file

nano every30second.sh

and write script

#!/bin/bash
For  (( i=1; i <= 2; i++ ))
do
    write Command here
    sleep 30
done

then set cron for this script crontab -e

(* * * * * /home/username/every30second.sh)

this cron call .sh file in every 1 min & in the .sh file command is run 2 times in 1 min

if you want run script for 5 seconds then replace 30 by 5 and change for loop like this: For (( i=1; i <= 12; i++ ))

when you select for any second then calculate 60/your second and write in For loop




回答15:


I just had a similar task to do and use the following approach :

nohup watch -n30 "kill -3 NODE_PID" &

I needed to have a periodic kill -3 (to get the stack trace of a program) every 30 seconds for several hours.

nohup ... & 

This is here to be sure that I don't lose the execution of watch if I loose the shell (network issue, windows crash etc...)




回答16:


Have a look at frequent-cron - it's old but very stable and you can step down to micro-seconds. At this point in time, the only thing that I would say against it is that I'm still trying to work out how to install it outside of init.d but as a native systemd service, but certainly up to Ubuntu 18 it's running just fine still using init.d (distance may vary on latter versions). It has the added advantage (?) of ensuring that it won't spawn another instance of the PHP script unless a prior one has completed, which reduces potential memory leakage issues.




回答17:


Run in a shell loop, example:

#!/bin/sh    
counter=1
while true ; do
 echo $counter
 counter=$((counter+1))
 if [[ "$counter" -eq 60 ]]; then
  counter=0
 fi
 wget -q http://localhost/tool/heartbeat/ -O - > /dev/null 2>&1 &
 sleep 1
done


来源:https://stackoverflow.com/questions/9619362/running-a-cron-every-30-seconds

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!