Bash script giving me a different result on reboot? - bash

I worked on a Bash script for the last day or so and running and debugging it directly on the shell.
The final script will be executed when the Ubuntu server gets rebooted.
I have started testing this, but my script gives me a different result then what I was expected.
I have narrowed it down to an "or condition" and rewrote a more simpler script to test this anomaly:
A call to this script has been made in /etc/rc.local, with a redirection of the output to a log file (log/reboot.log).
I have this in my script (as a test):
#!/bin/bash
YESTERDAY=20131103
SYS_DATE=20131104
LAST_START=20131104
if [[ $LAST_START = $YESTERDAY || $LAST_START = $SYS_DATE ]];
then
echo "is equal"
else
echo "is not equal"
fi
Executing in the shell I get "is equal" (the right answer). After the reboot in the log I get "is not equal".
Could someone tell me why?

I am guessing here,
But do you realize your /bin/sh is not your SHELL.
In UBUNTU and Debian, /bin/sh is DASH, your login shell is BASH.
So it might be related to your syntax of [[ ]] which is BASH.
Did you right in your top of the script:
#!/bin/sh
or
#!/bin/bash
[[
The [[ builtin is a bashism, and has somewhat better-defined semantics
than [ (a.k.a. test). However, it is still quite reasonable to use [
instead, and portable scripts must do so. Note that argument handling
is not quite the same; as above, use = rather than ==.
See here:
https://wiki.ubuntu.com/DashAsBinSh
the right way to do stuff here
The best solution would be actually to put your script in /etc/init.d and link it to run level 6. Which is the run level executed when rebooting. You should consider reading man 8 init when you have got some spare time. It will help you understand how your system is starting and shuting down.

Related

Jenkins Execute shell if then statement fails with `Bad substitution`

I need an if statement in Jenkins Execute Shell, but it always fails on the same line, regardless of what’s there.
I’m trying to do something like this:
if [ " ${BuildVariants[*]} " =~ " VariantA " ]; then
# fails on this line even this line is just a comment
variant_config=""
fi
it fails when I try to assign a variable there, fails when I try to echo "anything", fails even on comment (as example above)
Reason: Bad substitution
Note: There's anything specified in Configure System, so it should be using default Bash.
What the problem might be?
I don't think =~ works inside of [ ... ] -- use [[ ... ]] instead.
Shellcheck is a great tool for find these types of things; it would show that you've hit SC2074.
re:
fails on this line even this line is just a comment
You cannot have an "empty" then block. You can use just : as code to be executed:
if [[ "$foo" == "bar" ]]; then
:
fi
Next idea: get your code to run in a shell script, then put the code up in Jenkins. You will probably need to mock up some of the Jenkins-supplied input to do that, but it takes one more moving part out of the equation. If the code runs from the command line and doesn't in Jenkins, then you need to start looking for Jenkins-specific causes, like maybe it's being run in a csh instead of Bash (I see you mention this specific possibility already, but maybe there's something else like it -- I don't know Jenkins, sorry).
So the problem was that I supposed Jenkins was giving me an array, but it was giving me a string. (I used with Extended Choice Parameter, with multiple choices).
So the condition should've been [[ "$BuildVariants" == *"VariantA"* ]].

bash rematch as chroot

I'm using this in my script and it works fine on my root server and on some others I tested.
But there's a problem when using it on my webhosting (Hosted Plesk): The chrooted shell, it doesn't output anything. Just quits. My webhoster said I need to use the absolute paths, but I dont know how to apply this on the bash rematch.
#!/bin/bash
str='"<result="Abc1234" />"'
regex='<result="([0-9a-zA-Z._-/:]*)" />'
[[ $str =~ $regex ]] && echo ${BASH_REMATCH[1]}
(My first post here, sorry if I forgot something or misformatted this whole post)
In the discussion below the question it turned out that the issue is related to different default locales on the servers. Make sure that you are running the command with the right locale:
LANG=en_US.UTF-8 bash script.sh
(en_US.UTF-8) turned out to be the right locale in your case.
PS: Please also keep in mind what Ondrej K. says.
Instead of:
regex='<result="([0-9a-zA-Z._-/:]*)" />'
say:
regex='<result="([0-9a-zA-Z._/:-]*)" />'
- is moved to where it no longer can be considered meaning a range.
Actually I am a surprised it worked on the other system. I've replaced && echo ${BASH_REMATCH[1]} with ; echo $? (this was another possible debugging step) and was getting 2 which according to man bash means "syntactically incorrect regular expression".
If this doesn't help. Than we must be seeing different reason, way our shell interpret the script, but in any case printing the return status could then be the next step to take.

Why is executing a ruby command on bash to command file not working?

Code from .command file:
cd "$(dirname "$0")"
g1=Hi-Lo
echo Welcome to Ruby_Games! So far, you can play $g1.
echo What game would you like to play?
read game_choice
if [$game_choice == $g1]
then
ruby Hi-Lo.rb
fi
Output:
Welcome to Ruby_Games! So far, you can play Hi-Lo.
What game would you like to play?
Hi-Lo
/Users/Abbas/Desktop/Ruby_Games/LAUNCHER.command: line 6: [Hi-Lo: command not found
logout
So what exactly is going wrong? Thanks
I believe you need double quotes in your if statement
Similar to example 6.4 here: http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-6.html
cd "$(dirname "$0")"
g1=Hi-Lo
echo Welcome to Ruby_Games! So far, you can play $g1.
echo What game would you like to play?
read game_choice
if [ "$game_choice" = "$g1" ]
then
ruby Hi-Lo.rb
fi
You need spaces between each element of the test (aka [) command. That is, you need a space between [ and $game_choice, between $game_choice and =, etc. Also, as #GregHNZ pointed out, you should use double-quotes around variable references, in case they contain spaces or certain other shell metacharacters. Finally, == in a test expression is a bash extension; use = instead, and it'll work in more basic shells as well. Result:
if [ "$game_choice" = "$g1" ]
Spaces are important delimiters in shell syntax; there are places they're required and places they're forbidden, and very very few places where they're optional. In many languages, you can add or remove spaces to make the code more readable, but that's not the case in shell.
BTW, I recommend using shellcheck.net; it does a pretty good job of spotting errors like this. Actually, it points out a couple I didn't think of: you should add a shebang line to the beginning of the script, and using cd without checking for an error risks the rest of the script running in an unexpected directory. So you should use something like this:
#!/bin/bash
cd "$(dirname "$0")" || {
echo "Error cd'ing to the script's directory" >&2
exit 1
}

How to check for bash shell syntax errors in practice?

I need to check whether a set of scripts are syntactically correct. I know there are couple of posts around suggesting to use bash -n <script_name> but I run this and I get nothing out e.g.
good.sh
#!/bin/bash
echo "hello"
bad.sh
#!/bin1/bash1
eco "hello"
If I do:
$ bash -n bad.sh; echo $?
0
$ bash -n good.sh; echo $?
0
So how do you discriminate between good and bad exactly?
bash -n checks whether Bash can parse the code (that is, the syntax is correct), not whether the code is "correct." "Correct" can have a lot of meanings, most of which programs will never be able to verify:
Can be parsed (bash -n).
Finishes without error (if ./script.sh; then [...]; fi).
Prints something which follows a specific format.
Prints something useful.
Any of the above within a specific environment, for example one which has a shell interpreter that lives in /bin1/bash1 and a command eco which shows you the most ecologically friendly beer bottles available within a 5 parsec radius.

What is [[: not found error?

I tried to execute a file containing a shell script.
I get an error called "[[: not found" error at the last line. How to resolve it?
[[ is bash. sh wants the [ variant.
Either change that to /usr/bin/bash (or wherever bash is located on your system), or adjust the expression accordingly:
if [ status_of_job -eq 0 ];
[ is actually an executable in linux. but [[ is not.
Try
if [ status_of_job -eq 0 ]; then
(note the single [] set).
This interpreter:
#!/usr/bin/sh
Is either not bash or your file doesn't have the shebang in the right place.
ls -l /usr/bin/sh will tell you if it's a symlink to something other than bash.
If it is bash, then check that there's no leading characters before the #!.
You may find you stumble at other blocks later with POSIX shell related issues. People don't really understand how much bash actually provides until it's taken away. Take a look at this so you can hopefully avoid any other issues:
http://pubs.opengroup.org/onlinepubs/7908799/xcu/shellix.html

Resources