실수로 파이프 대신 출력 리디렉션을 사용했습니다 |


21

한 달 전에 stdin의 MAC 및 IP 주소를 매핑하는 Python 스크립트를 작성했습니다. 그리고 이틀 전에 나는 그것을 기억하고 출력을 필터링하는 데 사용 tcpdump되었지만 오타 때문에 잘못되었습니다. 나는 타이핑했다

tcpdump -ne > ./mac_ip.py

출력은 아무것도 아닙니다. 그러나 입력을 구문 분석 할 수 없으면 출력을 "알 수 없음"이어야하므로 프로그램 대신 cat ./mac_ip.py모든 tcpdump데이터를 찾았습니다 . 그런 다음 사용해야한다는 것을 깨달았습니다.

tcpdump -ne | ./mac_ip.py

내 프로그램을 다시받을 수있는 방법이 있습니까? 어쨌든 나는 다시 프로그램을 작성할 수 있지만 더 중요한 프로그램으로 다시 발생하면 뭔가를 할 수 있어야합니다. 또는 파일을 확인하고 실행 파일인지 경고하도록 출력 리디렉션을 지시하는 방법이 있습니까?


18
덮어 쓰기 전에 마지막 백업에서 프로그램을 다시 가져올 수 있습니다. 쉘의 BTW는 지정할 수 set -o noglobber있으며 bash는 더 이상 기존 파일로 리디렉션되지 않습니다. 자세한 내용은 여기를 참조하십시오 : cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
eckes

12
중요한 실행 파일에 대한 쓰기 권한이 없어야합니다.
Hagen von Eitzen

20
@eckesset -o noclobber
GnP

38
@HagenvonEitzen 나는 당신이 그것을 실행하기 전에 작성한 모든 일회용 쉘 및 파이썬 스크립트에 대해 적절한 소유권과 권한을 설정 한 것처럼 (그리고 물론 편집 해야하는 경우 잠시 다시 돌아 오는 것처럼) 그런 조언을 싫어합니다. ). "의미 >할 때 입력 하면 안됩니다 |." 보다 조금 더 의미가 있습니다 . 현실을 잊지 마십시오.
Jason C

30
힘내 repos는 싸다. 아무리 작고 의미가 없는지에 관계없이 모든 코드를 커밋하면 이와 같은 실수는 빠르고 쉬운 해결책입니다.
케이시

답변:


22

슬프게도 다시 작성해야 할 것 같습니다. (백업이있는 경우 지금 백업 할 시간입니다. 그렇지 않은 경우 향후 백업 기간을 설정하는 것이 좋습니다. 많은 옵션을 사용할 수 있지만이 답변의 주제는 제외됩니다.)

실행 파일을 별도의 디렉토리에 넣고 해당 디렉토리를 추가하는 PATH것이 도움이된다는 것을 알았습니다 . 이렇게하면 명시 적 경로로 실행 파일을 참조 할 필요가 없습니다. 개인 (비공개) 스크립트에 대한 선호하는 프로그램 디렉토리는 "$HOME"/bin이며로 프로그램 검색 경로에 추가 할 수 있습니다 PATH="$HOME/bin:$PATH". 일반적으로 이것은 쉘 시작 스크립트 .bash_profile및 / 또는에 추가됩니다 .bashrc.

마지막으로 모든 실행 가능한 프로그램에서 쓰기 권한을 제거하는 것을 막을 수있는 것은 없습니다 :

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/bin는 사용자가 만든 실행 파일과 스크립트의 표준 위치입니다.
gardenhead

4
@gardenhead 시스템 설정 방법에 따라 다릅니다. /usr/local호스트에 특정한 것 (네트워크 마운트를 통해 호스트간에 공유되는 디렉토리와 반대)을위한 것이며 루트가 아닌 사용자가 쓸 수 있거나 쓸 수 없습니다.
chepner 2016 년

