Sengaja menggunakan redirection output> bukan pipa |

21

Sebulan yang lalu saya menulis skrip Python untuk memetakan alamat MAC dan IP dari stdin. Dan dua hari yang lalu saya ingat itu dan digunakan untuk menyaring output tcpdumptetapi salah karena kesalahan ketik. saya mengetik

tcpdump -ne > ./mac_ip.py

dan hasilnya tidak apa-apa. Tetapi output harus "Tidak Diketahui" jika tidak dapat menguraikan input, jadi saya lakukan cat ./mac_ip.pydan menemukan semua tcpdumpdata, bukan program. Kemudian saya menyadari bahwa saya harus menggunakannya

tcpdump -ne | ./mac_ip.py

Apakah ada cara untuk mendapatkan program saya kembali? Bagaimanapun saya dapat menulis program saya lagi, tetapi jika itu terjadi lagi dengan program yang lebih penting saya harus dapat melakukan sesuatu. ATAU adakah cara untuk memberi tahu pengalihan output untuk memeriksa file dan memperingatkan jika file tersebut dapat dieksekusi?

Bharath Teja
sumber
18
Anda bisa mendapatkan program Anda kembali dari cadangan terakhir sebelum Anda menimpa, jika tidak tidak. BTW di shell Anda dapat menentukan set -o noglobberdan bash tidak akan mengarahkan ulang ke file yang ada lagi. Lihat di sini untuk perincian: cyberciti.biz/tips/howto-keep-file-safe-from-overwriting.html
eckes
12
Anda seharusnya tidak memiliki izin tertulis untuk executables penting ...
Hagen von Eitzen
20
@eckesset -o noclobber
GnP
38
@HagenvonEitzen Saya benci saran seperti itu, seolah-olah Anda telah menetapkan kepemilikan dan izin yang tepat pada setiap shell dan skrip python yang pernah Anda tulis sebelum menjalankannya (dan, tentu saja, kembali lagi sebentar jika Anda harus mengeditnya ). Ini hanya sedikit lebih bermakna daripada "Anda tidak harus mengetik >ketika Anda maksudkan |." Jangan lupakan kenyataan.
Jason C
30
Repositori Git itu murah. Komit semua kode Anda, tidak peduli seberapa kecil dan tidak berarti dan kemudian kesalahan seperti ini adalah perbaikan yang cepat dan mudah.
Casey

Jawaban:

22

Sayangnya saya curiga Anda harus menulis ulang. (Jika Anda memiliki cadangan, ini adalah waktu untuk mengeluarkannya. Jika tidak, saya akan sangat menyarankan Anda mengatur rezim cadangan untuk masa depan. Banyak pilihan yang tersedia, tetapi di luar topik untuk jawaban ini.)

Saya menemukan bahwa menempatkan executable di direktori terpisah, dan menambahkan direktori itu ke PATHsangat membantu. Dengan cara ini saya tidak perlu referensi executable dengan jalur eksplisit. Direktori program pilihan saya untuk skrip pribadi (pribadi) adalah "$HOME"/bindan dapat ditambahkan ke jalur pencarian program dengan PATH="$HOME/bin:$PATH". Biasanya ini akan ditambahkan ke skrip startup shell .bash_profiledan / atau .bashrc.

Akhirnya, tidak ada yang menghentikan Anda menghapus izin menulis untuk diri sendiri pada semua program yang dapat dieksekusi:

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
roaima
sumber
2
/usr/local/binadalah lokasi standar untuk executable dan skrip yang dibuat pengguna
gardenhead
4
@gardenhead Tergantung pada bagaimana sistem diatur. /usr/localditujukan untuk hal-hal khusus host (sebagai lawan direktori yang dibagikan di seluruh host melalui jaringan mount), dan mungkin atau mungkin tidak dapat ditulisi oleh pengguna non-root.
chepner
4
@ardenhead itu satu lokasi standar, tentu saja. Saya menggunakan /use/local/binskrip dan program yang dipasang secara lokal yang kemungkinan akan digunakan oleh banyak akun pengguna, dan $HOME/binuntuk hal-hal pribadi bagi satu pengguna. Ada nilai di keduanya.
roaima
1
Perhatikan bahwa Fedora tampaknya mencoba mendorong menggunakan$HOME/.local/bin
Zan Lynx
1
@Ze eeeww! Serius, terima kasih. Sepertinya RH sedang mencoba untuk mendorong semuanya ke dalam ~/.localkarena itu adalah item lain yang dipindahkan dari tempat "tradisional".
roaima
38

