¿Qué sucede si accidentalmente ejecuto el comando "chmod -R" en los directorios del sistema (/, / etc, ...)

56

Accidentalmente corrí

sudo chmod 755 -R /

en lugar de

sudo chmod 755 -R ./

Lo detuve después de unos segundos, pero ahora hay algunos problemas como

sudo: must be setuid root

¿Cómo puedo revertir los permisos?

fl00r
fuente
18
oh querido ... sudosignifica que has pensado dos veces lo que harás!
antivirtel
2
Lo más fácil es reinstalar. Coloque el LiveCD / USB, y en la pantalla donde le pide que particione su disco, debería darle la opción de hacerlo Upgrade from Ubuntu 11.04 to Ubuntu 11.04. Acepte esta opción y volverá a instalar Ubuntu de manera efectiva, de la manera más sencilla.
user4124
13
Justo ahora has aprendido una lección. No necesita escribir /al final del nombre del directorio para especificar el directorio como destino. Es un mal hábito , ¡no lo hagas, nunca ! El .nombre de directorio es válido por sí mismo, no es necesario agregarlo /. Si todos siguieran esta regla, muchas sudooperaciones mal escritas no tendrían ningún efecto en el directorio raíz, por lo que no se habría hecho daño a sus sistemas. ¡No lo hagas!
ulidtko
3
@ fl00r, sí. Es un nombre de directorio que significa esto, o directorio "actual". cd .Por ejemplo, no hace nada. ls .es el mismo que ls. Además, ..es un nombre de directorio que significa "el padre de .", y probablemente ya lo sabía.
ulidtko
2
@ulidtko: Hay una excepción al no usar /al final. Si desea hacer una expansión de nombre de ruta solo para directorios. Ejemplo de listado de directorios dentro del directorio actual:echo */
pabouk

Respuestas:

57

En resumen: no puede, reinstale su sistema.

Quiero decir, los permisos de Posix se usan y se utilizan en gran medida; Hay una multitud de lugares en el sistema de archivos donde los permisos incorrectos romperían el sistema operativo (indicadores SUID) o, lo que es peor, lo expondrán en términos de seguridad ( /etc/ssh/ssh_host_rsa_key) mientras parece estar funcionando bien.

Por lo tanto, tal recuperación es difícil de hacer correctamente. Echo de menos una cosa y la arruinas. Usted ya cagado su sudo chmodcomando (si ese es su amigo en lugar de usted, bien podría aprender alguna lección de Linux, también) - y eso es un muy simple de un comando. La recuperación adecuada exigiría más órdenes y más vigilancia. Incluso si usas el guión de alguien.

Así que confía en mí, solo reinstala. Es una apuesta segura y garantizada para evitar problemas.


Finalmente, algunos consejos relevantes aquí.

Primero: las reinstalaciones serán menos dolorosas si configura la suya /homeen una partición separada la próxima vez. En realidad, serán una brisa.

Segundo: considere hacer ciencia loca de Linux en una máquina virtual como VirtualBox, y haga sus instantáneas.

Tercero: chmod -R .obras. Un punto en sí mismo .es un nombre de directorio válido. No hay necesidad real de agregar esa barra. Podrías haber evitado el riesgo catastrófico de saltear el punto por completo;
simplemente chmod: missing operand after ‘755’VS un sistema en ruinas.

ulidtko
fuente
1
Ahhh :) muy triste.
fl00r
14
Bien, podría obtener todos los permisos para cada archivo de otro sistema, pero hacer esto es tanto trabajo que probablemente sería más fácil y seguro reinstalarlo.
Oli
2
¡Y no estés triste! Con gran poder viene una gran responsabilidad
ulidtko
Sí, acabo de destruir mi computadora portátil con esto ... Increíble cómo puedes destruir fácilmente una máquina basada en Linux.
amanuel2
@ amanuel2 con gran poder conlleva una gran responsabilidad. Mira lo que escribes; sudosignifica que tienes que verificar dos veces.
ulidtko
26

