如果我不小心在系统目录(/,/ etc,...)上运行命令“ chmod -R”怎么办?


56

我不小心跑了

sudo chmod 755 -R /

代替

sudo chmod 755 -R ./

几秒钟后我将其停止,但现在出现了一些问题,例如

sudo: must be setuid root

如何还原权限?


18
哦,亲爱的... sudo意味着,您会三思而后行!
antivirtel

2
最简单的是重新安装。放入LiveCD / USB,并在要求您对磁盘进行分区的屏幕上,应该为您提供选择Upgrade from Ubuntu 11.04 to Ubuntu 11.04。接受此选项,它将以最轻松的方式为您有效地重新安装Ubuntu。
user4124 2011年

13
刚才您已经学到了教训。您无需/在目录名的末尾写入即可将目录指定为目标。这是一个坏习惯,不要做,永远不要!该.是由本身有效的目录名称,也没有必要追加/到它。如果每个人都遵循此规则,那么错误键入的sudo操作将对根目录没有任何影响,因此不会对他们的系统造成损害。不要做!
ulidtko 2011年

3
@ fl00r,是的。这是一个目录名称,表示该目录或“当前”目录。cd .,例如,什么也不做。ls .与相同ls。另外,..是目录名称,表示“的父项.”,您可能已经知道了。
ulidtko 2011年

2
@ulidtko:/最后不使用是一个例外。如果只想对目录进行路径名扩展。在当前目录中列出目录的示例:echo */
pabouk

Answers:


56

简而言之:您不能重新安装系统。

我的意思是,Posix权限被大量使用和依赖;在文件系统中有很多地方,错误的权限会破坏操作系统(SUID标志)甚至更糟,使它/etc/ssh/ssh_host_rsa_key在看起来可以正常工作的同时以安全方式公开()。

因此,这种恢复很难正确地进行。错过了一件事 -你把它搞砸了。您已经弄错了sudo chmod命令(如果不是您,而是您的朋友,那么她可能还应该学习一些Linux课)-这是一个非常简单的命令。正确的恢复将需要更多的命令和更多的警惕性。即使您使用某人的脚本。

所以相信我,只需重新安装即可。这是一个安全的选择,可以保证让您摆脱麻烦。


最后,这里有一些技巧。

第一:将重新安装,如果你那么痛苦设置您的/home一个单独的分区下一次。实际上,它们将是轻而易举的。

第二:考虑做疯狂的科学的Linux虚拟机像VirtualBox的,做你的快照。

第三:chmod -R .作品。点本身.就是有效的目录名称。并不需要真正添加该斜杠。您本来可以避免大胆地跳过点的灾难性风险;
仅仅chmod: missing operand after ‘755’VS毁了系统。


1
啊:)好伤心。
fl00r 2011年

14
那么你可能通过让所有的权限从另一个系统中每个文件,但是这样做这么多的工作,它很可能会更容易,更安全只是重新安装。
奥利(Oli)

2
而且不要难过!强大的力量带来巨大的责任
ulidtko '16

是的,我只是用这个破坏了我的笔记本电脑...令人惊讶的是,您如何轻松地破坏基于Linux的计算机。
amanuel2

@ amanuel2拥有强大的力量来承担巨大的责任。注意输入的内容;sudo意味着您必须检查两次。
ulidtko

26

我写了几年并且一直在使用两个Ruby脚本来rsync获得权限和所有权。脚本get-filesystem-acl通过递归遍历所有文件来收集所有信息,并将其全部放入文件中.acl。脚本.acl-restore将读取.acl并应用所有chown的和chmod

您可以运行get-filesystem-acl在一个类似Ubuntu的安装,然后在复制.acl文件到您的CHMOD损伤箱,放.acl.acl-restore中/,并运行.acl-restore

您将需要有root用户,所以请sudo按照Marco Ceppi的建议进行修复。

我可以.acl为我的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

Ubuntu 11.04。但是我已经重新安装了它。谢谢!
fl00r 2011年

您的脚本失败,因为owner_id未定义
Eliran Malka 2014年

8
有点过头了...发现做得很好:find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
reflog

12

总而言之:可以。您需要从Live CD挂载文件系统,然后开始在适当的位置还原权限。至少要恢复sudo,您需要sudo chmod u+s /usr/bin/sudo在LiveCD会话中运行-这将修复必须设置为setuid的根。

但是,简单地重新安装系统可能会更容易。


4

我会尝试使用重新安装所有软件包apt-get install --reinstall,可能使用的输出dpkg --get-selections | grep install来获取它们的列表。


