
最近在读《计算机程序的构造和解释》,里面有一句话:代码必须能够被人阅读,只是机器恰巧可以执行。我也想到了一句话:BUG一定能够被人写出,只是恰好我写的多而已。说多了都是泪,来看看我最近遇到的一个问题。......
最近在读《计算机程序的构造和解释》,里面有一句话:代码必须能够被人阅读,只是机器恰巧可以执行。
我也想到了一句话:BUG一定能够被人写出,只是恰好我写的多而已。
说多了都是泪,来看看我最近遇到的一个问题。
问题普通的一天,打开普通的电脑,登录一台普通的服务器,敲下一条普通的命令。
在我使用命令补全时,出现了一条不普通的提示:
-bash:cannotcreatetempfileforhere-document:Nospaceleftondevicels-bash
怎么磁盘满了?
使用df-h一看还真是。
什么原因呢?
解决首先,查找一下系统里的大文件,看看是哪个小可爱搞的鬼。
du-sh/*|grepG
很快就定位到了这个目录:/var/lib/docker/containers。
原来是Docker这家伙,这个目录下存放的都是容器运行过程中产生的日志。
使用下面命令来给这些文件按大小排个序:
du-d1-h/var/lib/docker/containers|sort-h32K/var/lib/docker/containers/d607c06e475191fff1abd0c2b4b672e7fe8a96cb197f4e8557b18600de2e60af36K/var/lib/docker/containers/0d4321106721b9d26335fefef7b9e8e23629691684a4da2f953ac8223c8240c336K/var/lib/docker/containers/7525aab4aa917aa10161691ac7b9cc712bef35cdc7035b50d20ce36K/var/lib/docker/containers/9252e1c373d59ef5613c2b6122eb6e43aa2bd822bd2c199aa67d6eb659c4adb7142M/var/lib/docker/containers142M/var/lib/docker/containers/15700ee92cd2831554b9a1e78127df0f07248c1498d35c17525407bc8a98bc1a
文件名称就是容器ID,每个文件对应一个容器,也就可以定位到,具体是哪个容器产生了大量的日志。
使用这个命令可以将大文件快速清空:
sh-c"cat/dev/null${log_file_name}"但是清空了文件哪算解决问题,新的日志还在源源不断往日志里打呢。看了看日志内容,很熟悉。前两天为了调试程序,刚加的一条print。
编辑代码,删除print,重启容器。好了,日志不再疯狂追加了。
为什么print语句将日志都输出到文件里了呢?别着急,后面再来详细介绍。
先处理一下眼前的问题,放任日志无限增长是肯定不行的,需要有一个单个文件大小限制。否则,明天张三再加一条print,磁盘又满了。
这里有两个方案:
单一容器配置
全局配置
单一容器配置启动容器时,通过参数来控制日志的文件个数和单个文件的大小:
dockerrun-it--log-optmax-size=10m--log-optmax-file=3redis
但这样做是比较麻烦的,更多的采用的是全局配置的方式。
全局配置编辑/etc/docker/:
{"log-driver":"json-file","log-opts":{"max-size":"50m","max-file":"3"}}重启Docker服务:
systemctldaemon-reloadsystemctlrestartdocker
注意:已存在的容器不会生效,需要重建才可以。
接下来再说说上文提到的print问题。
Docker日志Docker日志分为两类:
Docker引擎日志(也就是dockerd运行时的日志)
容器的日志,容器内的服务产生的日志
引擎日志Docker引擎日志一般是交给了Upstart()或者systemd(CentOS7,)。前者一般位于/var/log/upstart/下,后者一般通过journalctl-udocker进行查看。
不同系统的位置都不一样,网上有人总结了一份列表,我修正了一下,可以参考:
系统
日志位置
Ubuntu(14.04)
/var/log/upstart/
Ubuntu(16.04)
CentOS7/RHEL7/Fedora
CoreOS
OpenSuSE
OSX
~/Library/Containers//Data/
DebianGNU/Linux7
/var/log/
DebianGNU/Linux8
Boot2Docker
/var/log/
容器日志使用下面命令可以显示当前运行的容器的日志信息:
dockerlogsCONTAINER
UNIX和Linux命令有三种输入输出,分别是STDIN、STDOUT和STDERR。dockerlogs显示的内容包含STDOUT和STDERR。
在生产环境下,如果我们的应用输出到日志文件里,那么我们在使用dockerlogs时一般收集不到太多重要的信息。
这里来看一下nginx和httpd是怎么做的:
nginx官方镜像,使用了一种方式,让日志输出到STDOUT,也就是创建一个符号链接/var/log/nginx/到/dev/stdout。
httpd使用的是让其输出到指定文件,正常日志输出到/proc/self/fd/1(STDOUT),错误日志输出到/proc/self/fd/2(STDERR)。
当日志量比较大的时候,使用dockerlogs来查看日志,会对dockerdaemon造成比较大的压力,容易导致容器创建慢等一系列问题。
只有使用了local、json-file、journald日志驱动的容器才可以使用dockerlogs捕获日志,使用其他日志驱动无法使用dockerlogs。
Docker默认使用json-file作为日志驱动。
除此之外,Docker还提供了很多其他日志驱动,这里就不过多介绍。还有日志管理方案,我也不是很有经验,大家如果感兴趣的话自己搜搜看吧。
参考文章:
文章中的脑图和源码都上传到了GitHub,有需要的同学可自行下载。
地址: