bash init script - ambiguous redirect - linux

I am trying to execute a hadoop job from an init script and output to a log file. The commands are as follows
log_file="/home/hadoop/log_`date +%Y%m%d-%H:%M:%S`.log"
echo $log_file
su - hadoop -c 'java -jar /home/hadoop/testing.jar > $log_file'
But I keep getting -bash: $log_file: ambiguous redirect.
What is wrong with my statement?

The problem is that you are using single quotes around your command, so the variable $log_file is not being expanded.
edit
As clarified by William Pursell's comment, $log_file is being expanded but by the wrong shell. See this example (I am using set -x to show the commands being evaluated):
$ log_file="/dir/file.log"
$ set -x
$ su - -c 'set -x; echo $log_file'
+ su - -c 'set -x; echo $log_file' # no expansion of $log_file yet
+ echo # expansion here, no variable $log_file
$ su - -c "set -x; echo $log_file"
+ su - -c 'set -x; echo /dir/file.log' # expansion here, $log_file exists
+ echo /dir/file.log
/dir/file.log
solution
Try using double quotes instead, so $log_file is expanded at the correct point:
su - hadoop -c "java -jar /home/hadoop/testing.jar > $log_file"

Related

Script does not fail in certain cases when using set -e in bash. How to write modular code in bash with this behavior? [duplicate]

When I run this command
set -e; echo $(echo "$-");
I get himBH as the output. I was expecting the letter e to be included in the output. Whats going on?
I'm on Ubuntu 16.04.1 LTS with
GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)
Command substitutions do not inherit the errexit option unless you are in POSIX mode or you use the inherit_errexit shell option (added to bash 4.4).
192% bash -ec 'echo "$(echo "$-")"'
hBc
192% bash --posix -ec 'echo "$(echo "$-")"'
ehBc
192% bash -O inherit_errexit -ec 'echo "$(echo "$-")"' # 4.4+
ehBc
This question!
Worked on this for a couple of hours until I found htis.
I was not able to have set -e inherited to the subshells.
This is my proof of concept:
#!/usr/bin/env bash
set -euo pipefail
# uncomment to handle failures properly
# shopt -s inherit_errexit
function callfail() {
echo "SHELLOPTS - callfail - $SHELLOPTS" >&2
local value
value=$(fail)
echo "echo will reset the result to 0"
}
function fail() {
echo "SHELLOPTS - fail - $SHELLOPTS" >&2
echo "failing" >&2
return 1
}
function root() {
local hello
hello=$(callfail)
echo "nothing went bad in callfail"
callfail
echo "nothing went bad in callfail"
}
root
execution without shopt -s inherit_errexit:
$ ./test.sh
SHELLOPTS - callfail - braceexpand:hashall:interactive-comments:nounset:pipefail
SHELLOPTS - fail - braceexpand:hashall:interactive-comments:nounset:pipefail
failing
nothing went bad in callfail
SHELLOPTS - callfail - braceexpand:errexit:hashall:interactive-comments:nounset:pipefail
SHELLOPTS - fail - braceexpand:hashall:interactive-comments:nounset:pipefail
failing
execution with shopt -s inherit_errexit:
$ ./test.sh
SHELLOPTS - callfail - braceexpand:errexit:hashall:interactive-comments:nounset:pipefail
SHELLOPTS - fail - braceexpand:errexit:hashall:interactive-comments:nounset:pipefail
failing

Can't run bash file inside ZSH

