shell script error - linux

I have a shell script like this.
line="$#" # get the complete first line which is the complete script path
name_of_file = ${line%.*}
file_extension = ${line##*.}
if [ $file_extension == "php"]
then
ps aux | grep -v grep | grep -q "$line" || ( nohup php -f "$line" > /var/log/iphorex/$name_of_file.log & )
fi
if [ $file_extension == "java"]
then
ps aux | grep -v grep | grep -q "$line" || ( nohup java -f "$name_of_file" > /var/log/iphorex/$name_of_file.log & )
fi
here line variable has values like /var/www/dir/myphp.php or /var/www/dir/myjava.java.
The purpose of shell script is to check if these processes are already running and if not i try to run them.I get the following errors.
name_of_file: command not found
file_extension: command not found
[: missing `]'
[: missing `]'
Any ideas?

Firstly, the shell processor treats the line:
name_of_file = ${line%.*}
as the execution of the command:
name_of_file
with the parameters:
= ${line%.*}
you need to write it as:
name_of_file=${line%.*}
This makes it into a variable=value. You need to repeat this for the file_extension = line as well.
Secondly, the if:
if [ $file_extension == "php"]
has exactly the same parsing problem, you must have a space before the trailing ], because otherwise the parser thinks you're checking if $file_extension is equal to the string: "php]"
if [ $file_extension == "php" ]

delete the spaces first, maybe this will help...
name_of_file=${line%.*}
file_extension=${line##*.}
EDIT
Try this:
if [ $file_extension="php" ]
..
if [ $file_extension="java" ]

The other answers are right that the problem in your script lies in stray spaces in your variable assignments and [ .. ] statements.
(off-topic. FYI)
I took the liberty of refactoring your script (untested!) just to highlight some alternatives, namely:
using pgrep instead of ps aux | grep .....
using case
-
#!/bin/bash
line="$#" # get the complete first line which is the complete script path
name_of_file=${line%.*}
pgrep "$line" > /dev/null && exit # exit if process running
case "${line##*.}" in # check file extension
php)
nohup php -f "$line" > /var/log/iphorex/$name_of_file.log &
;;
java)
nohup java -f "$name_of_file" > /var/log/iphorex/$name_of_file.log &
;;
esac

Related

Check string and file empty in script shell

