Check if all "CMD_xxx" are executable using loop - bash

How do I check if all variables "CMD_xxx" are executable in bash script?
I can check one by one with [ or test command, but I'd like to know how I check them with loop.
[Question] How do I check all variables which start "CMD_" with loop command?
This is my image. (Does not work)
for v in ${!CMD_#}
do
if [ ! -x ${$v}} ]; then
echo ${${v}} does not executable.
exit 1
fi
done
My environment is CentOS6.6 bash 4.1.2

That's not how you perform indirection.
if [ ! -x "${!v}" ]

Related

Use Dockerfile commands inside of a shell script?

Suppose that I have an entry-point to a shell script as I want to use some conditionals in a dockerfile. Is there a way to do something like this?
ENTRYPOINT ["./entry.sh", "lambda-name"]
Inside of entry.sh
#!/usr/bin/env bash
lambda_name=$1
echo "$lambda_name"
if [ "$lambda_name" = "a.handler" ]; then
CMD [ "a.handler" ]
elif [ "$lambda_name" = "b.handler" ];then
CMD [ "b.handler" ]
else
echo "not found"
fi
first of all you don't need that complication.
why not like this?
#!/usr/bin/env bash
lambda_name=$1
echo "$lambda_name"
if [ "$lambda_name" = "a.handler" ]; then
./a.handler
elif [ "$lambda_name" = "b.handler" ];then
./b.handler
else
echo "not found"
fi
also in your script you could use something like
exec "$#"
at the end of your script. this would run all your arguments.
The ENTRYPOINT is the main container process. It executes when you docker run the built image; it's too late to run any other Dockerfile directives at that point.
In particular, the ENTRYPOINT gets passed the image's CMD (or a Compose command: or an alternate command after the docker run image-name) as arguments, and it can do whatever it wants with that. So at this point you don't really need to "set the container's command", you can just execute whatever command it is you might have wanted to run.
#!/bin/sh
case "$1" in
a.handler) a.handler ;;
b.handler) b.handler ;;
*)
echo "$1 not found" >&2
exit 1
;;
esac
With this setup, a fairly common Docker pattern is just to take whatever gets passed as arguments and to run that at the end of the entrypoint script.
#!/bin/sh
# ... do any startup-time setup required here ...
exec "$#"
That matches what you show in the question: if the first argument is a.handler then run that command, and so on.

Maven script shows that Java command is not executable

After installation on Ubuntu, mvn -version prints:
The JAVA_HOME environment variable is not defined correctly
This environment variable is needed to run this program
NB: JAVA_HOME should point to a JDK not a JRE
I detected that the problem is in
if [ ! -x "$JAVACMD" ] ; then
echo "The JAVA_HOME environment variable is not defined correctly" >&2
echo "This environment variable is needed to run this program" >&2
echo "NB: JAVA_HOME should point to a JDK not a JRE" >&2
exit 1
fi
When I remove quotes from "$JAVACMD" it works perfectly
I saw that other scripts use commands with in quotes and I doubt that Maven released this script with errors. So, what seems to be the problem? Why my script won't work in original version? Type of script is #!/bin/sh but I tested this condition separately in new file with bash script. The result is the same. When I ask with quotes is command executable, result is false. When I ask without quotes is true
Edit:
I put directly that case in new bash file. The result is interesting
#!/bin/bash
JAVACMD1="$JAVA_HOME/bin/java"
JAVACMD2="/usr/lib/jvm/java-8-openjdk-amd64/bin/java"
echo $JAVACMD1
echo $JAVACMD2
if [ ! -x "$JAVACMD1" ]
then
echo "NOT"
else
echo "YES"
fi
if [ ! -x $JAVACMD1 ]
then
echo "NOT"
else
echo "YES"
fi
if [ ! -x "$JAVACMD2" ]
then
echo "NOT"
else
echo "YES"
fi
Result:
/usr/lib/jvm/java-8-openjdk-amd64/bin/java
/usr/lib/jvm/java-8-openjdk-amd64/bin/java
NOT
YES
YES
The problem was in env variable JAVA_HOME. It started with one blank, but that I didn't see in echo command (I suppose it trims the string). In command prompt I also used echo, but when I listed all env variables I saw it

Meaning of "! -S" in shell script

