誤ってパイプの代わりに出力リダイレクトを使用しました|


21

1か月前に、標準入力からMACアドレスとIPアドレスをマップするPythonスクリプトを作成しました。そして2日前、私はそれを覚えていて、出力のフィルタリングに使用し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
あなたは、重要な実行ファイルへの書き込み権限を持つべきではありません...
ハーゲン・フォン・Eitzen

20
@eckesset -o noclobber
GnP

38
@HagenvonEitzen私はそのようなアドバイスが嫌いです、それはあなたがそれを実行する前にあなたがこれまでに書いたすべての一時シェルとPythonスクリプトに適切な所有権と許可を設定したかのようです)。「>意味するときに入力するべきではない」よりもわずかに意味があるだけです|。現実を忘れないでください。
ジェイソンC

30
Gitリポジトリは安価です。どんなに小さくて意味のないコードでも、すべてのコードをコミットし、このような間違いは迅速かつ簡単に修正できます。
ケーシー

回答:


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

4
@gardenheadは確かに1つの標準的な場所です。私は/use/local/bin、複数のユーザーアカウントで使用される可能性が高いローカルにインストールされたスクリプトとプログラム、および$HOME/bin1人のユーザーの個人的なものに使用します。両方に価値があります。
ロアイマ

1
Fedoraは次を使用してプッシュしようとしているようです$HOME/.local/bin
Zan Lynx

1
@Zan eeeww!真剣に、ありがとう。RHは~/.local、「従来の」場所から移動したさらに別のアイテムであるため、RHがすべてを押し込もうとしているように見えます。
ロアイマ

38

リダイレクトによって上書きされる既存のファイルを防止するため、>使用noclobber中のオプションbashも、あるいは任意のPOSIXのようなシェル((t)cshあなたが行うものの、機能は実際に元の場所set noclobberの代わりにset -o noclobber/set -Cも)。次に、あなたが使用し、ファイルを置き換えるために強制する必要がある場合>|(リダイレクト演算子を>!(t)csh)。

例:

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

ところで、次のコマンドで現在の設定を確認できますset -o

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

これは質問に完全に答えますが、お勧めしません。1.の>|代わりにタイピングすることは、タイピングすること|よりも少なくありません>。2.バックアップを作成するのは簡単であり、非常に賢明です(その名前に値するエディターは最後のバージョンを保存できます; cronなどがあります)。3.小さなスクリプトであっても、すべてのコードをバージョン管理する必要があります。YMMV。
-maaartinus

2
@maaartinusが登場します、1)1つではなく2つの別々の文字を入力することは、明らかに少ない確率です。2)バックアップは明らかに不可欠です。OPにバックアップを作成しないようにアドバイスする人はいません。この回答は、バックアップがないことを示唆するものではありません。3)繰り返しますが、この特定の例のように、OPが記述したコードのみを考えていますが、質問とこの回答は、システム実行可能ファイルを含むマシン上のすべてのファイルに適用できます。
テルドン

8

@caseyのコメントにあるように、重要なスクリプトgitリポジトリの下でリモートで同期することを強くお勧めします(派手なセルフホストプラットフォームでも可能です)。

これにより、ファイルを以前の作業状態に戻し、再度実行するなどの人為的なミスから保護されます。


4

ファイルは回復可能ですか?

短い答え:通常はありません。

@Mark Plotnickがコメントで指摘しているように、Uncompyle.py.pyc使用してファイルを回復できます。これはあなたの状況に最適です。

ただし、一般に、これははるかに困難です。理論的には、フォレンジックツールを使用してファイルの削除を取り消すことができます。おそらく私が使用した中で最も簡単なのはtestdisk(別名「PhotoRec」)です。それは時々しか動作せず、遅いプロセスです。通常は価値がないので、はい、可能ですですが、本当の答えは「いいえ」です。

>実行可能ファイルを上書きしないように変更できますか?

いいえ。実行可能とマークされたファイルのみをリダイレクトしないようにシェルに指示する標準的な方法はありません。実行可能かどうかにかかわらず、既存のファイルへのリダイレクトを防ぐ「noclobber」がありますが、それについては私のコメントを参照してください。

