What if I accidentally run command "chmod -R" on system directories (/, /etc, ...)
Solution 1
In short: you can't, reinstall your system.
I mean, Posix permissions are used and relied on heavily; there's a multitude of places in the filesystem where wrong permissions would break the OS (SUID flags) or even worse, make it exposed security-wise (/etc/ssh/ssh_host_rsa_key
) while it appears to be working OK.
Hence, such a recovery is hard to do properly. Miss one thing — and you screw it up. You already screwed up your sudo chmod
command (if that's your friend rather than you, she might as well learn some Linux lesson, too) — and that's a very simple of a command. Proper recovery would demand way more commands and way more vigilance. Even if you use someone's script.
So trust me, just reinstall. It's a safe bet and guaranteed to keep you out of trouble.
Finally, some tips relevant here.
First: reinstalls will be less painful if you setup your /home
on a separate partition next time. Actually, they will be a breeze.
Second: consider doing crazy Linux science in a virtual machine like the VirtualBox, and do your snapshots.
Third: chmod -R .
works. A dot by itself .
is valid directory name. There's no real need to append that slash. You could've avoided the catastrophic risk of skipping the dot entrirely;
mere chmod: missing operand after ‘755’
VS a ruined system.
Solution 2
I wrote and have been using for several years a couple of Ruby scripts to rsync
permissions and ownership. Script get-filesystem-acl
collects all the information by recursively traversing all the files and puts it all into the file .acl
. Script .acl-restore
will read .acl
and apply all the chown
's and chmod
's.
You can run get-filesystem-acl
on a similar Ubuntu installation and then copy over the .acl
file to your chmod-damaged box, put .acl
and .acl-restore
in /, and run .acl-restore
.
You will need to have root so fix your sudo
as Marco Ceppi suggested.
I can generate and give you the .acl
file for my Ubuntu.
get-filesystem-acl
#!/usr/bin/ruby
RM = "/bin/rm"
SORT = "/usr/bin/sort"
TMP = "/tmp/get_acl_#{Time.now.to_i}_#{rand * 899 + 100}"
require 'find'
IGNORE = [".git"]
def numeric2human(m)
return sprintf("%c%c%c%c%c%c%c%c%c",
(m & 0400 == 0 ? ?- : ?r),
(m & 0200 == 0 ? ?- : ?w),
(m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
(m & 04000 == 0 ? ?x : ?s)),
(m & 0040 == 0 ? ?- : ?r),
(m & 0020 == 0 ? ?- : ?w),
(m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
(m & 02000 == 0 ? ?x : ?s)),
(m & 0004 == 0 ? ?- : ?r),
(m & 0002 == 0 ? ?- : ?w),
(m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
(m & 01000 == 0 ? ?x : ?t)))
end
File.open(TMP, "w") do |acl_file|
# TODO: Instead of the current dir, find the .git dir, which could be
# the same or outside of the current dir
Find.find(".") do |path|
next if IGNORE.collect {|ig| !!(path[2..-1] =~ /\A#{ig}/)}.include? true
next if File.symlink?(path)
stat = File.lstat(path)
group_id = stat.gid
rules = "#{type}#{numeric2human(stat.mode)}"
acl_file.puts "#{path} #{rules} #{owner_id} #{group_id}"
end
end
`#{SORT} #{TMP} > .acl`
`#{RM} #{TMP}`
.acl-restore
#!/usr/bin/ruby
# This script will only work with .acl_ids
# Restore from...
FROM = ".acl"
MKDIR = "/bin/mkdir"
CHMOD = "/bin/chmod"
CHOWN = "/bin/chown"
known_content_missing = false
def numeric2human(m)
return sprintf("%c%c%c%c%c%c%c%c%c",
(m & 0400 == 0 ? ?- : ?r),
(m & 0200 == 0 ? ?- : ?w),
(m & 0100 == 0 ? (m & 04000 == 0 ? ?- : ?S) :
(m & 04000 == 0 ? ?x : ?s)),
(m & 0040 == 0 ? ?- : ?r),
(m & 0020 == 0 ? ?- : ?w),
(m & 0010 == 0 ? (m & 02000 == 0 ? ?- : ?S) :
(m & 02000 == 0 ? ?x : ?s)),
(m & 0004 == 0 ? ?- : ?r),
(m & 0002 == 0 ? ?- : ?w),
(m & 0001 == 0 ? (m & 01000 == 0 ? ?- : ?T) :
(m & 01000 == 0 ? ?x : ?t)))
end
def human2chmod(mode)
raise unless mode =~ /([r-][w-][xtsTS-])([r-][w-][xtsTS-])([r-][w-][xtsTS-])/
triple = [$1, $2, $3]
u,g,o = triple.collect do |i|
i.sub('s', 'sx').sub('t', 'tx').downcase.gsub('-', '')
end
return "u=#{u},g=#{g},o=#{o}"
end
File.open(FROM).each do |acl|
raise unless acl =~ /\A(([^ ]*? )+)([^ ]+) ([^ ]+) ([^ ]+)\Z/
path, rules, owner_id, group_id = $1, $3, $4, $5
path = path.strip
owner_id = owner_id.to_i
group_id = group_id.to_i
if !File.exists?(path) and !File.symlink?(path)
if rules =~ /\Ad/
STDERR.puts "Restoring a missing directory: #{path}"
STDERR.puts "Probably it was an empty directory. Git goes not track them."
`#{MKDIR} -p '#{path}'` # Creating the any parents
else
known_content_missing = true
STDERR.puts "ERROR: ACL is listed but the file is missing: #{path}"
next
end
end
s = File.lstat(path)
t = s.ftype[0..0].sub('f', '-') # Single character for the file type
# But a "-" istead of "f"
# Actual, but not neccesarely Desired
actual_rules = "#{t}#{numeric2human(s.mode)}"
actual_owner_id = s.uid
actual_group_id = s.gid
unless [actual_rules, actual_owner_id, actual_group_id] ==
[rules, owner_id, group_id]
chmod_argument = human2chmod(rules)
# Debug
#p chmod_argument
#p s.mode
## Verbose
puts path
puts "Wrong: #{[actual_rules, actual_owner_id, actual_group_id].inspect}"
puts "Fixed: #{[rules, owner_id, group_id].inspect}"
`#{CHMOD} #{chmod_argument} '#{path}'`
#puts
end
end
if known_content_missing
STDERR.puts "-" * 80
STDERR.puts "Some files that are listed in #{FROM.inspect} are missing in " +
"the current directory."
STDERR.puts
STDERR.puts "Is #{FROM.inspect} outdated?"
STDERR.puts "(Try retrograding the current directory to an earlier version)"
STDERR.puts
STDERR.puts "Or is the current directory incomplete?"
STDERR.puts "(Try to recover the current directory)"
STDERR.puts "-" * 80
end
Solution 3
In long: you can. You'll need to mount the the file system from the a Live CD and begin reverting the permissions in the appropriate places. At a minimum to get sudo back you'll want to run sudo chmod u+s /usr/bin/sudo
while in the LiveCD session - that will fix the must be setuid root.
However, it would likely be easier to simply reinstall the system.
Solution 4
You can try restoring permissions with apt-get
.
If you can not run these commands with sudo you may need to boot to recovery mode and run them as root.
For booting to recovery mode see https://wiki.ubuntu.com/RecoveryMode.
From http://hyperlogos.org/page/Restoring-Permissions-Debian-System
Note: This was originally posted on the Ubuntu Forums but I can not find the original post.
Try, in order,
sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1`
If that fails:
sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | egrep -v '(package1|package2)'`
And finally, as a last resort,
sudo dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | xargs apt-get --reinstall -y --force-yes install
Using apt-get
Here's the relevant snip, EDITED FOR CORRECTNESS and reformatted:
sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1`
Let's say you get messages about some packages that can't be reinstalled, and the command fails. Here's one way to fix it by skipping the packages in question:
sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | egrep -v '(package1|package2)'`
And finally, if you should somehow have so many things installed that the above command fails saying your argument list is too long, here's the fix, which will run apt-get many more times than you might like:
sudo dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | xargs apt-get --reinstall -y --force-yes install
Note the
-y
and--force-yes
options, which will stopapt-get
from prompting you over and over again. These are always fun options, if you're sure you know what you're doing.
Solution 5
I would try to reinstall all packages with apt-get install --reinstall
, possibly using the output of dpkg --get-selections | grep install
to get a list of them.
Related videos on Youtube
Comments
-
user1631605 almost 2 years
I accidently ran
sudo chmod 755 -R /
instead of
sudo chmod 755 -R ./
I stopped it after few seconds, but now there is some problems such as
sudo: must be setuid root
How can I revert permissions back?
-
user1631605 about 13 yearsAhhh :) so sad.
-
Oli about 13 yearsWell you could by getting all the permissions for every file from another system, but doing this is so much work that it'd probably be easier and safer just to reinstall.
-
user1631605 about 13 yearsUbuntu 11.04. But I've reinstalled it already. Thanks!
-
Oli about 13 yearsThis isn't a bad idea but you'd need to exclude things that are automatically installed or you'd permanently end up with those packages (even if you removed the dependant packages)... But then they wouldn't get reinstalled. Tough one. Perhaps getting a list of the automatic packages first, then reinstall every package then go through the list of autos, re-marking them as auto.
-
Wilf over 10 years@Oli - wouldn't (some of) that be solved by running
sudo apt-get autoremove
? -
Eliran Malka over 10 yearsyour script fails as
owner_id
is undefined -
reflog almost 9 yearskinda an overkill... find does that quite nicely:
find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
-
muru about 8 yearsWhy
chmod $(echo $LINE)
instead of justchmod $LINE
? Also, you can use justfind
withoutstat
:find … -printf "%#m %p\n"
. Better yet, you can create the entire command:find … -printf "chmod %#m %p\n"
, then execute the file as a script. -
Videonauth about 8 yearsThe find line isn't working as it is, it should be
michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.log
but then as well it runs over/proc
and some other places which you might not want in your list. -
blade19899 about 8 years@muru wrote this in the middle of the night. Will edit the code...
-
blade19899 about 8 yearsNot able to test, will rely on user input
-
ulidtko almost 8 yearsAnd don't be sad! With great power comes great responsibility
-
amanuel2 over 7 yearsYeah I just destroyed my laptop with this... Amazing how you can easily destroy a linux based machine.
-
ulidtko over 7 years@amanuel2 with great power comes great responsibility. Watch what you type;
sudo
means you have to check twice. -
Yahya Uddin over 7 yearsWill a
do-release-upgrade
help? -
Dmitry Grigoryev about 7 years@Wilf No -
autoremove
only removes packages that you haven't installed manually. -
Dmitry Grigoryev about 7 yearsIf you have a backup of permissions, why not just make a full backup and restore it when needed? That would save you in case of any command run accidentally, not just
chmod
. -
ulidtko over 4 yearsThere exist
apt-mark auto $pkg
/apt-mark manual $pkg
which allow you to modify the status of "manually installed/autoinstalled" per-package. -
ulidtko over 4 years>
... effectively 777-ing /bin/bash
— nope; that's not how it works. Are you saying I can replace/usr/bin/apt
with my own thing as a non-root user, just by writing to it through a 777 symlink? :) Exercise some critical thinking; symlinks can't, and don't, work that way. 777 permissions for symlinks are common and normal. -
mchid over 4 yearsYou can keep your home directory if you install "without formatting".
-
Bill Kotsias about 4 yearsUnfortunately this made things worse for me, by braking the system settings. I cannot access Display anymore... Reinstall is on its way it seems
-
Zanna over 2 yearsGenerally this approach is inadvisable because one cannot be sure one has correctly set all the permissions. Fixing enough stuff to get the system working may not mean that everything is okay. Also, things differ between Ubuntu and Debian. On my system there are no
initrd.img
andvmlinuz
files in the top level directory, and the real versions of those files should not have 777 permissions which would be a security disaster - on Ubuntu such files are likely to be found in/boot
and are symlinks - symlinks have dummy permissions of 777, not the permissions of the files they link to.