sed (Stream Editor, 文本流编辑器) 可谓是 shell 中必不可少一款文本处理工具了。我们经常会使用 sed -i 参数来对一些配置文件做自动化修改,但是此次在 docker 这样做中却遇到了问题sed: can't move '/etc/redis.confDhPCho' to '/etc/redis.conf': Resource busy

docker-entrypoint.sh 启动部分如下,# first boot

if [ ! -f /data/dump.rdb ]; then

if [ -z "$REDIS_PASSWORD" ]; then

REDIS_PASSWORD="$(pwgen 16 1)"

echo "[INFO] Generated Redis Password: $REDIS_PASSWORD"

fi

sed -i "s/^# requirepass foobared$/requirepass $REDIS_PASSWORD/" /etc/redis.conf

fi

docker-compose.yml 部分配置文件如下,redis:

build: ./redis

image: docker-lnmp-redis:latest

ports:

- "6379:6379"

networks:

- backend

volumes:

- ./redis/redis.conf:/etc/redis.conf:rw

- ./data/logs/redis/:/var/log/redis/:rw

- ./data/redis/:/data/:rw

environment:

REDIS_PASSWORD: 123456

restart: always

container_name: redis

根据启动文件可知由该镜像创建的容器首次启动会对 /etc/redis.conf 文件做修改,而在 docker-compose.yml 中配置外部文件映射到容器内 /etc/redis.conf,也即容器首次启动就会修改这个外部文件。

然而 sed 并不给面子,抛出了一个异常,究其原因,在于 sed -i 此操作看似是修改了文件,但实际上为使用具有修改后的内容的新文件覆盖了原文件,这将导致文件的 Inode 发生变化,而在 docker 中挂载的文件是不允许这样做的。类似的问题还存在于 sed -i 修改符号文件。$ echo 123 > txt

$ stat txt

File: txt

Size: 4               Blocks: 8          IO Block: 4096   regular file

Device: fc01h/64513d    Inode: 1179795     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1000/    choi)   Gid: ( 1000/    choi)

Access: 2019-03-09 03:11:32.293005107 +0800

Modify: 2019-03-09 03:11:32.293005107 +0800

Change: 2019-03-09 03:11:32.293005107 +0800

Birth: -

# 使用 sed -i 修改文件 Inode 会变

$ sed -i 's/123/abc/' txt

$ stat txt

File: txt

Size: 4               Blocks: 8          IO Block: 4096   regular file

Device: fc01h/64513d    Inode: 1179862     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1000/    choi)   Gid: ( 1000/    choi)

Access: 2019-03-09 03:12:42.571444788 +0800

Modify: 2019-03-09 03:12:42.571444788 +0800

Change: 2019-03-09 03:12:42.571444788 +0800

Birth: -

为了避免文件覆盖导致 Inode 变化,于是乎有了一个大胆的想法——使用重定向来重写文件内容$ echo 123 > txt

$ stat txt

File: txt

Size: 4               Blocks: 8          IO Block: 4096   regular file

Device: fc01h/64513d    Inode: 1179795     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1000/    choi)   Gid: ( 1000/    choi)

Access: 2019-03-09 03:14:10.738505467 +0800

Modify: 2019-03-09 03:14:10.738505467 +0800

Change: 2019-03-09 03:14:10.738505467 +0800

Birth: -

# 使用重定向修改不会导致文件 Inode 变化

$ echo abc > txt

$ stat txt

File: txt

Size: 4               Blocks: 8          IO Block: 4096   regular file

Device: fc01h/64513d    Inode: 1179795     Links: 1

Access: (0664/-rw-rw-r--)  Uid: ( 1000/    choi)   Gid: ( 1000/    choi)

Access: 2019-03-09 03:14:10.738505467 +0800

Modify: 2019-03-09 03:15:19.244883632 +0800

Change: 2019-03-09 03:15:19.244883632 +0800

Birth: -

接着有了如下修改......sed "s/^# requirepass foobared$/requirepass $REDIS_PASSWORD/" /etc/redis.conf > /etc/redis.conf

然鹅,正当沉浸在找到问题原因所在的欢乐中,现实再一次给了沉痛一击......

是的,Inode 是没变,但是文件内容已经空空如也了!!!

为什么会这样呢,原因在于 I/O 重定向时 stdout 与 stderr 的管道会先准备好再从 stdin 读入,也就是说 > file 时会先将 file 清空然后再读入数据,因此不等到 sed 读数据时文件已经就是空的了。# I/O 重定向会先清空文件

$ echo 123 > txt

$ cat  txt

$ cat test.txt

正确做法如下,既保证了 Inode 不变又修改了文件内容$ echo 123 > txt

# 注意不可以再将 tee txt >/dev/null 否则又是空

# https://github.com/koalaman/shellcheck/wiki/SC2094

$ cat txt | sed 's/123/abc/' | tee txt

# 或

$ sed 's/123/abc' txt > tmp && cat tmp > txt && rm tmp

