Variables cannot be compared in Makefile - makefile

i wrote following code.
but i faced the errors.
result=1
ifeq (,1)
/bin/sh: -c: line 1: syntax error near unexpected token `,1'
/bin/sh: -c: line 1: `ifeq (,1)'
test:
result=$(shell cat test_result | grep "Bad idea" | wc -l)
ifeq ($(result),1)
#echo "test passed"
else
#echo "test failed"
endif
Why does this happen?
Can you tell me?

These conditionals need to be at the top-level and are evaluated when the make file is read, not when the target is executed. Further, you'll need something like xargs to strip the whitespace on the result. Then it works like you might expect.
result := $(shell cat test_result | grep "Bad idea" | wc -l | xargs)
ifeq ($(result),1)
out := "test passed"
else
out := "test failed"
endif
test:
echo ${out}
This gives an exchange like:
➜ make
echo "test failed"
test failed
➜ echo "Bad idea" > test_result
➜ make
echo "test passed"
test passed

Related

How to force an error if file is missing?

This snippet of a makefile shall stop the execution if the file myFile does not exist:
test:
if [ -e myFile ] ; then \
echo "Error Message"; \
fi;
If I replace the echo-statement by $(error: Error Message); \ the make file is being stopped in both cases. But I need the makefile to be stopped if the file exists.
$(error ) is interpreted by make itself, so if it is hit during reading of the file, the error is produced. If you need an error during execution of a recipe, you have to run a command that returns an error exit code. Most straight-forward would be false for that, e.g.
test:
if [ -e myFile ] ; then \
echo "Error Message"; false; \
fi;
Of course, you could check for the file using $(shell ), without a recipe:
ifeq ($(shell test -e myFile && echo yes),)
$(error Error Message)
endif

Shell script condition checking in Makefile