Untuk mencegah file yang ada ditimpa oleh pengalihan >gunakan noclobberopsi di bashatau shell seperti POSIX (juga di (t)cshmana fitur tersebut sebenarnya berasal, meskipun Anda melakukan set noclobberalih - alih set -o noclobber/ di set -Csana). Kemudian, jika Anda perlu memaksa untuk mengganti file, gunakan >|operator redirection ( >!in (t)csh).

Contoh:

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

BTW, Anda dapat memeriksa pengaturan saat ini dengan set -o:

$ set -o
...
monitor         on
noclobber       on
noexec          off
...
jimmij
sumber
Meskipun ini menjawab pertanyaan dengan sempurna, saya tidak akan merekomendasikannya. 1. Mengetik >|alih-alih |tidak jauh lebih kecil kemungkinannya daripada mengetik >. 2. Mudah dan sangat disarankan untuk membuat cadangan (editor yang layak namanya dapat menyimpan versi terakhir; ada cron, dll.). 3. Setiap bagian kode harus diletakkan di bawah kontrol versi, bahkan skrip kecil. YMMV.
maaartinus
2
@maaartinus ayolah, 1) mengetik dua karakter yang terpisah dan bukannya satu kemungkinan kurang mungkin. 2) Jelas cadangan sangat penting, tidak ada yang menyarankan OP untuk tidak membuat cadangan, jawaban ini sama sekali tidak menyarankan tidak memiliki cadangan, dan cadangan editor menganggap Anda telah mengedit file dalam editor. 3) Sekali lagi, Anda hanya memikirkan kode yang ditulis OP, seperti dalam contoh khusus ini, tetapi pertanyaan dan jawaban ini berlaku untuk file apa pun pada mesin, termasuk sistem yang dapat dieksekusi.
terdon
8

Saya sangat menyarankan untuk memiliki skrip penting di bawah git repo , disinkronkan dari jarak jauh ( platform self-host mewah akan melakukan), seperti komentar @ casey.

Dengan cara ini Anda dilindungi dari kesalahan manusia yang buruk seperti mengembalikan file ke kondisi kerja sebelumnya dan menjalankannya kembali.

RcrdBrt
sumber
4

Apakah file dapat dipulihkan?

Jawaban singkat: Tidak biasanya.

@Mark Plotnick menunjukkan dalam komentar, Anda dapat memulihkan .pyfile dari .pycmenggunakan Uncompyle . Ini harus sempurna untuk situasi Anda.

Secara umum, ini jauh lebih sulit. Secara teoritis Anda dapat menggunakan alat forensik untuk membatalkan penghapusan file. Mungkin yang termudah yang saya gunakan adalah testdisk(alias "PhotoRec"). Kadang-kadang hanya berfungsi dan ini adalah proses yang lambat. Biasanya tidak sepadan, jadi, ya, itu mungkin , tetapi jawaban sebenarnya adalah "tidak".

Dapatkah > diubah menjadi tidak menimpa executable?

Tidak. Tidak ada cara standar untuk memberitahu shell untuk tidak mengarahkan hanya untuk file yang ditandai dapat dieksekusi. Ada "noclobber" yang akan mencegah pengalihan ke file yang ada, dieksekusi atau tidak, tetapi lihat komentar saya di bawah ini.

