A resposta mais simples (e provavelmente a mais correta) é "Você não pode", mas se quiser tentar, aqui está um script bash que corrigirá as permissões dos arquivos em / var pertencentes aos pacotes .deb.
NOTAS:
- não corrigirá permissões para arquivos que não pertencem a um pacote.
- ele não corrigirá permissões para arquivos em que o pacote não está mais disponível para download pelo apt-get - por exemplo, pacotes herdados ou de terceiros.
- AFAIK, nenhum arquivo nos pacotes debian tem guias no nome do arquivo, então usei a TAB como o IFS para o loop while-read. Eu verifiquei o conteúdo-amd64.gz e o conteúdo-i386.gz quanto ao debian sid e confirmei que não existem guias, mas os pacotes de terceiros podem ter alguns.
O script funciona gerando uma lista de pacotes instalados com arquivos em var, dpkg-deb -c
fazendo o download desses pacotes e usando-os para descobrir quais devem ser as permissões.
A parte mais difícil foi escrever a função para converter a sequência de permissões (como exibida por ls -l
ou tar v
) em um modo numérico octal, incluindo restauração de bits setuid, setgid e sticky .... algumas coisas que seriam fáceis de escrever com um bom algoritmo em, digamos, perl são muitos problemas no bash, por isso é mais fácil forçá-lo com força bruta.
Por fim, o script foi escrito para estar no modo "depuração" ou "execução a seco". Para que ele realmente altere o proprietário / grupo / permissões, comente ou exclua as duas linhas com os __EOF__
marcadores de documento aqui.
#! /bin/bash
perm_string_to_mode() {
string="$1"
let perms=0
[[ "${string}" = ?r???????? ]] && perms=$(( perms + 400 ))
[[ "${string}" = ??w??????? ]] && perms=$(( perms + 200 ))
[[ "${string}" = ???x?????? ]] && perms=$(( perms + 100 ))
[[ "${string}" = ???s?????? ]] && perms=$(( perms + 4100 ))
[[ "${string}" = ???S?????? ]] && perms=$(( perms + 4000 ))
[[ "${string}" = ????r????? ]] && perms=$(( perms + 40 ))
[[ "${string}" = ?????w???? ]] && perms=$(( perms + 20 ))
[[ "${string}" = ??????x??? ]] && perms=$(( perms + 10 ))
[[ "${string}" = ??????s??? ]] && perms=$(( perms + 2010 ))
[[ "${string}" = ??????S??? ]] && perms=$(( perms + 2000 ))
[[ "${string}" = ???????r?? ]] && perms=$(( perms + 4 ))
[[ "${string}" = ????????w? ]] && perms=$(( perms + 2 ))
[[ "${string}" = ?????????x ]] && perms=$(( perms + 1 ))
[[ "${string}" = ?????????t ]] && perms=$(( perms + 1001 ))
[[ "${string}" = ?????????T ]] && perms=$(( perms + 1000 ))
echo $perms
}
# generate a list of installed packages that have files etc in /var
grep -l /var/ /var/lib/dpkg/info/*.list | \
sed -e 's:/var/lib/dpkg/info/::' -e 's/\.list$//' | \
xargs dpkg -l | \
awk '/^[hi]/ {print $2}' > /tmp/packages.list
# clean out the apt cache, so we only have one version of each package
apt-get clean
# download the packages as if we were going to reinstall them
# NOTE: packages which are no longer available for download
# will not have their permissions fixed. apt-get will complain about
# those packages, so you can get a list by redirecting or tee-ing the
# output of this script.
xargs apt-get -y -d -u --reinstall install < /tmp/packages.list
for pkg in $(cat /tmp/packages.list) ; do
PKGFILE="/var/cache/apt/archives/${pkg}_*.deb"
if [ -e $PKGFILE ] ; then
dpkg-deb -c /var/cache/apt/archives/${pkg}_*.deb | \
awk '/\.\/var\// {print $1, $2, $6}' | \
sed -e 's/ /\t/' -e 's/ /\t' | \
while IFS=$'\t' read permstring ownergroup filename ; do
# don't change owner/group/perms on symlinks
if ! [[ "${permstring}" =~ ^l ]] ; then
mode=$(perm_string_to_mode $permstring)
# change "owner/group" to "owner:group" for chown
ownergroup=${ownergroup//\//:}
# remove leading '.' from filename
filename=${filename#?}
cat <<__EOF__
chown "$ownergroup" "$filename"
chmod "$mode" "$filename"
__EOF__
fi
done
echo
fi
done
Obviamente, o script pode ser facilmente adaptado para corrigir permissões de arquivo compactado em qualquer outro diretório ou em todos os diretórios.
Esse script seria muito mais simples se os arquivos $ packagename.list /var/lib/dpkg/info
continham permissões de proprietário, grupo e octal, bem como o nome do arquivo ... mas eles não têm.
chown
comando? e teria sido fechado.