Bagaimana jika saya secara tidak sengaja menjalankan perintah "chmod -R" pada direktori sistem (/, / etc, ...)

56

Saya tidak sengaja berlari

sudo chmod 755 -R /

dari pada

sudo chmod 755 -R ./

Saya menghentikannya setelah beberapa detik, tetapi sekarang ada beberapa masalah seperti

sudo: must be setuid root

Bagaimana saya bisa mengembalikan izin?

fl00r
sumber
18
oh sayang ... sudoberarti, bahwa Anda telah berpikir dua kali apa yang akan Anda lakukan!
antivirtel
2
Cara termudah adalah menginstal ulang. Letakkan LiveCD / USB, dan pada layar di mana ia meminta Anda untuk mempartisi disk Anda, itu akan memberi Anda pilihan untuk Upgrade from Ubuntu 11.04 to Ubuntu 11.04. Terima opsi ini, dan itu akan menginstal ulang Ubuntu secara efektif untuk Anda, dengan cara yang paling tidak menyakitkan.
user4124
13
Baru saja Anda telah belajar pelajaran. Anda tidak perlu menulis /di akhir nama direktori untuk menentukan direktori sebagai target. Itu kebiasaan buruk , jangan lakukan itu, jangan pernah ! Itu .dengan sendirinya nama direktori yang valid, tidak perlu menambahkannya /. Jika semua orang mengikuti aturan ini, maka banyak sudooperasi yang salah ketik tidak akan berpengaruh pada direktori root, jadi tidak ada salahnya dilakukan pada sistem mereka. Jangan lakukan itu!
ulidtko
3
@ fl00r, ya. Ini adalah nama direktori yang berarti direktori ini, atau "saat ini". cd ., misalnya, tidak melakukan apa pun. ls .sama dengan ls. Juga, ..ini adalah nama direktori yang berarti "induk .", dan Anda mungkin sudah mengetahuinya.
ulidtko
2
@ulidtko: Ada pengecualian untuk tidak menggunakan /di akhir. Jika Anda ingin melakukan ekspansi pathname hanya untuk direktori. Contoh daftar direktori di dalam direktori saat ini:echo */
pabouk

Jawaban:

57

Singkatnya: Anda tidak bisa, instal ulang sistem Anda.

Maksud saya, izin Posix digunakan dan sangat diandalkan; ada banyak tempat di sistem file di mana izin yang salah akan merusak OS (SUID flags) atau bahkan lebih buruk, membuatnya terkena keamanan-bijaksana ( /etc/ssh/ssh_host_rsa_key) sementara tampaknya berfungsi dengan baik.

Karenanya, pemulihan seperti itu sulit dilakukan dengan benar. Kehilangan satu hal - dan Anda mengacaukannya. Anda telah mengacaukan sudo chmodperintah Anda (jika itu teman Anda dan bukan Anda, dia mungkin juga belajar beberapa pelajaran Linux) - dan itu perintah yang sangat sederhana. Pemulihan yang tepat akan menuntut lebih banyak perintah dan lebih banyak kewaspadaan. Bahkan jika Anda menggunakan skrip seseorang.

Jadi percayalah, instal ulang. Ini adalah taruhan yang aman dan dijamin untuk membuat Anda keluar dari masalah.


Akhirnya, beberapa tips relevan di sini.

Pertama: menginstal ulang tidak akan terlalu menyakitkan jika Anda membuat /homepartisi lain di lain waktu. Sebenarnya, mereka akan sangat mudah.

Kedua: pertimbangkan untuk melakukan ilmu Linux gila di mesin virtual seperti VirtualBox, dan lakukan snapshot Anda.

Ketiga: chmod -R .bekerja. Titik dengan sendirinya .adalah nama direktori yang valid. Tidak perlu menambahkan garis miring itu. Anda bisa menghindari risiko bencana melewatkan titik masuk;
hanya chmod: missing operand after ‘755’VS sistem yang hancur.

ulidtko
sumber
1
Ahhh :) sangat sedih.
fl00r
14
Yah Anda bisa dengan mendapatkan semua izin untuk setiap file dari sistem lain, tetapi melakukan ini adalah pekerjaan yang sangat banyak sehingga mungkin lebih mudah dan aman hanya untuk menginstal ulang.
Oli
2
Dan jangan sedih! Dengan kekuatan besar datang tanggung jawab besar
ulidtko
Ya saya baru saja menghancurkan laptop saya dengan ini ... Luar biasa bagaimana Anda dapat dengan mudah menghancurkan mesin berbasis linux.
amanuel2
@ amanuel2 dengan kekuatan besar datang tanggung jawab besar. Perhatikan apa yang Anda ketik; sudoberarti Anda harus memeriksa dua kali.
ulidtko
26

