用vim保存文件和echo命令到底有什么不同?

探讨使用Vim编辑器和echo命令修改文件时,因inode变更导致Filebeat日志采集行为的不同,揭示Vim编辑过程中的文件替换机制。

现象

最近在调试一个filebeat程序时需要制造一些log,我是直接使用vim直接对文件打开然后直接保存的。

但是有个奇怪的现象:每次写入一行新的日志,filebeat都会将整个文件的内容又重新进行上报一遍导致日志上传重复,同时观察到filebeat的文件采集状态文件registry都会进行增加一个重复的文件。

操作一番后以为是程序的问题,最后才反应过来,最终使用echo "test some log">>test.log追加的方式发现不会有此问题。

同时看了下两者的inode信息,确认了是因为vim会改变文件的inode(一个新的文件),echo则不会:

1、查看文件inode为908488

[root@localhost work]# stat test.log
  文件:"test.log"
  大小:0          块:0          IO 块:4096   普通空文件
设备:fd00h/64768d Inode:908488      硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
环境:unconfined_u:object_r:admin_home_t:s0
最近访问:2020-05-10 04:38:39.399791808 -0400
最近更改:2020-05-10 04:38:39.399791808 -0400
最近改动:2020-05-10 04:38:39.399791808 -0400
创建时间:-

2、当我用vim/vi工具进行编辑保存之后,变为了:908490

[root@localhost work]# vi test.log
[root@localhost work]# stat test.log
  文件:"test.log"
  大小:7         	块:8          IO 块:4096   普通文件
设备:fd00h/64768d	Inode:908490      硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
环境:unconfined_u:object_r:admin_home_t:s0
最近访问:2020-05-10 04:39:01.950055784 -0400
最近更改:2020-05-10 04:39:01.950055784 -0400
最近改动:2020-05-10 04:39:01.953305882 -0400
创建时间:-

3、而用echo命令修改看到inode信息并没有改变, 908490

[root@localhost work]# echo "test some log">>test.log
[root@localhost work]# stat test.log
  文件:"test.log"
  大小:21        	块:8          IO 块:4096   普通文件
设备:fd00h/64768d	Inode:908490      硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
环境:unconfined_u:object_r:admin_home_t:s0
最近访问:2020-05-10 04:39:01.950055784 -0400
最近更改:2020-05-10 04:41:16.794459151 -0400
最近改动:2020-05-10 04:41:16.794459151 -0400
创建时间:-

验证

其实通过inode的改变以及可以猜测出在使用vi/vim进行编辑的时候,文件以及变为了一个新的文件,这里我主要通过inotifywait来看一下,在进行vim编辑的时候,文件会产生什么时间

一开始本来打算使用golang中github.com/fsnotify/fsnotify去看的,但是发现包中对event进行了合并,不够原始。所以才直接使用inotifywait来看

inotifywait命令:

inotifywait -rm test.log

1、使用vim进行编辑的结果:

[root@localhost work]# inotifywait -rm test.log
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
test.log OPEN
test.log ACCESS
test.log CLOSE_NOWRITE,CLOSE
test.log MOVE_SELF
test.log ATTRIB
test.log DELETE_SELF

可以看到对文件进行了DELETE_SELF

注意当再次进行编辑的时候,已经无法监听到了,因为原有文件已经被删除,需要重新监听

2、使用echo进行追加写入的结果

[root@localhost work]# inotifywait -rm test.log
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
test.log OPEN
test.log MODIFY
test.log CLOSE_WRITE,CLOSE

3、监听整个目录,可以看到更多信息

[root@localhost work]# inotifywait -rm ./dir/
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.

# 当进行文件写入时
./dir/ OPEN test.log
./dir/ CREATE .test.log.swp
./dir/ OPEN .test.log.swp
./dir/ CREATE .test.log.swx
./dir/ OPEN .test.log.swx
./dir/ CLOSE_WRITE,CLOSE .test.log.swx
./dir/ DELETE .test.log.swx
./dir/ CLOSE_WRITE,CLOSE .test.log.swp
./dir/ DELETE .test.log.swp
./dir/ CREATE .test.log.swp
./dir/ OPEN .test.log.swp
./dir/ MODIFY .test.log.swp
./dir/ ATTRIB .test.log.swp
./dir/ ACCESS test.log
./dir/ CLOSE_NOWRITE,CLOSE test.log
./dir/ MODIFY .test.log.swp

# 当进行文件保存是

./dir/ CREATE 4913
./dir/ OPEN 4913
./dir/ ATTRIB 4913
./dir/ CLOSE_WRITE,CLOSE 4913
./dir/ DELETE 4913
./dir/ MOVED_FROM test.log
./dir/ MOVED_TO test.log~
./dir/ CREATE test.log
./dir/ OPEN test.log
./dir/ MODIFY test.log
./dir/ CLOSE_WRITE,CLOSE test.log
./dir/ ATTRIB test.log
./dir/ MODIFY .test.log.swp
./dir/ DELETE test.log~
./dir/ CLOSE_WRITE,CLOSE .test.log.swp
./dir/ DELETE .test.log.swp

