Điều gì sẽ xảy ra nếu tôi vô tình chạy lệnh chmod -Riến trên các thư mục hệ thống (/, / etc, tầm)


56

Tôi vô tình chạy

sudo chmod 755 -R /

thay vì

sudo chmod 755 -R ./

Tôi đã dừng nó sau vài giây, nhưng bây giờ có một số vấn đề như

sudo: must be setuid root

Làm thế nào tôi có thể hoàn nguyên các quyền trở lại?


18
oh thân yêu ... sudocó nghĩa là, bạn đã nghĩ gấp đôi những gì bạn sẽ làm!
antivirtel

2
Đơn giản nhất là cài đặt lại. Đặt LiveCD / USB và tại màn hình nơi nó yêu cầu bạn phân vùng đĩa, nó sẽ cung cấp cho bạn tùy chọn Upgrade from Ubuntu 11.04 to Ubuntu 11.04. Chấp nhận tùy chọn này và nó sẽ cài đặt lại Ubuntu một cách hiệu quả cho bạn, theo cách không đau đớn nhất.
user4124

13
Chỉ cần bây giờ bạn đã học được một bài học. Bạn không cần phải viết /vào cuối tên thư mục để chỉ định thư mục làm mục tiêu. Đó là một thói quen xấu , đừng làm điều đó, đừng bao giờ ! Các .là do bản thân tên thư mục hợp lệ, không có cần phải gắn /với nó. Nếu mọi người tuân theo quy tắc này, thì rất nhiều sudothao tác bị nhầm lẫn sẽ không có tác dụng đối với thư mục gốc, do đó, sẽ không có tác hại nào đối với hệ thống của họ. Đừng làm thế!
ulidtko

3
@ fl00r, vâng. Đó là một tên thư mục có nghĩa là thư mục này hoặc "hiện tại". cd ., ví dụ, không làm gì cả. ls .cũng giống như ls. Ngoài ra, ..tên thư mục có nghĩa là "cha mẹ của ." và có lẽ bạn đã biết nó.
ulidtko

2
@ulidtko: Có một ngoại lệ là không sử dụng /ở cuối. Nếu bạn muốn mở rộng tên đường dẫn cho các thư mục. Ví dụ về các thư mục liệt kê trong thư mục hiện tại:echo */
pabouk

Câu trả lời:


57

Nói tóm lại: bạn không thể, cài đặt lại hệ thống của bạn.

Ý tôi là, quyền Posix được sử dụng và dựa nhiều vào; có vô số vị trí trong hệ thống tập tin trong đó các quyền sai sẽ phá vỡ HĐH (cờ SUID) hoặc thậm chí tệ hơn, làm cho nó bị lộ bảo mật-khôn ngoan ( /etc/ssh/ssh_host_rsa_key) trong khi nó có vẻ hoạt động tốt.

Do đó, phục hồi như vậy là khó để làm đúng. Bỏ lỡ một điều - và bạn làm hỏng nó lên. Bạn đã làm hỏng sudo chmodlệnh của mình (nếu đó là bạn của bạn chứ không phải bạn, cô ấy cũng có thể học một số bài học về Linux) - và đó là một lệnh rất đơn giản. Phục hồi đúng cách sẽ đòi hỏi nhiều cách hơn và cảnh giác hơn. Ngay cả khi bạn sử dụng kịch bản của ai đó.

Vì vậy, hãy tin tôi, chỉ cần cài đặt lại. Đó là đặt cược an toàn và đảm bảo giúp bạn tránh khỏi rắc rối.


Cuối cùng, một số lời khuyên có liên quan ở đây.

Đầu tiên: cài đặt lại sẽ bớt đau hơn nếu bạn thiết lập /hometrên một phân vùng riêng vào lần tới. Trên thực tế, họ sẽ là một làn gió.

Thứ hai: xem xét thực hiện khoa học Linux điên rồ trong một máy ảo như VirtualBox và thực hiện các ảnh chụp nhanh của bạn.

Thứ ba: chmod -R .công trình. Một dấu chấm của chính nó .là tên thư mục hợp lệ. Không có nhu cầu thực sự để nối thêm dấu gạch chéo đó. Bạn có thể tránh được rủi ro thảm khốc khi bỏ qua dấu chấm một cách tuyệt đối;
chỉ là chmod: missing operand after ‘755’một hệ thống bị hủy hoại.


1
Ahhh :) buồn quá.
fl00r

14
Vâng, bạn có thể bằng cách nhận tất cả các quyền cho mọi tệp từ một hệ thống khác, nhưng thực hiện công việc này rất nhiều nên có thể dễ dàng hơn và an toàn hơn nếu chỉ cài đặt lại.
Oli