Escribí y he estado usando durante varios años un par de scripts de Ruby para rsyncpermisos y propiedad. La secuencia de comandos get-filesystem-aclrecopila toda la información atravesando recursivamente todos los archivos y los coloca en el archivo .acl. El script .acl-restoreleerá .acly aplicará todos los chown'sy chmod' s.

Puede ejecutar get-filesystem-acluna instalación similar de Ubuntu y luego copiar el .aclarchivo a su caja dañada por chmod, colocar .acly .acl-restore/ y ejecutar .acl-restore.

Necesitarás tener root, así que arregla tu sudocomo Marco Ceppi sugirió.

Puedo generar y darte el .aclarchivo de mi 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
fuente
Ubuntu 11.04. Pero ya lo reinstalé. ¡Gracias!
fl00r
su guión falla como no owner_idestá definido
Eliran Malka
8
un poco exagerado ... find hace eso muy bien:find SOME_DIR -depth -printf 'chmod %m %p\n' > saved_permission
vuelva a registrar el
12

En mucho tiempo: puedes. Deberá montar el sistema de archivos desde un Live CD y comenzar a revertir los permisos en los lugares apropiados. Como mínimo para recuperar sudo, querrá ejecutar sudo chmod u+s /usr/bin/sudomientras está en la sesión de LiveCD, eso solucionará la raíz que debe configurarse.

Sin embargo, probablemente sería más fácil simplemente reinstalar el sistema.

Marco Ceppi
fuente
4

Intentaría reinstalar todos los paquetes con apt-get install --reinstall, posiblemente usando la salida de dpkg --get-selections | grep installpara obtener una lista de ellos.

Adam Byrtek
fuente
Esta no es una mala idea, pero necesitaría excluir las cosas que se instalan automáticamente o terminaría permanentemente con esos paquetes (incluso si eliminó los paquetes dependientes) ... Pero luego no se reinstalarían. Una dificil. Quizás obtenga primero una lista de los paquetes automáticos, luego reinstale cada paquete y luego revise la lista de autos, volviéndolos a marcar como automáticos.
Oli
@Oli: ¿no se resolvería (algo de eso) ejecutando sudo apt-get autoremove?
Wilf
@Wilf No: autoremovesolo elimina los paquetes que no ha instalado manualmente.
Dmitry Grigoryev
Existen apt-mark auto $pkg/ apt-mark manual $pkgque le permiten modificar el estado de "paquete instalado / autoinstalado manualmente".
ulidtko
3

Bien, no he probado esto (así que úselo bajo su propio riesgo), pero aún podría funcionar. Probaré esto en una máquina virtual cuando tenga la oportunidad de:

Primero, en un sistema que todavía funciona, hice lo siguiente para obtener todos los permisos de archivo en una lista, omitiendo el /home/directorio:

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

Esto imprimirá los permisos y el nombre de archivo para cada archivo o directorio en el sistema, seguido de un \0carácter (esto se necesita más adelante para tratar con nombres de archivo extraños como los que contienen líneas nuevas).

Luego, en un sistema donde los permisos de archivo se han visto comprometidos:

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

Esto leerá cada línea de fileper.log, guardando los permisos como $permy el nombre del archivo como $filey luego establecerá los permisos del archivo (o directorio) a lo que esté listado en elfileper.log


Algunas cosas a tener en cuenta aquí:

  • Durante la salida al archivo: /tmp/fileper.loges posible que esté enumerando configuraciones personalizadas y procesos, etc.
  • es posible que no pueda iniciar o ejecutar comandos,

Lo que sugeriría es que inicie un LiveCD con la versión de Linux que tiene en su disco, ejecute el comando, modifique la ruta donde tiene montado el disco local y ejecute el segundo comando.


He probado que cuando se inicia desde un CD / USB de Ubuntu, puedo elegir no formatear el disco, lo que significa que reemplazará todo en el /directorio, PERO omitir el /home/directorio. Lo que significa que sus usuarios tendrán la configuración de aplicaciones / DATOS (Música, Video, Documentos) aún intacta. Y al reemplazar los archivos del sistema, chmodse establece el número adecuado.