4
@gardenhead 그것은 확실히 하나의 표준 위치입니다. /use/local/bin여러 사용자 계정에서 사용할 수있는 로컬로 설치된 스크립트 및 프로그램과 $HOME/bin단일 사용자에게 개인적인 일에 사용합니다. 둘 다 가치가 있습니다.
roaima

1
페도라 보이는 것을 참고하여 추진하려고합니다$HOME/.local/bin
ZAN 살쾡이

1
@Zan eeeww! 진심으로 감사합니다. RH가 ~/.local또 다른 아이템을 "전통적인"장소에서 옮겨 놓은 것처럼 모든 것을 밀어 붙이고있는 것 같습니다.
roaima

38

리디렉션으로 기존 파일을 덮어 쓰지 못하게하려면 POSIX와 유사한 셸 >noclobber옵션을 사용하십시오 bash( / 대신 대신 (t)csh기능이 실제로 시작된 위치 ). 그런 다음 파일을 강제로 교체해야하는 경우 리디렉션 연산자 ( in )를 사용하십시오 .set noclobberset -o noclobberset -C>|>!(t)csh

예:

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

BTW, 당신은 현재 설정을 확인할 수 있습니다 set -o:

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

이것이 질문에 완벽하게 대답하지만 권장하지는 않습니다. 1. >|대신 타이핑하는 것이 타이핑 하는 |것보다 덜 쉬운 것은 아닙니다 >. 2. 백업을하는 것이 쉽고 강력하게 권장됩니다 (이름이 가치있는 편집기는 마지막 버전을 저장할 수 있습니다 cron. 등). 3. 모든 코드는 작은 스크립트라도 버전 관리를해야합니다. YMMV.
maaartinus

2
@maaartinus가 등장합니다 .1) 하나 대신 두 개의 별도 문자를 입력하는 것이 확실하지 않습니다. 2) 분명히 백업은 필수적이며, 아무도 OP에게 백업하지 말라고 조언하지 않았습니다.이 답변은 백업이 없다는 것을 암시하지 않으며 편집기 백업은 편집기에서 파일을 편집했다고 가정합니다. 3) 다시 한 번,이 특정 예에서와 같이 OP가 작성한 코드 만 생각하지만 질문과 대답은 시스템 실행 파일을 포함하여 시스템의 모든 파일에 적용됩니다 .
terdon

8

@casey의 의견에 따르면 git repo 아래 에서 중요한 스크립트 를 원격으로 동기화 ( 멋진 자체 호스팅 플랫폼 이 수행 할 것)가 좋습니다.

이렇게하면 파일을 이전 작업 상태로 되돌리고 다시 실행하는 것과 같은 나쁜 사람의 실수로부터 보호 할 수 있습니다.


4

파일을 복구 할 수 있습니까?

짧은 대답 : 보통은 아닙니다.

@Mark Plotnick은 주석 .py에서 지적한 것처럼 Uncompyle.pyc사용하여 파일을 복구 할 수 있습니다 . 이것은 귀하의 상황에 완벽해야합니다.

그러나 일반적으로 이것은 훨씬 어렵습니다. 이론적으로 법의학 도구를 사용하여 파일 삭제를 취소 할 수 있습니다. 아마도 내가 사용한 가장 쉬운 방법은 testdisk"PhotoRec"입니다. 때로는 작동하며 속도가 느립니다. 일반적으로 가치가 없으므로 가능합니다 . 그러나 실제 대답은 "아니오"입니다.

실행 파일을 덮어 쓰지 않도록 > 를 변경할 수 있습니까 ?

아니요. 실행 파일로 표시된 파일에 대해서만 셸을 리디렉션하지 않도록 표준 방법은 없습니다. "noclobber"가있어 실행 파일의 존재 여부와 상관없이 기존 파일로의 리디렉션을 방지 할 수 있지만 아래에 대한 내 의견을 참조하십시오.

