Sed com edição inplace altera a propriedade do grupo de arquivos

8

Eu tenho o script shell ( php ) que entra em contato com o arquivo de destino dessa maneira:

  • inspeciona se o arquivo e o diretório são graváveis com php ' is_writable() (não acho que isso seja um problema)
  • faz edição de arquivo no local com o comando sed :

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 o mais correto, mas) arquivo que foi myuser:www-data para ser myuser:myuser .

O sed altera a propriedade do grupo de arquivos da maneira que parece, e como evitá-lo, se possível?

    
por Miloš Đakonović 15.04.2016 / 10:01

3 respostas

16

Existe um pequeno problema com o modo de edição no local sed -i . sed cria um arquivo temporário no mesmo diretório chamado sedy08qMA , em que y08qMA é uma string gerada aleatoriamente. Esse arquivo é preenchido com o conteúdo modificado do arquivo original. Após a operação, sed remove o arquivo original e renomeia o arquivo temporário com o nome do arquivo original. Portanto, não é uma verdadeira edição local . Ele cria um novo arquivo com permissões do usuário chamador e um novo número de inode. Esse comportamento geralmente não é ruim, mas, por exemplo, links rígidos são quebrados.

No entanto, se você quiser true na edição local, você deve usar ed . Ele lê os comandos do stdin e edita o arquivo diretamente, sem um arquivo temporário (é feito sobre o buffer de memória de ed ). Uma prática comum é usar printf para gerar a lista de comandos:

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

O comando printf produz a saída da seguinte forma:

1,$s/search/replace/g
wq

Essas duas linhas são ed de comandos. O primeiro pesquisa a string search e a substitui por replace . O segundo escreve ( w ) as alterações no arquivo e sai ( q ). -s suprime a saída de diagnóstico.

    
por 15.04.2016 / 10:53
8

O parâmetro -i de sed funciona criando um arquivo temporário durante a operação e, em seguida, sobrescreve o arquivo real com o arquivo temporário no final. Essa é a causa mais provável do problema, já que ao criar a propriedade do arquivo temporário, o padrão é myuser:myuser

Você pode definir o setgid bit no diretório pai (somente se o diretório pai pertencer ao grupo www-data ), para que os arquivos criados sob esse diretório herdem o mesmo grupo.
para fazer isso:

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

Acho que esse é um uso muito típico do setgid bit.

    
por 15.04.2016 / 10:35
2

O uso de ed em vez de sed parece bastante supérfluo para isso, já que você precisa inserir uma entrada adicional. A distro na qual estou trabalhando agora (CentOS 5.10) tem a opção -c para sed que utiliza 'cópia' do arquivo temporário em vez de simplesmente renomeá-lo quando usado com a opção -i . Eu testei e funcionou perfeitamente, preservando o proprietário original e o grupo ao fazer uma edição em linha. NÃO preserva o tempo de modificação.

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

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

Não tenho certeza da extensão dessa opção para sed em outras distros. O Solaris 10 não tem isso, mas o Solaris não tem muitas coisas que eu quero.

    
por 01.08.2018 / 15:23