Я случайно запустил
sudo chmod 755 -R /
вместо
sudo chmod 755 -R ./
Я остановил его через несколько секунд, но теперь есть некоторые проблемы, такие как
sudo: must be setuid root
Как я могу вернуть разрешения обратно?
Одним словом: вы не можете, переустановите свою систему.
Я имею в виду, что разрешения Posix используются и сильно зависят от них; в файловой системе есть множество мест, где неправильные разрешения могут нарушить работу операционной системы (SUID-флаги) или, что еще хуже, сделать ее уязвимой с точки зрения безопасности (/etc/ssh/ssh_host_rsa_key
), в то время как она, кажется, работает нормально.
Следовательно, такое восстановление сложно сделать должным образом. Пропустите одну вещь - и вы все испортите. Вы уже напортачили со своей командой sudo chmod
(если это ваша подруга, а не вы, то она тоже может выучить какой-нибудь урок Linux) - и это очень простая команда. Правильное восстановление потребует гораздо большего количества команд и гораздо большей бдительности. Даже если вы используете чей-то скрипт.
- так что поверьте мне, просто переустановите. Это безопасная ставка и гарантированно убережет вас от неприятностей.
Наконец, здесь уместны некоторые советы.
Во-первых: переустановка будет менее болезненной, если в следующий раз вы установите свой /home
на отдельный раздел . На самом деле, это будет просто ветерок.
Во-вторых: подумайте о том, чтобы сделать сумасшедшую Linux science в виртуальной машине , такой как VirtualBox, и сделайте свои снимки.
Третий: chmod -R .
работает. Точка сама по себе .
является действительным именем каталога. Нет никакой реальной необходимости добавлять этот слэш. Вы могли бы избежать катастрофического риска пропустить точку искренне;
.
просто chmod: пропущенный операнд после '755'
VS разрушенная система.
Я написал и уже несколько лет использую пару Ruby скриптов для rsync
разрешений и прав собственности. Скрипт get-filesystem-acl
собирает всю информацию, рекурсивно обходя все файлы и помещает все это в файл .acl
. Скрипт .acl-restore
прочитает .acl
и применит все chown
и chmod
.
Вы можете запустить get-filesystem-acl
в аналогичной установке Ubuntu, а затем скопировать файл .acl
на ваш ящик chmod, поставить .acl
и . acl-restore
в /, и запустите .acl-restore
.
Вам нужен корень, так что исправьте ваше 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
Я бы попытался переустановить все пакеты с apt-get install --reinstall
, возможно, используя вывод dpkg --get-selections | grep install
, чтобы получить их список.
В длинном: можно. Вам нужно будет смонтировать файловую систему с Live CD и начать возвращать разрешения в соответствующих местах. Как минимум, чтобы получить sudo обратно, вам нужно запустить sudo chmod u+s /usr/bin/sudo
во время сессии LiveCD - это исправит необходимость в setuid root.
Однако, скорее всего, будет проще просто переустановить систему.
Хорошо, я не тестировал это (так что используйте на свой страх и риск), но это все равно может работать. Я протестирую это на виртуальной машине, когда у меня будет возможность:
Во-первых, в все еще работающей системе я сделал следующее, чтобы получить все права доступа к файлам в списке, пропустив / home /
directory:
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
, возможно, вы перечисляете пользовательские настройки, процедуру и т. д. Wh Я бы предложил загрузить LiveCD с версией Linux, которая у вас есть на вашем диске, запустить команду, изменить путь к тому месту, где у вас смонтирован локальный диск, и запустить вторую команду!
Я тестировал это при загрузке с CD / USB Ubuntu, я могу выбрать не форматировать диск, то есть он заменит все в каталоге /
, НО пропустит каталог / home /
. Это означает, что ваши пользователи сохранят конфигурацию приложений / ДАННЫХ (Музыка, Видео, Документы) без изменений. И при замене системных файлов chmod
устанавливается на правильный номер.
Многие из ответов являются проблематичными, потому что они требуют sudo
, но sudo
не работает. Вы не можете использовать sudo
для исправления sudo
. Другие ответы требуют перезагрузки компьютера с использованием Live CD или режима восстановления, что неудобно.
Другой вариант - использовать pkexec
для доступа к оболочке с правами root.
Запустите pkexec bash
в терминале, чтобы получить оболочку с правами root.
Установите бит setuid:
chmod u+s /usr/bin/sudo
sudo
теперь должно быть доступно для любых дальнейших ремонтов, которые могут потребоваться.
(Я знаю, что не должен комментировать в ответе, но не достаточно репутации, чтобы комментировать)
blade19899 ответ сработал для меня, за исключением симлинков. Например, он применил 755 к /bin/bash, но затем применил 777 к симлинку /bin/rbash, фактически 777-ing /bin/bash.
Так как у меня уже был файл fileper.log, я просто изменил команду назначения:
while IFS=: read -r -d '' perm file; do
if [[ ! -L "$file" ]]; then
chmod "$perm" "$file"
fi
done < /tmp/fileper.log
Вы можете попробовать восстановить разрешения с помощью 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
Вот соответствующий фрагмент, EDITED FOR ПРАВИЛЬНОСТЬ и переформатировано:
sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | вырезать -f1`
Допустим, вы получаете сообщения о том, что некоторые пакеты не могут быть переустановлены, и команда не выполняется. Вот один из способов исправить это, пропустив указанные пакеты:
sudo apt-get --reinstall install `dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | egrep -v '(пакет1 | пакет2)' '
И, наконец, если вы каким-то образом должны установить так много вещей, что приведенная выше команда не сможет сказать, что ваш список аргументов слишком длинный, вот исправление, которое будет запускать apt-get гораздо чаще, чем вам хотелось бы:
sudo dpkg --get-selections | grep install | grep -v deinstall | cut -f1 | xargs apt-get --reinstall -y --force-yes установить
Обратите внимание на параметры
-y
и- force-yes
, которые не позволяютapt-get
снова и снова запрашивать вас. Это всегда забавные варианты, если вы уверены, что знаете, что делаете.
Есть закрытый вопрос (с отличным ответом), дублирующий этот из:
Поэтому я отдаю должное Тердону , но вот мой собственный ответ, основанный на его.
Во время разработки нового скрипта переменная $ TMP_DIRECTORY /
дала неожиданный результат ] /
. За ним последовали chmod 700
и chown -R $ UDO_USER
, указывающие на $ TMP_DIRECTORY
, что на самом деле было /
.
Система медленно разбился и сгорел. После этого он не перезагружался. Все кричат «НЕОБХОДИМО ПЕРЕУСТАНОВИТЬ», но это означает потерю многих лет работы. Этот сценарий представляет собой вариант ответа Тердона:
#!/bin/bash
if [[ $(id -u) != 0 ]]; then # root powers needed to call this script
echo >&2 "$0 must be called with sudo powers"
exit 1
fi
# Parameters blank?
[[ $1 == "" ]] && echo "Parm 1 must be source directory" && exit 1
[[ $2 == "" ]] && echo "Parm 2 must be target directory" && exit 1
# Parameters valid directories?
[[ ! -d "$1" ]] && echo "Parm 1 must be a directory" && exit 1
[[ ! -d "$2" ]] && echo "Parm 2 must be a directory" && exit 1
# [[ ! "$2" == "/mnt/"* ]] && echo "Parm 2 must start with /mnt/..." && exit 1
# shopt -s globstar # From original
shopt -s dotglob
liveSystem="$1"
deadSystem="$2"
# Parameters must end in same subdirectory
[[ "${liveSystem##*/}" != "${deadSystem##*/}" ]] && \
echo "subdirectory ${liveSystem##*/} not same as ${deadSystem##*/}" && \
exit 1
cd "$deadsystem"
Count=0
NoRef=0
one() {
path="$1"
MountlessPath="${path##*$deadSystem/}"
if [ -e "$liveSystem/$MountlessPath" ] ; then
echo chown --reference "$liveSystem/$MountlessPath" "$path"
echo chmod --reference "$liveSystem/$MountlessPath" "$path"
(( Count++ ))
else
echo "No reference for: $path"
(( NoRef++ ))
fi
}
# From: https://stackoverflow.com/questions/51654041/loop-through-all-files-in-a-directory-and-subdirectories-using-bash
# Note typo "If" instead of "if" in above link
recurse() {
path="$1"
if [ -d "$path" ] ; then
# echo "Path: $path"
one "$path" # Enhancement: chown of directories too
for i in "$path/"* # "$path/."* # Enhancement: do hidden directories
do
# Skip over .. which gives endless loop
[[ "$path" == *".cache/speech-dispatcher"* ]] && continue
[[ "$path" == *"/usr/bin/X11"* ]] && continue
BaseName=${path##*/}
[[ "${#BaseName}" -gt 300 ]] && continue
# [[ ${#BaseName[@]} -gt 1 ]] && continue
# echo BaseName: $BaseName
# [[ $BaseName == ".." || $BaseName == "*" ]] && continue
recurse "$i"
done
# Original code selected only files but we want links too
# elif [ -f "$path" ] ; then
else
[ ! -f "$path" ] && printf "Not a file -> "
one "$path"
fi
}
recurse "$deadSystem"
echo "========================================================================"
echo "$Count references found for chown command to process"
echo "$NoRef files, directories and links, etc. could not be processed"
# From: https://unix.stackexchange.com/questions/193368/can-scp-create-a-directory-if-it-doesnt-exist/193372?noredirect=1#comment1111576_193372
# Original didn't have much luck?
#for file in **/*; do
# [ -e "$liveSystem/$file" ] &&
# echo sudo chown --reference "$liveSystem/$file" "$file"
#done
При запуске сценария с $ sudo reset-owner / mnt / old / var / var | grep "No reference"
хвостовая часть говорит следующее:
Not a file -> No reference for: /var/tmp/systemd-private-fdbc599820b645f4a461404675af3b5d-rtkit-daemon.service-jvV8tG/tmp/*
No reference for: /var/tmp/systemd-private-fdbc599820b645f4a461404675af3b5d-systemd-timesyncd.service-vmgqTh
No reference for: /var/tmp/systemd-private-fdbc599820b645f4a461404675af3b5d-systemd-timesyncd.service-vmgqTh/tmp
Not a file -> No reference for: /var/tmp/systemd-private-fdbc599820b645f4a461404675af3b5d-systemd-timesyncd.service-vmgqTh/tmp/*
No reference for: /var/tmp/uefi.dat
No reference for: /var/tmp/uefi.dsl
========================================================================
12369 references found for chown command to process
7676 files, directories and links, etc. could not be processed
Каким бы устрашающим ни казалось, потребовался всего час, чтобы разобраться со всем этим. К тому времени, как я закончил, у меня осталось следующее:
$ sudo reset-owner /mnt/old/var /var | grep "No reference" | grep -v /var/tmp/ | grep -v /var/spool/ | grep -v '\/\*' | grep -v /var/run | grep -v /unattended | grep -v /upstart | grep -v /log/journal | grep -v /log/pm | grep -v /log/cron | grep -v /log/dpkg | grep -v /log/apt | grep -v /log/altern | grep -v /lib/u | grep -v /lib/systemd | grep -v /lib/snapd | grep -v /lib/shim | grep -v /lib/NetworkManager | grep -v /lib/lightdm | grep -v /lib/initram | grep -v /lib/dpkg | grep -v /lib/doc-base | grep -v /var/lib/dkms | grep -v /lib/blue | grep -v /lib/binfmts | grep -v /lib/apt | grep -v /lib/app-info | grep -v /lib/Accounts | grep -v /var/crash | grep -v /var/cache
No reference for: /var
No reference for: /var/lib/flashplugin-installer
No reference for: /var/lib/gems
No reference for: /var/lib/gems/2.3.0
No reference for: /var/lib/git
No reference for: /var/lib/tlp/rfkill-saved