Sample Header Ad - 728x90

exit from running, sourcing, or pasting a series of commands in bash

1 vote
0 answers
129 views
I'm writing a script that I run directly, "source" from the bash console, or cut/paste as a sequence of commands into a console from an editor window. The script or its pasted commands may encounter an error and need to exit; when it does, I do not want to exit the console. The problem is pasting commands into the terminal because each line is treated independently: aborting on one line will still execute the subsequent lines. I do not want to rely on external commands, only Bash. I have come up with a way to do this, but am wondering if there's an easier/better way. Put this into a script then either run it, source, it, or paste the commands into a console window:
#!/bin/bash
# test of exit from running, sourcing, or pasting a series of commands

# return fails implies either running or pasting; if not running, then pasting
shopt -s expand_aliases
SAVEOPTS=/tmp/$$.bashopts
saveopts () {
	set | egrep -v '(BASHOPTS|BASH_VERSINFO|EUID|PPID|SHELLOPTS|UID)=' >$SAVEOPTS
	alias >>$SAVEOPTS
}
alias EXIT="{ echo 'exit required, terminating' ; \
	return 2 >&/dev/null || \
	[[ '${0}' == '${BASH_SOURCE}' ]] && exit 2; \
	saveopts ; exec bash --rcfile $SAVEOPTS; }" 

# usage
echo "good stuff"			# commands that should pass
true || EXIT				# example of a successful command
echo "more good stuff"		# another good command
false || EXIT				# failed command
echo "SHOULD NOT SEE THIS"	# do not want this to run
I'm using this in GNU bash, version 5.2.15(1). How it works - call EXIT when you wish to terminate. 1. If sourcing the script, e.g., source 1.sh, the return 2 in the alias causes the sourcing to stop. 2. If running the script directly, e.g., bash 1.sh or just ./1.sh, the return 2 fails and falls through to the second condition that checks whether the name of the process is the name of the script. This succeeds, resulting in an exit 2. 3. If pasting, these first two conditions don't take effect, so instead it re-execs the current shell bringing back in the previous settings. Using exec preserves the PID of the shell. (The grep -v's are for unsettable options and is done to prevent the shell from trying to set these.) This generally feels fragile. Is there a better way? I'd like to have EXIT as the command, but am open to eval something, or a function call, or something else, as long as it's relatively short. I also prefer not to depend on external commands (which I don't have installed) such as xclip. *Revisions to this post:* - Added the exec logic simplifying the entire thing - This is a different question than another question having to do with aliases and not terminating a list of pasted commands.
Asked by Russ (159 rep)
Jul 29, 2024, 02:53 PM
Last activity: Jul 29, 2024, 06:32 PM