Bash script seems to be ignoring first variable - linux

I am trying to make a simple script to swap between my server and main computer to compile nginx, but everytime I run the script, it ignores the first variable in $nginxsrc which is $code.
I stripped the build stuff out, because its not relevant to the question.
#!/bin/bash
home="/home/michael"
code="/src/nginx"
NGINX="nginx-1.13.11"
nginxsrc="$code/$NGINX"
echo "$code"
echo "$NGINX"
echo "$nginxsrc"
Here is what happens when it runs:
$ sudo bash /usr/local/bin/build-nginx
/src/nginx
nginx-1.13.11
/nginx-1.13.11
I have tried putting them in {} like so: nginxsrc="${code}/${NGINX}"
I have tried with and without quotes: nginxsrc=$code/$NGINX
My server is running ubuntu 16.04.4 LTS 64-bit with all the latest updates.
Bash version is 4.3.48
Obviously the expected result is:
/src/nginx
nginx-1.13.11
/src/nginx/nginx-1.13.11

This will happen when you have carriage returns in your file -- your file was saved with DOS-style line endings:
Display such a file:
$ cat -e cr.sh
code="/src/nginx"^M$
NGINX="nginx-1.13.11"^M$
nginxsrc="$code/$NGINX"^M$
echo "$code"^M$
echo "$NGINX"^M$
echo "$nginxsrc"^M$
and run it with tracing on
$ bash -x cr.sh
+ code=$'/src/nginx\r'
+ NGINX=$'nginx-1.13.11\r'
+ nginxsrc=$'/src/nginx\r/nginx-1.13.11\r\r'
+ echo $'/src/nginx\r\r'
/src/nginx
+ echo $'nginx-1.13.11\r\r'
nginx-1.13.11
+ echo $'/src/nginx\r/nginx-1.13.11\r\r\r'
/nginx-1.13.11
Edit your files in an editor where you can set "unix" line endings, or fix it with dos2unix or
sed -i 's/\r$//'

Not sure how helpful it will be, but on my Ubuntu this actually works as expected:
jhartman#wieloryb:~$ bash /tmp/xxx
/src/nginx
nginx-1.13.11
/src/nginx/nginx-1.13.11
This sounds so unbelievable that there is any kind of bug in Bash around variables.
As you wrote, the snippet you've posted is just an extract. Perhaps somewhere in fragment not posted here there is an operation on your $code variable.
All I can suggest is to run it in debug using bash -x <script>, e.g.:
jhartman#wieloryb:~$ bash -x /tmp/xxx
+ home=/home/michael
+ code=/src/nginx
+ NGINX=nginx-1.13.11
+ nginxsrc=/src/nginx/nginx-1.13.11
+ echo /src/nginx
/src/nginx
+ echo nginx-1.13.11
nginx-1.13.11
+ echo /src/nginx/nginx-1.13.11
/src/nginx/nginx-1.13.11
This should help you to narrow down what is happening.
Good luck & best regards,
Jarek

Related

bash script variable concatenation

