Vô tình sử dụng chuyển hướng đầu ra> thay vì đường ống |


21

Một tháng trước tôi đã viết một tập lệnh Python để ánh xạ địa chỉ MAC và IP từ stdin. Và hai ngày trước tôi đã nhớ nó và sử dụng để lọc đầu ra tcpdumpnhưng nó đã bị lỗi do lỗi đánh máy. Tôi đã gõ

tcpdump -ne > ./mac_ip.py

và đầu ra là không có gì. Nhưng đầu ra phải là "Không xác định" nếu nó không thể phân tích cú pháp đầu vào, vì vậy tôi đã làm cat ./mac_ip.pyvà tìm thấy tất cả tcpdumpdữ liệu thay vì chương trình. Sau đó tôi nhận ra rằng tôi nên sử dụng

tcpdump -ne | ./mac_ip.py

Có cách nào để lấy lại chương trình của tôi không? Dù sao tôi có thể viết lại chương trình của mình, nhưng nếu nó xảy ra lần nữa với chương trình quan trọng hơn thì tôi có thể làm được điều gì đó. HOẶC có cách nào để báo hướng chuyển hướng đầu ra để kiểm tra tệp và cảnh báo nếu nó là tệp thực thi không?


18
Bạn có thể lấy lại chương trình của mình từ bản sao lưu cuối cùng trước khi ghi đè, nếu không thì không. BTW trong shell bạn có thể chỉ định set -o noglobbervà bash sẽ không chuyển hướng vào các tệp hiện có nữa. Xem tại đây để biết chi tiết: cyberciti.biz/tips/howto-keep-file-safe-from-over
Writing.html

12
Bạn không nên có quyền viết thư cho các thực thi quan trọng ...
Hagen von Eitzen

20
@eckesset -o noclobber
GNP

38
@HagenvonEitzen Tôi ghét lời khuyên như vậy, như thể bạn đã đặt quyền sở hữu và quyền thích hợp cho mọi tập lệnh shell và python mà bạn đã từng viết trước khi chạy nó (và dĩ nhiên, quay lại một lần nữa nếu bạn phải chỉnh sửa nó ). Nó chỉ có ý nghĩa hơn một chút so với "Bạn không nên gõ >khi bạn muốn nói |." Đừng quên thực tế.
Jason C

30
Git repos là giá rẻ. Cam kết tất cả mã của bạn, cho dù nhỏ và vô nghĩa và sau đó một lỗi như thế này là một sửa chữa nhanh chóng và dễ dàng.
casey

Câu trả lời:


22

Đáng buồn là tôi nghi ngờ bạn sẽ cần phải viết lại nó. (Nếu bạn có bản sao lưu, đây là lúc để đưa chúng ra. Nếu không, tôi thực sự khuyên bạn nên thiết lập chế độ sao lưu cho tương lai. Rất nhiều tùy chọn có sẵn, nhưng không có chủ đề cho câu trả lời này.)

Tôi thấy rằng việc đặt các tệp thực thi trong một thư mục riêng và thêm thư mục đó vào PATHlà hữu ích. Bằng cách này, tôi không cần phải tham chiếu các tệp thực thi bằng đường dẫn rõ ràng. Thư mục chương trình ưa thích của tôi cho các tập lệnh cá nhân (riêng tư) "$HOME"/binvà nó có thể được thêm vào đường dẫn tìm kiếm chương trình với PATH="$HOME/bin:$PATH". Thông thường, điều này sẽ được thêm vào các kịch bản khởi động shell .bash_profilevà / hoặc .bashrc.

Cuối cùng, không có gì ngăn bạn xóa quyền viết cho chính mình trên tất cả các chương trình thực thi:

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/binlà vị trí tiêu chuẩn cho các tập lệnh và tập lệnh do người dùng tạo
vườn

4
@gardenhead Nó phụ thuộc vào cách thiết lập hệ thống. /usr/localđược dành cho những thứ dành riêng cho máy chủ (trái ngược với thư mục được chia sẻ trên các máy chủ thông qua giá treo mạng) và có thể hoặc không thể ghi được bởi người dùng không phải root.
chepner

4
@gardenhead đó là một vị trí tiêu chuẩn, chắc chắn. Tôi sử dụng /use/local/bincho các tập lệnh và chương trình được cài đặt cục bộ có khả năng được sử dụng bởi nhiều tài khoản người dùng và $HOME/bincho những thứ cá nhân cho một người dùng. Có giá trị trong cả hai.
roaima

