E se eu acidentalmente executar o comando “chmod -R” nos diretórios do sistema (/, / etc,…)

56

Eu acidentalmente corri

sudo chmod 755 -R /

ao invés de

sudo chmod 755 -R ./

Parei depois de alguns segundos, mas agora existem alguns problemas, como

sudo: must be setuid root

Como posso reverter as permissões novamente?

fl00r
fonte
18
oh querido ... sudosignifica que você pensou duas vezes o que fará!
Antivirtel
2
O mais fácil é reinstalar. Coloque o LiveCD / USB e, na tela em que ele pede para você particionar seu disco, ele deve lhe dar a opção Upgrade from Ubuntu 11.04 to Ubuntu 11.04. Aceite esta opção e ela efetivamente reinstalará o Ubuntu para você, da maneira mais indolor.
User4124 18/04/11
13
Agora mesmo você aprendeu uma lição. Você não precisa escrever /no final do nome do diretório para especificar o diretório como um destino. É um mau hábito , não faça isso, nunca ! O .nome do diretório é por si só válido, não há necessidade de anexá /-lo. Se todos seguissem essa regra, sudooperações muito digitadas incorretamente não teriam efeito no diretório raiz; portanto, nenhum dano teria sido causado a seus sistemas. Não faça isso!
Ulidtko 18/05/11
3
@ fl00r, sim. É um nome de diretório que significa este, ou diretório "atual". cd ., por exemplo, não faz nada. ls .é o mesmo que ls. Além disso, ..é um nome de diretório que significa "o pai de ." e você provavelmente já sabia.
Ulidtko 18/05/11
2
@ulidtko: Há uma exceção para não usar /no final. Se você deseja fazer a expansão do nome do caminho apenas para diretórios. Exemplo de listagem de diretórios dentro do diretório atual:echo */
pabouk

Respostas:

57

Em resumo: você não pode, reinstale o seu sistema.

Quero dizer, as permissões do Posix são usadas e muito dependentes; existem vários lugares no sistema de arquivos em que permissões erradas podem interromper o sistema operacional (sinalizadores SUID) ou pior ainda, torná-lo exposto em termos de segurança ( /etc/ssh/ssh_host_rsa_key) enquanto parece estar funcionando bem.

Portanto, é difícil fazer essa recuperação corretamente. Perca uma coisa - e você estraga tudo. Você estragou o seu sudo chmodcomando (se esse é seu amigo e não você, ela também pode aprender algumas lições do Linux) - e esse é um comando muito simples. A recuperação adequada exigiria muito mais comandos e muito mais vigilância. Mesmo se você usar o script de alguém.

Então confie em mim, basta reinstalar. É uma aposta segura e garantida para mantê-lo longe de problemas.


Finalmente, algumas dicas relevantes aqui.

Primeiro: as reinstalações serão menos dolorosas se você configurar sua /homepartição separada na próxima vez. Na verdade, eles serão uma brisa.

Segundo: considere fazer ciência maluca do Linux em uma máquina virtual como a VirtualBox e faça seus instantâneos.

Terceiro: chmod -R .funciona. Um ponto por si só .é um nome de diretório válido. Não há necessidade real de acrescentar essa barra. Você poderia ter evitado o risco catastrófico de pular o ponto totalmente;
mero chmod: missing operand after ‘755’VS um sistema arruinado.

ulidtko
fonte
1
Ahhh :) tão triste.
Fl00r
14
Bem, você poderia obter todas as permissões para cada arquivo de outro sistema, mas fazer isso é tão trabalhoso que provavelmente seria mais fácil e seguro apenas para reinstalar.
Oli
2
E não fique triste! Com grande poder vem grande responsabilidade
ulidtko
Sim, acabei de destruir meu laptop com isso ... Incrível como você pode facilmente destruir uma máquina baseada em Linux.
precisa saber é o seguinte
@ amanuel2 com grande poder vem com grande responsabilidade. Veja o que você digita; sudosignifica que você precisa verificar duas vezes.
ulidtko
26

Escrevi e utilizo há vários anos alguns scripts Ruby para rsyncpermissões e propriedade. O Script get-filesystem-aclcoleta todas as informações atravessando recursivamente todos os arquivos e coloca tudo no arquivo .acl. O script .acl-restorelerá .acle aplicará todos os chown's chmod' e 's.

Você pode executar get-filesystem-aclem uma instalação semelhante do Ubuntu e, em seguida, copiar o .aclarquivo na sua caixa danificada pelo chmod, colocar .acle .acl-restore/ / e executar .acl-restore.

Você precisará ter o root para consertar o seu sudocomo Marco Ceppi sugeriu.

Eu posso gerar e fornecer o .aclarquivo para o meu 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
Aleksandr Levchuk
fonte
Ubuntu 11.04. Mas eu já o reinstalei. Obrigado!
Fl00r
seu script falha como owner_idé indefinido
Eliran Malka
8
meio que um exagero ... achado faz isso muito bem:find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
reflog
12

Em muito tempo: você pode. Você precisará montar o sistema de arquivos a partir de um Live CD e começar a reverter as permissões nos locais apropriados. No mínimo, para recuperar o sudo, você deverá executar sudo chmod u+s /usr/bin/sudoenquanto estiver na sessão do LiveCD - isso corrigirá a raiz do setuid.

No entanto, provavelmente seria mais fácil simplesmente reinstalar o sistema.

Marco Ceppi
fonte
4

Eu tentaria reinstalar todos os pacotes com apt-get install --reinstall, possivelmente usando a saída de dpkg --get-selections | grep installpara obter uma lista deles.

