停止运行一定时间的Docker容器

4
我想创建一个定时任务,如果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脚本实现这一点?

你的问题是什么? - Travis
6个回答

4
这是一个老帖子,但如果有人正在寻找答案。以下命令将停止运行超过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

将从先前输出中获取的容器名称打印出来,并将其作为参数传递给停止容器的命令。

你的答案将停止运行X个小时的容器,但不会影响运行Y周或Z个月的容器。 - suren
这也是危险的,因为包含了.Names。如果那个自由文本名称恰好包含字符串hours,并且第一个值大于2,它将被删除。最好使用"{{.RunningFor}} {{.ID}}" - Martin

1

@Siru的一行代码很棒,但是我不得不更改以下部分,以便正确查找超过两位数天数的容器:

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

1

这个问题早在2013年就在问题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)。

0
我本来希望在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

关于使用日期计算偏移量的其他示例,请参见unix.SE中的此帖子


0

我使用这个简单的方法(源自Siru's answer)来停止运行超过24小时的任何程序。

docker ps --format="{{.ID}} {{.RunningFor}}" | grep "day\|week\|month" | awk '{print $1}' | xargs docker stop

如果你同时运行了Siru's answer和这个方法,那么你可以可靠地清理指定数量的小时,但在那时可能最好使用Itiel's solution


有一种情况是docker ps显示33小时前,但没有显示"day",所以你的解决方案无法捕捉到这种情况。 - undefined

0

@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

说明:

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

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接