Como inspecionar permissões de grupo de um arquivo

9

Gostaria de inspecionar as permissões de grupo de um arquivo a partir de um script bash. Especificamente, preciso verificar se um arquivo tem o bit gravável do grupo.

É isso aí. Simples assim. Contudo:

  1. Eu também preciso que isso seja portátil.
  2. test -w <file não vai me dizer se é gravável em grupo.
  3. A saída de ls -ldé boa para humanos, mas não tem tanta certeza sobre scripts. Tecnicamente, eu poderia analisar a saída drwxrwxr-xpara extrair os bits do grupo, mas isso parece frágil.
  4. A interface para staté completamente incompatível entre o OS X e outros sistemas.
  5. find <file> -perm ... não pode ser a resposta?
mislav
fonte
Você precisa verificar o bit de permissão do grupo ou se um grupo específico tem permissões de gravação? O grupo (ou o usuário) pode ter permissão de gravação por meio de uma ACL.
Gilles 'SO- stop be evil'
Apenas o bit de permissão do grupo. Nenhum grupo específico é relevante.
Mislav

Respostas:

8

Método # 1 - stat

Você pode usar o statcomando para obter os bits de permissão. statestá disponível na maioria dos Unixes (OSX, BSD, não AIX pelo que posso encontrar). Isso deve funcionar na maioria dos Unixes, exceto OSX e BSD, pelo que posso encontrar.

$ stat -c "%a" <file>

Exemplo

$ ls -l a
-rw-rw-r-- 1 saml saml 155 Oct  6 14:16 afile.txt

Use este comando:

$ stat -c "%a" afile.txt
664

E use um simples greppara ver se o modo de permissões de grupos é 6 ou 7.

$ stat -c "%a" afile.txt | grep ".[67]."

Para OSX e BSD você precisa usar esta forma de stat, stat -f(ou talvez stat -x), e analisar em conformidade. Como as opções statsão diferentes, você pode agrupar esse comando em um lsb_release -acomando e chamar a versão apropriada com base no sistema operacional. Não é o ideal, mas viável. Perceba que lsb_releaseestá disponível apenas para distribuições Linux, portanto, outra alternativa precisaria ser criada para testar outros sistemas operacionais Unix.

Método # 2 - encontrar

Acho que esse comando pode atendê-lo melhor. Eu uso finde o printfinterruptor.

Exemplo

$ find a -prune -printf '%m\n'
664

Método # 3 - Perl

Perl pode ser uma maneira mais portátil de fazer isso, dependendo dos sistemas operacionais que você está tentando cobrir.

$ perl -le '@pv=stat("afile.txt"); printf "%04o", $pv[2] & 07777;'
0664

NOTA: O item acima utiliza a stat()função do Perl para consultar os bits do sistema de arquivos.

Você pode tornar isso mais compacto renunciando ao uso de uma matriz @pve lidando com a saída stat()diretamente:

$ perl -le 'printf "%04o", (stat("a"))[2] & 07777;'
0664
slm
fonte
Eu acho que você perdeu o ponto 4. O statcomando varia muito entre os diferentes sistemas e não é portátil.
Jordanm 26/10/2013
@ Jordanm - obrigado, eu vi, estava procurando uma alternativa. Eu acho que find . -printfpode fazê-lo, mas não pode determinar se está disponível no achado do OSX.
slm
1
Também não consegui encontrá-lo mencionado no guia POSIX2008, por isso estou inclinado a concordar. Não tenho certeza de outros métodos. Eu acho que você tem que morder a bala aqui e detectar qual SO e chamar o approp. comando, parece ser a melhor abordagem.
Slm
1
Também não conseguia pensar em um método usando um utilitário de shell padrão. É por isso que minha resposta usa perl.
Jordanm 26/10/2013
1
@jordanm - grandes mentes. Eu também estava trabalhando em uma solução perl 8-)
slm
1

Uma opção é usar perl, que será portátil em qualquer lugar perldisponível. É difícil encontrar um sistema unix sem ele. Aqui está um exemplo de como ele pode ser integrado a um script de shell:

if perl -e 'use Fcntl ":mode"; exit( ((stat("file.txt"))[2] & S_IWGRP) >> 3)'; then
    echo "file is group writable"
else
    echo "file is not group witeable"
fi

perlExemplos semelhantes podem ser encontrados no stat perldoc .

jordanm
fonte
1

Acabei lsanalisando:

is_group_writable() {
  local ls="$(ls -ld "$1")"
  [ "${ls:5:1}" = "w" ]
}

Sou grato pela extensa resposta do @ slm, mas nenhum dos outros métodos é tão direto. O statmétodo exigiria que eu escrevesse pelo menos duas invocações diferentes para cobrir o OS X, e mesmo depois disso ele retorna a representação octal à qual ainda preciso aplicar aritmética. O método Perl está OK, mas exige que eu inicie um intérprete para uma tarefa tão simples, e gostaria de mantê-lo simples e usando apenas os utilitários posix.

mislav
fonte
2
Você está usando o bash, não apenas o POSIX. Em POSIX:perms=$(ls -ld -- "$1"); perms=${perms%% *}; case $perms in ?????w????) …
Gilles 'SO- stop be evil'
0
FILE="filename";G=$(stat -c '%a' ${FILE} | cut -c2);
if [ $G -gt 5 ];then   echo "Group write is set on ${FILE}";fi

Todas as ferramentas padrão Unix / Linux.

Suponho que seja possível ter gravação em grupo, mas não leitura em grupo. Nessa possibilidade, seria uma declaração de caso 2 | 3 | 6 | 7) ou um grep '[2 | 3 | 6 | 7]'

Doc
fonte