1
Lưu ý rằng Fedora dường như đang cố gắng sử dụng$HOME/.local/bin
Zan Lynx

1
@Zan eeeww! Nghiêm túc mà nói, cảm ơn bạn. Có vẻ như RH đang cố gắng đẩy mọi thứ vào ~/.localđó vì đó là một mặt hàng khác được chuyển từ vị trí "truyền thống" của nó.
roaima

38

Để ngăn các tệp hiện có bị ghi đè bằng chuyển hướng, hãy >sử dụng noclobbertùy chọn trong bashhoặc bất kỳ vỏ nào giống như POSIX (cũng là (t)cshnơi tính năng thực sự bắt nguồn, mặc dù bạn làm set noclobberthay vì set -o noclobber/ set -Cở đó). Sau đó, nếu bạn cần buộc phải thay thế một tệp, hãy sử dụng >|toán tử chuyển hướng ( >!trong (t)csh).

Thí dụ:

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

BTW, bạn có thể kiểm tra các cài đặt hiện tại với set -o:

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

Trong khi điều này trả lời hoàn hảo câu hỏi, tôi sẽ không đề nghị nó. 1. Gõ >|thay vì |không có nhiều khả năng hơn gõ >. 2. Thật dễ dàng và rất khuyến khích để tạo bản sao lưu (một trình soạn thảo có tên của nó có thể lưu phiên bản cuối cùng; có cron, v.v.). 3. Mỗi đoạn mã phải được đặt dưới sự kiểm soát phiên bản, ngay cả các tập lệnh nhỏ. YMMV.
maaartinus

2
@maaartinus đi nào, 1) gõ hai ký tự riêng biệt thay vì một ký tự rõ ràng là ít có khả năng hơn. 2) Rõ ràng sao lưu là rất cần thiết, không ai khuyên OP không nên sao lưu, câu trả lời này không có nghĩa là không có bản sao lưu và sao lưu trình chỉnh sửa giả định rằng bạn đã chỉnh sửa tệp trong trình chỉnh sửa. 3) Một lần nữa, bạn chỉ nghĩ về mã mà OP đã viết, như trong ví dụ cụ thể này, nhưng câu hỏi và câu trả lời này có thể áp dụng cho bất kỳ tệp nào trên máy, bao gồm cả hệ thống thực thi.
terdon

8

Tôi thực sự khuyên bạn nên có các tập lệnh quan trọng theo repo git , được đồng bộ hóa từ xa (một nền tảng tự lưu trữ ưa thích sẽ làm), như nhận xét của @ casey nói.

Bằng cách này, bạn được bảo vệ khỏi những sai lầm xấu của con người như hoàn nguyên tệp về trạng thái làm việc trước đó và thực hiện lại.


4

Là tập tin có thể phục hồi?

Câu trả lời ngắn gọn: Không thường xuyên.

@Mark Plotnick chỉ ra trong các bình luận, bạn có thể khôi phục .pycác tệp từ .pycviệc sử dụng Uncompyle . Điều này nên hoàn hảo cho tình huống của bạn.

Nói chung, mặc dù, điều này là khó khăn hơn nhiều. Về mặt lý thuyết bạn có thể sử dụng các công cụ pháp y để phục hồi các tập tin. Có lẽ cách dễ nhất tôi đã sử dụng là testdisk(còn gọi là "PhotoRec"). Nó chỉ hoạt động đôi khi và nó là một quá trình chậm. Nó thường không có giá trị, vì vậy, vâng, điều đó là có thể , nhưng câu trả lời thực sự là "không".

Có thể > được thay đổi để không ghi đè thực thi?

Không. Không có cách tiêu chuẩn nào để báo cho shell không bao giờ chuyển hướng chỉ cho các tệp được đánh dấu thực thi. Có "noclobber" sẽ ngăn chuyển hướng vào các tệp hiện có, có thể thực thi được hay không, nhưng hãy xem nhận xét của tôi về điều đó bên dưới.

