OSX: Why does exit work when written manually in the terminal, but not with a shell script I run from the terminal? - macos

This bash script in osx does not exit the script. I have changed the settings (as suggested here so that writing exit in terminal closes the window, and I've checked that writing exit does close the terminal window if I write it in the terminal, What could be the reason for this? I restarted terminal and my mac after changing the settings to see if that solved the problem. But exit in at location(s) nr 1 or at the end of the script does not work.
#!/bin/bash
PATH=/opt/local/bin:/opt/local/sbin:$PATH
read -p "What do you want to do?"
if test "$pass" = "f"
then
sh ~/f.sh
exit # nr 1
fi
if test "$pass" = "s"
then
sh ~/s.sh
exit # nr 1
fi
exit # nr 2

Assuming you mean that when you do:
$ exit
your terminal exits.
But when you run
$ ./script.sh
your terminal doesn't exit.
The answer is that your script is being run in its own shell process and so when it exits it isn't exiting from the shell that is running in the terminal.
If you use
$ . script.sh
then you will run the script in the current shell process so exit will exit the running shell and cause the terminal to exit.

Related

bash function - determine if running as a script or tty

Say I have a bash function:
run_stuff(){
if is_in_script; then
exit 1
fi
return 1;
}
basically, if I am running it in a script:
$ ./my-script.sh
then I want to exit with 1, but if I am running it directly in the terminal:
$ run_stuff
then I want to return 1 (o/w my terminal window will close)
what is the best way to check this cross-platform?
You can use $0.
echo $0 when run in my (bash) terminal returns -bash.
echo $0 in a script with no #! run with bash test.sh returns test.sh
echo $0 in a script with #!/bin/bash run as ./test.sh returns ./test.sh
It's not bullet proof, but you can check whether the current shell is interactive:
is_in_script() {
[[ $- == *i* ]]
}
However, I would just make run_stuff always return, and if a script should exit when the command reports failure, it can do run_stuff || exit rather than leaving this behavior up to the function itself.

trap exec return code in shell script

I have to run a command using exec in a shell script, and I need to trap the exit code in case of error and run another command e.g
#!/bin/sh
set +e
exec command_that_will_fail
if [ $? -eq 1 ]; then
echo "command failed, running another command"
fi
I understand that exec replaces the current shell and carries on, my problem is that I need to run another command if the exec is not sucessfull.
Your code works if there's some immediate error when it tries to run the process:
$ echo 1
1
$ echo $?
0
$ exec asd123
-bash: exec: asd123: not found
$ echo $?
127
If the executable file was found, and is started, then it will not return, because it will overtake the whole script and never return to bash again.
For example this never returns:
$ exec grep asd /dev/null
(the exit code of grep is 1, but the parent shell is overtaken, so nobody can check)
If you want to get an exit code from the process in this case, you have to start it as a subprocess, i.e. not using exec (just command_that_will_fail). In this case the bash process will act as a supervisor that waits until the subprocess finishes and can inspect the exit code.

Exit not getting executed in the script

date
ls
exit
On executing this script, the commands date and ls are executed but the terminal doesn't close. Why?
The script will exit only the shell it's running in. When you do ./abc then parent shell forks and execs a subshell in which ./abc is run.
Just to be bit more obvious about subshell exit, consider the following example:
#!/bin/bash
echo hi
(exit)
echo hello
prints both hi and hello. The exit happens in the subshell. So, the script won't exit and hence the last echo hello gets executed.
To see that the script itself exits, try
#!/bin/bash
echo hi
exit
echo hello
Running this script will output just "hi"; the exit command terminates the script (but not the shell running in your terminal) before it reaches echo hello.

Run two shell commands

What would be the correct format for the following, where I want to execute two scripts? The following is only executing the first one for me:
if ps aux | grep -E "[a]ffiliate_download.py|[g]oogle_download.py" > /dev/null
then
echo "Script is already running. Skipping"
else
exec "$DIR/affiliate_download.py"
exec "$DIR/google_download.py"
fi
The exec command replaces the current shell process with the program it runs. Since the shell is no longer running, it can't run commands after that.
Just execute the commands normally:
else
"$DIR/affiliate_download.py"
"$DIR/google_download.py"
fi

Check if a nohup script is running or start it

we are running a tool on different machine by calling the shell script to run it,
the script is in background by using "nohup scriptname ", for some reasons which i don't know the script stops after some time, i want to make a script to keep on checking if the script is stopped and runs it again.
I have very little knowledge on shell script, but suddenly this requirement came and i searched on google but not getting proper answer, please help.
Here is a simple and working solution.
First, the script which has to be run again, let's call it bar.sh:
#! /bin/bash
echo "bar is living"
sleep 5
echo "bar is dying"
exit
Second, the script which runs bar.sh and watches for his death, called foo.sh:
#! /bin/bash
while true ; do
echo "Running bar ..."
./bar.sh &
echo "Waiting bar's termination"
wait
done
Now just type in the terminal:
$ chmod +x foo.sh bar.sh
$ ./foo.sh

Resources