Why does this POSIX sh function set $? = 1 - sh

Very simple script but no idea why it sends an exit code of 1...
docker run --rm -it alpine
/ # apk update && apk add curl
...
...
/ # func() { RESPCODE=$(curl -sS -w "%{http_code}" -o /dev/null https://jsonplaceholder.typicode.com/todos/1); EXITCODE=$?; [ $EXITCODE -ne 0 ] && return 2; }
/ # func
/ # echo $?
1
Why does it not exit with zero code?!

We assume curl suceeds.
EXITCODE=0
From https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html: The exit status of an AND list shall be the exit status of the last command that is executed in the list.
[ $EXITCODE -ne 0 ] exits with 1 exit status
return 2 does not execute
the last command in [ $EXITCODE -ne 0 ] && return 2 is [ $EXITCODE -ne 0 ]
[ $EXITCODE -ne 0 ] exited with 1 exit status
so the exit status of [ $EXITCODE -ne 0 ] && return 2 is 1
the last command in a function exited with 1 exit status.
the function exits with 1 exit status
echo $? outputs 1
Do not use && nor || as a condition. Use if.

Related

Read variable further down in code in shell script

In a shell script I need to know the value of a variable further down in the code, without running through it first.
This pings $IP which is extracted from $VAR below the while loop.
The $VAR is unknown at the time this is extracted (IP=$(echo $VAR | awk '{print $1}'))
Is it possible to read VAR in before the while loop runs?
The code:
#!/bin/sh
TIMEOUT=10
IP=$(echo $VAR | awk '{print $1}')
while [ $TIMEOUT -ne 0 ];do
ping -c 1 -W 1 "$IP" >/dev/null
rc=$?
if [ $rc -eq 0 ];then
TIMEOUT=0
else
TIMEOUT=$(($TIMEOUT - 1))
echo $TIMEOUT
sleep 1
fi
done
# rest of code to run after while loop
VAR="192.168.0.1 t,r 20,e"

PID increments automatically

I'm writing a init-script for a microservice and have the problem, that the PID of the process, that the program gives out (via echo) is not the process ID the process is having. The code:
#!/bin/bash
### BEGIN INIT INFO
# Provides: temp
# Description: temp
# required-start: $local_fs $remote_fs $network $syslog
# required-stop: $local_fs $remote_fs $network $syslog
# default-start: 3 5
# default-stop: 0 1 2 6
# chkconfig: 35 99 1
# description: Microservice init-script
### END INIT INFO
START_SCRIPT=${applicationDirectory}/script/start.sh
STOP_SCRIPT=${applicationDirectory}/script/stop.sh
PID_FILE=${runDirectory}/${microserviceName}_${environment}_${servicePort}
# ***********************************************
# ***********************************************
DAEMON=$START_SCRIPT
# colors
red='\e[0;31m'
green='\e[0;32m'
yellow='\e[0;33m'
reset='\e[0m'
echoRed() { echo -e "${red}$1${reset}"; }
echoGreen() { echo -e "${green}$1${reset}"; }
echoYellow() { echo -e "${yellow}$1${reset}"; }
start() {
#PID=`bash ${START_SCRIPT} > /dev/null 2>&1 & echo $!`
PID=`$DAEMON $ARGS > /dev/null 2>&1 & echo $!`
}
stop() {
STOP_SCRIPT $1
}
case "$1" in
start)
if [ -f $PID_FILE ]; then
PID=`cat $PID_FILE`
if [ -z "`echo kill -0 ${PID}`" ]; then
echoYellow "Microservice is already running [$PID]."
exit 1
else
rm -f $PID_FILE
fi
fi
start
if [ -z $PID ]; then
echoRed "Failed starting microservice."
exit 3
else
echo $PID > $PID_FILE
echoGreen "Microservice successfully started [$PID]."
exit 0
fi
;;
status)
if [ -f $PID_FILE ]; then
PID=`cat $PID_FILE`
if [ ! -z "`echo kill -0 ${PID}`" ]; then
echoRed "Microservice is not running (process dead but pidfile exists)."
exit 1
else
echoGreen "Microservice is running [$PID]."
exit 0
fi
else
echoRed "Microservice is not running."
exit 3
fi
;;
stop)
if [ -f $PID_FILE ]; then
PID=`cat $PID_FILE`
if [ ! -z "`echo kill -0 ${PID}`" ]; then
echoRed "Microservice is not running (process dead but pidfile exists)."
exit 1
else
PID=`cat $PID_FILE`
stop $PID
echoGreen "Microservice successfully stopped [$PID]."
rm -f $PID_FILE
exit 0
fi
else
echoRed "Microservice is not running (pid not found)."
exit 3
fi
;;
*)
echo "Usage: $0 {status|start|stop}"
exit 1
esac
Now, the program gives for example 2505 as PID. But when I use
ps aux | grep trans | grep -v grep
It outputs a number, that is the previously outputted number +1.
Can anyone give a guess? Any help is appreciated!
Your PID variable gets the pid of the shell that executes start.sh. The actual program executed by the script gets a different pid.

Starting multiple tomcat instances in one server with init.d script

