Detect if docker ran successfully within the same script - shell

My script.sh:
#/bin/sh
docker run --name foo
(Just assume that the docker command works and the container name is foo. Can't make the actual command public.)
I have a script that runs a docker container. I want to check that it ran successfully and echo the successful running status on the terminal.
How can I accomplish this using the container name? I know that I have to use something like docker inspect but when I try to add that command, it only gets executed after I ^C my script probably because docker has the execution.
In this answer, the docker is executed in some other script so it doesn't really work for my use case.

The linked answer from Jules Olléon works on permanently running services like webservers, application servers, database and similar software. In your example, it seems that you want to run a container on-demand, which is designed to do some work and then exit. Here, the status doesn't help.
When running the container in foreground mode as your example shows, it forwards the applications return code to the calling shell. Since you didn't post any code, I give you a simple example: We create a rc.sh script returning 1 as exit-code (which normally indicates some failure):
#!/bin/sh
echo "Testscript failed, returning exitcode 1"
exit 1
It got copied and executed in this Dockerfile:
FROM alpine:3.7
COPY rc.sh .
ENTRYPOINT [ "sh", "rc.sh" ]
Now we build this image using docker build -t rc-test . and execute a short living container:
$ docker run --rm rc-test
Testscript failed, returning exitcode 1
Bash give us the return code in $?:
$ echo $?
1
So we see that the container failed and could simply check them e.g. inside some bash script with an if-condition to perform some action when it fails:
#!/bin/bash
if ! docker run --rm rc-test; then
echo "Docker container failed with rc $?"
fi

After running your docker run command you can check this way if your docker container is still up and running:
s='^foo$'
status=$(docker ps -qf "name=$s" --format='{{.Status}}')
[[ -n $status ]] && echo "Running: $status" || echo "not running"

You just need to execute it with "-d" to execute the container in detached mode. With this, the solutions provided in the other post or the solution provided by #anubhava are both good solutions.
docker run -d -name some_name mycontainer
s='^some_name$'
status=$(docker ps -qf "name=$s" --format='{{.Status}}')
[[ -n $status ]] && echo "Running: $status" || echo "not running"

Related

How can I build a shell script to build a Docker-Compose Image and start up the Docker container if successful?

I'm trying to write a shell script that will attempt to build a Docker-Compose image, then if that's successful, start up the Docker container with it by doing a Docker-Compose up -d.
In the second step, I load some JSON files into Mongo, but then if there's a problem with that step, I want want to stop all Docker services and print out an error message saying "Could not start Docker service because there was a problem seeding the DB."
My problem is that I don't know how to check if the image was created successfully in the first step. (I want to stop and print out a message saying that there were errors in the build.)
I think I can figure out something that checks if both services are running at the end, but I'm wondering if there is a way to print out the name of the problematic JSON file that couldn't load.
Does anyone have a similar script that I can use or modify for my own use?
My understanding is you are trying to branch out the logic of the script based on whether the build command was a success. Here is what you can do:
cat create-image.sh
#!/bin/bash
docker build -q -t test-image .
if [ $? -eq 0 ]; then
echo OK, images created
else
echo FAIL, image not created
exit 1
fi
echo "...DOING OTHER THINGS... (like docker-compose up)"
Let me know if this is what you were looking for.
You don't need a script if you just want to build images before starting containers:
docker-compose --build up
If you must use a script, you can certain call the above command and check its exit code. There is no need to call docker build individually for every service in the docker-compose file.

Troubleshooting PM2 Restart in Cron

Update: I was not able to get this working as I desired. I ended up using the pm2 --cron flag since cron couldn't find my pm2 processes.
I am using pm2 restart in a bash script and it always fails on the pm2 restart projectName commands when run by cron (as root) but works when run manually with sudo. I am not sure how to troubleshoot as the pm2 log files don't show anything obvious. It looks like someone else has had the same issue so perhaps it's just a bug? Has anybody else found a way to resolve this issue?
Thank you!
Edit: Adding some context for #kevinnls
Here's the .sh script; I've isolated the command so I can test cron
# Vars
NOW=$(date +"%Y-%m-%d")
LOGS_PATH="/scriptLoc/logs"
LOG_FILE="$LOGS_PATH/$NOW-log.txt"
BE_PATH="/beLoc"
# Start log file
date >> $LOG_FILE
echo "Running..." >> $LOG_FILE
# Temp
cd $BE_PATH
pm2 restart be >> $LOG_FILE
pm2 restart be || echo "ERROR: BE pm2 restart: $?" >> $LOG_FILE
echo "Done." >> $LOG_FILE
exit
If I run the command with sudo ./script.sh it works
If I run it with cron I see the following output in my log file:
Fri Mar 26 17:35:01 UTC 2021
Running...
Use --update-env to update environment variables
ERROR: BE pm2 restart: 1
Done.
If I view pm2 logs:
I see it exit with code 0 and restart when I run the script manually.
I see no output for the failed restart from cron
The error you got:
[PM2][ERROR] Process or Namespace be not found
What is "be"? seems like pm2 from inside of cron has no idea what to make of it.
If it is a file, when you ran the script in your shell, was the file be in your working directory?
You can make these changes to log your error messages to $LOG_FILE.
This should help you get more details.
#redirect output *and* errors to log
pm2 restart be &>> $LOG_FILE
exit_code=$?
# if previous exit code != 0 do everything after `&&'
[[ $exit_code -ne 0 ]] && echo "ERROR: BE pm2 restart: $exit_code" >> $LOG_FILE
Then try running your script again and share the errors encountered.
I was not able to resolve this in the manner I desired. Ultimately I used the -c (cron) flag with pm2 itself.
pm2 cli reference
gitlab issue

Nagios custom plugin calling python Openstack Swift client

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

executing command on vagrant-mounted

I'm trying to run a command after a share is mounted with vagrant. bu I've never written an upstart script before. What I have so far is
start on vagrant-mounted
script
if [ "$MOUNTPOINT" = "/vagrant" ]
then
env CMD="echo $MOUNTPOINT mounted at $(date)"
elif [ "$MOUNTPOINT" = "/srv/website" ]
then
env CMD ="echo execute command"
fi
end script
exec "$CMD >> /var/log/vup.log"
of course that's not the actual script I want to run but I haven't gotten that far yet but the structure is what I need. My starting point has been this article. I've had a different version that was simply
echo $MOUNTPOINT mounted at `date`>> /var/log/vup.log
that version did write to the log.
Trying to use init-checkconf faile with failed to ask Upstart to check conf file

How to detect if docker run succeeded programmatically?

I'm writing a very simple bash script to quickly check that my container still builds and starts correctly and that the app inside responds to requests.
Sometimes docker run fails, e.g. because the port I'm trying to bind the container to is already allocated. But when this happens docker run's exit code is still 0 so I can't use the exit code. How can I check programmatically that the container got started correctly?
The solutions I'm considering are:
parse the output for errors
docker ps to see if the container is running
but these both seem a little overkill and ugly. Am I missing a better way to check whether docker run succeeded?
As suggested by Abel Muiño in comments, this may have been fixed in more recent Docker versions (I'm currently running 0.9.1).
But, if you're temporarily stuck like me with an older version, I did find a decent workaround to check if the container started by using docker inspect.
docker inspect returns a JSON object with a lot of info about the container, and in particular whether the container is currently running or not. The -f flag lets you easily extract the bits needed:
docker inspect -f {{.State.Running}} $CONTAINER_ID
or
docker inspect -f "{{.State.Running}}" $CONTAINER_ID
will return true or false.
Note that you probably want to sleep 1 (or more) between starting the container and checking if it is up. If there's something wrong with your setup it's possible that it would appear as 'running' for a very short time before actually exiting.
To avoid parsing anything, you could use docker top, which returns 1 if the container is not running:
id=$(docker run mycontainer)
if ! docker top $id &>/dev/null
then
echo "Container crashed unexpectedly..."
return 1
fi
We could use docker exec $id true 2>/dev/null || echo not running.
This command does not write to stdout, as "docker top" does. It writes to stderr when the container is not running, the same message as "docker top".
Applying the suggestions aforementioned to a script.
1 - Create a script keepMyDockerUp.sh :
vi keepMyDockerUp.sh
#!/bin/bash
Container_ID=INSERT_YOUR_CONTAINER_ID HERE
result=$( docker inspect -f {{.State.Running}} $Container_ID)
echo "result is" $result
if [ $result = "true" ]
then
echo "docker is already running"
else
systemctl restart docker
docker start $Container_ID
fi
2 - Then simply add it to cron, so your script verifies whether your Docker container is up from time to time:
crontab -e
Go to the last line and add your script file. For example:
* * * * * /root/keepMyDockerUp.sh
3 - Save crontab and never worry about your Docker container being down again.
Hope it helps...
;-)
I had to use:
$ docker inspect -f {{.State.Health.Status}} xxx
(the container was in state running but the service inside the container wasn't fully started.
Part of inspect output:
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 1618,
"ExitCode": 0,
"Error": "",
"StartedAt": "2019-03-08T10:39:24.061732398Z",
"FinishedAt": "0001-01-01T00:00:00Z",
"Health": {
"Status": "starting",
"FailingStreak": 0,
"Log": []

Resources