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

Mil*_*vić 9 shell bash permissions shell-script chown

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

  • 检查文件和目录是否可以用php's写入is_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更改文件组所有权,如果可能,我该如何避免?

cha*_*aos 18

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

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

printf "%s\n" '1,$s/search/replace/g' wq | ed -s file
Run Code Online (Sandbox Code Playgroud)

printf命令产生如下输出:

1,$s/search/replace/g
wq
Run Code Online (Sandbox Code Playgroud)

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


Spa*_*sle 8

-i参数sed通过创建操作过程中的临时文件的工作,然后覆盖在年底的临时文件的实际文件。这很可能是问题的原因,因为在创建临时文件所有权时默认为myuser:myuser

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

chmod g+s parent-dir-of-your-file  
Run Code Online (Sandbox Code Playgroud)

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