cuchilla19899
fuente
1
¿Por qué en chmod $(echo $LINE)lugar de solo chmod $LINE? Además, se puede usar simplemente findsin stat: find … -printf "%#m %p\n". Mejor aún, puede crear el comando completo: find … -printf "chmod %#m %p\n"y luego ejecutar el archivo como un script.
muru
La línea de búsqueda no funciona como es, debería serlo, michael@NEXUS-TWO:~$ sudo find / -name '*' -exec stat -c "%a %n" {} \; >> /tmp/fileper.logpero también se ejecuta /procy algunos otros lugares que quizás no desee en su lista.
Videonauth
@muru escribió esto en medio de la noche.
Editaré
No se puede probar, dependerá de la entrada del usuario
blade19899
2

(Sé que no debería comentar en una respuesta, pero no tengo suficiente reputación para comentar).

La respuesta de blade19899 funcionó para mí, excepto para los enlaces simbólicos. Por ejemplo, aplicó 755 a / bin / bash, pero luego aplicó 777 al enlace simbólico / bin / rbash, efectivamente 777-ing / bin / bash.

Como ya tenía el archivo fileper.log, simplemente modifiqué el comando end-end:

while IFS=: read -r -d '' perm file; do  
    if [[ ! -L "$file" ]]; then    
        chmod "$perm" "$file"
    fi
done < /tmp/fileper.log 
Marjan
fuente
Si tiene una copia de seguridad de los permisos, ¿por qué no hacer una copia de seguridad completa y restaurarla cuando sea necesario? Eso lo salvaría en caso de que algún comando se ejecute accidentalmente, no solo chmod.
Dmitry Grigoryev
> ... effectively 777-ing /bin/bash- no; Así no es cómo funciona. ¿Estás diciendo que puedo reemplazarlo /usr/bin/aptcon mi propio usuario como usuario no root , simplemente escribiéndolo a través de un enlace simbólico 777? :) Ejercita algo de pensamiento crítico; los enlaces simbólicos no pueden y no funcionan de esa manera. Los permisos 777 para enlaces simbólicos son comunes y normales.
ulidtko
2

Puede intentar restaurar los permisos con apt-get.

Si no puede ejecutar estos comandos con sudo, es posible que deba iniciar el modo de recuperación y ejecutarlos como root.

Para iniciar el modo de recuperación, consulte https://wiki.ubuntu.com/RecoveryMode .

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

Nota: Esto se publicó originalmente en los foros de Ubuntu pero no puedo encontrar la publicación original.

Intenta, en orden,

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

Si eso falla:

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

Y finalmente, como último recurso,

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

Usando apt-get

Aquí está el recorte relevante, EDITADO PARA CORRECCIÓN y reformateado:

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

Supongamos que recibe mensajes sobre algunos paquetes que no se pueden reinstalar y el comando falla. Aquí hay una forma de solucionarlo omitiendo los paquetes en cuestión:

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

Y finalmente, si de alguna manera tienes tantas cosas instaladas que el comando anterior falla diciendo que tu lista de argumentos es demasiado larga, aquí está la solución, que se ejecutará apt-get muchas más veces de las que te gustaría:

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

Tenga en cuenta las opciones -yy --force-yes, que evitarán que le apt-getpregunten una y otra vez. Estas son siempre opciones divertidas, si está seguro de saber lo que está haciendo.

Pantera
fuente
-3

Tuve el mismo problema, puedo solucionarlo. En mi caso Ubuntu 19.10

Abra su terminal y escriba debajo del código simple

sudo -i

abra otra terminal y verifique debajo del comando.

sudo apt update
Elavarasan r
fuente
1
¿Cómo ayudaría esto al usuario a solucionar su problema con los permisos? Edite su respuesta y proporcione más detalles.
Kevin Bowen