Nagios custom plugin calling python Openstack Swift client - bash

I want to check with NAGIOS whether my server can connect to Openstack Swift container. I wrote a simple script where I use Swift Python client to get stat of the container
Script looks like that
#!/bin/bash
set -e
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4
if ! which /usr/bin/swift >/dev/null 2>&1
then
echo "Swift command not found"
exit $STATE_UNKNOWN
fi
my_swift="/usr/bin/swift -V 2.0 -A http://my-swift-domain.com:5000/v2.0/ --insecure --os-username my-user-name --os-password my-password --os-tenant-name tenant-name stat container"
output=`$my_swift | grep Objects | sed 's/Objects:\s*\([0-9]*\).*/\1/'`
if [ "$output" -eq "$output" ] 2>/dev/null
then
echo "successfully connected to swift. Number of objects in container $output";
exit $STATE_OK
else
echo "Number of container objects is not correct";
exit $STATE_CRITICAL
fi
Script has right permissions and NAGIOS is able to run it properly. The script itself called from bash works and returns something like:
successfully connected to swift. Number of objects in container 4973123
But it doesn't when I run it via nrpe. I checked it by running /usr/lib64/nagios/plugins/check_nrpe -H 127.0.0.1 -c check_swift
I just get Number of container objects is not correct
After debugging I'm pretty sure that the command
output=`$my_swift | grep Objects | sed 's/Objects:\s*\([0-9]*\).*/\1/'`
is not even called.
I tried to put swift --version there just to see if it will give me some output and it does. So, it let me think that there is something wrong with parameters but I really don't know what, because the command itself called in a shell works perfectly fine.
Any help appreciated :)

Try to change de first line for this:
#!/usr/bin/env bash

Turns out that it was SELinux (on CentOS) blocking the execution of the command because of the wrong context of the file. I copied the file from home directory to Nagios' plugins directory.
restorecon check_swift_container -v helped

Related

Bash script runs but no output on main commands and not executed

I'm setting a cron job that is a bash script containing the below:
#!/bin/bash
NUM_CONTAINERS=$(docker ps -q | wc -l)
if [ $NUM_CONTAINERS -lt 40 ]
then
echo "Time: $(date). Restart containers."
cd /opt
pwd
sudo docker kill $(docker ps -q)
docker-compose up -d
echo "Completed."
else
echo Nothing to do
fi
The output is appended to a log file:
>> cron.log
However the output in the cron file only shows:
Time: Sun Aug 15 10:50:01 UTC 2021. Restart containers.
/opt
Completed.
Both command do not seem to execute as I don't see any change in my containers either.
These 2 non working commands work well in a standalone .sh script without condition though.
What am I doing wrong?
User running the cron has sudo privileges, and we can see the second echo printing.
Lots of times, things that work outside of cron don't work within cron because the environment is not set up in the same way.
You should generally capture standard output and error, to see if something going wrong.
For example, use >> cron.log 2>&1 in your crontab file, this will capture both.
There's at least the possibility that docker is not in your path or, even if it is, the docker commands are not working for some other reason (that you're not seeing since you only capture standard output).
Capturing standard error should help out with that, if it is indeed the issue.
As an aside, I tend to use full path names inside cron scripts, or set up very limited environments at the start to ensure everything works correctly (once I've established why it's not working correctly).

bash -x /var/lib/cloud/instance/user-data.txt runs but user-data from terraform gives error

I am trying to run a script using terraform. The content of the user-data is as follows:
.
.
cat <<EOH | java -jar ./jenkins-cli.jar -s $JENKINS_URL -auth admin:$PASSWORD create-credentials-by-xml system::system::jenkins _
<com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey plugin="ssh-credentials#1.16">
<scope>GLOBAL</scope>
<id>$CRED_ID</id>
<description>$SLAVE_IP pem file</description>
<username>ec2-user</username>
<privateKeySource class="com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey\$DirectEntryPrivateKeySource">
<privateKey>${worker_pem}</privateKey>
</privateKeySource>
</com.cloudbees.jenkins.plugins.sshcredentials.impl.BasicSSHUserPrivateKey>
EOH
.
.
When it executes as part of user-data it gives out an error as No such command create-credentials-by-xml.
But when I log in to the instance and execute bash -x /var/lib/cloud/instance/user-data.txt it runs as expected.
Can anyone please tell what is the reason for it and how to fix it? Thanks!
I have tried #cloudhook and separating the lines as well, but didn't work.
Answering my question:
Where was the problem:
The issue was not with bash but with jenkins-cli.jar itself.
The error message showed No such command create-credentials-by-xml which made me think, it was bash error but in reality, it was jar file error all along.
Reason:
The reason it was failing at user-data execution and not at bash execution was that it was unable to load configuration of plugins in a short amount of time.
Solution:
From the given reason, it is obvious that it needs time so I gave it sleep 25 to confirm it works or not and yes it does work but it was not an ideal solution.
Optimized Solution:
To make it better I listed the plugins before executing any jar commands and if the list came empty re run the commnd
# Creating CMD utility for jenkins-cli commands
jenkins_cmd="java -jar /opt/jenkins-cli.jar -s $JENKINS_URL -auth admin:$PASSWORD"
# Waiting for Jenkins to load all plugins
while (( 1 )); do
count=$($jenkins_cmd list-plugins 2>/dev/null | wc -l)
ret=$?
echo "count [$count] ret [$ret]"
if (( $count > 0 )); then
break
fi
sleep 30
done

