簡體   English   中英

在bash腳本中平穩停止inotifywait管道

[英]graceful stop inotifywait pipeline inside a bash script

我正在使用泊塢窗通過inotify和aws-cli監視和同步文件夾中的數據,但是當我嘗試使用SIGTERM殺死泊塢窗時,退出代碼143,但我想獲得零退出代碼。 而且,如果我在docker中殺死了inotify進程,它將返回零代碼。

那么,如何使用TERM信號殺死entrypoint.sh並返回0碼?

碼頭工人在這里 我將bash腳本放在下面:

#!/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 "$@"

嘗試這樣的陷阱,但失敗了:

trap "exit" INT TERM
trap "kill 0" EXIT

由docker映像的貢獻者回答。

https://github.com/vladgh/docker_base_images/issues/62

該圖像使用Tini,它不對接收到的信號的含義進行任何假設,而只是將其轉發給其子級。

為了使陷阱起作用,您需要在Dockerfile中的Tini中添加-g標志(krallin / tini#process-group-killing):

ENTRYPOINT ["/sbin/tini", "-g", "--", "/entrypoint.sh"]

只有這樣,您才能在entrypoint.sh的頂部設置陷阱:

trap "exit 0" INT TERM EXIT

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM