I am using a docker to watch and sync data in a folder with inotify and aws-cli but when I try to kill the docker with SIGTERM
it exit with code 143 but I want to get a zero exit code. And if i kill the inotify process inside the docker it do return a zero code.
So how can I kill the entrypoint.sh
with TERM
signal and return a 0 code?
The docker is here. I put the bash script below:
#!/usr/bin/env bash
# S3Sync Entry Point
# Bash strict mode
set -euo pipefail
IFS=$'\n\t'
# VARs
S3PATH=${S3PATH:-}
SYNCDIR="${SYNCDIR:-/sync}"
CRON_TIME="${CRON_TIME:-10 * * * *}"
INITIAL_DOWNLOAD="${INITIAL_DOWNLOAD:-true}"
# Log message
log(){
echo "[$(date "+%Y-%m-%dT%H:%M:%S%z") - $(hostname)] ${*}"
}
# Sync files
sync_files(){
local src="${1:-}"
local dst="${2:-}"
mkdir -p "$dst" # Make sure directory exists
log "Sync '${src}' to '${dst}'"
if ! aws s3 sync --no-progress --delete --exact-timestamps "$src" "$dst"; then
log "Could not sync '${src}' to '${dst}'" >&2; exit 1
fi
}
# Download files
download_files(){
sync_files "$S3PATH" "$SYNCDIR"
}
# Upload files
upload_files(){
sync_files "$SYNCDIR" "$S3PATH"
}
# Run initial download
initial_download(){
if [[ "$INITIAL_DOWNLOAD" == 'true' ]]; then
if [[ -d "$SYNCDIR" ]]; then
# directory exists
if [[ $(ls -A "$SYNCDIR" 2>/dev/null) ]]; then
# directory is not empty
log "${SYNCDIR} is not empty; skipping initial download"
else
# directory is empty
download_files
fi
else
# directory does not exist
download_files
fi
elif [[ "$INITIAL_DOWNLOAD" == 'force' ]]; then
download_files
fi
}
# Watch directory using inotify
watch_directory(){
initial_download # Run initial download
log "Watching directory '${SYNCDIR}' for changes"
inotifywait \
--event create \
--event delete \
--event modify \
--event move \
--format "%e %w%f" \
--monitor \
--quiet \
--recursive \
"$SYNCDIR" |
while read -r changed
do
log "$changed"
upload_files
done
}
# Install cron job
run_cron(){
local action="${1:-upload}"
# Run initial download
initial_download
log "Setup the cron job (${CRON_TIME})"
echo "${CRON_TIME} /entrypoint.sh ${action}" > /etc/crontabs/root
exec crond -f -l 6
}
# Main function
main(){
if [[ ! "$S3PATH" =~ s3:// ]]; then
log 'No S3PATH specified' >&2; exit 1
fi
mkdir -p "$SYNCDIR" # Make sure directory exists
# Parse command line arguments
cmd="${1:-download}"
case "$cmd" in
download)
download_files
;;
upload)
upload_files
;;
sync)
watch_directory
;;
periodic_upload)
run_cron upload
;;
periodic_download)
run_cron download
;;
*)
log "Unknown command: ${cmd}"; exit 1
;;
esac
}
main "$@"
Trying trap like this but failed:
trap "exit" INT TERM
trap "kill 0" EXIT
Answered by the contributor of the docker image.
https://github.com/vladgh/docker_base_images/issues/62
This image uses Tini, which does not make any assumptions about the meaning of the signal it receives and simply forwards it to its child.
In order for your traps to work you need to add the -g flag to Tini in the Dockerfile (krallin/tini#process-group-killing):
ENTRYPOINT ["/sbin/tini", "-g", "--", "/entrypoint.sh"]
An only then you can set a trap at the top of the entrypoint.sh
:
trap "exit 0" INT TERM EXIT