这不是一个坏主意,但是您需要排除自动安装的东西,否则您将永久获得这些软件包(即使您删除了相关的软件包)……但是那样就不会重新安装它们了。坚强的。也许先获取自动软件包列表,然后重新安装每个软件包,然后遍历自动列表,然后将它们重新标记为自动。
奥利(Oli)

@Oli-(某些)运行不会解决sudo apt-get autoremove吗?
Wilf 2014年

@Wilf否- autoremove仅删除尚未手动安装的软件包。
德米特里·格里戈里耶夫

3

好的,我尚未对此进行测试(因此使用后果自负),但仍然可以使用。有机会时,我将在虚拟机中对此进行测试:

首先,在仍然正常工作的系统中,我执行以下操作以跳过列表而获得列表中的所有文件权限/home/

sudo find / -not -path /home -printf "%m:%p\0" > /tmp/fileper.log

这将打印系统上每个文件或目录的权限和文件名,后跟一个\0字符(以后需要使用该字符来处理奇怪的文件名,例如包含换行符的文件名)。

然后,在文件权限受到损害的系统上:

while IFS=: read -r -d '' perm file; do  
    chmod "$perm" "$file"
done < /tmp/fileper.log 

这将读取的每一行fileper.log,将权限另存为$perm,将文件名另存为$file,然后将文件(或目录)的权限设置为fileper.log


这里需要注意的几件事:

  • 输出到文件:时/tmp/fileper.log,您可能会列出自定义设置和proc等。
  • 您可能无法启动或运行命令,

我的建议是使用磁盘上的Linux版本启动LiveCD,运行命令,修改安装本地磁盘的路径,然后运行第二条命令!


我已经测试过,从Ubuntu CD / USB引导时,我可以选择不格式化磁盘,这意味着它将替换/目录中的所有内容,但会跳过/home/目录。这意味着您的用户将完整保留app / DATA(音乐,视频,文档)的配置。并通过替换系统文件将chmod设置为适当的编号。


1
为什么chmod $(echo $LINE)不只是chmod $LINE?此外,您还可以只使用findstatfind … -printf "%#m %p\n"。更好的是,您可以创建整个命令:find … -printf "chmod %#m %p\n",然后将其作为脚本执行。
muru

查找行不能按原样运行,但是应该可以michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.log运行,但它也会遍历,/proc并且可能还会在列表中不希望包含其他位置。
Videonauth

@muru在深夜写了这个。将编辑代码...
blade19899'5

无法测试,将取决于用户输入
blade19899'5

3

(我知道我不应该在答案中发表评论,但是声誉不足以发表评论。)

blade19899的答案对我有用,除了符号链接。例如,将755应用于/ bin / bash,但随后将777应用于符号链接/ bin / rbash,有效地将777-ing送到/ bin / bash。

因为已经有了fileper.log文件,所以我刚刚修改了destination-end命令:

while IFS=: read -r -d '' perm file; do  
    if [[ ! -L "$file" ]]; then    
        chmod "$perm" "$file"
    fi
done < /tmp/fileper.log 

如果您有权限的备份,为什么不只进行完整备份并在需要时还原它呢?如果有任何命令意外运行,而不仅仅是,那可以节省您的时间chmod
德米特里·格里戈里耶夫

2

您可以尝试使用恢复权限apt-get

如果无法使用sudo运行这些命令,则可能需要引导至恢复模式并以root用户身份运行它们。

有关启动到恢复模式的信息,请参见https://wiki.ubuntu.com/RecoveryMode

来自http://hyperlogos.org/page/Restoring-Permissions-Debian-System

注意:这最初是在Ubuntu论坛上发布的,但是我找不到原始的帖子。

依次尝试

sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1`

如果失败:

sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | egrep -v '(package1|package2)'`

最后,作为最后的手段,

sudo dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | xargs apt-get --reinstall -y --force-yes install

使用apt-get

这是相关的片段,为正确而编辑并重新格式化:

sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1`

假设您收到有关无法重新安装的某些软件包的消息,并且命令失败。这是跳过有问题的软件包来解决此问题的一种方法:

sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | egrep -v '(package1|package2)'`

最后,如果您应该以某种方式安装了太多东西,以致上面的命令无法显示您的参数列表太长,则此修复程序可以比大多数人运行apt-get多次:

sudo dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | xargs apt-get --reinstall -y --force-yes install

注意-y--force-yes选择,这将停止apt-get从一遍遍提示您。如果您确定自己知道自己在做什么,这些总是很有趣的选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.