How to restore default group/user ownership of all files under /var?
Solution 1
Similar to one of the answers above, if you have a copy of the directory with the correct permissions named "var" in your local directory, you can use the following two commands to restore permissions to the /var directory.
sudo find var -exec chown --reference="{}" "/{}" \;
sudo find var -exec chmod --reference="{}" "/{}" \;
Solution 2
The simplest (and probably most correct) answer is "You can't", but if you want to try, here's a bash script that will fix the permissions of files under /var belonging to .deb packages.
NOTES:
- it won't fix perms for files not belonging to a package.
- it won't fix perms for files where the package is no longer available for download by apt-get - e.g. legacy or third-party packages.
- AFAIK, no files in debian packages have tabs in the filename, so I've used TAB as the IFS for the while-read loop. I've checked the Contents-amd64.gz and Contents-i386.gz for debian sid and confirmed that there are no tabs, but third-party packages may have some.
The script works by generating a list of installed packages that have files in var, downloading those packages, and then using dpkg-deb -c
to find out what the permissions should be.
The hardest part was writing the function to convert the permissions string (as displayed by ls -l
or tar v
) to an octal numeric mode, including catering for setuid, setgid, and sticky bits....some things that would be easy to write with a nice algorithm in, say, perl are too much trouble in bash, so it's easier to just brute-force it.
Finally, the script is written to be in "debug-mode" or "dry-run" mode. To make it actually change the owner/group/perms, comment-out or delete the two lines with the __EOF__
here document markers on them.
#! /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 -v OFS='\t' '/\.\/var\// {print $1, $2, $6}' | \
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
The script could, of course, be quite easily adapted to fix packaged-file perms in any other directory, or in all directories.
This script would have been a lot simpler if the $packagename.list files in /var/lib/dpkg/info
had owner, group, and octal perms as well as the filename...but they don't.
Solution 3
You could.
Install the same distribution onto another machine or a VM, and use the chmod --refer
to synchronize permissions for /var
Solution 4
The simple answer is "you can't".
But.... if you have a filesystem like JFS that has a log you can restore it with it's tools. Some package managers allows you to reintall it's packages and maybe with this way you can recover your files owner.
Another way but more cumbersome is that you can mount the /var at another device and than the programs will recreate the missing directory..
Related videos on Youtube
sepehr
Updated on September 18, 2022Comments
-
sepehr almost 2 years
I accidentally changed
/var
owner/group to my username and then changed it back to root, but not all the/var
folders' owners are root, so is there anyway to change back owner/group of files/folders to default state? Or at least those files/folders that are created by packages?-
jw013 over 11 yearsEdited because your general question was an exact duplicate of How to revert
chown
command? and would have been closed. -
sepehr over 11 yearsIt seems there are some ways to fix this like this one but not just for /var and not just for rpm based distributions.
-
derobert over 11 yearsWhich distro are you running?
-
sepehr over 11 years@derobert debian testing aka wheezy
-
-
derobert over 11 yearsNice. Also, you may be able to replace your grep through *.list with
dpkg -S /var
. Also, after applying this script, one needs to checkdpkg-statoverride --list '/var/*'
. -
Alessio over 11 yearsTrue, but
dpkg -S
is slow (which is why i wrotedlocate
). Good point aboutdpkg-statoverride
, though....and the output format is perfect. -
Chelmite almost 10 yearsThanks for the script. There's a typo in one of the sed invocations, where blank is changed to tab, it's missing the final '/'. (and while we're at it, why not just write: sed -e 's/ +/\t/g' | \