How to quit terminal after script exits? - bash

I wrote a simple script
#!/bin/bash
nohup $1 &
exit
what it is supposed to do is if I execute 'scriptName' gedit, it must open gedit and then close the terminal. But, problem is terminal is not closed after the script is executed.
Things taken care of:
Checked terminal preferences to When command exits: Exit the terminal
I want to put this script in /usr/local/bin so, I cannot use execution like . ./scriptname
It appears like terminal is not the parent of this. How do I change this?

The approach you're trying won't work for the following reason:
The shell for your terminal session is one process; normally when you execute a shell script, the terminal session shell starts a second shell process and runs the script under that. So your exit at the end of the script tells the second shell to terminate - which it would do anyway, as it's reached the end of the script. While you could try killing the first shell process from the second shell process (see comment about $PPID in the other answer), this wouldn't be very good form.
For your script to work the way you expect it to work, you'll need to get your terminal session shell to run the commands in your script by using bash's builtin source command - type source /path/to/your/script gedit, or . /path/to/your/script gedit for short.
Because of the way you'd need to execute this, putting the script on your PATH wouldn't help - but you could create an alias (a "shortcut" that expands to a series of shell commands) to make running the script easier - add a line like alias your_alias_name='. /path/to/your/script' to your ~/.bashrc.

Given below the sample script.
#!/bin/bash
echo "hi"
/bin/bash/abc.sh &
sleep 2
#sleep is used to pause the execution temporary to see the output.
kill -25 $PPID
Value that pass to kill command determines the behavior. Here you can find the different values.
Kill -25 worked for me to close the terminal and make sure to add "&" at the end of command. :)

I am presuming you are on a Mac - because you mention Preferences. The question is how did you start the script?
If you started the Terminal and then ran "scriptName" from the Terminal, the Terminal won't quit because it is still running your shell. Check the Preferences closely, it says "When the shell exits", not "When the command exits".

Related

.bashrc file is looping "script" command

I'm trying to set up a little shell script using the linux command "script" to log every input on my Kali Linux machine.
#!/bin/bash
now=$(date +"%m_%d_%Y_%H:%M:%S")
script /root/Logs/log_$now.txt
The script itself seems to work but i want to add it to the bash autostart, so whenever i open a terminal, my shellscript gets executed.
I tried adding it to my .bashrc file but when I open a terminal now, the script gets looped.
I added a simple "echo 'test'" script and it only starts once on terminal launch.
Adding the script to my .profile file and executing .profile manually works as intended, but as soon as i enter a script using the "script" command to my .bashrc, it gets looped.
Thank you in advance.
A new terminal window is one way of starting a new interactive shell, but so is running script. You only want to run script in the first case, not in every case.
script itself sets a variable in the environment to let you know if you are already in a shell started by script. Check for that variable before trying to run script again.
if [[ -z $SCRIPT ]]; then
now=$(date +"%m_%d_%Y_%H:%M:%S")
script /root/Logs/log_$now.txt
fi
The value of SCRIPT, if set, is the name of the file being logged to.
Alternatively, you can configure your terminal emulator to run script directly, rather than having it continue to open an ordinary interactive shell and you trying to alter its configuration.
The above applies to BSD script; for GNU script, you'll have to set such a variable yourself.
if [[ -z $SCRIPT ]]; then
now=$(date +"%m_%d_%Y_%H:%M:%S")
export SCRIPT=/root/Logs/log_$now.txt
script "$SCRIPT"
fi
The script(1) command opens a new interactive shell.
The file .bashrc runs on every interactive bash shell that is started, hence your infinite recursion.
If you want something to run only on the login shell, you put it into .bash_profile.
This should avoid the infinite recursion.

I want to incorporate 'exit' inside a shell script

I have a code that is running something from the shell script and after that run it ends up in this state as a root
root#(none):/testjob/test#
I want to exit this root state by running a command through the shell script to
arnavs#linux-machine:/testjob/test$
Manually you can just type in 'exit' command and it will exit back to the original shell but if I add exit inside the shell script it will exit the shell script itself and will stopping running the shell script.
Can you help me with a command that I could add it into my shell script ?
Script lefts you as root? How do you do that?
Anyway, try to use logout from inside the script.
However, not sure it will help at all, because I think you have some troubles with script and/or your system environment.
Can you tell, how do your script gets superuser in the first place?