I am new to shell scripting, and I have encountered a script I didn't understand:
DOWN=true
while $DOWN; do
sleep 0.1
DOWN=false
for i in {1..7}
do
if [ ! -S "qdata/c$i/tm.ipc" ]; then
DOWN=true
fi
done
done
Specifically, what does this command mean:
! -S "qdata/c$i/tm.ipc"
The command you are looking at is actually this:
[ ! -S "qdata/c$i/tm.ipc" ]
Although it looks like punctuation, [ is actually the name of a command, also called test; so the command can also be written like this:
test ! -S "qdata/c$i/tm.ipc"
Which in context would look like this:
if test ! -S "qdata/c$i/tm.ipc"; then
DOWN=true
fi
As the name suggests, its job is to test some attribute of a string, number, or file, and return 0 (which represents true in shell scripts) if the test passes, and 1 (which represents false) if it doesn't.
Armed with this knowledge, you can run man test, and find the following explanations of the ! and -S arguments:
! EXPRESSION
EXPRESSION is false
and
-S FILE
FILE exists and is a socket
So test ! -S filename or [ ! -S filename ] can be read as "not is-socket filename".
So the command is checking whether a "socket" (a special kind of file) exists with each name in the loop. The script uses this command as the argument to an if statement (which can take any command, not just [) and sets DOWN to true if any of them does not exist.
You didn't really specify which shell you're talking about since they can vary a lot.
To answer you question, the context is a common construct
if [ <some test> ]
then
<commands>
fi
Where the [ <some test>] is a call to the command test
If you look at the documentation of that command you can see that ! negates the result and -S checks for True if file is a socket..
So you can read it as if "qdata/c$i/tm.ipc" is not a socket

Bash - A way to watch files for changes?

My current solution is to use the python library watchdog and the bash snippet (originally taken from here).
watchmedo shell-command client/js/src/templates/ proto/ --recursive \
--patterns="*.soy;*.proto" \
--command="echo \"WATCHMEDO file changed - rebuilding\"; make genfiles;"
Basically I'm watching a few template files, and then running make genfiles automatically if one of them changes.
I'm wondering if there's a way to do this in pure bash? I'd rather not have all my devs have to depend on that Python library.
I'm on OSX.
#!/bin/bash
watched_files=$# # pass watched files as cmd line arguments
if [ -z "$watched_files" ]; then
echo "Nothing to watch, abort"
exit
else
echo "watching: $watched_files"
fi
previous_checksum="dummy"
while [ 1 ]; do
checksum=$(md5 $watched_files | md5) # I use Mac so I have `md5`, in linux it's `md5sum`
if [ "$checksum" != "$previous_checksum" ]; then
echo "None shall pass!" # do your stuff here
fi
previous_checksum="$checksum"
sleep 1
done
This is a nice cli FAM client: http://fileschanged.sourceforge.net/

Make fails checking if directory exists

I googled for this, but I can't figure out why Bash complains with the following code to check if a directory exists:
test.mk
#!/bin/bash
MYDIR="dl"
all:
if [ ! -d $MYDIR ]; then
#if [ ! -d "${MYDIR}" ]; then
#if [ ! -d ${MYDIR} ]; then
#Here
fi
make -f test.mk
if [ ! -d YDIR ]; then
/bin/sh: Syntax error: end of file unexpected
make: *** [all] Error 2
Does someone know why it fails? And why does it call /bin/sh instead of /bin/bash? Thank you.
Edit: unlike Bash, make doesn't support multi-line block. Here's working code:
MYDIR="dl"
all:
if [ ! -d ${MYDIR} ]; then\
echo "Here";\
else\
echo "There";\
fi
The #!/bin/bash shebang that you inserted at top is useless, and it is treated by make as a comment.
make sends by default commands to /bin/sh. To specify a different shell, use the macro SHELL = /bin/bash.
Moreover, you need to escape your variable:
if [ ! -d ${MYDIR} ]
I'm not sure if make can handle multi-line statements, so try to put all the if block in a line.
if [ ! -d ${MYDIR} ]; then DO_SOMETHING; DO_SOMETHING_ELSE; fi
You're feeding test.mk to make, not to bash. Then make sends individual lines to the shell, not whole blocks.
make uses its SHELL macro to determine which shell to use. You can override it to make it use bash.
The reason why you're getting YDIR is that make has silly rules about variable interpolation. Write $(MYDIR), not $MYDIR.
try bracing your variable:
${MYDIR}

Resources