I have this kind of batch file
start /b ruby script.rb && echo done
...
However, it write 'done' immediately after i run the batch file, which is incorrect, as the script took about 5 mins.
So, how to echo done only after the bg task succesfully end?
thank you!
note: I think that && operator work this way if it is not used in batch file nor in usage to run bg task.
start "" /b cmd /c "ruby script.rb && echo done"
Without the quotes the conditional execution command is seen as the continuation of the start command instead of continuation of the ruby command.
As the && is an operator handled by cmd we need to start a new instance.
The "" at the start are needed as the first quoted argument to start is handled as a window title.
note: && is an conditional execution operator. If the previous command does not generate an error then the following command is executed. In this case with the process running in background, probably, &, the command concatenation operator, should be used to know that the script ended.
Related
I have some Batch scripts I use for automating application build processes, most of which involve chaining commands together using the && operator. Admittedly, I'm more experienced with Linux, but based on that experience some_command && other_command should result in other_command being run iff some_command returns an exit code of 0. This answer and this answer seem to agree with that. However this appears not to be the case on Windows cmd.exe, all of the scripts run regardless of the error code of the previous.
I decided to make a simple test for this to convince myself I wasn't going insane. Consider this test.bat, which returns an exit code of 1:
#echo off
EXIT /B 1
Running test.bat && echo This shouldn't print prints 'This shouldn't print'. But since the exit code is clearly 1, echo should not be called. I've tested that the error code was actually 1 using the %errorlevel% variable, they're coming out as expected (0 before I run the script, 1 after).
On Linux I tried the same thing. Here's test.sh:
#!/bin/bash
exit 1
Running ./test.sh && echo "This shouldn't print" gives no output, exactly what I expected.
What's going on here?
(Note: OS is Windows 7 Enterprise)
You need to use call to run the batch script, like this:
call test.bat && echo This shouldn't print
Without call, the && operator does not receive the ErrorLevel returned by the batch script.
When you run a batch file from within another one, you need to use call in order to return to the calling batch file; without call, execution terminates as soon as the called batch file has finished...:
call test.bat
echo This is going to be displayed.
...but:
test.bat
echo You will never see this!
When running test.bat is involved in a command line where multiple commands are combined (using the concatenation operator &, the conditional ones && and ||, or even a block of code within parentheses ()), all the commands following test.bat are ecexuted even if call was not used. This is because the entire command line/block has already been parsed by the command interpreter.
However, when call is used, the ErrorLevel value returned by the batch file is received (which is 1 in our situation) and the following commands behave accordingly:
call test.bat & echo This is always printed.
echo And this is also always printed.
call test.bat && echo This is not printed.
call test.bat || echo But this is printed.
(
call test.bat
echo This is printed too.
echo And again this also.
)
call test.bat & if ErrorLevel 1 echo This is printed.
But without call you will get this...:
test.bat & echo This is printed.
echo But this is not!
...and...:
test.bat && echo Even this is printed!
echo Neither is this!
...and...:
test.bat || echo But this is not printed!
echo And this is not either!
...and:
(
call test.bat
echo This is printed.
echo And this as well.
)
It seems that the && and || operators receive an ErrorLevel of 0 -- even in case ErrorLevel has already been set before test.bat is executed, strangely. Also when if ErrorLevel is used, the behaviour is similar:
test.bat & if ErrorLevel 1 echo This is not printed!
...and...:
set = & rem This constitutes a syntax error.
test.bat & if ErrorLevel 1 echo This is still not printed!
Note that the commands behind test.bat execute after the batch script, even without call.
basically I have written a shell script for a homework assignment that works fine however I am having issues with exiting. Essentially the script reads numbers from the user until it reads a negative number and then does some output. I have the script set to exit and output an error code when it receives anything but a number and that's where the issue is.
The code is as follows:
if test $number -eq $number >dev/null 2>&1
then
"do stuff"
else
echo "There was an error"
exit
The problem is that we have to turn in our programs as text files using script and whenever I try to script my program and test the error cases it exits out of script as well. Is there a better way to do this?
The script is being run with the following command in the terminal
script "insert name of program here"
Thanks
If the program you're testing is invoked as a subprocess, then any exit command will only exit the command itself. The fact that you're seeing contrary behavior means you must be invoking it differently.
When invoking your script from the parent testing program, use:
# this runs "yourscript" as its own, external process.
./yourscript
...to invoke it as a subprocess, not
# this is POSIX-compliant syntax to run the commands in "yourscript" in the current shell.
. yourscript
...or...
# this is bash-extended syntax to run the commands in "yourscript" in the current shell.
source yourscript
...as either of the latter will run all the commands -- including exit -- inside your current shell, modifying its state or, in the case of exit, exec or similar, telling it to cease execution.
I have a bash script start.sh which calls another run.sh, which takes me to another prompt where I have to delete a file file.txt and then exit out of that prompt.
When I call run.sh from inside start.sh, I see the prompt and I believe that it deletes the file.txt but the inner/new prompt waits for me to exit out of it while the script is running - meaning it needs intervention to proceed. How do I avoid it in bash?
In Python I can use Popen and get it going but not sure about bash.
EDIT: I would rather like to know what command to provide to exit out of the shell (generated from running run.sh") so I can go back to the prompt where "start.sh" was started.
Etan: To answer your question
VirtualBox:~/Desktop/ > ./start
company#4d6z74d:~$ ->this is the new shell
company#4d6z74d:~$ logout ---> I did a "Control D here" so the script could continue.
Relevant part of start.sh which:
/../../../../run.sh (this is the one that takes us to the new $ prompt)
echo "Delete file.txt "
rm -f abc/def/file.txt
You can run run.sh in the background using &. In start.sh, you would invoke the script via /path/run.sh &. Now, start.sh will exit without waiting for run.sh to finish (which is running in the background).
I am new to shelll script and my question here might be very basic.
I have a script(.sh file) which is making call to couple of scipt files. now suppose, I am getting error message on execution of script 1, I would like to abort the script and completely terminate the script flow. It should not go on next step.
could you please tell me how i can achieve this.
EDIT
My scriptA is making call to Script B, which internally making call to some other scriptC.
if execution of StopServer1.py script(part of script B) failed, flow should terminate here itself and should not come to StopServer2 and StopServer3 and control goes to Script A. which should also terminate .
please let me know if set -e will help here.
cd /usr/oracle/WSAutomate/
java weblogic.WLST /usr/oracle/StopServer1.py >> $logFileName
java weblogic.WLST /usr/oracle/StopServer2.py >> $logFileName
java weblogic.WLST /usr/oracle/StopServer3.py >> $logFileName
You can use:
set -e
for aborting the script on error.
main script snippet:
#!/bin/bash
set -e
# Any failure in these script calls will make main script to exit immediately
./script1
./script2
./script3
You can use the operator && this way <execute_script1> && <execute_script2>.
It executes script1 and, only if everything goes right, it executes script2. In case of error script2 will not run.
I'm writing a shell script with #!/bin/sh as the first line so that the script exits on the first error. There are a few lines in the file that are in the form of command || true so that the script doesn't exit right there if the command fails. However, I still want to know know the exit code of the command. How would I get the exit code without having to use set +e to temporarily disable that behavior?
Your question appears to imply set -e.
Assuming set -e:
Instead of command || true you can use command || exitCode=$?. The script will continue and the exit status of command is captured in exitCode.
$? is an internal variable that keeps the exit code of the last command.
Since || short-circuits if command succeeds, set exitCode=0 between tests or instead use: command && exitCode=0 || exitCode=$?.
But prefer to avoid set -e style scripting altogether, and instead add explicit error handling to each command in your script.
If you want to know the status of the command, then presumably you take different actions depending on its value. In which case your code should look something like:
if command; then
# do something when command succeeds
else
# do something when command fails
fi
In that case you don't need to do anything special, since the shell will not abort when command fails.
The only reasons set -e would give you any problems is if you write your code as:
command
if test $? = 1; ...
So don't do that.