可以看到在进行文件保存时,将原有test.log 移动为test.log~,并新创建一个文件test.log,最后对test.log~备份文件和.test.log.swp缓冲区文件进行删除

总结

  • vim编辑是产生了一个新的文件,所以看到inode信息变化了,而echo仅仅只是对文件进行写入。

  • 在vim编辑过程中,会生成swp缓冲区文件,在进行vim编辑时时刻将内容保存进入swp,防止程序退出未保存

  • 产生后缀带 ~ 的备份文件,这个是在对文件进行保存时产生,如果文件被正常保存则该文件会被立即删除,正常情况下是看不到这个文件

<think>我们正在讨论在没有vim的情况下如何修改文件。根据引用[4],在Docker精简版环境中,如果没有安装vim或vi,我们可以采用几种替代方法:安装vim、使用sed命令、使用docker cp方法。用户明确询问“没有vim命令时如何修改文件”,因此我们重点考虑不安装vim的方案。 根据引用[4]提供的docker cp方法,我们可以通过以下步骤实现: 1. 将需要修改的文件从容器复制到宿主机(使用docker cp) 2. 在宿主机上使用任意文本编辑器修改文件 3. 将修改后的文件从宿主机复制回容器 此外,还可以使用sed命令直接修改容器内的文件(无需交互式编辑器),但需要知道具体的修改命令。 因此,回答应分为两部分: - 方法1:使用docker cp(适合任意修改,尤其是多行修改) - 方法2:使用sed命令(适合简单替换,无需打开文件) 注意:引用[4]中提到的docker cp方法步骤略有不同,它演示的是将宿主机上已准备好的文件覆盖容器内的文件。我们也可以将容器内的文件复制出来修改后再覆盖回去。 步骤详细说明: 方法1(docker cp): 1. 从容器复制文件到宿主机:`docker cp <容器名或ID>:<容器内文件路径> <宿主机目标路径>` 2. 在宿主机上修改文件(使用本地编辑器) 3. 将修改后的文件复制回容器:`docker cp <宿主机文件路径> <容器名或ID>:<容器内文件路径>` 方法2(使用sed): 1. 进入容器:`docker exec -it <容器名或ID> /bin/bash` 2. 使用sed命令进行修改(例如替换文本):`sed -i 's/原字符串/新字符串/g' 文件路径` 注意:使用sed需要知道具体的修改操作,且对于复杂的修改可能不太方便。 另外,如果容器正在运行,修改配置文件后可能需要重启服务或容器以使配置生效。 最后,生成相关问题。 引用标注:我们在回答中会引用到引用[4]的内容,在相应的位置标注[^4]。 </think> ### 没有vim命令时修改文件的方法 当系统中没有安装`vim`或`vi`编辑器时,可以通过以下几种方法修改文件内容(基于Linux系统,特别适用于Docker容器环境): #### 方法1:使用`docker cp`命令(推荐) 这是最安全可靠的方式,尤其适合Docker容器环境[^4]: 1. **将文件复制到宿主机** ```bash docker cp <容器名或ID>:<容器内文件路径> <宿主机临时路径> ``` 示例: ```bash docker cp myapp:/app/config.yml /tmp/config.yml ``` 2. **在宿主机修改文件** 使用任意文本编辑器(如nano、gedit等)修改文件: ```bash nano /tmp/config.yml # 修改并保存 ``` 3. **将文件复制回容器** ```bash docker cp <宿主机文件路径> <容器名或ID>:<容器内文件路径> ``` 示例: ```bash docker cp /tmp/config.yml myapp:/app/config.yml ``` #### 方法2:使用流编辑器`sed` 适合简单文本替换(如修改配置参数)[^4]: ```bash docker exec <容器名或ID> sed -i 's/旧内容/新内容/g' <文件路径> ``` 示例: ```bash # 将配置文件中的"debug: false"改为"debug: true" docker exec myapp sed -i 's/debug: false/debug: true/g' /app/config.yml ``` #### 方法3:使用`echo`重定向 适合创建新文件或覆盖小文件: ```bash docker exec <容器名或ID> sh -c "echo '文件内容' > <文件路径>" ``` 示例: ```bash # 创建新配置文件 docker exec myapp sh -c "echo 'log_level: info' > /app/new_config.yml" ``` #### 方法4:安装轻量级编辑器 如果容器有网络连接,可安装`nano`等轻量编辑器: ```bash docker exec -it <容器名或ID> apt-get update && apt-get install -y nano docker exec -it <容器名或ID> nano <文件路径> ``` #### ⚠️ 注意事项 1. **权限问题**: 使用`docker cp`时,宿主机用户需有文件读写权限 2. **文件编码**: 确保修改后的文件保持原有编码(如UTF-8) 3. **容器状态**: 修改配置文件后,可能需要重启容器使更改生效: ```bash docker restart <容器名或ID> ``` > **应用场景建议**: > - 复杂修改 → 选择`docker cp`方法 > - 简单替换 → 使用`sed`命令 > - 紧急修复 → 用`echo`快速覆盖
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值