Exit not getting executed in the script - bash

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.

Related

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.

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

Displaying output of subshell in parent process

echo "echo in parent process"
bash
echo "echo in subshell"
exit
When I execute this code block form terminal (./test.sh)
I only see "echo in parent process" as output, but I also want to see the output that coming from subshell. What is the way to see the outputs that coming from subshell/child process.
You never see the second command because it hasn't happened yet. Instead, you're just starting bash again, interactively. You'll note you're inside an inner shell now if you type exit manually.
$ ./test.sh
echo in parent process
$ exit
echo in subshell
What you probably mean to do is:
#!/bin/bash
echo "echo in parent process"
bash -c 'echo "echo in child process"'

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

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.

Entering cshell from bash

I have a bash script and need to run some commands in cshell inside it.
#!/bin/bash
echo entering_to_cshell
csh
echo in_cshell
exit
echo exited_from_cshell
Why doesn't this script run as expected? It only prints entering_to_cshell and it doesn't exit from cshell.
By using
csh
you start a new subshell where your script isn't executed. That's why none of your following commands are executed. Your script waits for this subshell to end which, as you noted, never happens.
Try
csh -c "echo in_cshell"
This way you don't create a new subshell which isn't impacted by your script.
By simply calling csh in your script, you're starting an interactive csh subshell. You'll notice that once you quit from the csh session, your script will then continue to with the subsequent echo and quiting on exit.
To pass a series of commands to csh from you bash script, one approach would be to use the Here Document syntax to redirect commands to csh.
#!/bin/bash
echo entering_to_cshell
csh <<EOF
echo in_cshell
exit
EOF
echo exited_from_cshell
The lines between the EOF entries will be treated as a script that is interpreted by csh.

Resources