Làm gì trong tương lai?

  1. Điều này nghe có vẻ ngớ ngẩn, nhưng để ngăn ngừa những sai lầm trong tương lai, có lẽ bạn không cần phải làm gì. Đặt cược của tôi là bạn đã học bài học này.

    Tôi đã sử dụng và dạy Unix trong một thời gian rất dài và trong khi mọi người thường mắc lỗi này một lần, họ hiếm khi lặp lại. Tại sao không? Có khả năng vì cùng một lý do mà một người có kinh nghiệm với dao không tự cắt mình: con người học giỏi. Cuối cùng, làm điều đúng đắn trở thành bản chất thứ hai.

  2. Sử dụng một trình soạn thảo văn bản để sao lưu cho bạn. Ví dụ: nếu bạn sử dụng emacs, phiên bản trước của chương trình của bạn sẽ được lưu trong mac_ip.py ~. Các trình soạn thảo khác có thể được cấu hình để hoạt động tương tự (ví dụ: "thiết lập sao lưu" trong .nanorc). Đối với các trình soạn thảo không hỗ trợ sao lưu tự động, bạn có thể tạo một hàm đơn giản trong .bashrc:

    myeditor() { cp -p "$1" "$1~";  editor "$1"; }
    
  3. Làm cho nó dễ dàng để làm cho bản sao. Ví dụ: trong thư mục của dự án bạn đang thực hiện, bạn có thể có một Makefile với mục tiêu như thế này:

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

    (Lưu ý: stackexchange đang chuyển nhầm các TAB ở trên thành 4 khoảng trắng.)

  4. Tương tự, bạn có thể tạo một mục tiêu Makefile thực hiện một rsyncmáy chủ Unix từ xa mà bạn có sshquyền truy cập. (Sử dụng ssh-copy-idđể bạn sẽ không được hỏi mật khẩu nhiều lần.)

  5. Sử dụng git. Có rất nhiều hướng dẫn tuyệt vời về việc bắt đầu. Hãy thử man gittutorial, man gittutorial-2man giteveryday. Thiết lập kho lưu trữ git của riêng bạn không khó, nhưng bạn cũng có thể tạo một kho lưu trữ từ xa miễn phí tại github.com

  6. Nếu các giải pháp trên quá nặng, bạn có thể lưu các tập lệnh nhỏ vào gist.github.com . Mặc dù có thể dán hoặc tải lên từ trình duyệt web, tôi khuyên bạn nên sử dụng giao diện chính của dòng lệnh để làm cho mọi thứ trở nên siêu dễ dàng.

Tôi đặc biệt không khuyến khích sử dụng "noclobber".

Có, nếu bạn chọn, bạn có thể làm set -o noclobbernhư vậy, bạn sẽ nhận được thông báo lỗi bất cứ khi nào bạn cố ghi đè lên một tệp hiện có. Đây là một ý tưởng tồi, theo ý kiến ​​của tôi. *

Nó làm cho shell hoạt động theo cách không chuẩn mà không có dấu hiệu rõ ràng cho dù nó được kích hoạt. Bạn phải sử dụng một cú pháp khác nhau để làm những việc bình thường. Tệ nhất là, nếu bạn đã quen với noclobber, thì một ngày nào đó bạn sẽ sử dụng một máy Unix khác mà không cần noclobber và loại tai nạn này có thể xảy ra lần nữa.

Như bạn có thể biết, shell Unix được thiết kế để trở thành một công cụ sắc bén cho các chuyên gia. Nó rất nhanh để sử dụng và sẽ không cản trở bạn - và nó sẽ cắt bạn nếu bạn quên kết thúc nào là nhọn. Nhưng, bạn càng sử dụng nó, tôi càng nghĩ rằng bạn sẽ đánh giá cao điều đó có thể là một điều tốt.


* Chú thích: có thể lấy ý kiến ​​của tôi với một hạt muối. Tôi cũng là kiểu người nghĩ rằng bánh xe đạp xe đạp là một ý tưởng tồi.


Tôi cũng đã dạy Unix được một thời gian. Nhiều sinh viên của tôi chưa bao giờ học được đánh giá cao sự đơn giản trực tiếp của Unix; Tôi nói với họ rằng họ không đơn độc, và ít nhất vẫn có thể học hỏi trong khi tuyên dương cuốn Cẩm nang của Unix Hater, trong đó vạch ra một số mỏ khai thác cho họ. simson.net/ref/ugh.pdf
Jason

Ngoài ra: Tôi đồng ý - bánh xe huấn luyện trên xe đạp rất hữu ích cho bất cứ ai học cách lái xe ba bánh.
Jason

2

Bạn có thể đã có thể khôi phục dữ liệu sau lần đầu tiên xảy ra nếu gần đây bạn đã xem hoặc chỉnh sửa tập lệnh và nó vẫn còn trong bộ nhớ đệm. Nếu không, bạn là khá nhiều may mắn.