Saya menulis dan telah menggunakan selama beberapa tahun beberapa skrip Ruby untuk rsyncizin dan kepemilikan. Script get-filesystem-aclmengumpulkan semua informasi dengan secara rekursif melintasi semua file dan memasukkannya ke dalam file .acl. Script .acl-restoreakan membaca .acldan menerapkan semua chown's dan chmod' s.

Anda dapat menjalankan get-filesystem-aclpada instalasi Ubuntu yang serupa dan kemudian menyalin .aclfile ke kotak chmod-rusak Anda, letakkan .acldan .acl-restoredi /, dan jalankan .acl-restore.

Anda harus memiliki root, jadi perbaiki sudoseperti yang disarankan Marco Ceppi.

Saya dapat membuat dan memberi Anda .aclfile untuk Ubuntu saya.

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
Aleksandr Levchuk
sumber
Ubuntu 11.04. Tapi saya sudah menginstalnya kembali. Terima kasih!
fl00r
skrip Anda gagal seperti owner_idyang tidak ditentukan
Eliran Malka
8
agak berlebihan ... menemukan apakah itu cukup baik:find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
reflog
12

Panjang: Anda bisa. Anda harus memasang sistem file dari Live CD dan mulai mengembalikan izin di tempat yang sesuai. Minimal untuk mendapatkan kembali sudo Anda akan ingin menjalankan sudo chmod u+s /usr/bin/sudosementara di sesi LiveCD - yang akan memperbaiki harus setuid root.

Namun, sepertinya akan lebih mudah untuk menginstal ulang sistem.

Marco Ceppi
sumber
4

Saya akan mencoba menginstal ulang semua paket dengan apt-get install --reinstall, mungkin menggunakan keluaran dpkg --get-selections | grep installuntuk mendapatkan daftar mereka.

Adam Byrtek
sumber
Ini bukan ide yang buruk tetapi Anda harus mengecualikan hal-hal yang diinstal secara otomatis atau Anda akan berakhir secara permanen dengan paket-paket itu (bahkan jika Anda menghapus paket dependen) ... Tapi kemudian mereka tidak akan diinstal ulang. Yang tangguh. Mungkin mendapatkan daftar paket otomatis terlebih dahulu, lalu instal ulang setiap paket kemudian melalui daftar autos, menandainya kembali sebagai otomatis.
Oli
@Oli - tidak akan (sebagian) diselesaikan dengan menjalankan sudo apt-get autoremove?
Wilf
@Wilf No - autoremovehanya menghapus paket yang belum Anda instal secara manual.
Dmitry Grigoryev
Ada apt-mark auto $pkg/ apt-mark manual $pkgyang memungkinkan Anda untuk mengubah status "secara manual diinstal / diinstal secara otomatis" per-paket.
ulidtko
3

Baiklah, saya belum menguji ini (jadi gunakan dengan risiko Anda sendiri), tetapi masih mungkin berhasil. Saya Akan menguji ini di mesin virtual ketika saya mendapat kesempatan untuk:

Pertama, dalam sistem yang masih berfungsi, saya melakukan yang berikut untuk mendapatkan semua izin file dalam daftar, melewatkan /home/direktori:

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

Ini akan mencetak izin dan nama file untuk setiap file atau direktori pada sistem, diikuti oleh \0karakter (ini diperlukan nanti untuk menangani nama file aneh seperti yang berisi baris baru).

Kemudian, pada sistem di mana izin file telah dikompromikan:

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

Ini akan membaca setiap baris fileper.log, menyimpan izin sebagai $permdan nama file sebagai $filedan kemudian akan mengatur izin file (atau direktori) untuk apa pun yang tercantum dalamfileper.log


Beberapa hal yang perlu diperhatikan di sini:

  • Saat mengeluarkan ke file:, /tmp/fileper.logAnda mungkin mencantumkan pengaturan khusus, dan proc, dll.
  • Anda mungkin tidak dapat boot, atau menjalankan perintah,

Apa yang saya sarankan adalah boot LiveCD dengan versi Linux yang Anda miliki di disk, jalankan perintah, modifikasi path ke tempat Anda memasang disk lokal, dan jalankan perintah kedua!


