How can you hide env variables when executing a bash script with -xe? - bash

I have a bash script that I execute with /bin/sh -xe script.sh and I need to capture its output.
The problem is that inside the script I use some ENV variables that I would like to keep them from being displayed in the output.
Is there any way to do this?
Ie. if my script has touch $MY_ENV_VAR and MY_ENV_VAR=ok the output of /bin/sh -xe script.sh will be touch ok.
Is there any way to keep env vars from being replaced in the output of -x? So I would just get + touch $MY_ENV_VAR back.

There is nothing in the POSIX standard which allows this. All you could do is:
set +o xtrace # Switch xtrace off
some hidden code
set -o xtrace # Switch xtrace back on
Alternatively, use the verbose trace instead of xtrace, that's the -v option.
/bin/sh -ve script.sh
By the way, if you are executing with /bin/sh then it is not a bash script, it is a sh script.

Related

Use echo options when execution shell script

On mac OSX, I have this script:
#!/usr/local/bin/bash
echo -e "\e[41mError: Some error.\e[0m"
When I just run the echo -e ... in a console, it prints the colored text "Error: Some error."
When executed as a script sh myscript.sh, it litterally prints the flag and the escape characters: -e "\e[41mError: Some error.\e[0m".
When I add the script location to ~/.bash_profile and execute it as myscript.sh, it does work. But I need to be able execute it without adding it to my bash profile.
Edit: using printf works: printf "\e[41mError: Some error.\e[0m\n".
when you run the shell with sh it runs in posix compatibility mode (i.e. as the bourne shell does)
bash is a successor to this shell, one of the features it adds is the -e switch to echo
in posix shell you don't need the -e, the escapes will be evaluated anyway
in bash you do, so if you want to run bash do so explicitly

Is it possible to print all the commands when they are executed in Bash?

From How to echo shell commands as they are executed I've learned how to use set -v to print commands when they are executed. It works well if set -v is added at the beginning of foo.sh or bash -v foo.sh is run. However, if foo.sh invokes bar.sh by bash bar.sh or simply ./bar.sh, the commands in bar.sh are not printed. Is there a global switch that enables all the commands and functions, through all invoked scripts, to be printed when they are executed?
Is there a global switch that enables all the commands and functions, through all invoked scripts, to be printed when they are executed?
Yes, BASH_ENV can be used for that. The manual describes it as follows.
If this variable is set when Bash is invoked to execute a shell script, its value is expanded and used as the name of a startup file to read before executing the script.
So, you can just put set -v in a file and assign its path to BASH_ENV while invoking the first script. For example:
$ cat env.sh
set -v
$
$ cat foo
#!/bin/bash
true
./bar
$
$ cat bar
#!/bin/bash
false
$ BASH_ENV=./env.sh ./foo
#!/bin/bash
true
./bar
#!/bin/bash
false
Alternatively, to do this without having to create an extra file, you can start the script with a fabricated SHELLOPTS value
# too long, and might require adjustments for future versions
env SHELLOPTS=braceexpand:hashall:interactive-comments:verbose ./foo
or, enable verboseness by the set command or by adding -v to the shebang and export SHELLOPTS within the first script.
set -v
# exports all options, not only `verbose'
export SHELLOPTS
# the rest of the script

Running command as login shell without starting a new shell?

I'm trying to see what the output of a command would be if I were in a login shell, without having to go into a login shell. I've tried several variations of
zsh --login -c "alias"
But none of my aliases get shown; are --login and -c incompatible?
To test the difference between zsh --login -c "alias" and a normal login shell, you can/should add the -x option to see what the shell is up to.
When I run zsh -x --login -c "alias", then it processes /etc/zprofile.
When I run zsh -x --login, then it processes /etc/zprofile and /etc/zshrc.
I don't normally use zsh, so I don't have any personalized profile or start up file for it, but it seems plausible that it might look for (but, in my case, not find) ~/.zprofile and ~/.zshrc too.
I created trivial versions of those files:
$ echo "echo in .zprofile" > ~/.zprofile
$ echo "echo in .zshrc" > ~/.zshrc
and sure enough, they're processed. Further, the -c command with --login processed the .zprofile but did not process the .zshrc file.
Thus, using -c "alias" after the --login suppresses the processing of /etc/zshrc and ~/.zshrc. If you want those executed even so, you need to use something like:
zsh --login -c "[ -f /etc/zshrc ] && . /etc/zshrc; [ -f ~/.zshrc ] && . ~/.zshrc; alias"
Using -x to debug login processing is often informative.
It's nice that modern shells provide a command line option to induce login processing. I still have a program (which I don't use any more) that runs a login shell the old-fashioned way, by adding a - before the shell name in argv[0]. Thus, running -ksh would trigger login processing; the login program would run the login shell with the - at the start.

How to set $TERM to a value when running /bin/bash via command line?

When I run the /bin/bash process with 2 parameters -c and SomeUserInput,
where SomeUserInput is echo $TERM
The output is
xterm-256color
Is there a way I can set the value of $TERM via a command line parameter to /bin/bash so the above invokation of echo $TERM would print something else that I specify?
(Yes, I've done a lot of digging in man bash and searching elsewhere, but couldn't find the answer; although I think it's likely there.)
First of all, since you used double quotes, that prints the value of TERM in your current shell, not the bash you invoke. To do that, use /bin/bash -c 'echo $TERM'.
To set the value of TERM, you can export TERM=linux before running that command, set it only for that shell with either TERM=linux /bin/bash -c 'echo $TERM' (shell expression), or /usr/bin/env TERM=linux /bin/bash -c 'echo $TERM' (execve compatible (as for find -exec)).
Update:
As for your edit of only using command line parameters to /bin/bash, you can do that without modifying your input like this:
/bin/bash -c 'TERM=something; eval "$1"' -- 'SomeUserInput'
Well, you can either set the variable on your .bashrc file, or simply set with the bash invocation:
/bin/bash -c "TERM=something-else; echo $TERM"

How to specify zeroeth argument

I'm writing a bash script that starts the tcsh interpreter as a login shell and has it execute my_command. The tcsh man page says that there are two ways to start a login shell. The first is to use /bin/tcsh -l with no other arguments. Not an option, because I need the shell to execute my_command. The second is to specify a dash (-) as the zeroeth argument.
Now the bash exec command with the -l option does exactly this, and in fact the following works perfectly:
#!/bin/bash
exec -l /bin/tcsh -c my_command
Except... I can't use exec because I need the script to come back and do some other things afterwards! So how can I specify - as the zeroeth argument to /bin/tcsh without using exec?
You can enclose the exec command into a sub-shell of your script.
#!/bin/bash
(exec -l /bin/tcsh -c my_command)
# ... whatever else you need to do after the command is done
You can write a wrapper (w.sh) script that contains:
#!/bin/bash
exec -l /bin/tcsh -c my_command
and execute w.sh in your main script.

Resources