今後何をすべきか?

  1. これはばかげて聞こえるかもしれませんが、将来の間違いを防ぐために、おそらく何もする必要はありません。私の賭けは、あなたがすでにこのレッスンを学んだということです。

    私は非常に長い間Unixを使用し、教えてきました。人々はしばしば一度この間違いを犯しますが、めったにそれを繰り返すことはありません。何故なの?ナイフを経験した人が自分自身を切断しないのと同じ理由で、人間は学習が得意です。最終的に、正しいことをすることは第二の性質になります。

  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は、上記のTABを4つのスペースとして誤ってレンダリングします。)

  4. 同様に、アクセスできるrsyncリモートUnixホストに対して実行するMakefileターゲットを作成できますssh。(ssh-copy-idパスワードを繰り返し要求されないように使用します。)

  5. を使用しgitます。はじめに多くの優れたチュートリアルがあります。試してみてくださいman gittutorialman gittutorial-2man giteveryday。独自のgitリポジトリを設定するのは難しくありませんが、github.comで無料でリモートリポジトリを作成することもできます

  6. 上記のソリューションが重すぎる場合、小さなスクリプトをgist.github.comに保存できます。Webブラウザーから貼り付けたりアップロードしたりすることは可能ですが、コマンドラインの要点インターフェースを使用して非常に簡単にすることをお勧めします

「noclobber」を使用しないことを強くお勧めします。

はい、選択しset -o noclobberた場合は、既存のファイルを上書きしようとするたびにエラーメッセージが表示されます。私の意見では、これは悪い考えです。*

これにより、シェルが非標準の方法で動作し、有効になっているかどうかは表示されません。通常のことを行うには、異なる構文を使用する必要があります。最悪なことに、noclobberに慣れると、いつかnoclobberなしで別のUnixマシンを使用することになり、この種の事故が再び発生する可能性があります。

ご存知のとおり、Unixシェルは専門家向けの鋭いツールになるように設計されています。使いやすく、邪魔になりません。また、どちらの端が尖っているのかを忘れてしまうと、邪魔になりません。しかし、それを使用すればするほど、それが良いことであることに感謝するでしょう。


*脚注:おそらく私の意見を一粒の塩と一緒に受け取ってください。私も自転車のトレーニングホイールが悪い考えだと思う人です。


また、しばらくの間Unixを教えてきました。私の学生の多くは、Unixの直接的なシンプルさに感謝しています。私は彼らが彼らだけではなく、少なくとも彼らのために地雷原の一部を示しているUnix Hater's Handbookを熟考しながら学ぶことができると彼らに伝えます。 simson.net/ref/ugh.pdf
ジェイソン

また、私は同意します-自転車のトレーニングホイールは、三輪車の乗り方を学ぶ人にとって役立ちます。
ジェイソン

2

スクリプトを最近表示または編集していて、まだメモリバッファにあった場合、最初にデータが発生した後にデータを回復できた可能性があります。そうでなければ、あなたはほとんど運がありません。

あなたがするパイプ場合はtee、ファイルに書き込むために(だけでなく、STDOUTその代わりに)>(またはtee -a代わりに>>)、あなたは簡単に置き換えることができtee、彼らは書き込みしようとしているファイルの場合、ユーザーに警告するスクリプトへのエイリアス、関数、またはシンボリックリンクでtoは実行可能です。

以下は決して理想的なものではなく、多くの点で改善される可能性がありますが、これが可能な方法の例として、出発点です。

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スクリプトの2番目のバージョンはおそらく最初のものよりもはるかに優れているでしょう!


1

PCで作業しているかサーバーで作業しているかを指定しませんでした。ファイルがたまたま専用のファイルサーバーに保存されている場合は、ファイルサーバーハードウェア(上のOS)によって自動バックアップ(「スナップショット」)が保持されることがよくあります。

Linuxで

仮想の非表示のスナップショットディレクトリは、ファイルシステムのすべてのディレクトリに存在します。

試してください:

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

(ファイル上書きの間違いの前に)十分に古いタイムポイントディレクトリに移動します。タイム../..ポイントディレクトリ内に、過去のその時点でのディレクトリ(およびすべてのサブディレクトリ)の状態が表示されます。

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を使用すると、オフラインで作業したり、配布やバックアップのためにリモートサーバーと同期したりできます。

リビジョン管理を読んでから、リビジョン管理を配布して、それらを試してください。


私はリビジョンコントロールを使用すると、私のような状況に最適ですが、ファイルに必要な権限を与えることも同様に重要であることに同意
バーラトテジャ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.