I have one main script(deploy_test.sh) which loops through files using find command and executes several other shell scripts. The main script does not exit even if other shell encounters failure. I used several options at the start of script but still iam unable to exit and script is continuing till the end.
deploy_test.sh
#!/usr/bin/env bash
set -euo pipefail
shopt -s execfail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "Do you want to Continue: [Yes/No]"
read action
if [ $action = "Yes" ]
then
echo "Executing scripts"
find ${SCRIPT_DIR}/folder2 -type f -name '*.sh' -exec bash {} \;
echo $?
echo "This should also not be printed"
else
echo "nothing"
exit 1
fi
My folder2 has 2 .sh files (1.sh and 2.sh)
1.sh(have some special character at the end of script)
#!/usr/bin/env bash -eu
echo "hi iam in 1.sh and i have error in this file"
`
2.sh
#!/usr/bin/env bash -eu
echo "hi iam in 2.sh and i have no error in this file"
Ouptut when i execute script
(deploy) CSI-0048:test_test smullangi$ ./deploy_test.sh
Do you want to Continue: [Yes/No]
Yes
Executing scripts
hi iam in 1.sh and i have error in this file
/Users/smullangi/Desktop/test_test/folder2/1.sh: line 4: unexpected EOF while looking for matching ``'
/Users/smullangi/Desktop/test_test/folder2/1.sh: line 5: syntax error: unexpected end of file
hi iam in 2.sh and i have no error in this file
0
This should also not be printed
I expected this script to exit after encountering error in 1.sh file which had special character. But whatever options I tried the script is not exiting after it encounters error.
Any help is really appreciated. I am executing this on macbook (macos catalina v10.15.3) with bash version(3.2.57(1)-release)
#UPDATE1:
Also i feel script is not executing at all. If there are no errors in the script then also it exits. In short i feel my scripts in folder1/folder2 is not getting executed after modyfing code as per Phillippe suggestions
#!/usr/bin/env bash
set -euo pipefail
shopt -s execfail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "Do you want to Continue: [Yes/No]"
read action
if [ $action = "Yes" ]
then
echo "Executing scripts"
find ${SCRIPT_DIR}/folder2 -type f -name '*.sh' -exec false bash {} +
#find ${SCRIPT_DIR}/folder2 -type f -name '*.sh' -exec bash {} \;
echo $?
echo "This should also not be printed"
else
echo "nothing"
exit 1
fi
Output
(deploy) CSI-0048:test_test smullangi$ ./deploy_test.sh
Do you want to Continue: [Yes/No]
Yes
Executing scripts
find does not always exit with error code when commands it runs give error:
find ${SCRIPT_DIR}/folder1 -type f -exec false {} \;
Above find command itself runs successfully even though every command it runs gives error.
Following find gives error:
find ${SCRIPT_DIR}/folder1 -type f -exec false {} +
To have error handling of each script, you can do
cd ${SCRIPT_DIR}/folder1
for script in ./*.sh; do
$script
done
I did not find any elegant solution using exec. So i used xargs in find command and it is working perfectly fine. Shell exits with appropriate error message. I used this as my reference https://unix.stackexchange.com/questions/571215/force-xargs-to-stop-on-first-command-error
#!/usr/bin/env bash
set -euo pipefail
shopt -s execfail
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo "Do you want to Continue: [Yes/No]"
read action
if [ $action = "Yes" ]
then
echo "Executing scripts"
find ${SCRIPT_DIR}/folder2 -type f -name '*.sh' | xargs -I {} sh -c 'bash "$1" || exit 255' sh {}
echo $?
echo "This should also not be printed"
else
echo "nothing"
exit 1
fi
Related
I have a bash script that works as. A user inputs a filename and then the script searches through the directories and when its found it copies to another location so that the file gets re-processed again. The script works well on bash script. My problem is that I'm not sure how to process that with PHP so that the user does it through the website or html. Here is my bash script - user_input.sh
#!/bin/bash
echo -n "Enter required file: "
read file_name
search=`find /var/log -type f -name "$file_name*"`
if [[ $? == 0 ]]
then
echo "$search will be processed soon"
cp $search /root
echo "$search copied for re-processing. Please check after about 5 minutes."
else
echo "Required file $file_name not found"
fi
Here is my PHP script, user_in.php:
<?php
exec("user_input.sh");
?>
I get a lot of mails from cronjobs with rsync. And I've tried to ignore it with wrapper script like this:
#!/bin/bash
/usr/bin/rsync "$#"
e=$?
if test $e = 24; then
exit 0
fi
exit $e
And saved it like a /usr/bin/rsync-no24
After that, I changed my script for cronjob:
#!/bin/bash
SOURCE_BASE="/var/www/"
TARGETS="server30"
TARGET_DIR="/var/www/"
RSYNC_BIN="/usr/bin/rsync-no24"
RSYNC_OPTIONS="-aqqq"
/usr/bin/find ${SOURCE_BASE}/typo3temp ! -user www-data -exec chown -R www-data:www-data {} \;
#for SOURCE_DIR in fileadmin uploads typo3temp
#do
for TARGET_HOST in ${TARGETS}
do
${RSYNC_BIN} ${RSYNC_OPTIONS} ${SOURCE_BASE}/${SOURCE_DIR} ${TARGET_HOST}:${TARGET_DIR}/
done
#done
But anyway I still get mails from cron such as
file has vanished:
"/var/www/stage2/typo3temp/tx_ncstaticfilecache/OnlineBackup/index33.html.5"
How to ignore messages like this? Probably something wrong with wrapper script?
Thanks a lot.
Replace your /usr/bin/rsync-no24 with this:
#!/bin/bash
(rsync "$#"; if [ $? == 24 ]; then exit 0; else exit $?; fi) 2>&1 | grep -v 'vanished'
source
(on a side note, I don't think there's a difference between RSYNC_OPTIONS="-aqqq" and RSYNC_OPTIONS="-aq"
I am trying to assign an absolute path to a variable in Bash:
#!/bin/bash
DIR= "/home/foobar"
echo "$DIR/test"
The output:
./test.sh: line 2: /home/foobar: Is a directory
/test
I don't understand what is happening there, please help me.
Remove the space before "/home/foobar":
#!/bin/bash
DIR="/home/foobar"
echo "$DIR/test"
Try in another shell.
#!/bin/sh
DIR='/home/foobar'
echo "$DIR/test"
Or if you want to check if the variable is getting initialized or not using this.
#!/bin/sh
DIR='/home/foobar'
[ -z "$DIR" ] && echo "Variable not declared" && exit
echo "$DIR/test"
The general syntax is
[ assignment=value ... ] command arguments
so you are doing an assignment of DIR= and running the command /home/foobar -- which of course isn't a valid command, but a directory; hence the error message.
Try this:
DIR=/home/foobar bash -c 'echo "DIR is \"$DIR\""' # DIR is "/home/foobar"
echo "done. DIR is now \"$DIR\"" # DIR is now ""
and you will see that DIR is assigned only during the first command, then lost.
To set it for the remainder of your script, you can do
DIR=/home/foobar
echo "DIR is now $DIR"
and if you want to expose it to child processes, you can add an export:
DIR=/home/foobar
bash -c 'echo "Before export: DIR is \"$DIR\""' # DIR is ""
export DIR
bash -c 'echo "After export: DIR is \"$DIR\""' # DIR is "/home/foobar"
I am trying to write a bash/shell script to zip up a specific folder and ignore certain sub-dirs in that folder.
This is the folder I am trying to zip "sync_test5":
My bash script generates an ignore list (based on) and calls the zip function like this:
#!/bin/bash
SYNC_WEB_ROOT_BASE_DIR="/home/www-data/public_html"
SYNC_WEB_ROOT_BACKUP_DIR="sync_test5"
SYNC_WEB_ROOT_IGNORE_DIR="dir_to_ignore dir2_to_ignore"
ignorelist=""
if [ "$SYNC_WEB_ROOT_IGNORE_DIR" != "" ];
then
for ignoredir in $SYNC_WEB_ROOT_IGNORE_DIR
do
ignorelist="$ignorelist $SYNC_WEB_ROOT_BACKUP_DIR/$ignoredir/**\*"
done
fi
FILE="$SYNC_BACKUP_DIR/$DATETIMENOW.website.zip"
cd $SYNC_WEB_ROOT_BASE_DIR;
zip -r $FILE $SYNC_WEB_ROOT_BACKUP_DIR -x $ignorelist >/dev/null
echo "Done"
Now this script runs without error, however it is not ignoring/excluding the dirs I've specified.
So, I had the shell script output the command it tried to run, which was:
zip -r 12-08-2014_072810.website.zip sync_test5 -x sync_test5/dir_to_ignore/**\* sync_test5/dir2_to_ignore/**\*
Now If I run the above command directly in putty like this, it works:
So, why doesn't my shell script exclude working as intended? the command that is being executed is identical (in shell and putty directly).
Because backslash quotings in a variable after word splitting are not evaluated.
If you have a='123\4', echo $a would give
123\4
But if you do it directly like echo 123\4, you'd get
1234
Clearly the arguments you pass with the variable and without the variables are different.
You probably just meant to not quote your argument with backslash:
ignorelist="$ignorelist $SYNC_WEB_ROOT_BACKUP_DIR/$ignoredir/***"
Btw, what actual works is a non-evaluated glob pattern:
zip -r 12-08-2014_072810.website.zip sync_test5 -x 'sync_test5/dir_to_ignore/***' 'sync_test5/dir2_to_ignore/***'
You can verify this with
echo zip -r 12-08-2014_072810.website.zip sync_test5 -x sync_test5/dir_to_ignore/**\* sync_test5/dir2_to_ignore/**\*
And this is my suggestion:
#!/bin/bash
SYNC_WEB_ROOT_BASE_DIR="/home/www-data/public_html"
SYNC_WEB_ROOT_BACKUP_DIR="sync_test5"
SYNC_WEB_ROOT_IGNORE_DIR=("dir_to_ignore" "dir2_to_ignore")
IGNORE_LIST=()
if [[ -n $SYNC_WEB_ROOT_IGNORE_DIR ]]; then
for IGNORE_DIR in "${SYNC_WEB_ROOT_IGNORE_DIR[#]}"; do
IGNORE_LIST+=("$SYNC_WEB_ROOT_BACKUP_DIR/$IGNORE_DIR/***") ## "$SYNC_WEB_ROOT_BACKUP_DIR/$IGNORE_DIR/*" perhaps is enough?
done
fi
FILE="$SYNC_BACKUP_DIR/$DATETIMENOW.website.zip" ## Where is $SYNC_BACKUP_DIR set?
cd "$SYNC_WEB_ROOT_BASE_DIR";
zip -r "$FILE" "$SYNC_WEB_ROOT_BACKUP_DIR" -x "${IGNORE_LIST[#]}" >/dev/null
echo "Done"
This is what I ended up with:
#!/bin/bash
# This script zips a directory, excluding specified files, types and subdirectories.
# while zipping the directory it excludes hidden directories and certain file types
[[ "`/usr/bin/tty`" == "not a tty" ]] && . ~/.bash_profile
DIRECTORY=$(cd `dirname $0` && pwd)
if [[ -z $1 ]]; then
echo "Usage: managed_directory_compressor /your-directory/ zip-file-name"
else
DIRECTORY_TO_COMPRESS=${1%/}
ZIPPED_FILE="$2.zip"
COMPRESS_IGNORE_FILE=("\.git" "*.zip" "*.csv" "*.json" "gulpfile.js" "*.rb" "*.bak" "*.swp" "*.back" "*.merge" "*.txt" "*.sh" "bower_components" "node_modules")
COMPRESS_IGNORE_DIR=("bower_components" "node_modules")
IGNORE_LIST=("*/\.*" "\.* "\/\.*"")
if [[ -n $COMPRESS_IGNORE_FILE ]]; then
for IGNORE_FILES in "${COMPRESS_IGNORE_FILE[#]}"; do
IGNORE_LIST+=("$DIRECTORY_TO_COMPRESS/$IGNORE_FILES/*")
done
for IGNORE_DIR in "${COMPRESS_IGNORE_DIR[#]}"; do
IGNORE_LIST+=("$DIRECTORY_TO_COMPRESS/$IGNORE_DIR/")
done
fi
zip -r "$ZIPPED_FILE" "$DIRECTORY_TO_COMPRESS" -x "${IGNORE_LIST[#]}" # >/dev/null
# echo zip -r "$ZIPPED_FILE" "$DIRECTORY_TO_COMPRESS" -x "${IGNORE_LIST[#]}" # >/dev/null
echo $DIRECTORY_TO_COMPRESS "compressed as" $ZIPPED_FILE.
fi
After a few trial and error, I have managed to fix this problem by changing this line:
ignorelist="$ignorelist $SYNC_WEB_ROOT_BACKUP_DIR/$ignoredir/**\*"
to:
ignorelist="$ignorelist $SYNC_WEB_ROOT_BACKUP_DIR/$ignoredir/***"
Not sure why this worked, but it does :)
i have a sh-Script with:
#!/bin/sh
dirs=( $(find . -maxdepth 1 -type d -printf '%P\n') )
echo "There are ${#dirs[#]} dirs in the current path"
let i=1
for dir in "${dirs[#]}"; do
echo "$((i++)) $dir"
done
answer=2
echo "you selected ${dirs[$answer]}!"
But i got the error:
symfonymenu.sh: Syntax error: "(" unexpected (expecting "}")
its the line ...dirs=
I like to echo all available directories in a folder that user can select it in a prompt interface.
You use features from the bash shell, so you should execute the script in bash. Change the first line to:
#!/bin/bash
/bin/sh can be any POSIX-compatible shell, for example on Ubuntu it's dash.
That's a bash script so you should make sure that you're running it with bash. Call it as bash script.sh. Also you should start your index from 0 not 1: let i=0.