Что делать, если я случайно запустил команду «chmod -R» в системных каталогах (/, / etc,…)

56

Я случайно побежал

sudo chmod 755 -R /

вместо

sudo chmod 755 -R ./

Я остановил его через несколько секунд, но теперь есть некоторые проблемы, такие как

sudo: must be setuid root

Как я могу вернуть разрешения обратно?

fl00r
источник
18
о боже ... sudoзначит, ты дважды подумал, что будешь делать!
антивиртель
2
Самый простой - это переустановить. Поместите LiveCD / USB, и на экране, где он просит вас разбить диск, он должен дать вам возможность Upgrade from Ubuntu 11.04 to Ubuntu 11.04. Примите эту опцию, и она эффективно переустановит Ubuntu для вас самым безболезненным способом.
user4124
13
Только сейчас вы выучили урок. Вам не нужно писать /в конце имени каталога, чтобы указать каталог в качестве цели. Это плохая привычка , не делай этого никогда ! Это .само по себе допустимое имя каталога, нет необходимости добавлять /к нему. Если бы все следовали этому правилу, то очень много опечаток sudoне оказали бы влияния на корневой каталог, поэтому их системам не было бы причинено никакого вреда. Не делай этого!
ulidtko
3
@ fl00r, да. Это имя каталога, которое означает это, или «текущий» каталог. cd .Например, ничего не делает. ls .так же, как ls. Кроме того, ..это имя каталога, которое означает «родитель .», и вы, вероятно, уже знали это.
ulidtko
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’против разрушенной системы.

ulidtko
источник
1
Ааааа :) так грустно.
fl00r
14
Ну, вы могли бы получить все разрешения для каждого файла из другой системы, но сделать это так много, что, вероятно, было бы проще и безопаснее просто переустановить.
Оли
2
И не грусти! С большой властью приходит большая ответственность
ulidtko
Да, я только что уничтожил свой ноутбук с этим ... Удивительно, как легко можно уничтожить машину на основе 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
ваш сценарий не выполняется, так как owner_idон не определен
Eliran Malka
8
своего рода излишнее ... find делает это довольно хорошо: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чтобы получить список их.

Адам Быртек
источник
Это неплохая идея, но вам нужно исключить вещи, которые автоматически устанавливаются, или вы навсегда получите эти пакеты (даже если вы удалили зависимые пакеты) ... Но тогда они не будут переустановлены. Крепкий орешек. Возможно, сначала получите список автоматических пакетов, затем переустановите каждый пакет, затем просмотрите список auto, пометив их как auto.
Оли
@ Оли - не будет (некоторые из), которые могут быть решены с помощью бега sudo apt-get autoremove?
Уилф
@Wilf No - 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вы можете перечислять пользовательские настройки, процедуры и т. Д.
  • вы не сможете загружаться или запускать команды,

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


Я проверял, что при загрузке с Ubuntu CD / USB я могу не форматировать диск, то есть он заменит все в /каталоге, НО пропустить /home/каталог. Это означает, что у ваших пользователей конфигурация приложений / данных (музыка, видео, документы) остается неизменной. И, заменяя системные файлы, chmodустанавливается правильный номер.

blade19899
источник
1
Почему chmod $(echo $LINE)вместо просто chmod $LINE? Кроме того , вы можете использовать только findбез stat: find … -printf "%#m %p\n". А еще лучше, вы можете создать всю команду:, а find … -printf "chmod %#m %p\n"затем выполнить файл как скрипт.
Муру
Строка поиска не работает как есть, она должна быть, michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.logно затем она перебирает /procи некоторые другие места, которые вы, возможно, не захотите в своем списке.
Видеонавт
@muru написал это посреди ночи. Будет редактировать код ...
blade19899
Не в состоянии проверить, будет полагаться на пользовательский ввод
blade19899
2

(Я знаю, что не должен комментировать в ответе, но не достаточно репутации, чтобы комментировать.)

Ответ 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.
Дмитрий Григорьев
> ... effectively 777-ing /bin/bash- Нет; это не так, как это работает. Вы хотите сказать, что я могу заменить /usr/bin/aptна свою собственную вещь, не являющуюся пользователем root , просто написав ей через символическую ссылку 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из предлагающих снова и снова. Это всегда забавные варианты, если вы уверены, что знаете, что делаете.

пантера
источник
-3

У меня была такая же проблема, я могу это исправить. В моем случае Ubuntu 19.10

Откройте свой терминал и введите ниже простой код

sudo -i

откройте другой терминал и проверьте команду ниже.

sudo apt update
Елаварасан р
источник
1
Как это поможет пользователю решить проблему с разрешениями? Пожалуйста, отредактируйте свой ответ и предоставьте более подробную информацию.
Кевин Боуэн