Nếu bạn chuyển teesang ghi vào một tệp (cũng như STDOUT) thay vì >(hoặc tee -athay vì >>), thì bạn có thể dễ dàng thay thế teebằng bí danh, hàm hoặc liên kết tượng trưng đến tập lệnh cảnh báo người dùng nếu tệp họ sắp viết để được thực thi.

Điều sau đây không có nghĩa là lý tưởng và có thể được cải thiện rất nhiều , nhưng nó là điểm khởi đầu, giống như một ví dụ về cách điều này là có thể:

tuần sau

#!/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

... sau đó chỉ echo 'alias tee="/path/to/wee.sh"' >> ~/.bashrchoặc một cái gì đó tương tự.

Về mặt tươi sáng, ít nhất bạn sẽ được thực hành nhiều hơn và phiên bản thứ hai của tập lệnh Python của bạn có thể sẽ tốt hơn nhiều so với phiên bản đầu tiên!


1

Bạn đã không xác định xem bạn đang làm việc trên PC hay máy chủ. Nếu các tệp của bạn tình cờ được lưu trữ trên một máy chủ tệp chuyên dụng, thì thường có các bản sao lưu tự động ("ảnh chụp nhanh") được giữ bởi phần cứng máy chủ tệp (HĐH trên).

Theo Linux

Thư mục ảnh chụp ảo, ẩn tồn tại trong mọi thư mục trong hệ thống tệp của bạn.

Thử:

cd .snapshot   
ls -l

Nếu thư mục đó tồn tại, thì bạn có thể gặp may. Bạn sẽ thấy một loạt các thư mục giữ các bản sao lưu được lưu trữ tự động tại một số thời điểm nhất định. Tên cho biết thời gian tương đối trong quá khứ mà ảnh chụp được lưu trữ. Ví dụ:

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

Đi vào bất kỳ thư mục dấu thời gian nào đủ cũ (trước lỗi ghi đè tệp của bạn). Trong thư mục timepoint, bạn sẽ thấy trạng thái của ../..thư mục (và tất cả các thư mục con) kể từ thời điểm đó trong quá khứ.

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

Ghi chú:

  1. ls -asẽ không hiển thị .snapshotthư mục; bạn phải đặt tên cho nó một cách rõ ràng Nó được chèn hầu như bởi máy chủ tập tin. Nó không tồn tại như một thư mục thực trong hệ thống tập tin của bạn.
  2. Những ảnh chụp nhanh tự động là một lịch sử lăn. Những thay đổi cũ cuối cùng rơi ra cuối cùng và bị mất. Bạn cần sử dụng kỹ thuật này càng sớm càng tốt sau khi bạn nhận ra rằng bạn cần một tập tin trở lại.

Trong Windows

Thư mục ảnh chụp ẩn có thể được đặt tên ~ snapshot và chỉ tồn tại ở cấp gốc của một ổ đĩa nhất định.

Lời khuyên

Ảnh chụp nhanh là một mạng lưới an toàn hoạt động hầu hết thời gian, nhưng không phải mọi lúc. Tôi đồng tình với các khuyến nghị khác để sử dụng hệ thống kiểm soát phiên bản (chẳng hạn như git) ngay cả đối với các tệp tầm thường.


1

Nó đã được nói trước đây, và tôi sẽ nói lại. Sử dụng một hệ thống kiểm soát sửa đổi.

Sao lưu là để phục hồi một lỗi phần cứng. Kiểm soát sửa đổi dành cho các tình huống như của bạn (và nó có nhiều cách sử dụng khác). Các công cụ kiểm soát sửa đổi cho phép bạn giữ một lịch sử của một tệp và quay lại bất kỳ điểm nào trong lịch sử đó.

Ví dụ về các công cụ kiểm soát sửa đổi bao gồm lật đổ (SVN) (hiện tại hơi cũ, nhưng vẫn tốt), đồng bóng (hg) và git (git) (khó sử dụng). svn là tốt cho các tài liệu văn phòng, và các hợp nhất khác, git và hg đã vượt qua nó cho hầu hết các vai trò khác. hg và git cho phép bạn làm việc ngoại tuyến và đồng bộ hóa với một máy chủ từ xa, để phân phối và sao lưu.

Đọc về kiểm soát sửa đổi, sau đó phân phối kiểm soát sửa đổi, và sau đó thử chúng.


Tôi đồng ý rằng sử dụng kiểm soát sửa đổi là tốt nhất cho các tình huống như của tôi, nhưng việc cấp quyền đúng cho các tệp cũng quan trọng không kém
Bharath Teja
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.