Sed com edição local altera a propriedade do grupo do arquivo

8

Eu tenho o phpscript shell ( ) que entra em contato com o arquivo de destino desta maneira:

  • inspeciona se o arquivo e o diretório são graváveis ​​com php's is_writable()(não acho que isso seja problema)
  • O arquivo no local edita com o sedcomando:

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

Como resultado, recebo (tudo correto, mas) o arquivo que deveria myuser:www-dataser myuser:myuser.

Altera a sedpropriedade do grupo de arquivos como parece e como evitá-lo, se possível?

Miloš Đakonović
fonte

Respostas:

16

Há um pequeno problema sedno modo de edição local -i. sedcria um arquivo temporário no mesmo diretório chamado sedy08qMA, onde y08qMAé uma sequência gerada aleatoriamente. Esse arquivo é preenchido com o conteúdo modificado do arquivo original. Após a operação, sedremove o arquivo original e renomeia o arquivo temporário com o nome do arquivo original. Portanto, não é uma edição verdadeira no local . Ele cria um novo arquivo com permissões do usuário que está chamando e um novo número de inode. Esse comportamento geralmente não é ruim, mas, por exemplo, os links físicos são quebrados.

No entanto, se você deseja uma verdadeira edição no local, use ed. Ele lê comandos do stdin e edita o arquivo diretamente, sem um arquivo temporário (isso é feito através eddo buffer de memória). Uma prática comum é usar printfpara gerar a lista de comandos:

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

O printfcomando produz a saída da seguinte maneira:

1,$s/search/replace/g
wq

Essas duas linhas são edcomandos. O primeiro procura a string searche a substitui por replace. O segundo escreve ( w) as alterações no arquivo e fecha ( q). -ssuprime a saída de diagnóstico.

caos
fonte
8

O -iparâmetro sedfunciona, criando um arquivo temporário durante a operação e substitua o arquivo real pelo arquivo temporário no final. Essa é a causa mais provável do problema, pois ao criar a propriedade do arquivo temporário, o padrão émyuser:myuser

Você pode definir o setgidbit no diretório pai (apenas se o diretório pai pertencer ao grupo www-data), para que os arquivos criados nesse diretório herdem o mesmo grupo.
fazer isso:

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

Eu acho que esse é um uso muito típico do setgidbit.

Dave.d
fonte
@cuonglm Acabei de fazer um strace sed -i, encontrei a seguinte linha no trace, isso significa que ele criou o arquivo temporário no diretório atual? open("./sedKyG9Ei", O_RDWR|O_CREAT|O_EXCL, 0600) = 4
Dave.d
@ DavidDai: Sim, minha falta de memória.
precisa saber é
2

O uso de em edvez de sedparece supérfluo para isso, considerando que você precisa inserir uma entrada adicional. A distribuição em que estou trabalhando agora (CentOS 5.10) tem a -copção de sedutilizar 'copiar' o arquivo temporário em vez de simplesmente renomeá-lo quando usado com a -iopção. Eu testei e funcionou perfeitamente, preservando o proprietário e o grupo originais ao fazer uma edição embutida. NÃO preserva o tempo de modificação.

por exemplo, sed -ci -e '3,5d' file.txt

  • -c usa cópia em vez de renomear (ou seja, preserva a propriedade / grupo)
  • -i edição em linha
  • -e script / expressão a ser executado

Não tenho certeza de quão ampla é essa opção sedem outras distribuições. O Solaris 10 não o possui, mas o Solaris não tem muitas coisas que eu quero.

devnulldad
fonte
Parece bastante útil. Não no Ubuntu 14.04, porém, FWIW. :-(
John Rix 10/09