通过就地编辑进行Sed更改文件的组所有权


8

我有shell(php)脚本,可以通过这种方式与目标文件联系:

  • 检查文件和目录是否可写与phpis_writable()(我不认为这是问题)
  • 使用以下sed命令进行就地文件编辑:

grep -q "$search" "$passwd_file" && { sed -i "s|$search|$replace|" "$passwd_file"; printf "Password changed!\n"; } || printf "Password not changed!\n"

因此,我得到这是(一切正确的,但)文件myuser:www-datamyuser:myuser

是否可以sed更改文件组的所有权?如果可能,如何避免更改?


Answers:


16

sed就地编辑模式存在一点问题-ised在名为的同一目录中创建一个临时文件sedy08qMA,其中y08qMA是随机生成的字符串。该文件将填充原始文件的修改内容。操作后,sed删除原始文件,并使用原始文件名重命名临时文件。因此,这不是真正的就地编辑。它创建具有调用用户权限和新inode编号的新文件。这种行为通常还不错,但是例如,硬链接断开了。

但是,如果要进行真正的就地编辑,则应使用ed。它从stdin读取命令并直接编辑文件,而没有临时文件(通过ed的内存缓冲区完成)。一种常见的做法是用于printf生成命令列表:

printf "%s\n" '1,$s/search/replace/g' wq | ed -s file

printf命令产生的输出如下:

1,$s/search/replace/g
wq

这两行是ed命令。第一个搜索字符串search并将其替换为replace。第二个将w更改写入()并退出(q)。-s抑制诊断输出。


8

work的-i参数是sed在操作过程中创建一个临时文件,然后最后用该临时文件覆盖实际文件。这是最有可能导致此问题的原因,因为在创建临时文件时,其所有权默认为myuser:myuser

您可以setgid在父目录上设置该位(仅当父目录由group拥有时www-data),以便在此目录下创建的文件继承同一组。
要做到这一点:

chmod g+s parent-dir-of-your-file  

我认为这是位的非常典型的用法setgid


@cuonglm我刚刚在strace上sed -i进行了跟踪,在跟踪中找到了以下行,这是否意味着它在当前目录中创建了临时文件?open("./sedKyG9Ei", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
Dave.d

@DavidDai:是的,我的记忆不佳。
cuonglm '16

2

鉴于您必须通过管道输入其他输入,因此使用ed代替代替sed似乎是多余的。我现在正在开发的发行版(CentOS 5.10)可以使用该-c选项,sed它利用了temp文件的“复制”,而不是与该-i选项一起使用时只是简单地重命名。我已经对其进行了测试,并且效果很好,在进行内联编辑时可以保留原始所有者和组。它不会保留修改时间。

例如, sed -ci -e '3,5d' file.txt

  • -c 使用复制而不是重命名(即保留所有权/组)
  • -i 内联编辑
  • -e 要执行的脚本/表达式

不确定此选项sed在其他发行版中的普及程度。Solaris 10没有它,但是Solaris没有很多我想要的东西。


听起来很方便。FWIW不在Ubuntu 14.04中。:-(
John Rix
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.