How to run shell script as a client side hook script for tortoiseSVN?

I have written the shell script and i am trying to put that script as a client side hook script but not getting the script engine which one i should be using to run .sh file.Usually as i have seen .js file will be used as hook script for SVN unfortunately i don't know much about jscript so please help me how to add and run the script in SVN as client side hook script.I have tried using WScipt and CScirpt but both of them are not working for my shell script.
#!/bin/bash
MAIN_DIR="/cygdrive/e/Trunk/COMMON"
FILE_NAME="/cygdrive/e/Trunk_PRE_COMMIT_HOOK/long_path.txt"
lengthy_path=`find ${MAIN_DIR} -regextype posix-extended -regex '.{500,}'| awk -F'Trunk/' '{print $2}' > ${FILE_NAME}`
if [ -f ${FILE_NAME} ]
then
if [ -s ${FILE_NAME} ]
then
echo -e "\n\n\nSorry the path of a file exceeds 256 charectors, please make it shorten and try commiting again.You can see the path in $FILE_NAME"
else
echo -e "\n\n\nPath is perfect code can be committed..........."
fi
else
echo -e "\n\n\nFile not exists............"
fi
You're trying to execute a bash script on Windows, which means you either need Cygwin installed or can use the new bash shell functionality in Windows 10. I have little experience with either, but hopefully I can get you pointed in the right direction.
If you're using Cygwin, use the following command in the Tortoise hook script configuration dialog (Fig. 4.87 in the documentation):
C:\cygwin\bin\bash C:\path\to\your_script.sh
(Sourced from this answer)
If you're using the Windows 10 bash shell, use this command:
bash -c "/mnt/c/path/to/your_script.sh"
(Sourced from this page under "Run Linux Commands From Outside Bash")
Disclaimer: I haven't tested either of these because I don't have the time or means. Try it out, and leave some feedback either way.

How can I get the return code for a command which ran via ssh and not the ssh command itself?

I am trying to write a bash script in which one of the first steps is to check for the presence of a file in a remote host and whether it is executable or not. This sounds like a job for the test command, but I'd have to prefix it with ssh. Something like this:
$(ssh user#box 'test -x /path/thefile >/dev/null 2>&1; $?')
Except the above doesn't seem to be working to return to me whether the remote file exists and is executable...how would I do this?
When you use the $() syntax, you are getting the output of the command, and not the result code. You can just do:
if ssh user#box 'test -x /path/thefile'; then
echo "It exists"
fi

checking if a streaming server is up using bash?

I use Ubuntu and am trying to write a script that makes the following:
-test if an audio stream works
-if not, send an email.
I have tried the following code (running as a cron job every 10 minutes), which 'works' if I supply the wrong pw e.g.(it sends an email then), but does nothing if the actual server is down (tested by killing the server). any ideas on how to fix the script?
Thanks in advance!
#!/bin/bash
#servertest.sh
username=user1
password=xyz
url="http://wwww.streamingaudioserver.com -passwd $password -user $username"
mplayer $url &
sleep 5
test=$(pgrep -c mplayer)
if [ $test = 0 ]; then
#server is down!
mailfile="downmail.txt"
/usr/sbin/ssmtp test#maildomain.com < "/home/test/$mailfile"
fi
killall mplayer
sleep 5
exit
Your problem is in this line:
$mailfile="downmail.txt"
remove the dollar sign and that should do it.
You should be getting error messages in your cron log or emails to the crontab owner complaining about a command not found or no such file.
Edit:
Does your script work if run from the command line (with the stream down) rather than cron?
Try using set -x (or #!/bin/bash -x) in the script to turn on tracing or use echo "PID: $$, value of \$test: $test" > /tmp/script.out after the assignment to see if you're getting the zero you're expecting.
Also, try an ssmtp command outside the if to make sure it's working (but I think you already said it is under some circumstances).
Try your script without ever starting mplayer.

Resources