I've got the following bash script to check if a string length is nonzero using -n and equals "OK" by converting the variable to uppercase using ${1^^}:
#!/bin/bash
myfunction() {
result=0
if [[ -n $1 && ${1^^} = "OK" ]]; then
result=1
fi
echo $result >> /home/[REDACTED]/mylog
}
myfunction "ok"
myfunction "NO"
I made it executable using:
sudo chmod +x ./test
I then call it with either of the following:
bash ./test
./test
And the file always contains the expected result:
1
0
However, when trying to run from cron and the file contains:
0
0
I set up cron with this command:
sudo crontab -e
And here is the content:
* * * * * /home/[REDACTED]/test
I'm probably overlooking something obvious like syntax or cron environment... any suggestions?
Thanks!
Not sure why, but deleting the first line of the file and retyping has resolved it:
#!/bin/bash
Thanks all for the help!
Related
I have a bash script in a file named reach.sh.
This file is given exe rights using chmod 755 /Users/vb/Documents/util/bash/reach.sh.
I then created an alias using alias reach='/Users/vb/Documents/util/bash/reach.sh'
So far this works great.
It happens that I need to run this script in my current process, so theoretically I would need to add . or source before my script path.
So I now have alias reach='source /Users/vb/Documents/util/bash/reach.sh'
At this point when I run my alias reach, the script is failing.
Error /Users/vb/Documents/util/bash/reach.sh:7: = not found
Line 7 if [ "$1" == "cr" ] || [ "$1" == "c" ]; then
Full script
#!/bin/bash
# env
REACH_ROOT="/Users/vb/Documents/bitbucket/fork/self"
# process
if [ "$1" == "cr" ] || [ "$1" == "c" ]; then
echo -e "Redirection to subfolder"
cd ${REACH_ROOT}/src/cr
pwd
else
echo -e "Redirection to root folder"
cd ${REACH_ROOT}
pwd
fi
Any idea what I could be missing ?
I'm running my script in zsh which is not a bash shell, so when I force it to run in my current process it runs in a zsh shell and does not recognize bash commands anymore.
In your question, you say "It happens that I need to run this script in my current process", so I'm wondering why you are using source at all. Just run the script. Observe:
bash-script.sh
#!/bin/bash
if [ "$1" == "aaa" ]; then
echo "AAA"
fi
zsh-script.sh
#!/bin/zsh
echo "try a ..."
./bash-script.sh a
echo "try aaa ..."
./bash-script.sh aaa
echo "try b ..."
./bash-script.sh b
output from ./zsh-script.sh
try a ...
try aaa ...
AAA
try b ...
If, in zsh-script.sh, I put source in front of each ./bash-script.sh, I do get the behavior you described in your question.
But, if you just need to "run this script in my current process", well, then ... just run it.
source tries to read a file as lines to be interpreted by the current shell, which is zsh as you have said. But simply running it, causes the first line (the #!/bin/bash "shebang" line) to start a new shell that interprets the lines itself. That will totally resolve the use of bash syntax from within a zsh context.
I have a strange problem with bash that I cannot explain.
I created the script test.sh which contains the lines:
export TEST_HOME=`ls -d $HOME`
echo $TEST_HOME
if [ "$HOME" = "$TEST_HOME" ]
then
echo "Equal"
else
echo "Not equal"
fi
Now if I source test.sh:
$ . test.sh
the output is
/home/sven
Not equal
However, if I make it executable and run it as a normal script:
$ test.sh
the output is
/home/sven
Equal
Any explanation how this behavior is explained? I am using RedHat 5.
Best regards,
Sven
I'm begginner on shell, currently i wrote a small script and i got a problem without any error :/
This code always exit my script and i dont understand why :
[[ -x $PATH ]] || log_failure_msg "Binary file not found or not executable!"; exit 0
When $PATH is valid i got nothing and if the path is wrong i got my failure message.
If i remove log_failure_msg "Binary file not found or not executable!"; the script work perfectly -_-
Ho i can solve this problem without if/fi conditions?
Thank you for your help!
The issue is precedence, as explained by phlogratos. However, you can't use parenthesis as they spawn a sub-shell and you'll be exiting that shell. For this particular issue, curly braces exist. They have almost the same semantics but they spawn jobs in the current shell.
$ cat a.sh
[[ -f file ]] || { echo error; exit 0; }
echo "ok"
$ touch file
$ ./a.sh
ok
$ rm file
$ ./a.sh
error
$
[[ -x $PATH ]] || log_failure_msg "Binary file not found or not executable!"; exit 0
is equivalent to
{ [[ -x $PATH ]] || log_failure_msg "Binary file not found or not executable!" } ; exit 0
What you need is
[[ -x $PATH ]] || { log_failure_msg "Binary file not found or not executable!"; exit 0 }
I'm assuming you are using bash. The bash man page states:
..., && and || have equal precedence, followed by ; and &, which have equal precedence.
I'm a newbie to shell scripting. I have written a shell script to do incremental backup of MySQL database.The script is in executable format and runs successfully when executed manually but fails when executed through crontab.
Crontab entry is like this :
*/1 * * * * /home/db-backup/mysqlbackup.sh
Below is the shell script code -
#!/bin/sh
MyUSER="root" # USERNAME
MyPASS="password" # PASSWORD
MyHOST="localhost" # Hostname
Password="" #Linux Password
MYSQL="$(which mysql)"
if [ -z "$MYSQL" ]; then
echo "Error: MYSQL not found"
exit 1
fi
MYSQLADMIN="$(which mysqladmin)"
if [ -z "$MYSQLADMIN" ]; then
echo "Error: MYSQLADMIN not found"
exit 1
fi
CHOWN="$(which chown)"
if [ -z "$CHOWN" ]; then
echo "Error: CHOWN not found"
exit 1
fi
CHMOD="$(which chmod)"
if [ -z "$CHMOD" ]; then
echo "Error: CHMOD not found"
exit 1
fi
GZIP="$(which gzip)"
if [ -z "$GZIP" ]; then
echo "Error: GZIP not found"
exit 1
fi
CP="$(which cp)"
if [ -z "$CP" ]; then
echo "Error: CP not found"
exit 1
fi
MV="$(which mv)"
if [ -z "$MV" ]; then
echo "Error: MV not found"
exit 1
fi
RM="$(which rm)"
if [ -z "$RM" ]; then
echo "Error: RM not found"
exit 1
fi
RSYNC="$(which rsync)"
if [ -z "$RSYNC" ]; then
echo "Error: RSYNC not found"
exit 1
fi
MYSQLBINLOG="$(which mysqlbinlog)"
if [ -z "$MYSQLBINLOG" ]; then
echo "Error: MYSQLBINLOG not found"
exit 1
fi
# Get data in dd-mm-yyyy format
NOW="$(date +"%d-%m-%Y-%T")"
DEST="/home/db-backup"
mkdir $DEST/Increment_backup.$NOW
LATEST=$DEST/Increment_backup.$NOW
$MYSQLADMIN -u$MyUSER -p$MyPASS flush-logs
newestlog=`ls -d /usr/local/mysql/data/mysql-bin.?????? | sed 's/^.*\.//' | sort -g | tail -n 1`
echo $newestlog
for file in `ls /usr/local/mysql/data/mysql-bin.??????`
do
if [ "/usr/local/mysql/data/mysql-bin.$newestlog" != "$file" ]; then
echo $file
$CP "$file" $LATEST
fi
done
for file1 in `ls $LATEST/mysql-bin.??????`
do
$MYSQLBINLOG $file1>$file1.$NOW.sql
$GZIP -9 "$file1.$NOW.sql"
$RM "$file1"
done
$RSYNC -avz $LATEST /home/rsync-back
First of all, when scheduled on crontab it is not showing any errors. How can I get to know whether the script is running or not?
Secondly, what is the correct way to execute the shell script in a crontab.
Some blogs suggest for change in environment variables. What would be the best solution
When I did $echo PATH, I got this
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/mysql/bin:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/platform-tools:~/usr/lib/jvm/jdk-6/bin
The problem is probably that your $PATH is different in the manual environment from that under which crontab runs. Hence, which can't find your executables. To fix this, first print your path in the manual environment (echo $PATH), and then manually set up PATH at the top of the script you run in crontab. Or just refer to the programs by their full path.
Edit: Add this near the top of your script, before all the which calls:
export PATH="/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/mysql/bin:/opt/android-sdk-linux/tools:/opt/android-sdk-linux/platform-tools:~/usr/lib/jvm/jdk-6/bin"
Another more generic way is to have cron run the user's bash logon process. In addition to the PATH, this will also pick up any LD_LIBRARY_PATH, LANG settings, other environment variables, etc. To do this, code your crontab entry like:
34 12 * * * bash -l /home/db-backup/mysqlbackup.sh
My Issue was that I set the cron job in /etc/cron.d (Centos 7). It seems that when doing so I need to specify the user who executes the script, unlike when a cronjob is entered at a user level.
All I had to do was
*/1 * * * * root perl /path/to/my/script.sh
*/5 * * * * root php /path/to/my/script.php
Where "root" states that I am running the script as root.
Also need to make sure the following are defined at the top of the file. Your paths might be different. If you are not sure try the command "which perl", "which php".
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
Just import your user profile in the beginning of the script.
i.e.:
. /home/user/.profile
In your crontab file your script entry can have
* * * * * /bin/bash /path/to/your/script
Make sure to use full paths in your script. I have had a look through it and I have not seen any but just in case I missed it.
first run command env > env.tmp then run cat env.tmp copy PATH=.................. Full line and paste into crontab -e, line before your cronjobs. as like below
++=============================================================++
(# Edit this file to introduce tasks to be run by cron.
#
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
#
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
#
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
#
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
#
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
#
# For more information see the manual pages of crontab(5) and cron(8)
PATH=/root/.nvm/versions/node/v18.12.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/sna>
# m h dom mon dow command
0 3 * * * bash /home/ubuntu/test.sh
* * * * * bash /home/ubuntu/test2.sh >> /home/ubuntu/cronlog.log
* 3 * * * bash /home/ubuntu/logscron.sh)
++=====================================================================++
I would like to execute a command like this:
#!/bin/sh
`which rvmsudo` `which program` argument
but I get this issue
/usr/bin/env: argument: No such file or directory
Make sure, all of the which statements return valid:
#!/bin/bash
RVMSUDO=`which rvmsudo`
test -z "$RCMSUDO" && exit 1
PROGRAM=`which program`
test -z "$PROGRAM" && exit 2
$RVMSUDO $PROGRAM argument