call "exit" from within shell script

I'm trying to write a simple script (for an embedded system) that mounts an external file from the network and then calls exit on the command line (which exits the busybox terminal and boots the system from the newly-mounted root directory). Problem is, when I call exit from the shell script it exits the script, not the outer terminal. Any hints as to how to send the exit command outside the script?
My code looks something like this:
#!/bin/bash
mount /mnt/root 1.2.3.4:/path/to/external/files -o nolock
exit # exits the script, not the outside filesystem!
exit does indeed exit the current shell. However, running the script creates a new process, and it is that process that exits, not the shell from which you called the script.
You probably want to simply source the file:
$ source myScript.sh
Then myScript.sh is executed in the current shell, rather than a spawned process, and the exit will exit from your current shell (and therefore the terminal itself).
If you want that the scripts exits the outer terminal call it like this:
source your_script
or just
. your_script
where the . is the same as the source command. You can follow this article if you need more information.
Explanation: source will execute the script in the current shell and therefore the exit will be interpreted by the current shell - what will close the pseudo(!) terminal window, if the shell was the first shell in tree

new to bash scripting; trying to figure out why SOURCE command doesn't execute

I have made a really sincere effort to figure this out, and I just can't. This is my very simple bash script. The lines that begin "export" and "echo" seem to work, so I know my script is executing. If I enter the line that begins "source" at the prompt in the terminal I get a lot of printed output that indicates that the command is running, but if I execute my script, nothing happens (and in fact subsequent efforts to use Freesurfer indicate that it hasn't worked). I have a feeling there may be something very basic I don't get about bash scripting, but I can't figure out what that thing is from looking at tutorials.
#!/bin/bash
export FREESURFER_HOME=/foo/freesurfer
echo "starting freesurfer"
echo $FREESURFER_HOME
source $FREESURFER_HOME/SetUpFreeSurfer.sh
export SUBJECTS_DIR=/bar/my_dir
If you run your script using ./scriptname.sh it is exexuted in a subshell. Every variable that is set there etc cannot change the environment of the parent shell. In order to do so you need to source the script.
See eg. this question on superuser

Automatically run a program if another program returns an error

I have a program (grabface) that takes a picture of the face of a person using a webcam, and I also have a shell script wrapper that works like this:
On the command line the user gives the script the name of a program to run and its command line arguments. The script then executes the given command and checks the exit code. If there was an error the program grabface is run to capture the surprised face of the user.
This all works quite well. But the problem is that the wrapper script must always be used. Is there some way to automatically run this script whenever a command is entered in the shell? Or is there some other way to automatically run a given program after any program is run?
Preferably the solution should work in bash, but any other shell is also OK. I realize this could be accomplished by simply making some adjustments in the source code of the shell, but that's kind of a last measure.
Something that is probably even trickier would be to extend this to work with programs launched outside of the shell as well (e.g. from a desktop environment) but this may be too difficult.
Edit: Awsome! Since bash was so easy, what about other shells?
In Bash, you can use the trap command with an argument of ERR to execute a specified command whenever an executed command returns non-zero.
$ trap "echo 'there was an error'" ERR
$ touch ./can_touch
$ touch ./asfdsafds/fdsafsdaf/fdsafdsa/fdsafdasfdsa/fdsa
touch: cannot touch `./asfdsafds/fdsafsdaf/fdsafdsa/fdsafdasfdsa/fdsa': No such file or directory
there was an error
trap affects the whole session, so you'll need to make sure that trap is called at the beginning of the session by putting it in .bashrc or .profile.
Other special trap signals that Bash understands are: DEBUG, RETURN and EXIT as well as all the system signals (which can be listed using trap -l).
The Korn shell has a similar facility, while the Z shell has a more extensive trap capability.
By the way, in some cases for the command line, it can be useful in Bash to set the PROMPT_COMMAND variable to a script or command that will be run each time the prompt is issued.
Just subtitute your command where I have the false.
false || echo "It failed"
If you want to do the oposite, like when it succeeds, just put your command instead of true:
true && echo "It succeeded"
In the .profile of the user add:
trap grabface ERR

Resources