I wrote some C code to switch on and off some LEDs.
Actually, I want to trigger them accurate to music but haven't found a better way than using usleep() in between yet.
Anyway, turning on the LEDs, waiting at usleep() and turning off the LEDs again works pretty accurate when I call the program on the command line.
Now I'd like cron to execute the program let's say every five minutes. Therefore I added following cronjob with crontab -e:
*/5 * * * * bash ~/startShow.sh >~/log 2>&1
Same problem without the shell script.
*/5 * * * * ~/projects/startLEDShow >~/log 2>&1
startShow.sh
date
/usr/sbin/i2cset -y 1 0x40 0x00 0x21 # Preparation for communication via I2C
cd projects
./startLEDShow
The program is triggered every five minutes, but at some point (not always the same point) the execution seems to stop for a moment and resumes about a second later. That is only when the program is ran by cron, not when I call it from the commandLine.
Why is that so, is this perhaps due to the usleep() used in the program, and how can I make sure that the program execution isn't suspended for some time?
Update 1: Here is an extract with the usleep-section from the program
// Start reading
while(NULL != (word = readToChar(fp, wordBuffer))) {
// Values for the LEDs are stored in a struct
updateValuesForLEDs(next, word); // Update struct "next"
usleep(((next->time/timeFactor - lastTime)*1000000)); // Wait
lastTime = next->time / timeFactor; // Set lastTime for next iteration
setLEDs(i2cConnection, next, buffer); // Set the LEDs to the brightness values stored in struct "next" via I2C
}
Update 2:
After ensc's comment I found way to solve my issue.
The cronjob was started with a nice value of 10 whereas most other processes' values circled around 0. Setting my job to a lower nice value (which requires root privileges) gives it a higher priority and prevents it from being paused.
00 20 * * * sudo nice -n -20 ~/projects/startLEDShow >~/log.txt 2>&1
I doubt you're running a real-time operating system, so usleep is not guaranteed to wake up your process with any guarantee of performance. For that matter, even if your process is woken up at the right time, it's always possible for the kernel to interrupt it and do somehing else for an arbitrary amount of time.
Related
So my understanding is that if you terminate a command with ‘&,’ it runs the process in the background. If two commands were separated by ‘&,’ they would run simultaneously.
e.g. command1 & command2 //runs simultaneously
To implement this, I would have the shell fork a child process and have the child execute the 1st command I. The background. The parent would not wait and would execute the second command in parallel.
Is this the right approach? And how can I apply this to support wait()?
This is using bash on a generic unix:
BigMac:tmp steve$ sleep 10 & sleep 13 & sleep 20 &
[1] 69168
[2] 69169
[3] 69170
BigMac:tmp steve$ wait %1; wait 69169; kill %3
[1] Done sleep 10
[2]- Done sleep 13
[3]+ Terminated: 15 sleep 20
The first line launches three separate sleeps. The shell assigns them job numbers [1], [2], [3]; whereas the system assigns them process id's 69178,69169,69170 resp. The commands wait and kill can take either identifier, as shown in the second line.
The second line waits for the first job % indicates to the shell that the following number is in its naming scheme, then waits for the second process the lack of % indicates a process identifier, then kills the third job.
There is a lot more to this than such a simple example can convey; particularly the notion of job is quite a bit more involved than this example portrays.
The UNIX Programming Environment ISBN despite being nearly 40 years old, provides a great fundamental understanding of how and why UNIX works the way it does. There are more modern, detailed, and system specific works as well.
I would like to write a script in batch that forces the computer to enter
sleep (s3) and/or hibernate(s4), for a certain amount of time. I couldn't find answer for this question nowhere.
Example:
Computer enters sleep state.
30 seconds pass.
Computer returns and continues the script.
I managed to use an external program, but after a few cycles of the procedure
the computer for some reason enters a sleep state for 4,294,966,391 seconds
and only continues the script when turned on manually.
I have a method that runs when I call a specific URL on my application. It processes rows in a database queue. The interval is set as lowest interval possible with Cron, ie. 1 minute. This needs dropping to 30 seconds, so I'm wondering how best to achieve this.
I was thinking I could build a loop into my script that runs the code twice, with a sleep of say 30 seconds in between, but I'm wondering if there's a cleaner way than this.
Also, is there a way of running this method from the command line, without the need to call an actual URL?
This answer is strongly inspired by this one
You can leave your code as it is. To call it twice a minute you can add a second cronjob and let one cronjob sleep 30 seconds before executing the task.
* * * * * /path/to/executable param1 param2
* * * * * ( sleep 30 ; /path/to/executable param1 param2 )
This has two advantages
Your code doesn't need to worry about when and how many times it is executed (e.g. if you call it manually it doesn't need to run twice!)
If your code takes 10 seconds to execute everything you would have a delay when using sleep inside of your function. This way you don't.
As in similar threads it was stated, cron is not usable for this, at least not directly. IMHO the most sane approach is to write a shell script, that does your task every 30 seconds, then set up a cron job to check if your script is running, and if not, it should start it.
By the way, a stored procedure would not be a good solution in your case?
I have written a program which calculates the amount of battery level available in my laptop. I have also defined a threshold value in the program. Whenever the battery level falls below threshold i would like to call another process. I have used system("./invoke.o") where invoke.o is the program that i have to run. I am running a script which runs the battery level checker program for every 5 seconds. Everything is working fine but when i close the bash shell the automatic invocation of invoke.o is not happening. How should i make the invoke.o to be invoked irrespective of whether bash is closed or not??. I am using UBUNTU LINUX
Try running it as: nohup ./myscript.sh, where the nohup command allows you to close the shell without terminating the process.
You could run your script as a cron job. This lets cron set up standard input and output for you, reschedule the job, and it will send you email if it fails.
The alternative is to run a script in the background with all input and output, including standard error output, redirected.
While you could make a proper daemon out of your program that kind of effort is probably not necessary.
man nohup
man upstart
man 2 setsid (more complex, leads to longer trail of breadcrumbs on daemon launching).
I am working on an application where I need to detect a system shutdown.
However, I have not found any reliable way get a notification on this event.
I know that on shutdown, my app will receive a SIGTERM signal followed by a SIGKILL. I want to know if there is any way to query if a SIGTERM is part of a shutdown sequence?
Does any one know if there is a way to query that programmatically (C API)?
As far as I know, the system does not provide any other method to query for an impending shutdown. If it does, that would solve my problem as well. I have been trying out runlevels as well, but change in runlevels seem to be instantaneous and without any prior warnings.
Maybe a little bit late. Yes, you can determine if a SIGTERM is in a shutting down process by invoking the runlevel command. Example:
#!/bin/bash
trap "runlevel >$HOME/run-level; exit 1" term
read line
echo "Input: $line"
save it as, say, term.sh and run it. By executing killall term.sh, you should able to see and investigate the run-level file in your home directory. By executing any of the following:
sudo reboot
sudo halt -p
sudo shutdown -P
and compare the difference in the file. Then you should have the idea on how to do it.
There is no way to determine if a SIGTERM is a part of a shutdown sequence. To detect a shutdown sequence you can either use use rc.d scripts like ereOn and Eric Sepanson suggested or use mechanisms like DBus.
However, from a design point of view it makes no sense to ignore SIGTERM even if it is not part of a shutdown. SIGTERM's primary purpose is to politely ask apps to exit cleanly and it is not likely that someone with enough privileges will issue a SIGTERM if he/she does not want the app to exit.
From man shutdown:
If the time argument is used, 5 minutes before the system goes down
the /etc/nologin file is created to ensure that further logins shall
not be allowed.
So you can test existence of /etc/nologin. It is not optimal, but probably best you can get.
Its a little bit of a hack but if the server is running systemd if you can run
/bin/systemctl list-jobs shutdown.target
... it will report ...
JOB UNIT TYPE STATE
755 shutdown.target start waiting <---- existence means shutting down
1 jobs listed.
... if the server is shutting down or rebooting ( hint: there's a reboot.target if you want to look specifically for that )
You will get No jobs running. if its not being shutdown.
You have to parse the output which is a bit messy as the systemctl doesnt return a different exit code for the two results. But it does seem reasonably reliable. You will need to watch out for a format change in the messages if you update the system however.
Making your application responding differently to some SIGTERM signals than others seems opaque and potentially confusing. It's arguable that you should always respond the same way to a given signal. Adding unusual conditions makes it harder to understand and test application behavior.
Adding an rc script that handles shutdown (by sending a special signal) is a completely standard way to handle such a problem; if this script is installed as part of a standard package (make install or rpm/deb packaging) there should be no worries about control of user machines.
I think I got it.
Source =
https://github.com/mozilla-b2g/busybox/blob/master/miscutils/runlevel.c
I copy part of the code here, just in case the reference disappears.
#include "libbb.h"
...
struct utmp *ut;
char prev;
if (argv[1]) utmpname(argv[1]);
setutent();
while ((ut = getutent()) != NULL) {
if (ut->ut_type == RUN_LVL) {
prev = ut->ut_pid / 256;
if (prev == 0) prev = 'N';
printf("Runlevel: prev=%c current=%c\n", prev, ut->ut_pid % 256);
endutent();
return 0;
}
}
puts("unknown");
see man systemctl, you can determine if the system is shutting down like this:
if [ "`systemctl is-system-running`" = "stopping" ]; then
# Do what you need
fi
this is in bash, but you can do it with 'system' in C
The practical answer to do what you originally wanted is that you check for the shutdown process (e.g ps aux | grep "shutdown -h" ) and then, if you want to be sure you check it's command line arguments and time it was started (e.g. "shutdown -h +240" started at 14:51 will shutdown at 18:51).
In the general case there is from the point of view of the entire system there is no way to do this. There are many different ways a "shutdown" can happen. For example someone can decide to pull the plug in order to hard stop a program that they now has bad/dangerous behaviour at shutdown time or a UPS could first send a SIGHUP and then simply fail. Since such a shutdown can happen suddenly and with no warning anywhere in a system there is no way to be sure that it's okay to keep running after a SIGHUP.
If a process receives SIGHUP you should basically assume that something nastier will follow soon. If you want to do something special and partially ignore SIGHUP then a) you need to coordinate that with whatever program will do the shutdown and b) you need to be ready that if some other system does the shutdown and kills you dead soon after a SIGHUP your software and data will survive. Write out any data you have and only continue writing to append-only files with safe atomic updates.
For your case I'm almost sure your current solution (treat all SIGHUPs as a shutdown) is the correct way to go. If you want to improve things, you should probably add a feature to the shutdown program which does a notify via DBUS or something similar.
When the system shuts down, the rc.d scripts are called.
Maybe you can add a script there that sends some special signal to your program.
However, I doubt you can stop the system shutdown that way.