I am trying to provide opts to a bash script when piping the script contents to bash for execution.
#!/bin/bash
SETUP_PACKAGES=""
while getopts ":u:" opt; do
case $opt in
p)
if [[ "$OPTARG" =~ "mysql" ]] ; then SETUP_PACKAGES="$SETUP_PACKAGES mysql-client libmysqlclient-dev"; fi
;;
# other parts omitted...
esac
done
Executing the script in a shell like ./script.sh -p mysql works. The aim is to store the script in a repository so I tried curl -L example.com/my/script | bash -p mysql. This however throws /usr/bin/mysql: /usr/bin/mysql: cannot execute binary file.
What do I need to do to achieve my goal?
You need -s option for bash in order to set positional parameters for an interactive shell:
curl -L example.com/my/script | bash -s -p mysql
The above example is misleading because you wait for "u" option but set only "p" option.
Any way here is how to call it with curl:
bash <(curl -L example.com/my/script) -p mysql
Related
I have an SSH command that is able to use variables defined in the script.
Example:
b="03-18-2022"
I'm able to pass this in to my ssh call and use it.
However I want to be able to define $b when I run the script: bash file.sh -b 03-18-2022
.. When I try doing this the SSH command cannot recognize the variable
CODE:
Getting the variable from the input:
while getopts ":b:" arg; do
case "${arg}" in
b) b="$OPTARG";;
esac
done
echo "Locally using begin: $b
printf -v b_str %q "$b"
ssh myserver "bash -s $b_str" << 'EOF'
b=$1
echo "remotely using $b"
The last echo works when the variable is defined in the script but not when it is passed in from the command line
I create a bash file test.sh. The content of this bash is like below:
#!/bin/bash
#source another file
export ICS_START=/rdrive/ics/itools/unx/bin/
source $ICS_START/icssetup.sh
XMAIN=false
MAINLINE=false
STARTDIR=${PWD}
# Get args.
usage() {
echo "Usage: $0 [-t <timestamp>] [-m] [-x]"
exit 1
}
parse_args(){
while getopts "ht:mx" OPT; do
case $OPT in
t) DATE=${OPTARG};;
m) MAINLINE=true;;
x) XMAIN=true;;
h) usage;;
?) usage;;
esac
done
}
echo "$#"
parse_args "$#"
#other commands
myrun -d xxx -p xxx --time xxxx
I run this bash file with ./test.sh -t xxx -m -x
During this process,the second source command is affected by the args -t xxx -m -x, it always throw errors as :
Ambigous switch. Please use more characters. I think icssetup.sh also define these args so we have conflicts with each other. How could I avoid this without changing arg characters?
I checked that the first two lines(source command) and the parse_args can both work well separately.
Any help would be appreciated.
This is something that happens with bash but not other shells. The arguments of your script are passed to any sourced script.
A simple example showing this:
test.sh
#!/bin/bash
source source.sh
echo Original Script: $# : $#
source.sh
#!/bin/bash
echo Sourced Script $# : $#
When you run test.sh, you see that even if no arguments are passed to the sourced script, it actually receives the original script arguments:
# ./test.sh a b
Sourced Script 2 : a b
Original script: 2 : a b
If you're attempting to pass no arguments to the sourced script, you might try to force it like:
source $ICS_START/icssetup.sh ""
I want to use /bin/bash (possibly /bin/sh) with the option -f passed to, and handled by, the script.
Precisely,
while getopts f OPT
do
case $OPT in
"f" ) readonly FLG_F="TRUE"
esac
done
if [ $FLG_F ]; then
rm -rf $KIBRARY_DIR
fi
and when these lines are in a file http://hoge.com/hoge.sh,
I can do this, for instance,
wget http://hoge.com/hoge.sh
/bin/bash hoge.sh -f
but not
/bin/bash -f hoge.sh
I know the reason but I want to do like this,
wget -O - http://hoge.com/hoge.sh | /bin/bash
with -f option for hoge.sh not for /bin/bash
Are there any good ways to do this?
/bin/bash <(wget -O - http://hoge.com/hoge.sh) -f
worked. but this is only for bash users, right?
Using bash you can do
wget -O - http://hoge.com/hoge.sh | /bin/bash -s -- -f
as with -s commands are read from the standard input. This option allows the positional parameters to be set too.
It should work with other POSIX shells too.
I have a script starting with:
#!/usr/bin/sudo bash
It does a non instant processing and is not meant to be interrupted, so I would like to add the -b option to sudo to run it in background after the password has been entered.
#!/usr/bin/sudo -b bash
However, the script does not accept the option. Am I doing something wrong ? Can one even pass an option that way ? And if not, why ?
Thank you in advance.
Let's ask shellcheck:
$ shellcheck yourscript
In yourscript line 1:
#!/usr/bin/sudo -b bash
^-- SC2096: On most OS, shebangs can only specify a single parameter.
A fair workaround is to have the script invoke itself with sudo based on a flag:
#!/bin/bash
if [[ $1 == "-n" ]]
then
echo "Processing as $(whoami)"
else
printf "Option -n not specified: invoking sudo -b %q -n:" "$0"
exec sudo -b "$0" -n
fi
This has the additional benefit of letting you run yourscript -n directly to not invoke sudo and not run in the background. This allows things like sudo yourscript -n && mail -s "Processing complete" you#example.com which would not be possible if the script unconditionally backgrounded itself.
Caveat: sudo "$0" is not a bullet proof way of reinvoking the current script.
I am trying to check if md5sum or digest exists on solaris and script is used on different machines.
Here is the function in sh script which is called from a ksh script
getMD5cmd ()
{
PATH="${PATH}:/bin:/usr/bin:/usr/sfw/bin:/usr/local/bin:/usr/sbin/bin"
if type -p md5sum;then
MD5CMD=`type -p md5sum`
elif type -p digest;then
MD5CMD="`type -p digest` -a md5"
fi
echo "HERE ${MD5CMD}"
}
When I run scripts I get
-p not found
md5sum not found
-p not found
digest is /bin/digest
HERE
However, when I type it in a terminal, works as exptected
Any Ideas?
Thanks
You are likely running ksh or possibly Bash for your interactive shell. Both of these have a -p option for type. The shell (probably sh) that your script is running in has type but doesn't have the -p option so it's looking for "-p" as the name of an executable and it doesn't find it.
So you could change your script to use ksh or you could use the which program. The latter is probably more portable, since some systems don't have ksh.
As you are setting the PATH, knowing where precisely the command is seems unnecessary.
getMD5cmd ()
{
PATH=${PATH}:/bin:/usr/bin:/usr/sfw/bin:/usr/local/bin:/usr/sbin/bin
md5sum /dev/null >/dev/null 2>&1 && MD5CMD=md5sum || MD5CMD="digest -a md5"
echo "HERE ${MD5CMD}"
}
getMD5cmd
Have you tried the following syntax:
MD5CMD="$(type -p md5sum digest |sed -e 's/digest$/digest -a md5/' |head -1)"
if [ -z "$MD5CMD" ]; then
echo 'no md5 sum command found' >&2
exit 1
fi
echo "HERE $MD5CMD"
I tried this in Cygwin and type will return multiple rows, so it works.
if which md5sum >/dev/null 2>&1; then
md5cmd="md5sum"
elif which digest >/dev/null 2>&1; then
md5cmd="digest -a md5"
else
echo "No md5 command found" >&2
exit 1
fi
$md5cmd YOUR_FILE