When I run the following script in Bash 3.2.48:
#!/bin/bash
export var1='var1'
echo "UID=$UID"
if [ x"$UID" != x"0" ]
then
export var2='var2'
while ! { sudo -v; }; do { sudo -v; }; done;
sudo $0
exit
fi
echo $var1
echo $var2
exit 0
What I get as output is:
UID=1000
UID=0
var1
Why is var2 not exported and echoed? I'm pretty sure that the same script worked with older Bash versions.
you enter first time with UID == 1000, you enter the if clause
you sudo to execute the script with UID == 0;
sudo doesn't preserve the environment if env_reset is set in /etc/sudoers (default in most distros). You need sudo -E to preserve env.
you exit (before echoing)
from the sudo call you enter with clean env.
you enter with UID == 0
you don't enter the if clause, var2 is not set
you echo the variables.
The answer is much more simpler than is seems: you never echo those vars (when not running as root, obviously), because you already exit :))
Try avoiding/minimizing confusion by adding more appropriate/concise debug statements. For instance, use a single echo that contains everything that's relevant to your problem (i.e. process ID, user ID, var1, var2):
#!/bin/bash
export var1='var1'
if [ "$UID" != "0" ] ; then
export var2='var2'
while ! { sudo -v; }; do { sudo -v; }; done;
sudo $0
# this is "the key exit" ;-)
#exit
fi
echo "pid=[$$] uid=[$UID] var1=[$var1] var2=[$var2]"
With the exit commented out you get what you expect (obviously, in the "parent" process, as the "child" one - the one running as "root" - never reaches that part of the code that exports var2):
pid=[12346] uid=[0] var1=[var1] var2=[]
pid=[12345] uid=[1] var1=[var1] var2=[var2]
++ sometimes running scripts in debug mode (bash -x) helps too ;-)
Related
I tried to run bash script which is like that :
#!/bin/bash
export LD_LIBRARY_PATH=X ## censored
export PATH=$PATH:$LD_LIBRARY_PATH
CONNECTION='X' ## censored
echo $CONNECTION
RETVAL=`sqlplus -silent $CONNECTION <<EOF
SET PAGESIZE 50 FEEDBACK OFF VERIFY OFF HEADING OFF ECHO OFF
SELECT 'Alive' FROM dual;
EXIT;
EOF`
echo $RETVAL
if [ "$RETVAL" = "Alive" ];
then
echo 'Database is running.'
exit 1
else
echo 'Database is NOT running.'
fi
exit
When I run this sh result is like that :
sh checkdbstatus.sh
X
Alive
Database is NOT Running.
Why result is not Database is running ?
$RETVAL and Alive are equal ? And I am sure db is running.
Thank you
I expect to see result is Database is running.
I mean, i had read string testing should be done like this (at least with Busybox sh):
if [[ "$RETVAL" == "Alive" ]];
I looked trough some of my own scripts, and since 3 Years i use double brackets "[[" and double equalsigns "=="
I'll also remember i had a problem with invisible char (was some ansi-escape code) in output of an command. I found that by piping the command output to a textfile..
The sqlplus command probably adds an invisible newline character to $RETVAL.
Try this:
if [[ "$RETVAL" =~ ^Alive ]];
I am looking into how a particular exploit works, and I chose to look at one in the program 'chkrootkit' which allows for any user to run a malicious file as root. The source code for this vulnerable shellscript is as follows
slapper (){
SLAPPER_FILES="${ROOTDIR}tmp/.bugtraq ${ROOTDIR}tmp/.bugtraq.c"
SLAPPER_FILES="$SLAPPER_FILES ${ROOTDIR}tmp/.unlock ${ROOTDIR}tmp/httpd \
${ROOTDIR}tmp/update ${ROOTDIR}tmp/.cinik ${ROOTDIR}tmp/.b"a
SLAPPER_PORT="0.0:2002 |0.0:4156 |0.0:1978 |0.0:1812 |0.0:2015 "
OPT=-an
STATUS=0
file_port=
if ${netstat} "${OPT}"|${egrep} "^tcp"|${egrep} "${SLAPPER_PORT}">
/dev/null 2>&1
then
STATUS=1
[ "$SYSTEM" = "Linux" ] && file_port=`netstat -p ${OPT} | \
$egrep ^tcp|$egrep "${SLAPPER_PORT}" | ${awk} '{ print $7 }' |
tr -d :`
fi
for i in ${SLAPPER_FILES}; do
if [ -f ${i} ]; then
file_port=$file_port $i
STATUS=1
fi
done
if [ ${STATUS} -eq 1 ] ;then
echo "Warning: Possible Slapper Worm installed ($file_port)"
else
if [ "${QUIET}" != "t" ]; then echo "not infected"; fi
return ${NOT_INFECTED}
fi
}
I know that the reason the exploit works is because the line 'file_port=$file_port $i' will execute all files specified in $SLAPPER_FILES as the user chkrootkit is running (usually root), if $file_port is empty, because of missing quotation marks around the
variable assignment."
My question is why does the command
file_port=$file_port $i
result in execution of the file? Assuming that $i refers to the path of the file (/tmp/update)
I can see that file_port might be changed to some long netstat command in the previous if statement, is this something to do with it?
I've been trying to get my head around this all day to no avail, so at this point any help will be greatly appreciated :)
This is the one-shot variable assignment feature of any Bourne shell. Any command can be prefixed with zero or more variable assignments:
VAR1=VALUE1 VAR2=VALUE2 command arguments ...
Runs command arguments ... with the respective environment variables set for just this command. A typical use might be
EDITOR=vim crontab -e
I have just basic knowledge on Unix and know how to run shell script.
Process: we have created a batch (ex:test.bat)which will call shell script(shelltest.sh) by passing arguments.
when user enter a command on UI application front,the test.bat file will invoke with command-line( ex: test.bat "-h checkwriter -A 20141203")
bat file is calling sh file and passing arguments ,but the problems is i have a function/method in the sh file to verify certain checks ,this check is within the while block.
here the function is calling but exiting without entering into the while condition.
The same shell script working fine on testing environments but where as which is failing on PROD environment.
test.bat
sh shelltest.sh
shelltest.sh
#!/bin/sh
#set -x
PROGRAMNAME=`basename $0`
echo "Prog name is $PROGRAM"
QUIT=0
Check_test()
{
echo "Check1:$#"
echo "Check2:$#"
echo "Check3:$*"
echo "Param1 : is $1"
echo "Param2 : is $2"
echo "Param3 : is $3"
while [ $# -ne 0 ]
do
case `echo $1 | tr "[:lower:]" "[:upper:]"` in
-K)
echo "Inside MYVAR before:${1}"
shift
MYVAR=${1}
echo "Inside MYVAR after:${1}"
;;
*)
echo "Inside what is"
;;
esac
if [ $# -ne 0 ]
then
shift
fi
done
if [ "${MYVAR}" == "" ]
then
echo "Failed to enter into while condition "
QUIT=1;
fi
}
Check_test $*
Output of the above code for respective environment is,
**'---The out put in Testing environment (-K checkwriter -A 20141203)
Prog name is shelltest.sh
Check1 : -K checkwriter -A 20141203
Check2 : 4
Check3 : -K checkwriter -A 20141203
'after entered in while loop
Inside MYVAR before:-K
Inside MYVAR after: checkwriter**
**'----The output in PROD environment
Prog name is (no file is coming...it is empty)
Check1 : -K checkwriter -A 20141203
Check2 : 4
Check3 : -K checkwriter -A 20141203
'Not entering into while loop
Failed to enter into while condition**
the above shell script giving out put what am expecting,but in PROD environment it is failing to enter into the while loop. and one more 'basename' also coming as empty in prod.
Please,any one can suggest me how i can fix this issue.
Note: we are running on windows machine but to support unix commands we got installed some 3rd party apis.
I have the following variables set in a script.
SU="/bin/su -s /bin/sh
WSO2_SCRIPT="JAVA_HOME=$JAVA_HOME /opt/autopilot/wso2is/bin/wso2server.sh"
WSO2_USER=autoplt
This part of the script is of concern:
if [ "$RETVAL" -eq "0" ]; then
if [ "$(whoami)" != "${WSO2_USER}" ]; then
$SU - $WSO2_USER -c "${WSO2_SCRIPT} start" >> ${WSO2_LOG} 2>&1 || RETVAL="4"
else
${WSO2_SCRIPT} start >> ${WSO2_LOG} 2>&1 || RETVAL="4"
fi
fi
If I am root, then the following command gets executed:
/bin/su -s /bin/sh - autoplt -c 'JAVA_HOME=/usr/java/latest /opt/autopilot/wso2is/bin/wso2server.sh start'
and
RETVAL
will get evaluated to 0.
When I am user autoplt, the following command gets executed:
JAVA_HOME=/usr/java/latest /opt/autopilot/wso2is/bin/wso2server.sh start
However
RETVAL
will get evaluated to 4?
Are they not the same commands? Shouldn't RETVAL be 0 in each case?
The command gets executed successfully when I run it in the shell as autoplt user.
Therefore is there something wrong with the way I have written it?
the double pipe || used in lines :
$SU - $WSO2_USER -c "${WSO2_SCRIPT} start" >> ${WSO2_LOG} 2>&1 || RETVAL="4"
${WSO2_SCRIPT} start >> ${WSO2_LOG} 2>&1 || RETVAL="4"
means if the first command succeed, then the second will not be executed
It means when running as root, it succeed then no change to RETVAL
and as a user, if fails so change RETVAL to 4
Suppose I create my own script and I want that script to be the default command to be executed if command is not found, how do I go about configuring bash to make this happen
Eg. the command is called defCMD
Suppose I type some random string into the command line:
$ viosjaldfksajflsfa
Normally it would output 'viosjaldfksajflsfa not found'
However, instead of that happening I want 'viosjaldfksajflsfa' to be fed as parameter into the defCMD script I wrote and therefore have bash execute defCMD instead.
is there a way to make this happen?
My bash (Fedora) has the following
$ type command_not_found_handle
command_not_found_handle is a function
command_not_found_handle ()
{
runcnf=1;
retval=127;
[ ! -S /var/run/dbus/system_bus_socket ] && runcnf=0;
[ ! -x /usr/libexec/packagekitd ] && runcnf=0;
if [ $runcnf -eq 1 ]; then
/usr/libexec/pk-command-not-found $#;
retval=$?;
else
echo "bash: $1: command not found";
fi;
return $retval
}
You can start from here and add it to your .bashrc file. Change the else branch.