I have some bash code that i am running in a zsh shell on macos.
Code seems to work fine when i run in the shell, but when i run the file from my path, it only brings back the initial and not the initial+surname, any help most appreciated.
user="Steve Thomas"
dbuser=$user
initial="${user%"${user#?}"}"
userie=( $( echo $dbuser | cut -d' ' -f1- ) )
userlastname=${userie[2]}
fulluser="${initial}${userlastname}"
echo $fulluser
when run in shell i get what is expected
SThomas
and when i run as file.sh from path i get..
S
Not sure what i am doing wrong here, please advise.
In bash, arrays are indexed from 0, not 1 like in zsh. So, to make the script work in bash, change line 5 to
userlastname=${userie[1]}
You can even make it universal for both the shells:
startindex=2
if [[ $BASH_VERSION ]] ; then
startindex=1
fi
...
userlastname=${userie[startindex]}

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

How to handle quotes, backtick special characters for running linux bash shell command in remote server

Someone, please help me in correcting below command I wasted more than a day fixing below but failed, please help, I will be using below in ansible shell module.
ssh -o ConnectTimeout=5 splunk#10.145.32.172 '
sdline="`
grep -n TA-aws-hf-{{client_code}}-{{env_name}} /opt/splunk/etc/system/local/serverclass.conf
| awk -F \":\" \'{print $1}\'
`
&& sed -ie \"$sdline,`
echo $sdline + 3
| bc
`d\" /opt/splunk/etc/system/local/serverclass.conf
"
> ^C
Even tried below way:
ssh -o ConnectTimeout=5 splunk#10.145.32.172 exec sdline=`grep -n TA-aws-hf-{{client_code}}-{{env_name}} /opt/splunk/etc/system/local/serverclass.conf|awk -F ":" '{print $1}'` && sed -ie "$sdline,`echo $sdline + 3|bc` d" /opt/splunk/etc/system/local/serverclass.conf
grep: /opt/splunk/etc/system/local/serverclass.conf: No such file or directory
bash: line 0: exec: sdline=: not found
Context: It seems this question originated as an XY Problem. OP appears to want to remove the 3 lines including and after the string "TA-aws-hf-{{client_code}}-{{env_name}}".
Backticks are deprecated; use $(modern $(command) substitution) when necessary. It is not necessary in this case.
If your remote server has GNU sed:
ssh splunk#10.145.32.172 'sed -i "/TA-aws-hf-{{client_code}}-{{env_name}}/,+2d" /opt/splunk/etc/system/local/serverclass.conf'
If that gives you sed: -e expression #1, char 19: unexpected ',':
ssh splunk#10.145.32.172 '
cd /opt/splunk/etc/system/local
awk "/TA-aws-hf-{{client_code}}-{{/ {i=-3} i++>0" \
serverclass.conf > temp && mv $_ serverclass.conf
'
Your remote command is quite complicated.
I suggest the following:
Use ssh to gain interactive shell in 10.145.32.172
Create a script on 10.145.32.172 that do the work, with everything hard coded.
Refactor command line parameters to your script.
Call your script remotely from your local machine.
This strategy simplify the script and its maintenance. Allowing you to send only the important parameters.
If you have to deploy the script on many remote machines. Use shared storage resources, like NFS. Optionally copy the script using scp prior to running it.

grep in bash script not working as expected

If I run
grep -i "echo" *
I get the results I want, but if I try the following simple bash script
#search.sh
grep -i "$1" *
echo "####--DONE--####"
and I run it with sh -x search.sh "echo" I get the following error output:
' grep -i echo '*
: No such file or directory
' echo '####--DONE--####
####--DONE--####
How come? I'm on CentOS
Add the sha-bang line at the top of your script
#!/bin/bash
and after making it executable, run the script using
./search.sh "echo"
The "sh -x" should print the files that '*' matches. It looks like it's not matching any files. Are you maybe running it in a directory with no readable files?

save wild-card in variable in shell script and evaluate/expand them at runtime

I am having trouble running the script below (in Cygwin on win 7 mind you).
Lets call it "myscript.sh"
When I run it, the following is what I input:
yearmonth: 2011-03
daypattern: 2{5,6,7}
logfilename: error*
query: WARN
#! /bin/bash
yearmonth=''
daypattern=''
logfilename=''
sPath=''
q=''
echo -n "yearmonth: "
read yearmonth
echo -n "daypattern: "
read daypattern
echo -n "logfilename: "
read logfilename
echo -n "query: "
read q
cat "$yearmonth/$daypattern/$logfilename" | grep --color $q
The output I get is:
cat: /2011-03/2{5,6,7}/error* No such
directory of file exists.
However, if I enter daypattern=25 OR daypattern=26 etc. the script will work.
Also, of course if I type the command in the shell itself, the wildcards are expanded as expected.
But this is not what I want.
I want to be able to PROMPT the user to enter the expressions as they need, and then later, in the script, execute these commands.
Any ideas how this can be possible?
Your help is much appreciated.
Try eval, this should work for the {a,d} and * cases
eval grep --color $q ${yearmonth}/${daypattern}/${logfilename}
Use quote to prevent wildcard expansion:
$ a="*.py"
$ echo $a
google.py pair.py recipe-523047-1.py
$ echo "$a"
*.py

Resources