具有就地编辑功能的 Sed 更改文件的组所有权

具有就地编辑功能的 Sed 更改文件的组所有权

我有 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会更改文件组所有权,如果可能的话,如何避免它?

答案1

sed就地编辑模式有一个小问题-ised在同一目录中创建一个名为 的临时文件sedy08qMA,其中y08qMA是随机生成的字符串。该文件填充了原始文件的修改内容。操作完成后,sed删除原文件,并将临时文件重命名为原文件名。所以这不是真的就地编辑。它使用调用用户的权限和新的索引节点号创建一个新文件。这种行为大多不错,但例如硬链接被破坏。

但是,如果你想要真的就地编辑,您应该使用ed.它从标准输入读取命令并直接编辑文件,无需临时文件(它是在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抑制诊断输出。

答案2

-i参数的工作原理是sed在运行时创建一个临时文件,最后用该临时文件覆盖实际文件。这最有可能是问题的原因,因为创建临时文件所有权时默认为myuser:myuser

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

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

我认为这是setgid钻头的一个非常典型的用途。

答案3

考虑到您必须通过管道输入额外的输入,因此使用代替ed似乎是多余的。sed我现在正在开发的发行版(CentOS 5.10)具有利用临时文件“复制”的-c选项sed,而不是在与该-i选项一起使用时简单地重命名它。我已经测试过它,它工作得很好,在进行内联编辑时保留了原始所有者和组。它不保留修改时间。

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

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

不确定这个选项sed在其他发行版中有多普遍。 Solaris 10没有,但是Solaris没有很多我想要的东西。

答案4

我努力了https://crates.io/crates/sd仅替换字符串即可正常工作。不修改标志。

要安装它,您需要安装 Rust,然后安装“cargo install sd”。

目前,在许多用例中,Rust 是 C/C++ 的可行替代语言,如下所示。您不会后悔安装它,以便时不时地获得更好的替代品。

相关内容