앞으로 무엇을해야합니까?

  1. 이것은 어리석게 들릴지 모르지만 미래의 실수를 막기 위해 아무것도 할 필요가 없습니다. 내 생각에 당신은 이미이 교훈을 배웠습니다.

    나는 오랫동안 유닉스를 사용하고 가르쳤으며 사람들은 종종 한 번 실수를 저 지르지 만 거의 반복하지 않습니다. 왜 안돼? 같은 이유로 칼을 경험 한 사람은 스스로 자르지 않습니다. 인간은 배우는 데 능숙합니다. 결국, 옳은 일을하는 것이 제 2의 본성이됩니다.

  2. 백업 할 텍스트 편집기를 사용하십시오. 예를 emacs들어을 사용하면 프로그램의 이전 버전이 mac_ip.py ~에 저장됩니다. 다른 편집기도 비슷하게 작동하도록 구성 할 수 있습니다 (예 :의 "백업 설정" .nanorc). 자동 백업을 지원하지 않는 편집기의 경우 .bashrc에서 간단한 기능을 수행 할 수 있습니다.

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. 쉽게 복사 할 수 있습니다. 예를 들어, 작업중인 프로젝트의 디렉토리에 다음과 같은 대상을 가진 Makefile이있을 수 있습니다.

    # 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}")
    

    (참고 : stackexchange는 위의 탭을 4 개의 공백으로 잘못 렌더링합니다.)

  4. 마찬가지로 액세스 권한 rsync이있는 원격 Unix 호스트에 대한 Makefile 대상을 만들 수 있습니다 ssh. ( ssh-copy-id비밀번호를 반복해서 묻지 않도록 사용하십시오 .)

  5. 사용하십시오 git. 시작하기에 대한 훌륭한 자습서가 많이 있습니다. 보십시오 man gittutorial, man gittutorial-2하고 man giteveryday. 자체 git 저장소를 설정하는 것은 어렵지 않지만 github.com에서 무료로 원격 저장소를 만들 수도 있습니다

  6. 위의 솔루션이 너무 무겁다면 작은 스크립트를 gist.github.com에 저장할 수 있습니다 . 웹 브라우저에서 붙여 넣기 또는 업로드가 가능하지만, 명령 행 요지 인터페이스 를 사용하여 작업을 쉽게 수행 하는 것이 좋습니다 .

"noclobber"를 사용하지 않는 것이 좋습니다.

예, 원하는 경우 set -o noclobber기존 파일을 덮어 쓰려고 할 때마다 오류 메시지가 표시됩니다. 제 생각에는 이것은 나쁜 생각입니다. *

활성화 여부를 표시하지 않고 비표준 방식으로 쉘을 작동시킵니다. 정상적인 일을하려면 다른 구문을 사용해야합니다. 최악의 경우, 노 클로버에 익숙해지면 언 클로버없이 다른 유닉스 머신을 사용할 수 있습니다. 이런 종류의 사고는 다시 발생할 수 있습니다.

아시다시피, 유닉스 쉘은 전문가를위한 날카로운 도구로 설계되었습니다. 사용이 빠르며 방해가되지 않습니다. 어느 쪽이 뾰족한 지 잊어 버리면 잘릴 것입니다. 그러나 더 많이 사용할수록 좋은 일이 될 것입니다.


* 각주 : 아마 한 알의 소금으로 내 의견을 받아들이십시오. 나는 또한 자전거 훈련 바퀴가 나쁜 생각이라고 생각하는 사람입니다.


나는 또한 유닉스를 잠시 동안 가르쳤다. 많은 학생들이 유닉스의 직접적인 단순성에 대해 감사 한 적이 없습니다. 나는 그들에게 혼자가 아니라고 말하면서 유닉스 해더 핸드북을 통해 최소한의 지식을 쌓을 수 있습니다. simson.net/ref/ugh.pdf
Jason

또한 : 동의합니다. 자전거의 바퀴를 훈련하면 세발 자전거를 타는 법을 배우는 사람에게 도움이됩니다.
Jason

2

최근에 스크립트를 보거나 편집했지만 여전히 메모리 버퍼에있는 경우 데이터가 처음 발생한 후 데이터를 복구 할 수있었습니다. 그렇지 않으면, 당신은 운이 거의 없습니다.

