Usó accidentalmente la redirección de salida> en lugar de una tubería |


21

Hace un mes escribí un script de Python para mapear las direcciones MAC e IP de stdin. Y hace dos días lo recordaba y solía filtrar la salida de, tcpdumppero salió mal debido a un error tipográfico. escribí

tcpdump -ne > ./mac_ip.py

Y la salida es nada. Pero la salida debería ser "Desconocida" si no puede analizar la entrada, así que lo hice cat ./mac_ip.pyy encontré todos los tcpdumpdatos en lugar del programa. Entonces me di cuenta de que debería usar

tcpdump -ne | ./mac_ip.py

¿Hay alguna forma de recuperar mi programa? De todos modos, puedo volver a escribir mi programa, pero si vuelve a ocurrir con un programa más importante, debería poder hacer algo. ¿O hay alguna forma de decirle a la redirección de salida que verifique el archivo y advierta si es un ejecutable?


18
Puede recuperar su programa desde la última copia de seguridad antes de sobrescribir, de lo contrario no. Por cierto, en shell puede especificar set -o noglobbery bash ya no redirigirá a los archivos existentes. Ver aquí para más detalles: cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
Eckes

12
No debería tener permiso de escritura para ejecutables importantes ...
Hagen von Eitzen

20
@eckesset -o noclobber
GnP

38
@HagenvonEitzen Odio consejos como ese, como si hubiera establecido la propiedad y los permisos adecuados en cada shell único y script de Python que haya escrito antes de ejecutarlo (y, por supuesto, vuelva brevemente de nuevo si tiene que editarlo ) Es marginalmente más significativo que "No deberías escribir >cuando quieras |". No olvides la realidad.
Jason C

30
Los repositorios Git son baratos. Confirme todo su código, sin importar cuán pequeño y sin sentido, y luego un error como este es una solución rápida y fácil.
casey

Respuestas:


22

Lamentablemente sospecho que tendrá que volver a escribirlo. (Si tiene copias de seguridad, este es el momento de sacarlas. De lo contrario, le recomendaría que configure un régimen de copias de seguridad para el futuro. Muchas opciones disponibles, pero fuera de tema para esta respuesta).

Me parece PATHútil colocar ejecutables en un directorio separado y agregar ese directorio al . De esta manera no necesito hacer referencia a los ejecutables por ruta explícita. Mi directorio de programas preferido para scripts personales (privados) es "$HOME"/biny se puede agregar a la ruta de búsqueda del programa con PATH="$HOME/bin:$PATH". Por lo general, esto se agregaría a los scripts de inicio de shell .bash_profiley / o .bashrc.

Finalmente, no hay nada que le impida eliminar el permiso de escritura para usted en todos los programas ejecutables:

touch some_executable.py
chmod a+x,a-w some_executable.py    # chmod 555, if you prefer

ls -l some_executable.py
-r-xr-xr-x+ 1 roaima roaima 0 Jun 25 18:33 some_executable.py

echo "The hunting of the Snark" > ./some_executable.py
-bash: ./some_executable.py: Permission denied

2
/usr/local/bines la ubicación estándar para los archivos ejecutables y los scripts creados por el usuario
gardenhead

44
@gardenhead Depende de cómo esté configurado el sistema. /usr/localestá destinado a cosas específicas del host (a diferencia de un directorio compartido entre hosts a través de un montaje de red), y puede ser o no escribible por usuarios no root.
chepner

44
@gardenhead es una ubicación estándar, sin duda. Lo uso /use/local/binpara scripts y programas instalados localmente que es probable que sean utilizados por múltiples cuentas de usuario, y $HOME/binpara cosas personales de un solo usuario. Hay valor en ambos.
roaima

1
Tenga en cuenta que Fedora parece estar tratando de empujar usando$HOME/.local/bin
Zan Lynx

1
@Zan eeeww! En serio, gracias. Parece que RH está tratando de introducir todo, ~/.localya que ese es otro elemento más movido de su lugar "tradicional".
roaima

38

Para evitar que los archivos existentes se sobrescriban mediante la redirección, >use la noclobberopción en basho en cualquier shell similar a POSIX (también en (t)cshdonde se originó la característica, aunque lo haga en set noclobberlugar de set -o noclobber/ set -Callí). Luego, si necesita forzar el reemplazo de un archivo, use el >|operador de redirección ( >!in (t)csh).

Ejemplo:

$ echo abc > file
$ set -o noclobber
$ echo xyz > file
bash: file: cannot overwrite existing file
$ echo xyz >| file
$ cat file
xyz

Por cierto, puede verificar la configuración actual con set -o:

$ set -o
...
monitor         on
noclobber       on
noexec          off
...

Si bien esto responde perfectamente a la pregunta, no lo recomendaría. 1. Escribir en >|lugar de |no es mucho menos probable que escribir >. 2. Es fácil y altamente recomendable hacer copias de seguridad (un editor que valga su nombre puede guardar la última versión; hay cron, etc.). 3. Cada fragmento de código debe ser puesto bajo control de versión, incluso pequeños scripts. YMMV.
maaartinus

