How would I create a simple shell script that doesn't do anything, just runs forever, without overloading the CPU. I am using an appify script to make it into an app, so that I can have an app that just runs forever. The reason I do this is so that I can always have an app running and therefore quit out of finder without it opening back up again.
Note: to allow quitting out of finder, run the command defaults write com.apple.finder QuitMenuItem -bool yes in terminal.
Ideally, you could create a job that would sleep forever and just wait on it:
sleep forever &
wait
but in reality you have to pick a finite amount of time to sleep.
while :; do
sleep 65535 &
wait
done
This will only use minimal CPU every 18 hours or so to restart the sleep process. There is probably an upper limit to the size of the argument you can give to sleep, but I don't know what that is (and it is probably implementation-dependent). You can experiment; a larger number will reduce total CPU usage over the life of the program, but even calling sleep once an hour (every 3600 seconds) will use very little CPU.
Related
I know that you can use the time.Sleep(d Duration) function to let the Go program wait for a certain duration. Now I have the use-case that I want to keep the point in time even when the whole OS goes to sleep.
So as an example: When I sleep the go program at 1pm for two hours. And I turn off my computer on 2pm for half an hour until 2:30pm. I still want the code to resume at 3pm and not at 3:30pm.
(Of course when I sleep my OS longer than 3pm the code should resume immediately).
How should I do that with go? Is there a nice function or library for that or should I use cron as a workaround?
Quite simply I have a shell script with some long-running operations that I run in the background and then wait for in a loop (so I can check if they're taking too long, report progress etc.).
However one case that I'd also like to check for is when the system has been put to sleep manually (I've already taken steps to ensure it shouldn't auto-sleep while my script is running).
Currently I do this in a fairly horrible way, namely my script runs sleep in a loop for a few seconds at a time, checking each time if the task is still running. To detect sleep I check if the time elapsed was longer than expected, like so:
start=$(date +%s)
while sleep 5; do
if [ $(($(date +%s) - $start)) -gt 6 ]; then
echo 'System may have been asleep'
start=$(date +%s)
elif kill -0 $PID; then
echo 'Task is still running'
start=$(date +%s)
else
echo 'Task is complete'
break
fi
done
The above is very much simplified so please forgive any mistakes, it's just to give the basic idea; for example, on platforms where the wait command supports timeouts I already use that in place of sleep.
Now, while this mostly works, it's not especially pretty and it's not really detecting sleep, but guessing whether the system might have slept; for example, it can't differentiate cases where a system hangs long enough to confound the check, making the check time longer will help with this, but it's still guesswork.
On macOS I can more reliably check for sleep using pmset -g uuid which returns a new UUID if the system went to sleep. What I would like to know is, are there any alternatives for other platforms?
In essence all I need is a way to find out if the system has been asleep since the last time I checked, though if there's a way to receive a signal or such instead then that may be even better.
While I'm looking to hear of the best options available on various platforms, I crucially need a shell agnostic option as well that I can use as a reliable fallback, as I'd still like the shell script to be as portable as possible.
I want to do a task every 5 mins. I want to control when i can start and when i can end.
One way is to use sleep in a while true loop, another way is to use cronjob. Which one is preferred performance-wise?
Thanks!
cron is almost always the best solution.
If you try to do it yourself with a simple script running in a while loop:
while true; do
task
sleep 300
done
you eventually find that nothing is happening because your task failed due to a transient error. Or the system rebooted. Or some such. Making your script robust enough to deal with all these eventualities is hard work, and unnecessary. That's what cron is for, after all.
Also, if the task takes some non-trivial amount of time, the above simple-minded while loop will slowly shift out of sync with the clock. That could be fixed:
while true; do
task
sleep $((300 - $(date +%s) % 300))
done
Again, it's hardly worth it since cron will do that for you, too. However, cron will not save you from starting the task before the previous invocation finished, if the previous invocation got stuck somehow. So it's not a completely free ride, but it still provides you with some additional robustness.
A simple approach to solving the stuck-task problem is to use the flock utility. For example, you could cron a script containing the following:
(
flock -n 8 || {
logger -p user.warning Task is taking too long
# You might want to kill the stuck task here. See pkill
exit 1
}
# Do the task here
) 8> /tmp/my_task.lck
Use a cron job. Cron is made for this type of use case. It frees you of having to to code the while loop yourself.
However, cron may be unsuitable if the run time of the script is unpredictable and exceeds the timer schedule.
Performance-wise It is hard to tell unless you share what the script does and how often it does it. But generally speaking, neither option should have a negative impact on performance.
This is a simple question. If I use the read command in bash script, while the script is waiting for the input command, what really happens, is the memory consumption reduced to a sleep state, like if we use the sleep command?
The memory consumption is not affected at all, the thing that happens in both cases is that the shell process changes its state from runnable to suspended.
In the case of read, the shell process goes in kernel space to read the user input, and is later rescheduled whenever data is available.
sleep voluntarily yields to kernel space where the process is suspended, and it is rescheduled after the timeout has passed.
how can i control two processes to run alternately in separate terminal windows.
for example i run the code for each on separate terminal windows at 11:59 and both of them wait for the time to be 12:00. at this moment process one starts execution and process two waits for say 10 seconds. then they switch, process two executes and process one waits.
in this way they take turns until the process is complete.
Pipes, or named pipes? Each process waits in a read for the other to write a byte to it.
Also, possibly use signal files. Process B sleeps for 100 ms, checks for file Foo, and repeats. When process A creates the file, process B deletes it, and proceeds. Then the reverse happens with file Bar.
You can use System V semaphores or Windows named mutexes (via CreateMutex). You could even resort to file locks. Which OS are you on and what are your restrictions?