I'm trying to configure tomcat init.d start script to work with multiple instances (at this time 2 instances)
I'm following below sample script to create init.d script
#!/bin/bash
#
# tomcat This shell script takes care of starting and stopping Tomcat
#
# chkconfig: - 80 20
#
### BEGIN INIT INFO
# Provides: tomcat
# Required-Start: $network $syslog
# Required-Stop: $network $syslog
# Default-Start:
# Default-Stop:
# Short-Description: start and stop tomcat
### END INIT INFO
TOMCAT_USER=root
TOMCAT_HOME="/opt/tomcat7/node1"
SHUTDOWN_WAIT=45
tomcat_pid() {
echo `ps aux | grep org.apache.catalina.startup.Bootstrap | grep -v grep | awk '{ print $2 }'`
}
start() {
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo "Tomcat is already running (pid: $pid)"
else
# Start tomcat
echo "Starting tomcat service"
/bin/su - -c "cd $TOMCAT_HOME/bin && $TOMCAT_HOME/bin/startup.sh" $TOMCAT_USER
fi
return 0
}
stop() {
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo "Stoping Tomcat"
/bin/su - -c "cd $TOMCAT_HOME/bin && $TOMCAT_HOME/bin/shutdown.sh" $TOMCAT_USER
let kwait=$SHUTDOWN_WAIT
count=0
count_by=5
until [ `ps -p $pid | grep -c $pid` = '0' ] || [ $count -gt $kwait ]
do
echo "Waiting for processes to exit. Timeout before we kill the pid: ${count}/${kwait}"
sleep $count_by
let count=$count+$count_by;
done
if [ $count -gt $kwait ]; then
echo "Killing processes which didn't stop after $SHUTDOWN_WAIT seconds"
kill -9 $pid
fi
else
echo "Tomcat is not running"
fi
return 0
}
case $1 in
start)
start
;;
stop)
stop
;;
restart)
stop
start
;;
status)
pid=$(tomcat_pid)
if [ -n "$pid" ]
then
echo "Tomcat is running with pid: $pid"
else
echo "Tomcat is not running"
fi
;;
esac
exit 0
problem is tomcat_pid() method returns process ids of all tomcat instances, because of that, the second instance cannot be started. Is there a better method to handle this?
found a workaround, but expecting better solution
using netstat we can find process id via running port number
echo `netstat -tlnp | awk '/:80 */ {split($NF,a,"/"); print a[1]}'`
So i modified the function tomcat_pid() as below
tomcat_pid() {
echo `netstat -tlnp | awk '/:<port> */ {split($NF,a,"/"); print a[1]}'`
}

Trying to clone a ksh function with little modification with a one liner perl

I've a short ksh script that is often generated automatically. However, it's missing some stuff and I want to be able to "fix it" like I want by running a simple 1 liner perl to sed it.
Let say that the ksh contains the following function:
foo()
{
/some/command param1
if [[ $? -eq 0 ]]
then
/some/other/command stop param1
fi
/some/command param2
if [[ $? -eq 0 ]]
then
/some/other/command stop param2
fi
#...
}
and what I really want looks like this
foo_force()
{
/some/command param1
if [[ $? -eq 0 ]]
then
/some/other/command stop -f param1
fi
/some/command param2
if [[ $? -eq 0 ]]
then
/some/other/command stop -f param2
fi
#...
}
foo()
{
/some/command param1
if [[ $? -eq 0 ]]
then
/some/other/command stop param1
fi
/some/command param2
if [[ $? -eq 0 ]]
then
/some/other/command stop param2
fi
#...
foo_force
}
So far I've been able to get something "close", ie 2 perl commands, which would be ok with me. However, the second command only replace the last stop by a -f stop... which is not what I'm looking for.
/usr/bin/perl -i -pe "BEGIN{undef $/;}; s/^(foo)(\(\)\n{.*\n)}/\1_force\2}\n\n\1\2\t\1_force\n}/gms" /tmp/foo.ksh
/usr/bin/perl -i -pe "BEGIN{undef $/;}; s/^(foo\(\)\n{.* stop)( .*\n})/\1 -f\2/gms" /tmp/foo.ksh
This might work for you (GNU sed):
sed -i '/^foo()/{:a;$!N;/\n}/!ba;h;s/^foo/&_force/;s/stop /&-f /g;s/$/\n/p;g;s/\n}/\n\n foo_force&/}' /file
Using perl
perl -0777 -i -pe '
s{(^foo\(\).*?\n\})}{
my $foo = my $force = $1;
$foo =~ s/\}$/ foo_force()\n\}/;
$force =~ s/^foo\K/_force/;
$force =~ s/ stop \K/-f /g;
"$foo\n$force"
}mse;
' /tmp/foo.ksh

boolean expression in sh script

I have this simple script, which wouldn't run because of the line with if [ ... ]
Could anyone tell me what is wrong with this?
#! /bin/sh
if [ $# -ne 2 AND $# -ne 3 ]
then
echo "Usage $0 <input> <output> [<comment>]"
exit 1
fi;
Thanks!
Try the following :
#! /bin/sh
if [ $# -ne 2 -a $# -ne 3 ]
then
echo >&2 "Usage $0 <input> <output> [<comment>]"
exit 1
fi
Or :
#! /bin/sh
if [ $# -ne 2 ] && [ $# -ne 3 ]
then
echo >&2 "Usage $0 <input> <output> [<comment>]"
exit 1
fi
If you'd like to use bash :
#! /bin/bash
if [[ $# -ne 2 && $# -ne 3 ]]
then
echo >&2 "Usage $0 <input> <output> [<comment>]"
exit 1
fi