Here's what I'm trying to achieve.
#!/bin/bash
safemode=on
if [ $safemode == 'off' ];then
run dangerous code
fi
I have 129 dangerous lines that are all separated. What's the best way to do this?
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
Sign up to join this community"Best way" strongly depends on how much effort you consider the maximum. One rather easy way is to use &&
-connected command lists for a slight modification of your example. You can use either Bash's arithmetic test construct:
#!/bin/bash
safemode=1
(( ! safemode )) && run dangerous code 1
uncritical code
(( ! safemode )) && run dangerous code 2
or the normal string-based operator
#!/bin/bash
safemode=on
[[ $safemode = "off" ]] && run dangerous code 1
uncritical code
[[ $safemode = "off" ]] && run dangerous code 2
This is merely a rather short-hand notation for what you did already: The [[ ... ]]
test will yield false
if safemode
is not off
, hence the execution of the command list will stop at the &&
.
It might be worth noting that in case of a &&
-chained command list, the exit code will be that of the last command executed, so if safemode
is set, the $?
will be 1
after such "protected" lines (just in case you use the exit code in that way).
If we define a variable safemode
to be one of the two commands true
or false
, then we can use that as a prefix:
#!/bin/sh
safemode=true
safe_mode_off() { safemode=false }
"$safemode" || run dangerous code 1
uncritical code
"$safemode" || run dangerous code 2
I guess we'd normally set the variable from our options processing, so true
/false
is as easy as on
/off
.
We could perhaps extend this (though I don't necessarily think we should) to just make the dangerous commands become the arguments to false
, like this:
#!/bin/sh
risky=false
safe_mode_off() { risky= }
$risky run dangerous code 1
uncritical code
$risky run dangerous code 2
However in this case, expansion will still take place within the arguments - e.g. $(dangerous subcommand)
would still be executed, so we'd need to change that to $($risky dangerous subcommand)
. I think that's too error-prone for serious use.
risky='false &&'
and $risky ...
works, but not because of the &&
. The shell doesn't parse operators like &&
from the result of an expansion, so the &&
just gets passed as an argument to false
(and ignored). You'll see that if you try risky="echo &&"
, and you could just set risky=false
to get the same effect as risky="false &&"
gives. While I said it works with false
like that, there's still the fact that any expansions in the "dangerous" line still run, so something like $risky echo dangerous $(date >&2)
would run the date
, but not the echo
.
If you want a shorthand, you could use an alias. They're more like text replacement than any regular expansions, so syntax constructs can be inserted through them. Just need to explicitly enable in Bash scripts, and you want to make sure to not accidentally enable unwanted aliases too.
#!/bin/bash
unalias -a
shopt -s expand_aliases
# default safe
alias risky='[ "$riskymode" = enabled ] &&'
riskymode=
if [ "$1" = risky ]; then
riskymode=enabled
fi
echo this is normal
risky echo this is risky
But note that there's still the caveat that the condition is still just part of an &&
-list, so this:
risky echo try something risky || echo oopsie it failed
would run the echo oopsie
even if riskymode is disabled.
But you could do:
risky ( echo try something risky || echo oopsie it failed )
or even
risky if ! echo another risky attempt; then echo another failure; fi
(you can put a compound command inside a &&
-list)
We could even have the alias make the line a comment:
#!/bin/bash
unalias -a
shopt -s expand_aliases
alias risky='#'
if [ "$1" = risky ]; then
alias risky=''
fi
risky echo something risky, again || echo "does it fail now?"
but then of course it'll just ignore the first line, so this would again run the second line in "safe" mode:
risky echo something even more risky ||
echo "_now_ does it fail?"
[ "$safemode" = "off" ] && run dangerous code