【问题标题】:Stop a Docker container that's been running for a certain amount of time停止运行了一段时间的 Docker 容器
【发布时间】:2017-06-06 04:17:30
【问题描述】:

我想创建一个 cron 作业,如果 Docker 容器已经运行超过 2 小时,它将停止它们。

我可以知道他们开始的时间。

$ docker inspect -f '{{ .State.StartedAt }}' $(docker ps -q)

只需将其与 2 小时前进行比较...

$ date --utc --date="-2 hours" +"%Y-%m-%dT%H:%M:%S.%NZ"

...如果它更早停止容器

$ docker stop <<container_id>>

如何使用 bash 脚本执行此操作?

【问题讨论】:

  • 你的问题到底是什么?

标签: bash docker


【解决方案1】:

这是一个旧线程,但如果有人正在寻找答案。以下命令将停止容器运行超过 2 小时。

docker ps --format="{{.RunningFor}} {{.Names}}"  | grep hours |  awk -F: '{if($1>2)print$1}' | awk ' {print $4} ' | xargs docker stop

说明:

docker ps --format="{{.RunningFor}} {{.Names}}" 

将打印容器名称和运行时间。

grep hours 

将打印几小时内运行的容器。

 awk -F: '{if($1>2)print$1}' 

只会打印运行超过 2 小时的容器。

awk ' {print $4} ' | xargs docker stop

将打印从先前输出中获得的容器名称并将其作为参数传递以停止容器。

【讨论】:

    【解决方案2】:

    早在 2013 年,issue 1905 就对此进行了讨论

    bash 替代方案是:

    #!/bin/bash
    set -e
    
    to=$1
    shift
    
    cont=$(docker run -d "$@")
    code=$(timeout "$to" docker wait "$cont" || true)
    docker kill $cont &> /dev/null
    echo -n 'status: '
    if [ -z "$code" ]; then
        echo timeout
    else
        echo exited: $code
    fi
    
    echo output:
    # pipe to sed simply for pretty nice indentation
    docker logs $cont | sed 's/^/\t/'
    

    与:

    $ docker-run-timeout.sh 10s busybox sh -c 'echo start && sleep 30 && echo finish'
    status: timeout
    output:
        start
    

    注意,使用 docker 1.13,您可以使用--rm -d 运行(请参阅PR 20848)。

    【讨论】:

      【解决方案3】:

      @Siru 的单线器很棒,但是我必须更改下面的部分才能正确找到超过两位数天数的容器:

      awk -F " " '{if($1>14)print$0}'
      

      【讨论】:

        【解决方案4】:

        我希望在格式字符串的 Go 模板中执行此操作,但我认为我们没有任何时间解析函数包含在内(可能是一个不错的 PR)。

        相反,这是一个利用 date 命令进行时间解析的版本:

        #!/bin/sh
        # adjust threshold as needed
        threshold="2 hours"
        # cutoff is seconds since epoc of the threshold time
        cutoff="$(date --date="-$threshold" "+%s")"
        # loop through the running containers by id
        docker container ls -q | while read cid; do
          # retrieve the start time as a string
          startedat="$(docker container inspect "$cid" --format "{{.State.StartedAt}}")"
          # convert to seconds since epoc
          start="$(date --date="$startedat" "+%s")"
          # then we can do a numeric comparison in shell
          if [ "$start" -lt "$cutoff" ]; then
            docker container stop "$cid"
          fi
        done
        

        有关使用日期计算偏移量的其他示例,请参阅this post in unix.SE

        【讨论】:

          【解决方案5】:

          @siru 的解决方案启发了我寻找一个选项来控制确切的时间,因为 docker ps running for 是一个四舍五入的格式结果,而不是精确的:

          docker ps -q | xargs docker inspect --format='{{.Id}} {{.State.StartedAt}}' |\
           awk '{"date -d " $2 " +%s" | getline startedAt
           "date +%s" | getline now
           if((now-startedAt)/(60*60) > 5) print $1}' |\
           xargs docker rm -f
          

          解释:

          第一行将以 ISO 8601 格式传递容器 ID 及其开始时间的列表。

          然后我们将每个日期转换为 UNIX 时间,计算当前时间的 delta,并仅将运行时间超过指定时间的行传递给 docker rm -f

          在本例中,所有运行时间超过 6 小时的容器都将被移除。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2023-03-18
            • 2020-07-21
            • 2017-06-26
            • 1970-01-01
            • 1970-01-01
            • 2020-06-10
            • 2022-12-10
            相关资源
            最近更新 更多