Що робити, якщо я випадково запускаю команду "chmod -R" в системних каталогах (/, / і т.д., ...)


56

Я випадково побіг

sudo chmod 755 -R /

замість

sudo chmod 755 -R ./

Я зупинив це через кілька секунд, але зараз є такі проблеми, як

sudo: must be setuid root

Як я можу відновити дозволи назад?


18
о, дорогий ... sudoозначає, що ти подумаєш двічі, що ти будеш робити!
антивіртел

2
Найпростіше - перевстановити. Покладіть LiveCD / USB, і на екрані, де він просить розділити диск, він повинен дати вам можливість Upgrade from Ubuntu 11.04 to Ubuntu 11.04. Прийміть цю опцію, і вона дозволить ефективно перевстановити Ubuntu для вас самим безболісним способом.
user4124

13
Тільки тепер ви засвоїли урок. Не потрібно писати /в кінці імені каталогу, щоб вказати каталог як ціль. Це шкідлива звичка , не робіть цього ніколи ! Це .саме по собі дійсне ім'я каталогу, до нього додавати не потрібно /. Якби всі дотримувались цього правила, то дуже багато помилкових sudoоперацій не впливало б на кореневий каталог, тому шкоди їхнім системам не було б зроблено. Не робіть цього!
улідко

3
@ fl00r, так. Це ім'я каталогу, яке означає це, або "поточний" каталог. cd .наприклад, нічого не робить. ls .те саме, що ls. Також ..ім'я каталогу - це "батько .", і ви, мабуть, це вже знали.
улідко

2
@ulidtko: Є виняток із того, що не використовувати /в кінці. Якщо ви хочете зробити розширення імені шляху лише для каталогів. Приклад переліку каталогів у поточному каталозі:echo */
pabouk

Відповіді:


57

Якщо коротко: ви не можете перевстановити систему.

Я маю на увазі, що дозволи на Posix широко використовуються та покладаються на них; У файловій системі є безліч місць, де неправильні дозволи порушують ОС (прапорці SUID) або ще гірше, роблять це викритим із безпеки ( /etc/ssh/ssh_host_rsa_key), хоча це, здається, працює добре.

Отже, таке відновлення важко зробити належним чином. Пропустіть одне - і ви його викрутите. Ви вже накрутили свою sudo chmodкоманду (якщо це ваш друг, а не ви, вона також може засвоїти якийсь урок Linux) - і це дуже проста команда. Правильне відновлення вимагало б більше команд і більшої пильності. Навіть якщо ви використовуєте чийсь сценарій.

Тож повірте мені, просто перевстановіть. Це безпечна ставка і гарантовано позбавить вас від неприємностей.


Нарешті, кілька порад, що стосуються тут.

Перша: Перевстановлення буде менш болючою , якщо ви налаштувати ваш /homeна окремий розділ в наступний раз. Власне, вони будуть вітерцем.

По-друге: подумайте про те, щоб робити божевільну науку Linux у віртуальній машині, як VirtualBox, і робіть свої знімки.

Третє: chmod -R .твори. Крапка сама по собі .є дійсним ім'ям каталогу. Немає реальної потреби додавати цю косу рису. Ви могли б уникнути катастрофічного ризику невдало пропустити крапку;
просто chmod: missing operand after ‘755’VS зруйнованої системи.


1
Аааа :) так сумно.
fl00r

14
Добре ви могли , отримавши всі дозволи для кожного файлу з іншої системи, але робити це так багато роботи, що, мабуть, було б легше і безпечніше просто перевстановити.
Олі

2
І не сумуй! З великою силою приходить велика відповідальність
улідтко

Так, я просто знищив свій ноутбук цим ... Дивовижно, як можна легко знищити машину на базі Linux.
amanuel2

@ amanuel2 з великою силою приходить до великої відповідальності. Дивіться, що ви вводите; sudoзначить, вам доведеться перевірити двічі.
ulidtko

26

