Se houvesse um processo gravando continuamente em um arquivo, e eu quisesse assumir o controle do arquivo com raiz, eu poderia fazer algo assim:
sudo rm somefile; sudo touch somefile
É possível que o processo anexado seja anexado ao arquivo entre esses dois comandos? Em caso afirmativo, existe uma maneira de garantir que nenhum outro comando seja executado no meio?
Respostas:
Uma linha de comando encadeada é basicamente um pequeno script de shell; ele executará o primeiro comando usando o procedimento usual fork + exec, espere que ele saia e execute o segundo da mesma maneira. Entre os dois comandos, há uma quantidade arbitrária de tempo que o shell leva em sua contabilidade e processamento, durante o qual o multiprocessamento comum ocorre e outros processos arbitrários podem fazer outras coisas arbitrárias. Então a resposta é 'não'. (Se você realmente fizer isso, verá que a entrada do diretório
somefile
desaparece, mas o próprio arquivo permanece (desde que foi aberto por um processo) até ser fechado. O espaço em disco usado pelo arquivo não será recuperado até que isso aconteça. , otouch
comando criará um novo arquivo não relacionado com o mesmo nome e caminho.)Se você deseja alterar a propriedade do arquivo para root, faça-o
sudo chown root:root somefile
(embora não tenha certeza de como isso afetará os processos com uma manipulação de arquivo aberta). Se você deseja destruir o conteúdo atual do arquivo, tentetruncate -s 0 somefile
(o processo em execução continuará sendo anexado ao arquivo agora vazio). Se for outra coisa, talvez esclareça o que você quer fazer.fonte
chown
A criação de algum arquivo não afetará os processos que possuem um identificador de arquivo para algum arquivo.exec 3>somefile; sudo chmod 0600 somefile; echo hello world >&3; sudo cat somefile; exec 3>&-
.Não. Um
rm
comando seguido por umtouch
comando não é atômico. Vai demorar muito tempo entre os dois comandos - possivelmente na faixa de milissegundos. Muita coisa pode acontecer durante esse tempo. Se você não tiver sorte, suas credenciais sudo podem até expirar.Um único programa chamando as chamadas
unlink
eopen
deixaria uma janela muito mais curta para uma corrida, mas isso ainda poderia acontecer.Uma abordagem mais segura seria criar o novo arquivo com um nome temporário e usar a
rename
chamada do sistema. "Substituir" um nome com arename
chamada do sistema é garantido como atômico. Isso pode ser alcançado usandotouch
emv
.Mas um processo que abriu o arquivo antigo para gravação pode continuar gravando nele muito tempo depois de ter sido excluído. Este será o caso de um arquivo excluído usando
unlink
e um excluído usandorename
.fonte
Depois que um processo tem um identificador de arquivo aberto para leitura, não importa o que você faz com a propriedade ou as permissões: o processo pode continuar acessando o arquivo. Você pode até excluir o arquivo e o processo poderá continuar acessando-o através do tratamento de arquivos.
Considere as permissões como um portão de controle para obter um identificador de arquivo.
Se você deseja criar um arquivo atomicamente, em vez de fazer isso:
você pode considerar isso:
que substituirá atomicamente
somefile
poranotherfile
. (Eu preferiria usar,mv -f
mas não consigo encontrar uma instrução que garanta isso de chamada derename(2)
sistema.Talvez você possa atualizar sua pergunta para explicar o que você quer dizer com "assuma o controle do arquivo". Você pode ter um problema XY aqui.
fonte
mv -f
para receber umarename(2)
chamada do sistema. Você está certo queln
não, porque sempre usa alink(2)
chamada do sistema, que não pode substituir atomicamente.ln -f
apenas fazunlink(2)
no alvo primeiro.ln
no cérebro. Eu não tinha certeza de como obterrename(2)
a garantia de ser envolvido e era tarde demais para ir cavar ainda maismv
"deve executar ações equivalentes a"rename(old, new)
. pubs.opengroup.org/onlinepubs/9699919799/utilities/mv.html .mv -f
age comomv -i
se o destino não fosse gravável, mas não é comocp -f
ouln -f
onde será desvinculado primeiro.Não mas
sudo rm somefile; sudo touch somefile
é seguro na maioria das situações.
A maioria dos processos abre arquivos e, em seguida, usa o descritor de arquivo adquirido para acessar o conteúdo do arquivo.
Se um processo abrir algum arquivo, em sh:
Em seguida, outro processo é livre para desvincular (= remover) algum arquivo e o editor de arquivo no qual o arquivo foi aberto pelo primeiro processo (3 neste caso) continuará a se referir ao conteúdo original do arquivo, que agora é um arquivo no limbo.
criará um novo arquivo de arquivo não relacionado e todos os processos que tiveram o arquivo de arquivo antigo aberto e agora estão usando apenas um editor de arquivo para se referir a ele não serão afetados porque estão se referindo a um arquivo diferente - que agora está no limbo.
Se um processo não raiz tentar se referir a algum arquivo por nome, ele receberá um erro EPERM, porque o novo arquivo é propriedade da raiz.
Se você deseja impedir que vários processos sob o mesmo usuário (por exemplo, root) corrompam um arquivo, o linux possui um bloqueio obrigatório e consultivo. Você pode usar o
flock
comando em scripts de shell para bloqueio de arquivo consultivo (consulte a página de manual para obter mais informações).fonte