Apa yang harus dilakukan di masa depan?

  1. Ini mungkin terdengar konyol, tetapi untuk mencegah kesalahan di masa depan, Anda mungkin tidak perlu melakukan apa pun. Taruhan saya adalah bahwa Anda sudah mempelajari pelajaran ini.

    Saya telah menggunakan dan mengajar Unix untuk waktu yang sangat lama dan sementara orang sering membuat kesalahan ini sekali, mereka jarang mengulanginya. Kenapa tidak? Mungkin karena alasan yang sama seseorang yang berpengalaman dengan pisau tidak memotong diri mereka sendiri: manusia pandai belajar. Akhirnya, melakukan hal yang benar menjadi kebiasaan.

  2. Gunakan editor teks yang membuat cadangan untuk Anda. Misalnya, jika Anda menggunakan emacs, versi program Anda sebelumnya disimpan di mac_ip.py ~. Editor lain dapat dikonfigurasikan untuk bekerja dengan cara yang sama (misalnya, "mengatur cadangan" di .nanorc). Untuk editor yang tidak mendukung backup otomatis, Anda dapat membuat fungsi sederhana di .bashrc Anda:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Buatlah mudah bagi Anda untuk membuat salinan. Misalnya, dalam direktori proyek yang sedang Anda kerjakan, Anda mungkin memiliki Makefile dengan target seperti ini:

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

    (Catatan: stackexchange salah menuliskan TAB di atas sebagai 4 spasi.)

  4. Demikian pula, Anda bisa membuat target Makefile yang melakukan rsyncke host Unix jarak jauh yang memiliki sshakses. (Gunakan ssh-copy-idsehingga Anda tidak akan diminta kata sandi berulang kali.)

  5. Gunakan git. Ada banyak tutorial bagus untuk memulai. Coba man gittutorial, man gittutorial-2dan man giteveryday. Menyiapkan repositori git Anda sendiri tidak sulit, tetapi Anda juga dapat membuat repositori jarak jauh tanpa biaya di github.com

  6. Jika solusi di atas terlalu berat, Anda dapat menyimpan skrip kecil ke gist.github.com . Meskipun dimungkinkan untuk menempel atau mengunggah dari peramban web, saya sarankan menggunakan antarmuka inti baris perintah untuk menjadikannya super mudah.

Saya sangat tidak menyarankan menggunakan "noclobber".

Ya, jika Anda memilih, Anda bisa melakukannya set -o noclobbersehingga Anda akan mendapatkan pesan kesalahan setiap kali Anda mencoba untuk menimpa file yang ada. Ini adalah ide yang buruk, menurut saya. *

Itu membuat shell bekerja dengan cara yang tidak standar tanpa indikasi yang terlihat apakah itu diaktifkan. Anda harus menggunakan sintaks yang berbeda untuk melakukan hal-hal normal. Yang terburuk, jika Anda terbiasa dengan noclobber, maka suatu hari nanti Anda akan menggunakan mesin Unix lain tanpa noclobber dan kecelakaan semacam ini mungkin terjadi lagi.

Seperti yang mungkin Anda ketahui, cangkang Unix dirancang untuk menjadi alat yang tajam bagi para ahli. Ini cepat digunakan dan tidak akan menghalangi Anda - dan itu akan memotong Anda jika Anda lupa ujung mana yang runcing. Tapi, semakin Anda menggunakannya, semakin saya pikir Anda akan menghargai bahwa itu bisa menjadi hal yang baik.


* Catatan Kaki: mungkin mengambil pendapat saya dengan sebutir garam. Saya juga tipe orang yang menganggap roda pelatihan sepeda adalah ide yang buruk.

hackerb9
sumber
Saya juga sudah mengajar Unix sebentar. Banyak siswa saya tidak pernah belajar menghargai kesederhanaan langsung Unix; Saya mengatakan kepada mereka bahwa mereka tidak sendirian, dan setidaknya masih bisa belajar sambil bersimpati pada Buku Pegangan Unix, yang memetakan beberapa ladang ranjau untuk mereka. simson.net/ref/ugh.pdf
Jason
Juga: Saya setuju - roda pelatihan pada sepeda sangat membantu bagi siapa pun yang belajar cara mengendarai sepeda roda tiga.
Jason
2

Anda mungkin dapat memulihkan data setelah pertama kali terjadi jika Anda baru saja melihat atau mengedit skrip dan masih dalam buffer memori. Kalau tidak, Anda kurang beruntung.