Saya telah menguji bahwa ketika di-boot dari CD / USB Ubuntu, saya dapat memilih untuk tidak memformat disk, artinya akan mengganti semua yang ada di /direktori, TAPI lewati /home/direktori. Berarti pengguna Anda akan memiliki konfigurasi aplikasi / DATA (Musik, Video, Dokumen) masih utuh. Dan dengan mengganti file sistem, chmoddiatur ke nomor yang tepat di sana.

blade19899
sumber
1
Kenapa chmod $(echo $LINE)bukannya adil chmod $LINE? Juga, Anda dapat menggunakan hanya findtanpa stat: find … -printf "%#m %p\n". Lebih baik lagi, Anda dapat membuat seluruh perintah find … -printf "chmod %#m %p\n":, lalu jalankan file sebagai skrip.
muru
Baris find tidak berfungsi sebagaimana mestinya, itu seharusnya michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.logtetapi kemudian juga melewati /procdan beberapa tempat lain yang mungkin tidak Anda inginkan dalam daftar Anda.
Videonauth
@uru menulis ini di tengah malam. Akan mengedit kode ...
blade19899
Tidak dapat menguji, akan bergantung pada input pengguna
blade19899
2

(Saya tahu saya tidak harus berkomentar dalam jawaban, tetapi tidak memiliki reputasi yang cukup untuk berkomentar.)

Jawaban blade19899 bekerja untuk saya kecuali untuk symlink. Misalnya itu diterapkan 755 ke / bin / bash, tetapi kemudian diterapkan 777 ke symlink / bin / rbash, secara efektif 777-ing / bin / bash.

Karena saya sudah memiliki file fileper.log, saya baru saja memodifikasi perintah tujuan-akhir:

while IFS=: read -r -d '' perm file; do  
    if [[ ! -L "$file" ]]; then    
        chmod "$perm" "$file"
    fi
done < /tmp/fileper.log 
Marjan
sumber
Jika Anda memiliki cadangan izin, mengapa tidak membuat cadangan lengkap dan mengembalikannya saat diperlukan? Itu akan menyelamatkan Anda jika ada perintah yang dijalankan secara tidak sengaja, bukan hanya chmod.
Dmitry Grigoryev
> ... effectively 777-ing /bin/bash- tidak; bukan itu cara kerjanya. Apakah Anda mengatakan saya dapat mengganti /usr/bin/aptdengan hal saya sendiri sebagai pengguna non-root , hanya dengan menulis melalui 777 symlink? :) Latihanlah beberapa pemikiran kritis; symlink tidak bisa, dan tidak, bekerja seperti itu. 777 izin untuk symlink adalah umum dan normal.
ulidtko
2

Anda dapat mencoba mengembalikan izin dengan apt-get.

Jika Anda tidak dapat menjalankan perintah ini dengan sudo, Anda mungkin perlu menjalankan boot ke mode pemulihan dan menjalankannya sebagai root.

Untuk boot ke mode pemulihan lihat https://wiki.ubuntu.com/RecoveryMode .

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

Catatan: Ini awalnya diposting di Forum Ubuntu tetapi saya tidak dapat menemukan posting asli.

Coba, secara berurutan,

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

Jika gagal:

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

Dan akhirnya, sebagai pilihan terakhir,

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

Menggunakan apt-get

Berikut snip yang relevan, DIedit UNTUK KELEBIHAN dan diformat ulang:

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

Katakanlah Anda mendapatkan pesan tentang beberapa paket yang tidak dapat diinstal ulang, dan perintahnya gagal. Berikut ini salah satu cara untuk memperbaikinya dengan melewatkan paket-paket yang dimaksud:

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

Dan akhirnya, jika Anda entah bagaimana harus menginstal begitu banyak hal sehingga perintah di atas gagal mengatakan daftar argumen Anda terlalu panjang, inilah solusinya, yang akan berjalan dengan tepat beberapa kali lebih banyak daripada yang mungkin Anda sukai:

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

Perhatikan opsi -ydan --force-yes, yang akan berhenti apt-getmeminta Anda lagi dan lagi. Ini selalu merupakan opsi yang menyenangkan, jika Anda yakin tahu apa yang Anda lakukan.

Harimau kumbang
sumber
-3

Saya punya masalah yang sama, saya bisa memperbaikinya. Dalam kasus saya Ubuntu 19.10

Buka terminal Anda dan ketik kode sederhana di bawah ini

sudo -i

buka terminal lain dan periksa perintah di bawah ini.

sudo apt update
Elavarasan r
sumber
1
Bagaimana ini akan membantu pengguna memperbaiki masalah mereka dengan izin? Harap edit jawaban Anda dan berikan lebih banyak detail.
Kevin Bowen