Adam Byrtek
fonte
Isso não é uma má idéia, mas você precisaria excluir as coisas que são instaladas automaticamente ou você acabaria permanentemente com esses pacotes (mesmo se você removesse os pacotes dependentes) ... Mas eles não seriam reinstalados. Uma difícil. Talvez seja necessário primeiro obter uma lista dos pacotes automáticos, depois reinstalar todos os pacotes e depois percorrer a lista de automóveis, marcando-os como automáticos.
Oli
@ Oli - (alguns dos) que não seriam resolvidos executando sudo apt-get autoremove?
Wilf 22/02
@ Wilf No - autoremoveremove apenas pacotes que você não instalou manualmente.
Dmitry Grigoryev
Existem apt-mark auto $pkg/ apt-mark manual $pkgque permitem modificar o status de "manualmente instalado / instalado automaticamente" por pacote.
ulidtko 31/10
3

Tudo bem, eu não testei isso (use por sua conta e risco), mas ainda pode funcionar. Vou testar isso em uma máquina virtual quando tiver a chance de:

Primeiro, em um sistema ainda em funcionamento, fiz o seguinte para obter todas as permissões de arquivo em uma lista, pulando o /home/diretório:

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

Isso imprimirá as permissões e o nome do arquivo para cada arquivo ou diretório do sistema, seguido de um \0caractere (isso é necessário posteriormente para lidar com nomes de arquivos estranhos, como os que contêm novas linhas).

Em seguida, em um sistema em que as permissões de arquivo foram comprometidas:

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

Isso lerá cada linha de fileper.log, salvando as permissões como $perme o nome do arquivo $filee, em seguida, definirá as permissões do arquivo (ou do diretório) para o que estiver listado no diretóriofileper.log


Algumas coisas a serem observadas aqui:

  • Ao enviar para o arquivo:, /tmp/fileper.logvocê pode listar configurações personalizadas, proc, etc.
  • talvez você não consiga inicializar ou executar comandos,

O que eu sugeriria é inicializar um LiveCD com a versão Linux que você possui no disco, executar o comando, modificar o caminho para o local em que o disco local está montado e executar o segundo comando!


Eu testei que, quando inicializado a partir de um CD / USB do Ubuntu, posso optar por não formatar o disco, o que significa que ele substituirá tudo no /diretório, mas pule o /home/diretório. Isso significa que seus usuários ainda terão a configuração de apps / DATA (música, vídeo, documentos) intacta. E, substituindo os arquivos do sistema, o valor chmodé definido para o número adequado.

blade19899
fonte
1
Por que ao chmod $(echo $LINE)invés de apenas chmod $LINE? Além disso, você pode usar apenas findsem stat: find … -printf "%#m %p\n". Melhor ainda, você pode criar o comando inteiro: e find … -printf "chmod %#m %p\n", em seguida, executar o arquivo como um script.
muru 11/05
A linha de localização não está funcionando como está, mas deve ser michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.logexecutada, /procalém de alguns outros lugares que você pode não querer na sua lista.
Videonauth
@muru escreveu isso no meio da noite. Vai editar o código ...
blade19899
Não é capaz de testar, vai contar com a entrada do usuário
blade19899
2

(Eu sei que não devo comentar em uma resposta, mas não tenho reputação suficiente para comentar.)

A resposta do blade19899 funcionou para mim, exceto pelos links simbólicos. Por exemplo, aplicou 755 a / bin / bash, mas depois aplicou 777 ao link simbólico / bin / rbash, efetivamente 777-ing / bin / bash.

Como eu já tinha o arquivo fileper.log, apenas modifiquei o comando destination-end:

while IFS=: read -r -d '' perm file; do  
    if [[ ! -L "$file" ]]; then    
        chmod "$perm" "$file"
    fi
done < /tmp/fileper.log 
Marjan
fonte
Se você possui um backup de permissões, por que não fazer um backup completo e restaurá-lo quando necessário? Isso salvaria você no caso de qualquer comando ser executado acidentalmente, não apenas chmod.
Dmitry Grigoryev
> ... effectively 777-ing /bin/bash- não; não é assim que funciona. Você está dizendo que eu posso substituir o /usr/bin/aptmeu próprio usuário não root , escrevendo nele através de um link simbólico 777? :) Exercite um pensamento crítico; links simbólicos não podem e não funcionam dessa maneira. As permissões 777 para links simbólicos são comuns e normais.
ulidtko
2

Você pode tentar restaurar permissões com apt-get.

Se você não pode executar esses comandos com o sudo, pode ser necessário inicializar no modo de recuperação e executá-los como root.

Para inicializar no modo de recuperação, consulte https://wiki.ubuntu.com/RecoveryMode .

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

Nota: Isso foi originalmente publicado nos Fóruns do Ubuntu, mas não consigo encontrar a postagem original.

Tente, em ordem,

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

Se isso falhar:

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

E, finalmente, como último recurso,

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

Usando o apt-get

Aqui está o trecho relevante, EDITADO PARA A CORREÇÃO e reformatado:

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

Digamos que você receba mensagens sobre alguns pacotes que não podem ser reinstalados e o comando falha. Aqui está uma maneira de corrigi-lo, pulando os pacotes em questão:

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

E, finalmente, se você tiver tantas coisas instaladas que o comando acima falhe dizendo que sua lista de argumentos é muito longa, aqui está a correção, que será executada no apt-get muitas mais vezes do que você gostaria:

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

Observe as opções -ye --force-yes, que impedem apt-getque você o solicite repetidamente. Essas são sempre opções divertidas, se você tiver certeza de que sabe o que está fazendo.

Pantera
fonte
-3

Eu tive um mesmo problema, posso corrigi-lo. No meu caso Ubuntu 19.10

Abra seu terminal e digite abaixo o código simples

sudo -i

abra outro terminal e verifique o comando abaixo.

sudo apt update
Elavarasan r
fonte