2
Và đừng buồn! Với sức mạnh to lớn đi kèm với trách nhiệm lớn
ulidtko

Vâng, tôi vừa phá hủy máy tính xách tay của mình với điều này ... Thật tuyệt vời khi bạn có thể dễ dàng phá hủy một máy dựa trên linux.
amanuel2

@ amanuel2 với sức mạnh lớn đi kèm với trách nhiệm lớn. Xem những gì bạn gõ; sudocó nghĩa là bạn phải kiểm tra hai lần.
ulidtko

26

Tôi đã viết và đã sử dụng vài năm một vài tập lệnh Ruby để cấp rsyncquyền và quyền sở hữu. Script get-filesystem-aclthu thập tất cả thông tin bằng cách duyệt qua tất cả các tệp và đặt tất cả vào tệp .acl. Script .acl-restoresẽ đọc .aclvà áp dụng tất cả các chownchmod.

Bạn có thể chạy get-filesystem-acltrên bản cài đặt Ubuntu tương tự và sau đó sao chép .acltệp vào hộp bị hỏng chmod của bạn, đặt .acl.acl-restorevào /, và chạy .acl-restore.

Bạn sẽ cần phải có root để sửa lỗi sudonhư Marco Ceppi đề xuất.

Tôi có thể tạo và cung cấp cho bạn .acltệp cho Ubuntu của tôi.

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. Nhưng tôi đã cài đặt lại nó rồi. Cảm ơn!
fl00r

kịch bản của bạn thất bại vì không owner_idđược xác định
Eliran Malka

8
hơi quá mức ... tìm thấy điều đó khá độc đáo:find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
reflog

12

Trong dài hạn: bạn có thể. Bạn sẽ cần gắn hệ thống tệp từ CD Live và bắt đầu hoàn nguyên các quyền ở những nơi thích hợp. Tối thiểu để lấy lại sudo, bạn sẽ muốn chạy sudo chmod u+s /usr/bin/sudotrong phiên LiveCD - điều đó sẽ khắc phục lỗi gốc phải được thiết lập.

Tuy nhiên, có thể dễ dàng hơn để cài đặt lại hệ thống.


4

Tôi sẽ cố gắng cài đặt lại tất cả các gói với apt-get install --reinstall, có thể sử dụng đầu ra của dpkg --get-selections | grep installđể có được danh sách của chúng.


Đây không phải là một ý tưởng tồi nhưng bạn cần loại trừ những thứ được cài đặt tự động hoặc bạn sẽ kết thúc vĩnh viễn với các gói đó (ngay cả khi bạn đã xóa các gói phụ thuộc) ... Nhưng sau đó chúng sẽ không được cài đặt lại. Một khó khăn. Có lẽ trước tiên hãy lấy danh sách các gói tự động, sau đó cài đặt lại mọi gói sau đó đi qua danh sách các ô tô, đánh dấu lại chúng là tự động.
Oli

@Oli - sẽ không (một số) được giải quyết bằng cách chạy sudo apt-get autoremove?
Wilf

@Wilf Không - autoremovechỉ xóa các gói bạn chưa cài đặt thủ công.
Dmitry Grigoryev

Tồn tại apt-mark auto $pkg/ apt-mark manual $pkgcho phép bạn sửa đổi trạng thái của mỗi gói "cài đặt thủ công / tự động cài đặt".
ulidtko

3

Được rồi, tôi đã không kiểm tra điều này (vì vậy hãy tự chịu rủi ro khi sử dụng), nhưng nó vẫn có thể hoạt động. Tôi sẽ kiểm tra điều này trong một máy ảo khi tôi có cơ hội:

Đầu tiên, trong một hệ thống vẫn hoạt động, tôi đã làm như sau để có được tất cả các quyền của tệp trong danh sách, bỏ qua /home/thư mục:

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

Điều này sẽ in các quyền và tên tệp cho mỗi tệp hoặc thư mục trên hệ thống, theo sau là một \0ký tự (điều này cần thiết sau này để xử lý các tên tệp lạ như các tệp có chứa dòng mới).

Sau đó, trên một hệ thống nơi các quyền của tệp đã bị xâm phạm:

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

Điều này sẽ đọc từng dòng fileper.log, lưu các quyền như $permvà tên tệp $filevà sau đó sẽ đặt quyền của tệp (hoặc thư mục) thành bất cứ điều gì được liệt kê trongfileper.log