Jika Anda memilih teeuntuk menulis ke file (dan juga STDOUT) alih-alih >(atau tee -abukannya >>), maka Anda dapat dengan mudah mengganti teedengan alias, fungsi, atau symlink ke skrip yang memperingatkan pengguna jika file yang akan mereka tulis untuk dapat dieksekusi.

Berikut ini sama sekali tidak ideal dan dapat ditingkatkan pada banyak hal , tetapi ini adalah titik awal, sama seperti contoh bagaimana ini mungkin:

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

... kalau begitu echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrcatau sesuatu yang serupa.

Sisi baiknya, setidaknya Anda akan mendapatkan lebih banyak latihan dan versi kedua skrip Python Anda mungkin akan jauh lebih baik daripada yang pertama!

rubynorails
sumber
1

Anda tidak menentukan apakah Anda bekerja pada PC atau server. Jika file Anda kebetulan disimpan di server file khusus, maka sering ada cadangan otomatis ("snapshots") disimpan oleh perangkat keras server file (OS pada).

Di bawah Linux

Direktori snapshot virtual dan tersembunyi ada di setiap direktori di sistem file Anda.

Mencoba:

cd .snapshot   
ls -l

Jika direktori itu ada, maka Anda mungkin beruntung. Anda akan melihat serangkaian direktori yang menyimpan cadangan yang disimpan secara otomatis pada waktu tertentu. Nama-nama menunjukkan waktu relatif di masa lalu di mana foto itu disimpan. Sebagai contoh:

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

Pergilah ke direktori titik waktu apa pun yang cukup lama (sebelum kesalahan penimpa file). Di dalam direktori timepoint, Anda akan melihat status ../..direktori (dan semua subdirektori) pada saat itu di masa lalu.

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

Catatan:

  1. ls -atidak akan menampilkan .snapshotdirektori; Anda harus menyebutkannya dengan jelas. Ini dimasukkan secara virtual oleh server file. Itu tidak ada sebagai direktori nyata di sistem file Anda.
  2. Snapshots otomatis ini adalah sejarah bergulir. Perubahan lama akhirnya jatuh dari ujung dan hilang. Anda perlu menggunakan teknik ini sesegera mungkin setelah Anda menyadari bahwa Anda memerlukan file kembali.

Di bawah Windows

Direktori snapshot tersembunyi dapat dinamai ~ snapshot dan hanya ada pada level root dari drive yang diberikan.

Nasihat

Snapshots adalah jaring pengaman yang berfungsi sebagian besar waktu, tetapi tidak setiap saat. Saya setuju dengan rekomendasi lain untuk menggunakan sistem kontrol versi (seperti git) bahkan untuk file sepele.

Jskroch
sumber
1

Telah dikatakan sebelumnya, dan saya akan mengatakannya lagi. Gunakan sistem kontrol revisi.

Cadangan adalah untuk memulihkan kegagalan perangkat keras. Kontrol revisi adalah untuk situasi seperti milik Anda (dan memiliki banyak kegunaan lain). Alat kontrol revisi memungkinkan Anda menyimpan riwayat file, dan kembali ke titik mana pun dalam riwayat itu.

Contoh alat kontrol revisi termasuk subversi (SVN) (agak lama sekarang, tapi masih bagus), lincah (hg), dan git (git) (sulit digunakan). svn baik untuk dokumen kantor, dan um-mergables lainnya, git dan hg telah melampaui itu untuk sebagian besar peran lainnya. hg dan git memungkinkan Anda bekerja secara off-line, dan untuk melakukan sinkronisasi dengan server jarak jauh, untuk distribusi dan cadangan.

Baca tentang kontrol revisi, kemudian bagikan kontrol revisi, dan kemudian coba.

ctrl-alt-delor
sumber
Saya setuju bahwa menggunakan kontrol revisi adalah yang terbaik untuk situasi seperti milik saya, tetapi memberikan izin yang tepat untuk file sama pentingnya
Bharath Teja