linux sed i参数,sed 慎用 -i 参数相关推荐

  1. Linux进阶 vim grep sed awk 正则表达式

    01 Linux上的文本编辑器vim vim 编辑器是什么 vim 编辑器的三种模式 注意大小写!!! 打开文件时文件可以存在或者不存在,不存在时当关闭的时候系统会创建 命令模式 • 用vim FIL ...

  2. linux用户变量设置位置,linux---位置参数

    位置变量参数 在向脚本传递参数时,可以使用此位置变量来获取参数. 他们分别是: $0:脚本名字.此变量包含地址,可以使用basename $0获得脚本名称. $1:第一个参数 $2,$3,$4,$5, ...

  3. 在Linux里awk与sed的区别,linux awk和sed讲解

    sed 工具简介 在了解了一些正规表示法的基础应用之后,再来呢?呵呵-两个东西可以玩一玩的,那就是 sed 跟 awk 了! 这两个家伙可是相当的有用的啊!举例来说,鸟哥写的 logfile.sh 分 ...

  4. 怎么在linux终端上sed,Linux中如何使用sed命令

    Linux中sed命令主要用于文本的处理,可处理文本的行和列,下面小编就给大家详细介绍下Linux中sed命令的用法,有兴趣的朋友不妨来了解下吧. sed命令行格式为: sed [-nefri] 'c ...

  5. linux p 参数,tar的-p参数解决方案

    当前位置:我的异常网» Linux/Unix » tar的-p参数解决方案 tar的-p参数解决方案 www.myexceptions.net  网友分享于:2013-01-05  浏览:7次 tar ...

  6. linux下查询日志sed与或非,Linux命令之sed命令使用介绍

    sed是linux轻量级流编辑器,用于行的操作,主要用来数据的选取.替换.删除.新增等.从输入文件中一次一行的读取, 按顺序将列表中的命令应用到每一行,并将其编辑过的行,写到标准输出. 权  限:所有 ...

  7. linux sed工具,玩转Linux - 神级工具 sed awk

    简介 本文主要介绍 Linux 系统的两个神级工具:sed 和 awk ,他们是Linux高手们必备的技能,很值得我们去研究的东西. 这里是我在网上书上收集的相关资料,因为这两个工具很有名也很重要,所 ...

  8. Linux三大剑客之sed

    一.简介 sed英文全称是stream editor.由贝尔实验室开发,如今主流Unix/Linux操作系统上都集成了这个工具.sed由自由软件基金组织(FSF)开发和维护,并且随着GNU/Linux ...

  9. linux三剑客awk、sed、grep与cut的总结

    在Linux中,一切皆文件,对Linux的操作就是对文件的处理.对文件操作处理最重要的三个命令是grep.sed.awk,它们在业界被称为"三剑客". 三剑客的功能非常强大,但它们 ...

  10. 【Linux上分之路】第十二篇:Linux三剑客grep、sed、awk

    文章目录 Linux三剑客 三剑客特点及应用场景 grep grep命令的基本格式 grep范例 grep命令选项 -A.-B -c.-v -n.-w sed sed命令基本格式 sed命令功能 se ...

最新文章

  1. 这可能是史上最全的Python算法集!
  2. 一个电商供应链系统的DDD实战
  3. Java 内存泄漏监控检测与分析
  4. 引导扇区维护工具linux,BOOTICE(引导扇区维护工具)
  5. ABP理论学习之依赖注入
  6. delphi7下安装TMS component
  7. 基于django和vue的xdh官网设计
  8. 计算机专业和机电专业的区别,12届计算机专业和机电专业.doc
  9. hadoop 之NullWritable与ObjectWritable
  10. 数睿数据、艾瑞咨询联合发布《2021年中国企业级无代码开发白皮书》
  11. 线程创建方式3-实现 callable接口(Java)
  12. django数据库处理
  13. 双亲委派模型与 Flink 的类加载策略
  14. LBS (基于位置服务)-- Location Based Service
  15. CRNN——卷积循环神经网络结构
  16. 域——windows服务器域详解
  17. 让微积分穿梭于工作与学习之间(7):我自认为牛逼的成果之三:直接用定义求正切函数的导数
  18. ArcGIS 关于三维立体地图 简单使用,里面的资源就在 arcgis 的demo里面有
  19. docker创建jenkins、jenkins配置邮件模板、jenkins升级、jenkins更改插件源
  20. 霸气牵手众多手机品牌商,苏宁手机蜜蜂节实力彰显行业影响力

热门文章

  1. Mysql5.6 自动化部署
  2. Qtum手机钱包教程
  3. win10 安装 mysql解压版安装步骤
  4. 练手小程序之约瑟芬杀人法
  5. PHP如何关闭notice级别的错误提示
  6. android 对象传输及parcel机制
  7. 寻找节点d=n的节点算法
  8. android笔记集one
  9. linux中如何记录时间
  10. 用reloadRowsAtIndexPaths刷新单个cell 跳动问题