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)
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 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
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
I have a C++ program which I need to run it multiple times.
For example:-
Run ./addTwoNumbers 50 times.
What would be a good approach to solve this problem?
In POSIX shells,
for i in {1..50} ; do ./addTwoNumbers ; done
If this is code you are writing, take the number of times you want to "run" as an argument:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
int numTimes = 1;
if (argc > 1)
{
numtimes = atoi(argv[1]);
}
for (int i = 0; i < numTimes; i++)
{
// Your code goes here
}
}
(Note this doesn't do any sanity checking on the input, but it should point you in the right direction)
The way you were asking the question indicated that you had a finished binary. You want to run it as if it was from the command line. The forward slash, to me, is a clue that you are a Unix like operating system user. Well, that, and the fact that this post is tagged "Unix", which I just saw after writing the below. It should all be applicable.
The scheme of using the shell is probably the simplest one.
man bash tells you how to write a shell script. Actually we need to figure out what shell you are using. From the command line, type:
echo $SHELL
The response I get is
/bin/bash
Meaning that I am running bash. Whatever you get, copy down, you will need it later.
The absolutely lowest knowledge base is to simply create a file with any standard text editor and no suffix. Call it, simply (for example) run50.
The first line is a special line that tells the unix system to use bash to run the command:
#! /bin/bash
(or whatever you got from echo $SHELL).
Now, in the file, on the next line, type the complete path, from root, to the executable.
Type the command just as if you were typing it on the command line. You may put any arguments to your program there as well. Save your file.
Do you want to run the program, and wait for it to finish, then start the next copy? Or do you want to start it 50 times as fast as you can without waiting for it to finish? If the former, you are done, if the latter, end the line with &
That tells the shell to start the program and to go on.
Now duplicate that line 50 times. Copy and paste, it is there twice, select all, and then paste at the end, for 4 times, again for 8, again for 16, and again for 32. Now copy 18 more lines and paste those at the end and you are done. If you happen to copy the line that says #! /bin/bash don't worry about it, it is a comment to the shell.
Save the file.
From the command line, enter the following command:
chmod +x ./filenameofmyshellcommand
Where you will replace filenameofmyshellcommand with the name of the file you just created.
Finally run the command:
./filenameofmyshellcommand
And it should run the program 15 times.
If you are using bash, instead of duplicating the line 50 times, you can write a loop:
for ((i=1;i<=50;i++)) do
echo "Invocation $i"
/complete/path/to/your/command
done
I have included a message that tells you which run the command is on. If you are timing the program I would not recommend a "feelgood" message like this. You can end the line with & if you want the command to be started and the script to continue.
The double parenthesis are required for this syntax, and you have to pay your syntax.
for ((i=1;i<=50;i++)) do echo "invocation $i" & done
is an interesting thing to just enter from the command line, for fun. It will start the 50 echos disconnected from the command line, and they often come out in a different order than 1 to 50.
In Unix, there is a system() library call that will invoke a command more or less as if from the terminal. You can use that call from C++ or from perl or about a zillion other programs. But this is the simplest thing you can do, and you can time your program this way. It is the common approach in Unix for running one program or a sequence of programs, or for doing common tasks by running a series of system tools.
If youy are going to use Unix, you should know how to write a simple shell script.
int count=0;
int main()
{
beginning:
//do whatever you need to do;
int count++;
if (count<=50);
{
goto beginning;
}
return 0;
}
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/