Make tcsh wait until specific background job ends + alert me - wait

What "nonblocking" command makes tcsh wait until a specific background
task completes and then "alerts" me by running a command of my choosing?
I want "wait %3 && xmessage job completed &" to wait until background
job [3] is finished and then xmessage me "job completed", but want
this command itself to return immediately, not "block" the terminal.
Obviously, my syntax above doesn't work. What does?
I've written a Perl program that can do this, but surely tcsh can do
it natively?

You may be able to do something like (untested):
while (! $?)
kill -s 0 $!
sleep 1
end
Or take a look at the notify command. I'm not sure if it would do what you want.

Related

Parallelize a bash script and wait for each loop to finish

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

Sequentially Run Programs in Unix

I have several programs that need to be ran in a certain order (p1 then p2 then p3 then p4).
Normally I would simply make a simple script or type p1 && p2 && p3 && p4.
However, these programs to not exit correctly. I only know it is finished successfully when "Success" is printed. Currently, I SIGINT once I see "Success" or "Fail" and then manually run the next program if it's "Success".
Is there a simpler way to sequentially execute p1, p2, p3, p4 with less human intervention?
Edit: Currently using ksh, but I wouldn't mind knowing the other ones too.
In bash, you can pipe the command to grep looking for 'Success', then rely on grep's result code. The trick to that is wrapping the whole expression in curly braces to get an inline sub-shell. Like so:
$ cat foo.sh
#!/bin/bash
[ 0 -eq $(( $RANDOM %2 )) ] && echo 'Success' || echo 'Failure'
exit 0
$ { ./foo.sh | grep -q 'Success'; } && ls || df
The part inside the curly braces ({}) returns 0 if "Success" is in the output, otherwise 1, as if the foo.sh command had done so itself. More details on that technique.
I've not used ksh in a long while, but I suspect there is a similar construction.
I'm also new to linux programming, but I found something that might be helpful for you. Have you tried using the 'wait' command?
from this answer on stackexchange:
sleep 1 &
PID1=$!
sleep 2 &
PID2=$!
wait $PID1
echo PID1 has ended.
wait
echo All background processes have exited.
I haven't tested it myself, but it looks like what you described in your question.
all the answers so far would work fine if your programs would actually terminate.
here is a couple ideas you can use look through documentation for more details.
1st - option would be to modify your programs to have them terminate after printing the result message by returning a success code.
2nd - if not possible use forks.
write a main where you make a fork each time you want to execute a program.
in the child process use dup2 to have the process' output in a file of your choice.
in the main keep checking the content of said file until you get something and compare it with either success or failure.
-empty the file.
then you can make another fork and execute the next program.
repeat the same operation again.
bear in mind that execute is a command that replaces the code of the process it is executed in with the code of the file passed as a parameter so make the dup2 call first.
When your program returns Success or Fail and continues running, you should kill it as soon as the string passes.
Make a function like
function startp {
prog=$1
./${prog} | while read -r line; do
case "${line}" in
"Success")
echo OK
mykill $prog
exit 0
;;
"Fail")
echo NOK
mykill $prog
exit 1
;;
*) echo "${line}"
;;
esac
done
exit 2
}
You need to add a mykill function that looks for the px program and kills it (xargs is nice for it).
Call the function like
startp p1 && startp p2 && startp p3

while using script in unix how can I get the bell to chime more than once

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'

Kill fbi frame buffer process, after x time

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

Constantly updated clock in zsh prompt?

I know that I can exec a date command in my zsh prompt.
However, it shows the old time; to see the current time, I have to hit <return> and get a new prompt with the current time.
Is there a way to configure the zsh prompt to constantly update itself every second?
Note: I wrote this answer for a similar question, but seeing how this question has more views I think reposting my answer here would be useful.
This is in fact possible without resorting to strange hacks. I've got this in my .zshrc
RPROMPT='[%D{%L:%M:%S %p}]'
TMOUT=1
TRAPALRM() {
zle reset-prompt
}
The TRAPALRM function gets called every TMOUT seconds (in this case 1), and here it performs a prompt refresh, and does so until a command starts execution (and it doesn't interfere with anything you type on the prompt before hitting enter).
Source: http://www.zsh.org/mla/users/2007/msg00944.html (It's from 2007!)
Sounds like a pleasant request to me. If anything it makes more sense than showing the time when the prompt was displayed.
Fortunately Peter Stephenson posted a technique. Try something like this in .zshrc:
PROMPT="[%T] %n#%M %~ %# "
schedprompt() {
emulate -L zsh
zmodload -i zsh/sched
# Remove existing event, so that multiple calls to
# "schedprompt" work OK. (You could put one in precmd to push
# the timer 30 seconds into the future, for example.)
integer i=${"${(#)zsh_scheduled_events#*:*:}"[(I)schedprompt]}
(( i )) && sched -$i
# Test that zle is running before calling the widget (recommended
# to avoid error messages).
# Otherwise it updates on entry to zle, so there's no loss.
zle && zle reset-prompt
# This ensures we're not too far off the start of the minute
sched +30 schedprompt
}
schedprompt
This would be .... unpleasant in a standard zsh prompt (or bash, or other shells).
I suggest you'd be better off using Gnu Screen.
Screen can have a status line which can show the time.
Here's an example screenrc scroll down to "Red Hat Magazine A guide to GNU Screen" to see the sample (i'll reproduce that here) which will, when screen is run, show the current time in the lower right corner of the terminal:
~/.screenrc
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{=kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B}%Y-%m-%d %{W}%c %{g}]'
# Default screens
screen -t shell1 0
screen -t shell2 1
http://www.gnu.org/software/screen/

Resources