I have the script below that makes a query for the String ERROR generated by HTTP queries, I would like it to check all lines and just return me TRUE for when there is an error or file is empty
result.log
Collecting: LINK1 HTTP 200
EXCEPT ERROR - REST API LINK2 returned HTTP Error
Script:
1 cat /healthcheck/bin/gaps/result.log | grep HTTP | while read line
2 do
3 echo "$line" | grep "ERROR" >/dev/null
4 if [ $? = 0 ]; then
5 RESULT = "TRUE"
6 fi
7 done
8
9 echo $RESULT
Output:
./check.sh: line 5: RESULT: command not found
./check.sh: line 5: RESULT: command not found
Shell check:
$ shellcheck myscript
Line 1:
cat /healthcheck/bin/gaps/result.log | grep HTTP | while read line
^-- SC2148: Tips depend on target shell and yours is unknown. Add a shebang or a 'shell' directive.
^-- SC2002: Useless cat. Consider 'cmd < file | ..' or 'cmd file | ..' instead.
^-- SC2162: read without -r will mangle backslashes.
Line 4:
if [ $? = 0 ]; then
^-- SC2181: Check exit code directly with e.g. 'if mycmd;', not indirectly with $?.
Line 5:
RESULT = "TRUE"
^-- SC2030: Modification of RESULT is local (to subshell caused by pipeline).
^-- SC1068: Don't put spaces around the = in assignments (or quote to make it literal).
Line 9:
echo $RESULT
^-- SC2031: RESULT was modified in a subshell. That change might be lost.
$
Pipe runs in a subshell. Changes from a subshell are not visible to parent shell. The site bashfaq/024 presents possible workarounds.
You can put break the line if | is the last character on the line, no need to build super long lines for pipelines.
Upper case variables are by convention reserved for exported variables.
cat ... | grep is a useless use of cat. Just grep ... or < file grep.
When you check command return value, just if the command; then instead of the command; if [ $? ....
Use greps exit status in an if. In bash just if <<<"$string" grep -q "pattern"; then. In posix shell do if printf "%s\n" "$string" | grep -q "pattern"; then.
Bash is space aware. The RESULT = "TRUE" executes a command named RESULT with two arguments. It's RESULT="TRUE"
Use while IFS= read -r line to read the whole line exactly.
So while you could:
cat /healthcheck/bin/gaps/result.log |
grep HTTP |
{
while read line
do
echo "$line" | grep "ERROR" >/dev/null
if [ $? -eq 0 ]; then
RESULT="TRUE"
fi
done
echo $RESULT
}
In your case, it's just:
if grep "HTTP" /healthcheck/bin/gaps/result.log | grep -q "ERROR"; then
echo TRUE
fi

how to do if statements with "and" in sh

I try to solve this problem with the sh and not the bash.
All i want is a if statement that check some regex AND something else. Normally in bash this would be an easy job but with the sh i only find solutions online that wont work for me
First thing i want to check:
if echo "$1"| grep -E -q '^(\-t|\-\-test)$';
Than i want to check:
if echo "$#"| grep -E -q '^(1|2)$';
Combined:
if [ \(echo "$1"| grep -E -q '^(\-h|\-\-help)$'\) -a \(echo "$#"| grep -E -q '^(1|\2)$'\) ];
ERROR:
grep: grep: ./analysehtml.sh: 41: [: missing ]
Invalid back reference
(echo: No such file or directory
grep: 1: No such file or directory
I also try many diffrent combinations with this brackets but non of them worked for me. Maybe someone can help me here :)
logical and between commands is &&
if
echo "$1"| grep -E -q '^(\-h|\-\-help)$' &&
echo "$#"| grep -E -q '^(1|\2)$';
By default the exit status of a pipe is the exit status of last command.
set -o pipefail the exit status is fail if if any command of pipe has a fail exit status.
when only the exit status of the last command of a sequence must be checked
if { command11; command12;} && { command21; command22;};
However to check parameters there is no need to launch another process grep with a pipe there's an overhead.
Consider using following constructs work with any POSIX sh.
if { [ "$1" = -h ] || [ "$1" = --help ];} &&
{ [ $# -eq 1 ] || [ $# -eq 2 ];};
EDIT: Following are not POSIX but may work with many shell
if [[ $1 = -h || $1 = --help ]] && [[ $# = 1 || $# = 2 ]];
Works also with bash with set -o posix
Perhaps for your particular case, pattern matching might be better:
if [[ $1 =~ ^(\-h|\-\-help)$ && $# =~ ^(1|\2)$ ]]; then
The problem with your command is that the part within test or [ command is expression, not commands list.
So when you run [ echo 'hello' ] or [ \( echo 'hello' \) ] complains error in spite of sh or Bash. Refer to the classic test usage: The classic test command
And the syntax of if is:
if list; then list; fi
So you can just combine command with && operator in if statements:
if echo "$1"| grep -E -q '^(\-h|\-\-help)$' && echo "$#"| grep -E -q '^(1|\2)$';

How is this bash script launching a program?

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

Put grep output inside variable from a loop

I have CentOS and this bash script:
#!/bin/sh
files=$( ls /vps_backups/site )
counter=0
for i in $files ; do
echo $i | grep -o -P '(?<=-).*(?=.tar)'
let counter=$counter+1
done
In the site folder I have compressed backups with the following names :
site-081916.tar.gz
site-082016.tar.gz
site-082116.tar.gz
...
The code above prints :
081916
082016
082116
I want to put each extracted date to a variable so I replaced this line
echo $i | grep -o -P '(?<=-).*(?=.tar)'
with this :
dt=$($i | grep -o -P '(?<=-).*(?=.tar)')
echo $dt
however I get this error :
./test.sh: line 6: site-090316.tar.gz: command not found
Any help please?
Thanks
you still need the echo inside the $(...):
dt=$(echo $i | grep -o -P '(?<=-).*(?=.tar)')
Don't use ls in a script. Use a shell pattern instead. Also, you don't need to use grep; bash has a built-in regular expression operator.
#!/bin/bash
files=$( /vps_backups/site/* )
counter=0
for i in "${files[#]#/vps_backups/site/}" ; do
[[ $i =~ -(.*).tar.gz ]] && dt=${BASH_REMATCH[1]}
counter=$((counter + 1))
done

/etc/init.d/openibd: line 147: syntax error near unexpected token `;&'

Hi I am trying to install a fairly lengthy script to install infiniband and the OFED stack on rocks cluster 6.0
here is what i try to run
user#cluster # /etc/init.d/openibd restart
/etc/init.d/openibd: line 147: syntax error near unexpected token `;&'
/etc/init.d/openibd: line 147: `if ( grep -i 'SuSE Linux' /etc/issue >/dev/null 2>&1 ); then'
can any one share with me a fix or can identify a way to fix the error in this script?
in the file /etc/init.d/openibd
here is the part of the script which contains the error on the indicated line.
CONFIG="/etc/infiniband/openib.conf"
if [ ! -f $CONFIG ]; then
echo No InfiniBand configuration found
exit 0
fi
. $CONFIG
CWD=`pwd`
cd /etc/infiniband
WD=`pwd`
PATH=$PATH:/sbin:/usr/bin
if [ -e /etc/profile.d/ofed.sh ]; then
. /etc/profile.d/ofed.sh
fi
# Only use ONBOOT option if called by a runlevel directory.
# Therefore determine the base, follow a runlevel link name ...
base=${0##*/}
link=${base#*[SK][0-9][0-9]}
# ... and compare them
if [ $link == $base ] ; then
RUNMODE=manual
ONBOOT=yes
else
RUNMODE=auto
fi
ACTION=$1
shift
RESTART=0
max_ports_num_in_hca=0
# Check if OpenIB configured to start automatically
if [ "X${ONBOOT}" != "Xyes" ]; then
exit 0
fi
### ERROR ON FOLLOWING LINE ###
if ( grep -i 'SuSE Linux' /etc/issue >/dev/null 2>&1 ); then
if [ -n "$INIT_VERSION" ] ; then
# MODE=onboot
if LANG=C egrep -L "^ONBOOT=['\"]?[Nn][Oo]['\"]?" ${CONFIG} > /dev/null
; then
exit 0
fi
fi
fi
You've got some HTML encoding going on their you need to fix.
Replace > with >, and replace & with &.
Your script somehow had all of its > replaced with > (and & replaced by &, etc)
if ( grep -i 'SuSE Linux' /etc/issue >/dev/null 2>&1 ); then
^^
This is a syntax error because there is no command between the semi-colon that terminates the preceding command and the ampersand. The HTML encoding of certain symbols is confusing the bash parser as a result.

Resources