I have a problem with a sh script.
I am using a raspberry, and want in my script to display with fbi frame buffer an image for 10 seconds. After these 10 seconds I want my script to run other sequential commands.
I wrote:
[...]
if[...]
fbi --noverbose $MEDIAFILE
MYPID=pgrep fbi
echo "[$MYPID] this is MY PID - and now i kill it!!!"
[...]
but my script stops itself in the first line (fbi --noverbose...) and I can't kill it in the next line :(.
I can't execute the command in background because I need to see the image...
any idea? thank you!
If your goal is to not show anymore after a certain amount of seconds, you can also add the command line options "-t secs" and "-1". "-t secs" is used for slideshows and is the time after which the next image is shown and "-1" means that the slideshow wont loop.
In your case:
fbi --noverbose -t 10 -1 $MEDIAFILE
This shows the image for ten seconds and then the fbi command finishes. No need to kill the process.
If fbi can't be run in the background, put your kill command in the background. To make it happen after a delay, use a subshell that sleeps first, then runs the kill command. The script would look something like this:
( sleep 10 ; kill $(pgrep fbi) ) &
fbi somefile
Related
I'm trying to write a script, that we call pippo.R. pippo.R aim, is to run another script (for.sh) in a for loop with a parallelization using two values :
nPerm= total number of times the script has to be run
permAtTime= number of script that can run at the same time.
A very important thing to do, is to wait for each loop to be concluded, thats why I added a file in which all the PID are stored and then I use the wait function to wait for each of them. The main problem of this script is the following error :
./wait.sh: line 2: wait: pid 836844 is not a child of this shell
For reproducibility sake you can put in a folder the following files :
pippo.R
nPerm=10
permAtTime=2
cycles=nPerm/permAtTime
for(i in 1:cycles){
d=1
system(paste("./for.sh ", i," ",permAtTime,sep=""))
}
for.sh
#!/bin/bash
for X in $(seq $1)
do
nohup ./script.sh $(($X +($2 -1)*$1 )) &
echo $! >> ./save_pid.txt
done
./wait.sh
wait.sh
#!/bin/bash
while read p; do wait $p; done < ./save_pid.txt
Running Rscript pippo.R you will have the explained error. I know that there is the parallel function that can help me in this but for several reasons i cannot use that package.
Thanks
You don't need to keep track of PIDs, because if you call wait without any argument, the script will wait for all the child processes to finish.
#!/bin/bash
for X in $(seq $1)
do
nohup ./script.sh $(($X +($2 -1)*$1 )) &
done
wait
I'm trying to come up with a unix pipeline of commands that will allow me to log only the most recent n lines of a program's output to a text file.
The text file should never be more than n lines long. (it may be less when it is first filling the file)
It will be run on a device with limited memory/resources, so keeping the filesize small is a priority.
I've tried stuff like this (n=500):
program_spitting_out_text > output.txt
cat output.txt | tail -500 > recent_output.txt
rm output.txt
or
program_spitting_out_text | tee output.txt | tail -500 > recent_output.txt
Obviously neither works for my purposes...
Anyone have a good way to do this in a one-liner? Or will I have to write a script/utility?
Note: I don't want anything to do with dmesg and must use standard BSD unix commands. The "program_spitting_out_text" prints out about 60 lines/second, every second.
Thanks in advance!
If program_spitting_out_text runs continuously and keeps it's file open, there's not a lot you can do.
Even deleting the file won't help since it will still continue to write to the now "hidden" file (data still exists but there is no directory entry for it) until it closes it, at which point it will be really removed.
If it closes and reopens the log file periodically (every line or every ten seconds or whatever), then you have a relatively easy option.
Simply monitor the file until it reaches a certain size, then roll the file over, something like:
while true; do
sleep 5
lines=$(wc -l <file.log)
if [[ $lines -ge 5000 ]]; then
rm -f file2.log
mv file.log file2.log
touch file.log
fi
done
This script will check the file every five seconds and, if it's 5000 lines or more, will move it to a backup file. The program writing to it will continue to write to that backup file (since it has the open handle to it) until it closes it, then it will re-open the new file.
This means you will always have (roughly) between five and ten thousand lines in the log file set, and you can search them with commands that combine the two:
grep ERROR file2.log file.log
Another possibility is if you can restart the program periodically without affecting its function. By way of example, a program which looks for the existence of a file once a second and reports on that, can probably be restarted without a problem. One calculating PI to a hundred billion significant digits will probably not be restartable without impact.
If it is restartable, then you can basically do the same trick as above. When the log file reaches a certain size, kill of the current program (which you will have started as a background task from your script), do whatever magic you need to in rolling over the log files, then restart the program.
For example, consider the following (restartable) program prog.sh which just continuously outputs the current date and time:
#!/usr/bin/bash
while true; do
date
done
Then, the following script will be responsible for starting and stopping the other script as needed, by checking the log file every five seconds to see if it has exceeded its limits:
#!/usr/bin/bash
exe=./prog.sh
log1=prog.log
maxsz=500
pid=-1
touch ${log1}
log2=${log1}-prev
while true; do
if [[ ${pid} -eq -1 ]]; then
lines=${maxsz}
else
lines=$(wc -l <${log1})
fi
if [[ ${lines} -ge ${maxsz} ]]; then
if [[ $pid -ge 0 ]]; then
kill $pid >/dev/null 2>&1
fi
sleep 1
rm -f ${log2}
mv ${log1} ${log2}
touch ${log1}
${exe} >> ${log1} &
pid=$!
fi
sleep 5
done
And this output (from an every-second wc -l on the two log files) shows what happens at the time of switchover, noting that it's approximate only, due to the delays involved in switching:
474 prog.log 0 prog.log-prev
496 prog.log 0 prog.log-prev
518 prog.log 0 prog.log-prev
539 prog.log 0 prog.log-prev
542 prog.log 0 prog.log-prev
21 prog.log 542 prog.log-prev
Now keep in mind that's a sample script. It's relatively intelligent but probably needs some error handling so that it doesn't leave the executable running if you shut down the monitor.
And, finally, if none of that suffices, there's nothing stopping you from writing your own filter program which takes standard input and continuously outputs that to a real ring buffer file.
Then you would simply do:
program_spitting_out_text | ringbuffer 4096 last4k.log
That program could be a true ring buffer in that it treats the 4k file as a circular character buffer but, of course, you'll need a special marker in the file to indicate the write-point, along with a program that can turn it back into a real stream.
Or, it could do much the same as the scripts above, rewriting the file so that it's always below the size desired.
Since apparently this basic feature (circular file) does not exist on GNU/Linux, and because I needed it to track logs on my Raspberry Pi with limited storage, I just wrote the code as suggest above!
Behold: circFS
Unlike other tools quoted on this post and other similar, the maximum size is arbitrary and only limited by the actual available storage.
It does not rotate with several files, all is kept in the single file, which is rewritten on "release".
You can have as many log files as needed in the virtual directory.
It is a single C file (~600 lines including comments), and it builds with a single compile line after having installed fuse development dependencies.
This first version is very basic (see the README), if you want to improve it with some of the TODOs (see the TODO) be welcome to submit pull requests.
As a joke, this is my first "write only" fuse driver! :-)
I am writing a shell script and need the bell to chime several times. Is there a command variation or argument to make this happen ?
I have used the \a and the \007 and I get one chime. I can't seem to find how to make it happen more than once.
run your beep command once, wait a second with sleep and run it again
for instance
echo -n $'\a' ; sleep 1; echo -n $'\a'
I have a long running process (written in Java) that I wish to run asynchronously with system(..., wait=FALSE). In order to be able to determine when the process has ended i want to create a file afterwards as per the suggestions given in How to determine when a process started with system(..., wait=FALSE) has ended. The problem is that it seems the wait parameter only applies to the last line in a multiline system command, and I can't seem to find a way around that.
Example:
system('sleep 2') # waits 2 seconds before control is returned to the user
system('sleep 2', wait=FALSE) # control is returned immediately
system('sleep 2; ls', wait=FALSE) # waits 2 seconds before control is returned to the user
I'm running on a mac system btw...
I find strange that R's system only waits for the first command (it should be calling the shell, which then waits for both commands) but using && should do it:
system('sleep 2 && ls', wait=FALSE)
If R is appending a & to the command line, it becomes sleep 2; ls & and there the & affects only the second parameter.
Another solution would be to put brackets around the commands, ( sleep 2 ; ls ) & will perform both actions sequentially:
system('( sleep 2 ; ls )', wait=FALSE)
I am working on adding some nagios alerts to our system -- some of which will monitoring the rate of certain events hitting the nginx/apache logs (or parsing values from those logs.) The way I've approached the problem so far is with a simple shell script tail -f'ing the log for 25 seconds or so to a temporary file, killing the process, and then running awk, etc over the temp file. The goal here being to get a log "sample" over 25 seconds and then perform analysis.
This is less than ideal obviously because of the increase in disk IO due to these temp files -- what I really would like is an "enhanced" tail -f that would terminate the pipe cleanly after a certain number of seconds. Ie:
tail -f --interval '5 seconds' | grep "/serve"
Would tail the log for 5 seconds and show me all the lines that have "/serve".
I'd imagine I can whip up a ruby script to do this pretty quickly, but I wanted to make sure there wasn't a more unixy way to accomplish this. At a high level, is there a better way to be taking samples of a log from the last N seconds (and no, I'd rather not be parsing timestamps, etc.)
Found the solution. "apt-get install timeout" :)
Edit: Actually this kills tail, doesn't cause it to exit gracefully, so we lose the entire pipe. What I want to work is:
timeout -15 5 tail -f /mnt/log/nginx/nginx-access.log | grep '/javascripts' | wc -l
To tell me how many javascript files served in last 5 seconds, etc.
A slightly different approach:
(tail -f /var/log/messages & P=$! ; sleep 5; kill -9 $P) | grep /serve
I'm thinking that, as a Nagiios user myself, you do not want probe processes pausing for arbitrary amounts of time. That's going to, in the worst case, make Nagios check other things less often, or "clump" the checks.
What about a script that runs quickly (instantly) and parses the last few lines of the file, returning only interesting things with a timestamp later than a given time?
GNU's tail has a --pid flag that can be used for this (tail will exit once a process with that PID no longer exists). Just start up a sleep process in the background and tell tail to exit when it does. Like so:
sleep 5 & tail --pid=$! -f /var/log/system.log
tail will exit with a 0 exit code when time is out.