I've got the following Makefile script which calls a python test suite that writes the results to a file called test_results.txt. Then I display the files and read the last line which has a status that indicates whether all the test cases have been executed or not. Based on that value I echo a statement.
target: test.py
$(PYTHON) test.py
#cat test/test_results.txt
#if [ $(shell sed -e '$$!d' test/test_results.txt) = 0 ]; then\
echo "\nAll tests passed successfully";\
else \
echo "\nNot all the tests were passed";\
fi
When I run it, I get the following error: 0/bin/sh: 1: [: =: unexpected operator
It's much simpler to make test.py have a non-zero exit status if any test fails. Then your recipe is simply
target: test.py
#if $(PYTHON) test.py; then\
echo "\nAll tests passed successfully";\
else \
echo "\nNot all the tests were passed";\
fi
#cat test/test_results.txt

bash: echo in and also out of program

damn I'm getting sick of these titles.
I was getting:
(standard_in) 1: syntax error
(standard_in) 1: illegal character: S
(standard_in) 1: syntax error
(standard_in) 1: syntax error
types of errors.
I was convinced that this has to be caused by an unbalanced echo, or something, but I have 100s in my script so its hard to debug. so I made a function to debug the output:
#!/bin/bash
myecho ()
{
echo -e $1;
if [ $? != 0 ]
then
dev=$(ps | awk '{print $2}')
dev="/dev/$dev" # get the... whatever /dev/pts/2 is
echo "echo -e \x22last echo failed:\\x60\\x27$1\\x27\\x60\x22 > $dev" | sh # format to escape the string so I can see it
exit 2;
fi
}
and then I would change all the "echo -e"'s to "myecho". to debug. It didn't work. I'm wondering if this is possible, or even a possible problem, and if so how I can debug with a debug function.

Bash Script - Will not completely execute

I am writing a script that will take in 3 outputs and then search all files within a predefined path. However, my grep command seems to be breaking the script with error code 123. I have been staring at it for a while and cannot really seem the error so I was hoping someone could point out my error. Here is the code:
#! /bin/bash -e
#Check if path exists
if [ -z $ARCHIVE ]; then
echo "ARCHIVE NOT SET, PLEASE SET TO PROCEED."
echo "EXITING...."
exit 1
elif [ $# -ne 3 ]; then
echo "Illegal number of arguments"
echo "Please enter the date in yyyy mm dd"
echo "EXITING..."
exit 1
fi
filename=output.txt
#Simple signal handler
signal_handler()
{
echo ""
echo "Process killed or interrupted"
echo "Cleaning up files..."
rm -f out
echo "Finsihed"
exit 1
}
trap 'signal_handler' KILL
trap 'signal_handler' TERM
trap 'signal_handler' INT
echo "line 32"
echo $1 $2 $3
#Search for the TimeStamp field and replace the / and : characters
find $ARCHIVE | xargs grep -l "TimeStamp: $2/$3/$1"
echo "line 35"
fileSize=`wc -c out.txt | cut -f 1 -d ' '`
echo $fileSize
if [ $fileSize -ge 1 ]; then
echo "no"
xargs -n1 basename < $filename
else
echo "NO FILES EXIST"
fi
I added the echo's to know where it was breaking. My program prints out line 32 and the args but never line 35. When I check the exit code I get 123.
Thanks!
Notes:
ARCHIVE is set to a test directory, i.e. /home/'uname'/testDir
$1 $2 $3 == yyyy mm dd (ie a date)
In testDir there are N number of directories. Inside these directories there are data files that have contain data as well as a time tag. The time tag is of the following format: TimeStamp: 02/02/2004 at 20:38:01
The scripts goal is to find all files that have the date tag you are searching for.
Here's a simpler test case that demonstrates your problem:
#!/bin/bash -e
echo "This prints"
true | xargs false
echo "This does not"
The snippet exits with code 123.
The problem is that xargs exits with code 123 if any command fails. When xargs exits with non-zero status, -e causes the script to exit.
The quickest fix is to use || true to effectively ignore xargs' status:
#!/bin/bash -e
echo "This prints"
true | xargs false || true
echo "This now prints too"
The better fix is to not rely on -e, since this option is misleading and unpredictable.
xargs makes the error code 123 when grep returns a nonzero code even just once. Since you're using -e (#!/bin/bash -e), bash would exit the script when one of its commands return a nonzero exit code. Not using -e would allow your code to continue. Just disabling it on that part can be a solution too:
set +e ## Disable
find "$ARCHIVE" | xargs grep -l "TimeStamp: $2/$1/$3" ## If one of the files doesn't match the pattern, `grep` would return a nonzero code.
set -e ## Enable again.
Consider placing your variables around quotes to prevent word splitting as well like "$ARCHIVE".
-d '\n' may also be required if one of your files' filename contain spaces.
find "$ARCHIVE" | xargs -d '\n' grep -l "TimeStamp: $2/$1/$3"

syntax error near unexpected token `fi' while checking no of arguments passed

I am new to shell scripting and created a script to check arguments are passed or not using if else condition . But it is always giving a error 'syntax error near unexpected token `fi' '
is it always required to use ';' after if condition brackets.
I runned it online on http://www.compileonline.com/execute_bash_online.php it is working well but not on my system(Centos 6.2). Am i missing something in env settings or is it something else.
Code
#!/bin/bash
echo "print a message"
if [ $# -eq 1 ]; then
echo "Argument are passed to shell script"
else
echo "No arguments are passed to shell script"
fi
Error message
[root#local shell_scripts]# sh test.sh 12 13
test.sh: line 7: syntax error near unexpected token `fi'
test.sh: line 7: `fi'
[root#local shell_scripts]#
my env details
[root#local shell_scripts]# env
SHELL=/bin/bash
TERM=xterm
HISTSIZE=1000
SSH_CLIENT=192.168.1.17 49656 22
PERL5LIB=/home/bharat/perl5/lib/perl5/x86_64-linux-thread-multi:/home/bharat/perl5/lib/perl5
PERL_MB_OPT=--install_base /home/bharat/perl5
SSH_TTY=/dev/pts/6
USER=bharat
PATH=/home/bharat/perl5/bin:/usr/kerberos/sbin:/home/bharat/perl5/bin:/usr/kerberos/bin:/usr/local/bin:/bin:/usr/bin:/home/bharat/bin
MAIL=/var/spool/mail/bharat
INPUTRC=/etc/inputrc
LANG=en_US.UTF-8
SSH_ASKPASS=/usr/libexec/openssh/gnome-ssh-askpass
HOME=/root
SHLVL=4
PERL_LOCAL_LIB_ROOT=/home/bharat/perl5
LOGNAME=bharat
CVS_RSH=ssh
LESSOPEN=|/usr/bin/lesspipe.sh %s
G_BROKEN_FILENAMES=1
PERL_MM_OPT=INSTALL_BASE=/home/bharat/perl5
_=/bin/env
[root#local shell_scripts]#
Answering the first of your questions: ; is not required after if condition. Syntactically, then should go to a separate line. If then is in the 1st line, you use ;. The following code is correct:
if [ $# -eq 1 ]
then
echo ok
fi
Also, these brackets are not actually if condition brackets. If condition is any valid bash command, and brackets are equivalent to test, see man test for ref.
The following are valid if statement beginnings:
if cp a.txt b.txt ; then ...
if test $# -eq 1 ; then ...
The second one is equivalent to your if statement.
Works for me:
$ cat > f.sh
#!/bin/bash
echo "print a message"
if [ $# -eq 1 ]; then
echo "Argument are passed to shell script"
else
echo "No arguments are passed to shell script"
fi
$ bash f.sh
print a message
No arguments are passed to shell script

Resources