Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I'm running "Ubuntu 18.04" with every update/upgrade patch installed.
I am accessing it via "ssh" from both inside and outside the network.
I can access it directly from a console monitor.
I issued the following command "sudo chmod -R 777 /" on a separately mounted drive, and of course, it began to reset all the permissions on my system "/" (dumb, dumb, dumb)
Now, "sudo" does not work, and I've disconnected via "ssh" and cannot access it remotely.
How can I reset default permissions on "/" from the console?
contains the advice "... your options are (a) compare with a working Debian system and fix permissions manually or (b) backup and reinstallation. I'd recommend (b), which will probably be less time-consuming, and with (a) it is difficult to be sure you have got everything right."
This is a pretty old post. Perhaps there is a better solution by now.
For the future, let me say that I learned the hard way to always use the form
Code:
chmod --preserve-root ...
which causes chmod to "fail to operate recursively on '/'" (from man page).
I'm thinking of my options. I have a man onsite who can enter a command such as that, then I can work remotely to either "fix" what I need or reinstall.
Fortunately, data storage is held separately (the disc from which I was working), so I can backup for safety but possibly retain the file structure. That way, I can perform a fresh installation of the OS disc only. That would likely be quickest as has been stated. It's three discs, one for the OS and two set in a hardware RAID to create a storage disc.
another option ( which is slower and less likely to work well )
does not need root
does need mountpoint ( first arg. )
Code:
#!/bin/bash
MNTPOINT=${1:-/}
Extract () {
#
for deb in ${MNTPOINT%/}/var/cache/apt/archives/*deb
do
echo "Extracting Manifest from ${deb##*/}" 1>&2
tar -Jvtf - < <(unar "${deb}" *data.tar.xz -o -)
done
}
bzip2 > MANIFEST.bz2 < <(Extract)
#
unar is not usually installed by default
now,
mount the root partition of the ubuntu that needs to be fixed.
the following script takes two arguments, the first the MANIFEST.bz2
and the second is the mountpoint of the root partition you need to fix
it will only print the commands, not execute them
output to a file
Code:
sudo ./RestorePermisions.sh ./MANIFEST.bz2 /mnt/foobared/ | tee chmodcommands.txt
edit: added sudo
need sudo as it uses find to do initial sweep
it won't write anything ( unless you remove the XARGS echo )
review that file ( sorry it will have very long lines in it )
I never got round to writing a fancy menu for it
it dosn't try to fix home,
we can do that later
Code:
#!/bin/bash
Flags=( "${@}" ) # grab hold of flags early
################################################################################
# Default configuration
################################################################################
manifest_missing="return 10"
manifest_invalid="return 20"
UnknownError="return 99"
CompTypeUnknown="return 30"
#MODE=Textual_to_Symbolic
MODE=Textual_to_Octal
Manifest="$1"
MNTPOINT="$2"
XARGS="xargs -r echo"
# remove echo if you want to action immediately
################################################################################
Help () {
#TODO write this
echo "Use the Force, read the src."
}
ChkManifest () {
[[ -z "${Manifest}" ]] && $manifest_missing
[[ -e "${Manifest}" ]] || $manifest_missing
fileis=( $( file -i "${Manifest}" ) )
case ${fileis[1]:0:(-1)} in
text/plain)
GREP="$( type -p grep )"
;;
application/gzip)
GREP="$( type -p zgrep )"
;;
application/x-bzip2)
GREP="$( type -p bzgrep )"
;;
application/x-xz)
GREP="$( type -p xzgrep )"
;;
application/x-lzma)
GREP="$( type -p lzgrep )"
;;
application/x-zstd)
GREP="$( type -p zstdgrep )"
;;
*)
$CompTypeUnknown
;;
esac
chk=( $($GREP -m1 -E -- "^[bcd-][rwx-]{9}.*[a-z]/?$" ${Manifest}) )
[[ ${#chk[@]} == 6 ]] \
&& [[ ${chk[0]} =~ ^[bcdrwxsStT-]{10}$ ]] \
&& [[ ${chk[1]} =~ ^[a-z]*/[a-z]*$ ]] \
&& [[ ${chk[2]} =~ ^[0-9]+,?[0-9]*$ ]] \
&& [[ ${chk[3]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
&& [[ ${chk[4]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
&& [[ ${chk[5]} =~ ^[.]/[[:print:]]+$ ]] \
|| $manifest_invalid
return
}
ChkDistro () {
DISTRO=$(grep -E ^ID=[[:print:]]+ ${MNTPOINT%/}/etc/os-release 2>/dev/null)
}
################################################################################
# GetIndex #
# unlikely with slackware's ( tar vtf package.txz )>> MANIFEST
# but if the manifest were in a different order to what we expect
# this could be used to find the array indices we need
# only PERMS, OWNER_GRP and FILEPATH are used in this script
# they are META[0] , META[1] and META[5]
GetIndex () {
################################################################################
for i in ${!chk[@]}
do
[[ ${chk[i]} =~ ^[bcdrwxsStT-]{10}$ ]] \
&& PERMS=$i || continue
[[ ${chk[i]} =~ ^[a-z]+/[a-z]+$ ]] \
&& OWN_GRP=$i || continue
#[[ ${chk[i]} =~ ^[0-9]+,?[0-9]*$ ]] \
# && SIZE=$i || continue
#[[ ${chk[i]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
# && FILEDATE=$i || continue
#[[ ${chk[i]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
# && FILETIME=$i || continue
[[ ${chk[i]} =~ ^[.]/[[:print:]]+$ ]] \
&& FILE_PATH=$i || continue
done
}
ReadManifest () {
sort -u -d -k6 <($GREP -E -- "$1" "${Manifest}" )
return 0
}
Textual_to_Octal () {
################################################################################
S=0 # unset special bits by default
# bash arrays start at 0, so 3 is 4th in string
[[ ${1:3:1} =~ [sS] ]] && S=$(( ${S} + 4 )) ##\
[[ ${1:6:1} =~ [sS] ]] && S=$(( ${S} + 2 )) # set as per manifest
[[ ${1:(-1)} =~ [tT] ]] && S=$(( ${S} + 1 )) ##/
# only need to declare once
[[ $p ]] || declare -A \
p=(
[r]="4" [w]="2" [x]="1" [-]="0"
[s]="1" [S]="0" [t]="1" [T]="0"
)
# S ( s{u,g}id no exec. ) is unlikly to exist in manifest, but it is valid
printf "0%d%d%d%d" \
${S} \
$(( ${p[${1:1:1}]} + ${p[${1:2:1}]} + ${p[${1:3:1}]} )) \
$(( ${p[${1:4:1}]} + ${p[${1:5:1}]} + ${p[${1:6:1}]} )) \
$(( ${p[${1:7:1}]} + ${p[${1:8:1}]} + ${p[${1:9:1}]} ))
# ${1} is what we fed into the function ( drwxr-xr-x )
# p is our Associative (-A) array, bit values are indexed with textual char.
# :1:1} == r ( the second element of the string d(r)wxr-xr-x )
# special User Group Other
# no s / S ${p[r]} == 4 ${p[r]} == 4 ${p[r]} == 4
# no t / T ${p[w]} == 2 ${p[-]} == 0 ${p[-]} == 0
# ${p[x]} == 1 ${p[x]} == 1 ${p[x]} == 1
# sum == 0 sum == 7 sum == 5 sum == 5 >> 0755
################################################################################
}
Textual_to_Symbolic () {
################################################################################
SUID=",u-s" ##\
SGID=",g-s" # unset special bits by default
STICKY=",o-t" ##/
[[ ${1:3:1} =~ [sS] ]] && SUID="s" ##\
[[ ${1:6:1} =~ [sS] ]] && SGID="s" # set as per manifest
[[ ${1:(-1)} =~ [tT] ]] && STICKY="t" ##/
perms="${1//[st]/x}" # s and t imply exec. bit
perms="${perms//[ST-]/ }" # S and T imply no exec. bit
perms="\
u=${perms:1:3}${SUID}, \
g=${perms:4:3}${SGID}, \
o=${perms:7:3}${STICKY} \
"
perms="${perms//[[:space:]]}" # remove white space.
printf "%s" "${perms}"
}
Hammer () {
################################################################################
# chmod pretty much everything
# Why?
# it will fix anything "extra" that is not in the manifest
# no real sense in leaving rogue 777 dirs/files hanging around
# dirs 00755
$XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
-type d \
! -regex "${MNTPOINT%/}\(/lost.found\|/home\)/" \
! -perm 0755
)
# files in a /{s}bin/ 00755
$XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
-type f \
-regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
! -perm 0755
)
# files not in a /{s}bin/ 00644
$XARGS chmod -v 00644 < <( find ${MNTPOINT%/}/ -xdev \
-type f \
! -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
! -perm 0644
)
# Yes, many more locations should have exec. scripts
# These will be fixed when manifest is processed
}
################################################################################
LVM () {
#TODO add option for this ( or look to see if needed )
# lvm dirs
$XARGS chmod -v 00700 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
-type d \
-regex ".*/lvm/\(archive\|backup\|cache\)" \
! -perm 0700
)
# lvm files
$XARGS chmod -v 00600 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
-type f \
-regex ".*/lvm/\(archive\|backup\|cache\)/.*" \
! -perm 0600
)
$XARGS chmod -v 00444 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
-type f \
-regex ".*/lvm/profile/.*" \
! -perm 0444
)
}
################################################################################
QueryManifest (){
# [0]="Perms" [1]="Owner/Group [2]="Size|Major/Minor"
# [3]="Date" [4]="Time" [5]="Path/file"
while read -a META
do
[[ $DISTRO =~ slackware ]] && {
# fix 1994 var/run with incorrect perms
[[ ${META[5]} == var/run/ && ${META[0]} == drwxrwxr-x ]] \
&& META[0]="drwxr-xr-x"
}
#PrintCosmetic $FUNCNAME "${META[5]}"
# check file/dir exists
[[ -e "${MNTPOINT%/}/${META[5]}" ]] \
&& printf "%s\n" "${MNTPOINT%/}/${META[5]#./}"
[[ $DISTRO =~ slackware ]] && {
#Slackware Specific
# files ending .new may or may not exist
# But these are temp. files, so check after stripping .new
[[ ${META[5]:(-4)} == \.new ]] \
|| continue \
&& ni=${#META[@]} \
&& META[$ni]=${META[5]%.new}
#PrintCosmetic $FUNCNAME "${META[$ni]}"
[[ -e "${MNTPOINT%/}/${META[$ni]}" ]] \
&& printf "%s\n" "${MNTPOINT%/}/${META[$ni]#./}"
}
done< <( ReadManifest "${1}" )
}
################################################################################
ErrorReport () {
ExitCode=$?
# since I'm posting this where tabs cannot be input I have removed leading tabs.
# the - in <<- strips the leading tabs from output
# if you want readability re-add the tabs,
# NOTE I lead with two spaces, IMO output looks better with a margin.
#
# The nice thing about this function is Creepers will not dare come near!
case ${ExitCode} in
10) cat <<-EOF
MANIFEST required
$0 /path/to/MANIFEST.bz2
EOF
;;
20) cat <<-EOF
"${Manifest}" does not appear to be a validi Manifest
edit the script to skip this test
I will add a flag later
EOF
;;
30) Foo=($(grep -o -E "(text|application)/[a-z-]*" "$0" ))
Foo=(${Foo[@]#app*/})
cat <<-EOF
"${fileis[1]:0:(-1)}" not supported
valid compressions are ${Foo[@]/x-}
EOF
;;
99) cat <<-EOF
Unknown Error
I hope "$Error"
makes some sense to you
EOF
;;
esac
exit ${ExitCode}
}
################################################################################
PrintCosmetic () {
# calls to this are commented out as it slows things down quite a bit.
# Although, the slowdown is just mins, not 10s of mins.
case $1 in
Filter|OwnGrpFilter)
printf "%-${COLUMNS}s\n" "Current filter ${2}" 1>&2
;;
QueryManifest)
#TODO put prefix into a var
[[ $(( ${#2} + 9 )) -gt ${COLUMNS} ]] \
|| printf "%-${COLUMNS}s\r" \
"Checking ${2}" 1>&2 \
&& printf "%-${COLUMNS}s\r" \
"Checking ${2:$(( $(( ${#2} + 9 )) - $COLUMNS ))}" 1>&2
;;
esac
}
################################################################################
Filter () {
# Initially I had QueryManifest printing the chmod/chown for each line
# This Filter now groups each "unique" chmod and executes as a block via xargs
# Which should be much quicker ( but generated script will look ugly as hell )
filter="${1:-[drwxstT-]{10}}" #TODO include block/char when root is MNTPOINT
while read -a FILTER
do
#PrintCosmetic $FUNCNAME "${FILTER[0]}"
$XARGS chmod -v $( $MODE ${FILTER[0]} ) \
< <(QueryManifest "^${FILTER[0]}")
done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
################################################################################
OwnGrpFilter () {
# I ignored chown for a while, this re-adds that, same logic as Filter
# with regards to doing as a block
# Note, seperate chown does greatly increase the processing time
# However, in the case of fixing a "chmod -R 777 /" chown would not be
# needed, so I figured it would be better to have as a non default option.
filter="${1:- [a-z]+/[a-z]+ }"
while read -a FILTER
do
#PrintCosmetic $FUNCNAME "\" ${FILTER[0]/\//:} \""
$XARGS chown ${FILTER[0]/\//:} \
< <(QueryManifest " ${FILTER[0]} ")
done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
trap ErrorReport EXIT
################################################################################
ChkManifest || exit
Hammer
Filter
#OwnGrpFilter
################################################################################
Location: Montreal, Quebec and Dartmouth, Nova Scotia CANADA
Distribution: Arch, AntiX, ArtiX
Posts: 1,364
Rep:
Hi sankeny,
If you can actually solve your issue using firerat's recommendation, by all means. Before seeing his post, I was going to echo fishope's advice to reinstall. The last time I made a mistake with permissions, and it wasn't as far-reaching as your situation, I was never able to manually correct everything and had to reinstall.
Firerat's scripting abilities far outclass mine - so, again, if that does the trick - excellent - and kudos to firerat.
I will post once I resolve the issue or post any specific issues I find which might help someone else. It may be after Thanksgiving.
Meanwhile, I will mark this "solved" just to let someone know that I have answers (though not resolved until later)
ANSWER: If you can login with root or access root authority via "sudo," then use "Fireat's" scripts. If not, reinstall. My personal experience is that it's likely the BEST solution - BACK UP DATA FIRST and don't make silly mistakes like I did. "chmod --preserve-root" is an excellent suggestion.
I will post once I resolve the issue or post any specific issues I find which might help someone else. It may be after Thanksgiving.
Meanwhile, I will mark this "solved" just to let someone know that I have answers (though not resolved until later)
ANSWER: If you can login with root or access root authority via "sudo," then use "Fireat's" scripts. If not, reinstall. My personal experience is that it's likely the BEST solution - BACK UP DATA FIRST and don't make silly mistakes like I did. "chmod --preserve-root" is an excellent suggestion.
Thanks everyone!
no need to re-install
boot a liveCD
mount the root partition, and point the script at it
actually
if you have a "working" system, then this would generate a suitable command list
unset MNTPOINT
# unset as we are mapping a working systems perms
#
find ${MNTPOINT%/}/ \
-xdev \
-type f \
-regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
! -perm 0755 \
-printf "%05m\t%p\n"
#
the bold bit is actually slackware specific, that can safely be removed
the idea with this one is,
for each sbin and bin dir on the "broken" partition, recursively chmod to 755
then run the "script" generated by the above find
the trick with restoring permissions is knowing what they should be.
slackware's MANIFEST.bz2 was a handy reference point
the , ( unar some.deb | tar -Jvtf - ) seemed like a good way to get a "manifest" on Debian derivatives,
but it would depend on apt's caching policy
then I figured the
Code:
bzip2 > MANIFEST.bz2 < <( Find )
would be quicker/easier providing you have a suitable "template"
no need to re-install
boot a liveCD
mount the root partition, and point the script at it
So, once I mount the damaged partition ("/" on the damaged Ubuntu), run the following --
Code:
unset MNTPOINT
# unset as we are mapping a working systems perms
#
find ${MNTPOINT%/}/ \
-xdev \
-type f \
-regex "\(.*/s?bin/.*\)\|\" \
! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
! -perm 0755 \
-printf "%05m\t%p\n"
#
I will create it as a file called "Restore_file_permissions.sh" on my mounted "/" and run from there (just to simplify the process)
At first I thought YOU were "Alan Hicks" and felt HONORED that you would stoop to helping someone such as I who made a "dumb" mistake, and then I realized you were NOT the writer of the original Slackware script, though you are obviously a skilled programmer. I STILL FEEL HONORED that you would spend your time helping me resolve this issue.
I am not a newbie but I am not at your level, and I still make newbie mistakes! As stated above --
Quote:
Originally Posted by Rickkkk
Firerat's scripting abilities far outclass mine - so, again, if that does the trick - excellent - and kudos to firerat.
It appears I will tackle this firsthand Saturday, so will report over the weekend my results. Thanks again to everyone for their suggestions!
that is sbin and bin dirs.
they should have ( chmod -R 00755 ) run on them
Then, "run" the file generated by the "fix bins" find
but, to be honest, it is probably just easier to run the "find" in #6 to make the MANIFEST.bz2
on a "good" install ( as root because a normal user can't read some dirs. )
put that MANIFEST.bz2 and the "big script" on a usb stick/drive
boot a liveCD
make a mount point, mount the "bad" partition
and run ( as root )
it might be worth un-commenting the
#PrintCosmetic $FUNCNAME
lines
, it takes a bit longer ( not much really )
but they print to stderr, so you will still see things when redirecting stdout to file
the FixScript.sh will look ugly ( very long lines )
alternately, remove the "echo" from the XARGS var.
it will then run the chmods as it finds them.
how well this will all work depends on how close the "good" is to the "bad" ( with respect to the installed packages )
(3) discovered I couldn't "store" the script and "live-boot" at the same time, so created a 2nd USB to store my scripts
On reflection, no doubt I could have "stored" them on the "bad" partition which I had mounted. Nevertheless, I didn't.
(4) created a script from the following, also found at #6 above . . .
Code:
#!/bin/bash
Flags=( "${@}" ) # grab hold of flags early
################################################################################
# Default configuration
################################################################################
manifest_missing="return 10"
manifest_invalid="return 20"
UnknownError="return 99"
CompTypeUnknown="return 30"
#MODE=Textual_to_Symbolic
MODE=Textual_to_Octal
Manifest="$1"
MNTPOINT="$2"
XARGS="xargs -r echo"
# remove echo if you want to action immediately
################################################################################
Help () {
#TODO write this
echo "Use the Force, read the src."
}
ChkManifest () {
[[ -z "${Manifest}" ]] && $manifest_missing
[[ -e "${Manifest}" ]] || $manifest_missing
fileis=( $( file -i "${Manifest}" ) )
case ${fileis[1]:0:(-1)} in
text/plain)
GREP="$( type -p grep )"
;;
application/gzip)
GREP="$( type -p zgrep )"
;;
application/x-bzip2)
GREP="$( type -p bzgrep )"
;;
application/x-xz)
GREP="$( type -p xzgrep )"
;;
application/x-lzma)
GREP="$( type -p lzgrep )"
;;
application/x-zstd)
GREP="$( type -p zstdgrep )"
;;
*)
$CompTypeUnknown
;;
esac
chk=( $($GREP -m1 -E -- "^[bcd-][rwx-]{9}.*[a-z]/?$" ${Manifest}) )
[[ ${#chk[@]} == 6 ]] \
&& [[ ${chk[0]} =~ ^[bcdrwxsStT-]{10}$ ]] \
&& [[ ${chk[1]} =~ ^[a-z]*/[a-z]*$ ]] \
&& [[ ${chk[2]} =~ ^[0-9]+,?[0-9]*$ ]] \
&& [[ ${chk[3]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
&& [[ ${chk[4]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
&& [[ ${chk[5]} =~ ^[.]/[[:print:]]+$ ]] \
|| $manifest_invalid
return
}
ChkDistro () {
DISTRO=$(grep -E ^ID=[[:print:]]+ ${MNTPOINT%/}/etc/os-release 2>/dev/null)
}
################################################################################
# GetIndex #
# unlikely with slackware's ( tar vtf package.txz )>> MANIFEST
# but if the manifest were in a different order to what we expect
# this could be used to find the array indices we need
# only PERMS, OWNER_GRP and FILEPATH are used in this script
# they are META[0] , META[1] and META[5]
GetIndex () {
################################################################################
for i in ${!chk[@]}
do
[[ ${chk[i]} =~ ^[bcdrwxsStT-]{10}$ ]] \
&& PERMS=$i || continue
[[ ${chk[i]} =~ ^[a-z]+/[a-z]+$ ]] \
&& OWN_GRP=$i || continue
#[[ ${chk[i]} =~ ^[0-9]+,?[0-9]*$ ]] \
# && SIZE=$i || continue
#[[ ${chk[i]} =~ ^[1-2][0,9][0-3,7-9][0-9]-[0-1][0-9]-[0-3][0-9]$ ]] \
# && FILEDATE=$i || continue
#[[ ${chk[i]} =~ ^[0-5][0-9]:[0-5][0-9]$ ]] \
# && FILETIME=$i || continue
[[ ${chk[i]} =~ ^[.]/[[:print:]]+$ ]] \
&& FILE_PATH=$i || continue
done
}
ReadManifest () {
sort -u -d -k6 <($GREP -E -- "$1" "${Manifest}" )
return 0
}
Textual_to_Octal () {
################################################################################
S=0 # unset special bits by default
# bash arrays start at 0, so 3 is 4th in string
[[ ${1:3:1} =~ [sS] ]] && S=$(( ${S} + 4 )) ##\
[[ ${1:6:1} =~ [sS] ]] && S=$(( ${S} + 2 )) # set as per manifest
[[ ${1:(-1)} =~ [tT] ]] && S=$(( ${S} + 1 )) ##/
# only need to declare once
[[ $p ]] || declare -A \
p=(
[r]="4" [w]="2" [x]="1" [-]="0"
[s]="1" [S]="0" [t]="1" [T]="0"
)
# S ( s{u,g}id no exec. ) is unlikly to exist in manifest, but it is valid
printf "0%d%d%d%d" \
${S} \
$(( ${p[${1:1:1}]} + ${p[${1:2:1}]} + ${p[${1:3:1}]} )) \
$(( ${p[${1:4:1}]} + ${p[${1:5:1}]} + ${p[${1:6:1}]} )) \
$(( ${p[${1:7:1}]} + ${p[${1:8:1}]} + ${p[${1:9:1}]} ))
# ${1} is what we fed into the function ( drwxr-xr-x )
# p is our Associative (-A) array, bit values are indexed with textual char.
# :1:1} == r ( the second element of the string d(r)wxr-xr-x )
# special User Group Other
# no s / S ${p[r]} == 4 ${p[r]} == 4 ${p[r]} == 4
# no t / T ${p[w]} == 2 ${p[-]} == 0 ${p[-]} == 0
# ${p[x]} == 1 ${p[x]} == 1 ${p[x]} == 1
# sum == 0 sum == 7 sum == 5 sum == 5 >> 0755
################################################################################
}
Textual_to_Symbolic () {
################################################################################
SUID=",u-s" ##\
SGID=",g-s" # unset special bits by default
STICKY=",o-t" ##/
[[ ${1:3:1} =~ [sS] ]] && SUID="s" ##\
[[ ${1:6:1} =~ [sS] ]] && SGID="s" # set as per manifest
[[ ${1:(-1)} =~ [tT] ]] && STICKY="t" ##/
perms="${1//[st]/x}" # s and t imply exec. bit
perms="${perms//[ST-]/ }" # S and T imply no exec. bit
perms="\
u=${perms:1:3}${SUID}, \
g=${perms:4:3}${SGID}, \
o=${perms:7:3}${STICKY} \
"
perms="${perms//[[:space:]]}" # remove white space.
printf "%s" "${perms}"
}
Hammer () {
################################################################################
# chmod pretty much everything
# Why?
# it will fix anything "extra" that is not in the manifest
# no real sense in leaving rogue 777 dirs/files hanging around
# dirs 00755
$XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
-type d \
! -regex "${MNTPOINT%/}\(/lost.found\|/home\)/" \
! -perm 0755
)
# files in a /{s}bin/ 00755
$XARGS chmod -v 00755 < <( find ${MNTPOINT%/}/ -xdev \
-type f \
-regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
! -perm 0755
)
# files not in a /{s}bin/ 00644
$XARGS chmod -v 00644 < <( find ${MNTPOINT%/}/ -xdev \
-type f \
! -regex "\(.*/s?bin/.*\)\|\(.*/pkgtools/\(.*scripts|setup\)/.*\)" \
! -regex "${MNTPOINT%/}\(/home/.*\)\|\(/tmp/.*\)" \
! -perm 0644
)
# Yes, many more locations should have exec. scripts
# These will be fixed when manifest is processed
}
################################################################################
LVM () {
#TODO add option for this ( or look to see if needed )
# lvm dirs
$XARGS chmod -v 00700 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
-type d \
-regex ".*/lvm/\(archive\|backup\|cache\)" \
! -perm 0700
)
# lvm files
$XARGS chmod -v 00600 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
-type f \
-regex ".*/lvm/\(archive\|backup\|cache\)/.*" \
! -perm 0600
)
$XARGS chmod -v 00444 < <( find ${MNTPOINT%/}/etc/lvm -xdev \
-type f \
-regex ".*/lvm/profile/.*" \
! -perm 0444
)
}
################################################################################
QueryManifest (){
# [0]="Perms" [1]="Owner/Group [2]="Size|Major/Minor"
# [3]="Date" [4]="Time" [5]="Path/file"
while read -a META
do
[[ $DISTRO =~ slackware ]] && {
# fix 1994 var/run with incorrect perms
[[ ${META[5]} == var/run/ && ${META[0]} == drwxrwxr-x ]] \
&& META[0]="drwxr-xr-x"
}
#PrintCosmetic $FUNCNAME "${META[5]}"
# check file/dir exists
[[ -e "${MNTPOINT%/}/${META[5]}" ]] \
&& printf "%s\n" "${MNTPOINT%/}/${META[5]#./}"
[[ $DISTRO =~ slackware ]] && {
#Slackware Specific
# files ending .new may or may not exist
# But these are temp. files, so check after stripping .new
[[ ${META[5]:(-4)} == \.new ]] \
|| continue \
&& ni=${#META[@]} \
&& META[$ni]=${META[5]%.new}
#PrintCosmetic $FUNCNAME "${META[$ni]}"
[[ -e "${MNTPOINT%/}/${META[$ni]}" ]] \
&& printf "%s\n" "${MNTPOINT%/}/${META[$ni]#./}"
}
done< <( ReadManifest "${1}" )
}
################################################################################
ErrorReport () {
ExitCode=$?
# since I'm posting this where tabs cannot be input I have removed leading tabs.
# the - in <<- strips the leading tabs from output
# if you want readability re-add the tabs,
# NOTE I lead with two spaces, IMO output looks better with a margin.
#
# The nice thing about this function is Creepers will not dare come near!
case ${ExitCode} in
10) cat <<-EOF
MANIFEST required
$0 /path/to/MANIFEST.bz2
EOF
;;
20) cat <<-EOF
"${Manifest}" does not appear to be a validi Manifest
edit the script to skip this test
I will add a flag later
EOF
;;
30) Foo=($(grep -o -E "(text|application)/[a-z-]*" "$0" ))
Foo=(${Foo[@]#app*/})
cat <<-EOF
"${fileis[1]:0:(-1)}" not supported
valid compressions are ${Foo[@]/x-}
EOF
;;
99) cat <<-EOF
Unknown Error
I hope "$Error"
makes some sense to you
EOF
;;
esac
exit ${ExitCode}
}
################################################################################
PrintCosmetic () {
# calls to this are commented out as it slows things down quite a bit.
# Although, the slowdown is just mins, not 10s of mins.
case $1 in
Filter|OwnGrpFilter)
printf "%-${COLUMNS}s\n" "Current filter ${2}" 1>&2
;;
QueryManifest)
#TODO put prefix into a var
[[ $(( ${#2} + 9 )) -gt ${COLUMNS} ]] \
|| printf "%-${COLUMNS}s\r" \
"Checking ${2}" 1>&2 \
&& printf "%-${COLUMNS}s\r" \
"Checking ${2:$(( $(( ${#2} + 9 )) - $COLUMNS ))}" 1>&2
;;
esac
}
################################################################################
Filter () {
# Initially I had QueryManifest printing the chmod/chown for each line
# This Filter now groups each "unique" chmod and executes as a block via xargs
# Which should be much quicker ( but generated script will look ugly as hell )
filter="${1:-[drwxstT-]{10}}" #TODO include block/char when root is MNTPOINT
while read -a FILTER
do
#PrintCosmetic $FUNCNAME "${FILTER[0]}"
$XARGS chmod -v $( $MODE ${FILTER[0]} ) \
< <(QueryManifest "^${FILTER[0]}")
done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
################################################################################
OwnGrpFilter () {
# I ignored chown for a while, this re-adds that, same logic as Filter
# with regards to doing as a block
# Note, seperate chown does greatly increase the processing time
# However, in the case of fixing a "chmod -R 777 /" chown would not be
# needed, so I figured it would be better to have as a non default option.
filter="${1:- [a-z]+/[a-z]+ }"
while read -a FILTER
do
#PrintCosmetic $FUNCNAME "\" ${FILTER[0]/\//:} \""
$XARGS chown ${FILTER[0]/\//:} \
< <(QueryManifest " ${FILTER[0]} ")
done < <(sort -u < <($GREP -Eo -- "${filter}" "${Manifest}") )
}
################################################################################
trap ErrorReport EXIT
################################################################################
ChkManifest || exit
Hammer
Filter
#OwnGrpFilter
################################################################################
(5) booted "liveDebian" and mounted the "bad" partition then ran the following . . .
Everything completed with no errors. HOWEVER, it didn't change the permissions as I had hoped.
It appeared to have changed "some" directories and files, but most of the dirs were still marked "drwzrwzrwz"
At this point, I decided to reinstall Ubuntu Server. I had some difficulty with the RAID partitioning - it was initially setup to "mirror" and we needed more disc space - so I "blew" the existing partitions and installed from "scratch" It had also given me problem installing "grub" This is a redeployed Mark VI Integrator, and we will now use it with more disc space (1 TB)
Thanks to "Firerat" for his efforts! If I had had more time, I would have consulted with him to make the scripts works. I am convinced the DO work.
just a comment:
you can analyze packages and restore permissions based on that information, but you cannot restore files created without installation (like log files). Also there are postinstall scripts which may make it even more difficult.
So you can completely restore your system only from a full backup.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.