2
@maaartinus vamos, 1) escribir dos caracteres separados en lugar de uno es claramente menos probable. 2) Obviamente, las copias de seguridad son esenciales, nadie aconsejó al OP que no haga copias de seguridad, esta respuesta de ninguna manera sugiere no tener copias de seguridad, y las copias de seguridad del editor suponen que ha editado el archivo en un editor. 3) Nuevamente, solo está pensando en el código que el OP ha escrito, como en este ejemplo en particular, pero la pregunta y esta respuesta son aplicables a cualquier archivo en la máquina, incluidos los ejecutables del sistema.
terdon

8

Recomiendo encarecidamente tener los scripts importantes bajo un repositorio de git , sincronizados de forma remota ( lo hará una elegante plataforma autohospedada), como dice el comentario de @ casey.

De esta forma, está protegido de errores humanos graves, como revertir el archivo al estado de trabajo anterior y ejecutarlo nuevamente.


4

¿El archivo es recuperable?

Respuesta corta: generalmente no.

@ Mark Plotnick señala en los comentarios, puede recuperar .pyarchivos .pycusando Uncompyle . Esto debería ser perfecto para su situación.

En general, sin embargo, esto es mucho más difícil. Teóricamente puedes usar herramientas forenses para recuperar archivos. Probablemente la más fácil que he usado es testdisk(también conocido como "PhotoRec"). Solo funciona a veces y es un proceso lento. Por lo general, no vale la pena, así que sí, es posible , pero la respuesta real es "no".

¿Se puede > cambiar para no sobrescribir ejecutables?

No. No hay una forma estándar de decirle al shell que nunca redirija solo los archivos marcados como ejecutables. Hay "noclobber" que evitará la redirección a archivos existentes, ejecutables o no, pero vea mis comentarios al respecto a continuación.

¿Qué hacer en el futuro?

  1. Esto puede sonar tonto, pero para evitar futuros errores, probablemente no necesite hacer nada. Mi apuesta es que ya has aprendido esta lección.

    He estado usando y enseñando Unix durante mucho tiempo y, aunque la gente suele cometer este error una vez, rara vez lo repite. Por qué no? Probablemente por la misma razón que una persona experimentada con cuchillos no se corta: los humanos son buenos para aprender. Finalmente, hacer lo correcto se convierte en una segunda naturaleza.

  2. Use un editor de texto que haga copias de seguridad por usted. Por ejemplo, si usa emacs, la versión anterior de su programa se guarda en mac_ip.py ~. Se pueden configurar otros editores para que funcionen de manera similar (por ejemplo, "establecer copia de seguridad" en .nanorc). Para los editores que no admiten copias de seguridad automáticas, puede realizar una función simplista en su .bashrc:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Facilítese hacer copias. Por ejemplo, en el directorio del proyecto en el que está trabajando, puede tener un Makefile con un objetivo como este:

    # Use `make tar` to backup all files in this directory.
    # Tar filename will be ../<currentdirectory>-<date>.tar.gz 
    DIRNAME = $(shell basename `pwd`)
    TIMESTAMP = $(shell date +%s)
    tar:
        @echo "[Tarring up ${DIRNAME}.tar.gz]"
        (cd .. ; tar -zcvf "${DIRNAME}-${TIMESTAMP}.tar.gz" "${DIRNAME}")
    

    (Nota: stackexchange está representando erróneamente las TAB anteriores como 4 espacios).

  4. Del mismo modo, puede crear un destino Makefile que haga un rsynchost remoto de Unix al que tenga sshacceso. (Úselo ssh-copy-idpara que no se le solicite su contraseña repetidamente).

  5. Uso git. Hay muchos tutoriales excelentes para comenzar. Tratar man gittutorial, man gittutorial-2y man giteveryday. Configurar su propio repositorio git no es difícil, pero también puede crear un repositorio remoto sin costo en github.com

  6. Si las soluciones anteriores son demasiado pesadas, puede guardar pequeños scripts en gist.github.com . Si bien es posible pegar o cargar desde un navegador web, recomiendo usar una interfaz de línea de comando para facilitar las cosas.

Desaconsejo firmemente el uso de "noclobber".

Sí, si lo desea, puede hacerlo set -o noclobber, recibirá mensajes de error cada vez que intente sobrescribir un archivo existente. Esta es una mala idea, en mi opinión. * *

Hace que el shell funcione de una manera no estándar sin indicación visible de si está habilitado. Tienes que usar una sintaxis diferente para hacer cosas normales. Lo peor de todo es que si te acostumbras al noclobber, algún día usarás otra máquina Unix sin noclobber y este tipo de accidente podría volver a ocurrir.

Como probablemente sepa, el shell de Unix fue diseñado para ser una herramienta precisa para los expertos. Es rápido de usar y no se interpondrá en su camino, y le cortará si olvida qué extremo es puntiagudo. Pero, cuanto más lo use, más creo que apreciará que eso puede ser algo bueno.