I've placed a bash file inside .zshrc and tried all different ways to run it every time I open a new terminal window or source .zshrc but no luck.
FYI: it was working fine on .bashrc
here is .zshrc script:
#Check if ampps is running
bash ~/ampps_runner.sh & disown
Different approach:
#Check if ampps is running
sh ~/ampps_runner.sh & disown
Another approach:
#Check if ampps is running
% ~/ampps_runner.sh & disown
All the above approaches didn't work (meaning it supposes to run an app named ampps but it doesn't in zsh.
Note: It was working fine before switching to zsh from bash. so it does not have permission or syntax problems.
Update: content of ampps_runner.sh
#! /usr/bin/env
echo "########################"
echo "Checking for ampps server to be running:"
check=$(pgrep -f "/usr/local/ampps" )
#[ -z "$check" ] && echo "Empty: Yes" || echo "Empty: No"
if [ -z "$check" ]; then
echo "It's not running!"
cd /usr/local/ampps
echo password | sudo -S ./Ampps
else
echo "It's running ..."
fi
(1) I believe ~/.ampps_runner.sh is a bash script, so, its first line should be
#!/bin/bash
or
#!/usr/bin/bash
not
#! /usr/bin/env
(2) Then, the call in zsh script (~/.zshrc) should be:
~/ampps_runner.sh
(3) Note: ~/.ampps_runner.sh should be executable. Change it to executable:
$ chmod +x ~/ampps_runner.sh
The easiest way to run bash temporarily from a zsh terminal is to
exec bash
or just
bash
Then you can run commands you previously could only run in bash. An example
help exec
To exit
exit
Now you are back in your original shell
If you want to know your default shell
echo $SHELL
or
set | grep SHELL=
If you want to reliably know your current shell
ps -p $$
Or if you want just the shell name you might use
ps -p $$ | awk "NR==2" | awk '{ print $4 }' | tr -d '-'
And you might just put that last one in a function for later, just know that it is only available if it was sourced in a current shell.
whichShell(){
local defaultShell=$(echo $SHELL | tr -d '/bin/')
echo "Default: $defaultShell"
local currentShell=$(ps -p $$ | awk "NR==2" | awk '{ print $4 }' | tr -d '-')
echo "Current: $currentShell"
}
Call the method to see your results
whichShell

bash -c variable does not get assigned

I am trying to execute the following command:
$ bash -c "var='test' && echo $var"
and only an empty line is being printed.
If I execute the same command without bash -c
$ var='test' && echo $var
test
the value assigned to $var is being printed. Could someone explain why I can't assign variables in the first example?
Double quotes expand variables, so your command is expanded to
bash -c "var='test' && echo"
if $var is empty when you run it. You can verify the behaviour with
var=hey
bash -c "var='test' && echo $var"
Switch the quotes:
bash -c 'var="test" && echo $var'

What is the use of "bash -c" command?

What is the use of bash -c command, while surfing on the internet I came across the command
ssh -t "${SSH_USER}#${SERVER_IP}" bash -c
First part here is doing ssh obviously to a server but what exactly bash -c is responsible for?
bash -c option with ssh is one such method to execute multi line commands on the ssh server with variable expansion.
Say you have
VAR1="Variable 1"
ssh app#HOSTNAME '
ls
pwd
if true; then
echo "True"
echo $VAR1 # <-- it won't work
else
echo "False"
fi
'
But with bash -c
VAR1="Variable 1"
ssh -t "${SSH_USER}#${SERVER_IP}" bash -c "'
ls
pwd
if true; then
echo $VAR1 <-- This works
else
echo "False"
fi
'"

Executing a set of commands inside a new bash instance from as script

I'm trying execute a set of commands in a new bash session:
exec bash <<- EOF
ln -snf $JDK_REPO'/jdk'$1 $CURRENT;
JAVA_HOME=$(readlink -f $CURRENT);
echo $JAVA_HOME;
export PATH= $JAVA_HOME/bin:$PATH;
exec usejdk
EOF
I get this error :
warning: here-document at line 46 delimited by end-of-file (wanted `EOF')
I tried to debug it with whatswrongwithmyscript, I get :
Use <<- instead of << if you want to indent the end token.
Any suggestion to execute a set of commands in a new bash instance ?
doing it this way works for me:
cmd="
ln -snf $JDK_REPO'/jdk'$1 $CURRENT;
JAVA_HOME=$(readlink -f $CURRENT);
echo $JAVA_HOME;
export PATH= $JAVA_HOME/bin:$PATH;
exec usejdk"
bash <<< "$cmd"
The bash <<< "$cmd" is equivalent to echo "$cmd" | bash or bash -c "$cmd"

Resources