(또는 대신 ) tee파일에 쓰기로 파이프했다면 파일을 쓰려고하는 경우 사용자에게 경고하는 스크립트에 대한 별칭, 함수 또는 심볼릭 링크로 쉽게 바꿀 수 있습니다. 실행 파일입니다.STDOUT>tee -a>>tee

다음은 이상적이지 않고 많이 개선 될 수 있지만 이것이 가능한 방법의 예와 같이 시작점입니다.

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

... 그냥 echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrc또는 비슷한 것.

밝은면에서 적어도 연습을 더 많이하고 두 번째 버전의 Python 스크립트는 아마도 첫 번째 버전보다 훨씬 나을 것입니다!


1

PC에서 작업 중인지 서버에서 작업 중인지 지정하지 않았습니다. 파일이 전용 파일 서버에 저장되는 경우 (OS on the) 파일 서버 하드웨어에서 자동 백업 ( "스냅 샷")을 유지하는 경우가 종종 있습니다.

리눅스에서

가상의 숨겨진 스냅 샷 디렉토리는 파일 시스템의 모든 디렉토리에 있습니다.

시험:

cd .snapshot   
ls -l

해당 디렉토리가 있으면 운이 좋을 수 있습니다. 특정 시점에 자동으로 백업을 저장하는 일련의 디렉토리가 표시됩니다. 이름은 과거에 스냅 샷이 저장된 상대 시간을 나타냅니다. 예를 들면 다음과 같습니다.

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

파일 겹쳐 쓰기 실수 이전에 충분히 오래된 시간대 디렉토리로 이동하십시오. timepoint 디렉토리 안에는 과거의 ../..디렉토리와 모든 하위 디렉토리 의 상태가 표시되어야합니다 .

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

노트:

  1. ls -a.snapshot디렉토리를 표시하지 않습니다 . 명시 적으로 이름을 지정해야합니다. 파일 서버에 의해 실제로 삽입됩니다. 파일 시스템에 실제 디렉토리로 존재하지 않습니다.
  2. 이 자동 스냅 샷은 롤링 기록입니다. 오래된 변경 사항은 결국 끝나고 사라집니다. 파일을 다시 필요로한다는 것을 알게 된 후 가능한 빨리이 기술을 사용해야합니다.

Windows에서

숨겨진 스냅 샷 디렉토리의 이름은 ~ snapshot 일 수 있으며 지정된 드라이브의 루트 레벨에만 존재합니다.

조언

스냅 샷은 대부분의 시간 동안 작동하는 안전망이지만 항상 그런 것은 아닙니다. git사소한 파일에도 버전 제어 시스템 (예 :)을 사용하는 다른 권장 사항과 일치 합니다.


1

그것은 이전에 언급되었으며 다시 말할 것입니다. 개정 관리 시스템을 사용하십시오.

백업은 하드웨어 오류를 복구하기위한 것입니다. 개정 관리는 귀하와 같은 상황에 적용되며 다른 용도로도 많이 사용됩니다. 개정 관리 도구를 사용하면 파일 기록을 유지하고 해당 기록의 특정 지점으로 돌아갈 수 있습니다.

개정 관리 도구의 예로는 Subversion (SVN) (현재 약간 오래되었지만 여전히 좋은 제품), mercurial (hg) 및 git (git) (사용하기 어렵다)가 있습니다. svn은 사무실 문서에 적합하며 다른 um-mergables, git 및 hg는 대부분의 다른 역할에서 그것을 능가했습니다. hg 및 git을 사용하면 배포 및 백업을 위해 오프라인으로 작업하고 원격 서버와 동기화 할 수 있습니다.

개정판 제어를 읽고 분산 개정판을 읽고 사용해보십시오.


수정 제어를 사용하는 것이 내 상황에서는 가장 좋지만 파일에 대한 올바른 권한을 부여하는 것도 마찬가지로 중요합니다.
Bharath Teja
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.