* Nota al pie: quizás tome mis opiniones con un grano de sal. También soy el tipo de persona que piensa que las ruedas de entrenamiento para bicicletas son una mala idea.


También he enseñado a Unix por un tiempo. Muchos de mis alumnos nunca han aprendido a apreciar la simplicidad directa de Unix; Les digo que no están solos y que, al menos, aún pueden aprender mientras se compadecen del Manual del enemigo de Unix, que les asigna un poco del campo de minas. simson.net/ref/ugh.pdf
Jason

Además: estoy de acuerdo: las ruedas de entrenamiento en bicicleta son útiles para cualquiera que esté aprendiendo a andar en triciclo.
Jason

2

Es posible que haya podido recuperar los datos después de que ocurrieran por primera vez si había visto o editado recientemente el script y todavía estaba en el búfer de memoria. De lo contrario, no tienes suerte.

Si eligió teeescribir en un archivo (así como STDOUT) en lugar de >(o en tee -alugar de >>), podría reemplazarlo fácilmente teecon un alias, función o enlace simbólico a un script que advierta al usuario si el archivo está a punto de escribir to es ejecutable.

Lo siguiente no es ideal y podría mejorarse mucho , pero es un punto de partida, solo como un ejemplo de cómo esto es posible:

wee.sh:

#!/bin/bash

if [ -n "${2}" ]; then
  if [ "$(ls -l "${2}" | awk '{print $1}' | grep x)" ]; then
    echo executable
  else
    tee -a "${2}"
  fi
elif [ "$(ls -l "${1}" | awk '{print $1}' | grep x)" ]; then
  echo executable
else
  tee "${1}"
fi

... entonces solo echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrco algo similar.

En el lado positivo, al menos tendrás más práctica y la segunda versión de tu script Python probablemente será mucho mejor que la primera.


1

No especificó si está trabajando en una PC o un servidor. Si sus archivos están almacenados en un servidor de archivos dedicado, entonces el hardware del servidor de archivos (SO) guarda a menudo copias de seguridad automáticas ("instantáneas").

Bajo Linux

El directorio virtual de instantáneas ocultas existe en cada directorio de su sistema de archivos.

Tratar:

cd .snapshot   
ls -l

Si ese directorio existe, entonces puede que tengas suerte. Debería ver una serie de directorios que contienen copias de seguridad almacenadas automáticamente en determinados momentos. Los nombres indican el tiempo relativo en el pasado en el que se almacenó la instantánea. Por ejemplo:

hourly.0
hourly.1
hourly.2
hourly.3
hourly.4
hourly.5
nightly.0
nightly.1
nightly.2
nightly.3
nightly.4
nightly.5
nightly.6
weekly.0
weekly.1
weekly.2

Vaya a cualquier directorio de puntos de tiempo que sea lo suficientemente antiguo (antes de su error de sobrescritura de archivos). Dentro del directorio de puntos de tiempo, debería ver el estado del ../..directorio (y todos los subdirectorios) a partir de ese punto en el pasado.

cd nightly.6
ls  # look around   
tee < mac_ip.py  # check for the correct content
cp mac_ip.py ~/safekeeping/mac_ip.py  # save the old file

Notas:

  1. ls -ano mostrará el .snapshotdirectorio; debes nombrarlo explícitamente. Se inserta virtualmente por el servidor de archivos. No existe como un directorio real en su sistema de archivos.
  2. Estas instantáneas automáticas son un historial continuo. Los viejos cambios finalmente se caen y se pierden. Debe usar esta técnica lo antes posible después de darse cuenta de que necesita recuperar un archivo.

Bajo Windows

El directorio de instantáneas ocultas puede llamarse ~ instantánea y existir solo en el nivel raíz de una unidad determinada.

Consejo

Las instantáneas son una red de seguridad que funciona la mayor parte del tiempo, pero no siempre. Estoy de acuerdo con las otras recomendaciones para usar un sistema de control de versiones (como git) incluso para archivos triviales.


1

Se ha dicho antes, y lo diré nuevamente. Use un sistema de control de revisión.

Las copias de seguridad son para recuperar una falla de hardware. El control de revisión es para situaciones como la suya (y tiene muchos otros usos). Las herramientas de control de revisiones le permiten mantener un historial de un archivo y volver a cualquier punto de ese historial.

Los ejemplos de herramientas de control de revisión incluyen subversión (SVN) (un poco viejo ahora, pero sigue siendo bueno), mercurial (hg) y git (git) (difícil de usar). svn es bueno para documentos de oficina, y otros um-mergables, git y hg lo han superado para la mayoría de los otros roles. hg y git le permiten trabajar fuera de línea y sincronizarse con un servidor remoto, para distribución y respaldo.

Lea sobre el control de revisión, luego el control de revisión distribuido y luego pruébelos.


Estoy de acuerdo en que usar el control de revisión es mejor para situaciones como la mía, pero otorgar los permisos correctos a los archivos es igualmente importante
Bharath Teja el
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.