Я написав і вже кілька років використовую кілька сценаріїв Ruby для rsyncдозволів та прав власності. Сценарій get-filesystem-aclзбирає всю інформацію шляхом рекурсивного переходу всіх файлів і вводить її у файл .acl. Сценарій .acl-restoreбуде читати .aclі застосовувати всі chownchmod".

Ви можете запустити get-filesystem-aclна подібній установці Ubuntu, а потім скопіювати .aclфайл у вікно, пошкоджене chmod, поставити .aclта .acl-restoreввійти / та запустити .acl-restore.

Вам потрібно буде мати root, щоб виправити своє, sudoяк запропонував Марко Цеппі.

Я можу створити та надати вам .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

ваш сценарій не вдається, як owner_idне визначено
Еліран Малька

8
щось надмірне ... виявити це дуже добре:find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
відкласти

12

Якщо довго: можна. Вам потрібно буде встановити файлову систему з Live CD і почати повертати дозволи у відповідних місцях. Як мінімум, щоб повернути sudo, ви хочете запуститись sudo chmod u+s /usr/bin/sudoпід час сеансу LiveCD - це виправить корінь must setuid.

Однак, ймовірно, буде простіше просто встановити систему.


4

Я б спробував перевстановити всі пакунки apt-get install --reinstall, можливо, використовуючи висновок, dpkg --get-selections | grep installщоб отримати їх список.


Це не погана ідея, але вам потрібно буде виключити речі, які автоматично встановлюються або ви назавжди отримаєте ці пакунки (навіть якщо ви видалили залежні пакунки) ... Але вони не будуть перевстановлюватися. Жорсткий. Можливо, спочатку отримайте список автоматичних пакетів, потім перевстановіть кожен пакет, потім перейдіть до списку авто, повторно позначивши їх як автоматичні.
Олі

@Oli - чи не вдалося б (деякі) вирішити запуск sudo apt-get autoremove?
Вільф

@Wilf Ні - autoremoveвидаляє лише ті пакунки, які ви не встановили вручну.
Дмитро Григор’єв

Існують apt-mark auto $pkg/ apt-mark manual $pkgякі дозволяють змінювати стан "вручну встановленого / автоустановленого" для кожного пакета.
улідко

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 і т.д.
  • ви не зможете завантажуватись чи запускати команди,

Я б запропонував завантажувати LiveCD з версією Linux, яку ви маєте на своєму диску, запустити команду, змінити шлях до місця встановлення локального диска та виконати другу команду!


Я перевірив, що під час завантаження з Ubuntu CD / USB я можу вибрати не форматувати диск, тобто він замінить все в /каталозі, АЛЕ пропустити /home/каталог. Це означає, що конфігурація додатків / DATA (Музика, Відео, Документи) залишається незмінною. І замінюючи системні файли, chmodвстановлюється потрібне число.


1
Чому chmod $(echo $LINE)замість просто chmod $LINE? Крім того , ви можете використовувати тільки findбез stat: find … -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

Не в змозі перевірити, покладаються на введення користувача
blade19899

2

(Я знаю, що я не повинен коментувати відповідь, але недостатньо репутації для коментарів.)

відповідь blade19899 працювала на мене, за винятком символьних посилань. Наприклад, він застосував 755 до / bin / bash, але потім застосував 777 до symlink / bin / rbash, фактично 777-ї / bin / bash.

Оскільки у мене вже був файл fileper.log, я просто змінив команду-призначення:

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

Якщо у вас є резервна копія дозволів, чому б просто не зробити повну резервну копію та відновити її за потреби? Це врятувало б вас у випадку випадкової запуску команди, а не просто chmod.
Дмитро Григор’єв

> ... effectively 777-ing /bin/bash- ніпе; це не так, як це працює. Ви хочете сказати, що я можу замінити /usr/bin/aptсвою власну річ як позакористувальницького користувача , просто написавши на неї через символьну посилання 777? :) Виконайте критичне мислення; символьні посилання не можуть і не працюють таким чином. 777 дозволів для посилань є загальними та нормальними.
улідко

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вас знову і знову. Це завжди цікаві варіанти, якщо ви впевнені, що знаєте, що робите.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.