Một vài điều cần lưu ý ở đây:

  • Trong khi xuất ra tệp : /tmp/fileper.log, bạn có thể liệt kê các cài đặt tùy chỉnh và Proc, v.v.
  • bạn có thể không khởi động được hoặc chạy các lệnh

Những gì tôi muốn đề xuất là khởi động LiveCD với phiên bản Linux bạn có trên đĩa của mình, chạy lệnh, sửa đổi đường dẫn đến nơi bạn có đĩa cục bộ được gắn và chạy lệnh thứ hai!


Tôi đã kiểm tra rằng khi khởi động từ Ubuntu CD / USB, tôi có thể chọn không định dạng đĩa, nghĩa là nó sẽ thay thế mọi thứ trong /thư mục, NHƯNG bỏ qua /home/thư mục. Có nghĩa là người dùng của bạn sẽ có cấu hình của ứng dụng / DATA (Âm nhạc, Video, Tài liệu) vẫn còn nguyên. Và bằng cách thay thế các tập tin hệ thống, chmodđược đặt thành số thích hợp.


1
Tại sao chmod $(echo $LINE)thay vì chỉ chmod $LINE? Ngoài ra, bạn có thể sử dụng findmà không cần stat: find … -printf "%#m %p\n". Tốt hơn nữa, bạn có thể tạo toàn bộ lệnh : find … -printf "chmod %#m %p\n", sau đó thực thi tệp dưới dạng tập lệnh.
muru

Dòng tìm kiếm không hoạt động như nó vốn có, michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.lognhưng nó cũng chạy qua /procvà một số nơi khác mà bạn có thể không muốn trong danh sách của mình.
Videonauth

@muru đã viết cái này vào giữa đêm. Sẽ chỉnh sửa mã ...
blade19899

Không thể kiểm tra, sẽ dựa vào đầu vào của người dùng
blade19899

2

(Tôi biết tôi không nên bình luận trong một câu trả lời, nhưng không đủ danh tiếng để bình luận.)

Câu trả lời của blade19899 làm việc cho tôi ngoại trừ các liên kết tượng trưng. Ví dụ: nó đã áp dụng 755 cho / bin / bash, nhưng sau đó áp dụng 777 cho symlink / bin / rbash, hiệu quả là 777-ing / bin / bash.

Vì tôi đã có tệp fileper.log, tôi chỉ sửa đổi lệnh đích:

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

Nếu bạn có một bản sao lưu quyền, tại sao không tạo một bản sao lưu đầy đủ và khôi phục nó khi cần thiết? Điều đó sẽ giúp bạn tiết kiệm trong trường hợp bất kỳ lệnh nào vô tình chạy, không chỉ chmod.
Dmitry Grigoryev

> ... effectively 777-ing /bin/bash- không; Đó không phải là cách nó hoạt động. Bạn đang nói rằng tôi có thể thay thế /usr/bin/aptbằng thứ của riêng tôi với tư cách là người dùng không phải root , chỉ bằng cách viết cho nó thông qua một symlink 777? :) Luyện tập tư duy phản biện; symlink không thể, và đừng, làm việc theo cách đó. 777 quyền cho symlink là phổ biến và bình thường.
ulidtko

2

Bạn có thể thử khôi phục quyền với apt-get.

Nếu bạn không thể chạy các lệnh này với sudo, bạn có thể cần phải khởi động đến chế độ phục hồi và chạy chúng dưới quyền root.

Để khởi động vào chế độ phục hồi, hãy xem https://wiki.ubfox.com/RecoveryMode .

Từ http://hyperlogos.org/page/Restoring-Permissions-Debian-System

Lưu ý: Điều này ban đầu được đăng trên Diễn đàn Ubuntu nhưng tôi không thể tìm thấy bài viết gốc.

Hãy thử, theo thứ tự,

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

Nếu thất bại:

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

Và cuối cùng, như một phương sách cuối cùng,

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

Sử dụng apt-get

Đây là snip có liên quan, EDITED FOR CORRECTNESS và được định dạng lại:

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

Giả sử bạn nhận được thông báo về một số gói không thể cài đặt lại và lệnh không thành công. Đây là một cách để khắc phục bằng cách bỏ qua các gói trong câu hỏi:

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

Và cuối cùng, nếu bạn bằng cách nào đó nên cài đặt quá nhiều thứ mà lệnh trên không nói danh sách đối số của bạn quá dài, đây là bản sửa lỗi, sẽ chạy apt-get nhiều lần hơn bạn có thể:

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

Lưu ý -y--force-yescác tùy chọn, sẽ dừng apt-getnhắc bạn nhiều lần. Đây luôn là những lựa chọn thú vị, nếu bạn chắc chắn bạn biết mình đang làm gì.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.