Phát sinh lỗi khi sử dụng biến shell rỗng


22

Đôi khi tôi sử dụng, $PROJECT_HOME/*để xóa tất cả các tập tin trong dự án. Khi biến môi trường, PROJECT_HOMEkhông được đặt (vì tôi đã làm suvà người dùng mới không đặt biến môi trường này), nó bắt đầu xóa tất cả các tệp khỏi thư mục gốc. Đây là ngày tận thế.

Làm cách nào bashđể định cấu hình để ném lỗi, khi tôi sử dụng biến môi trường không xác định trong trình bao?


5
set -usẽ làm những gì bạn muốn.
cuonglm

bạn có thể làm cho nó như là câu trả lời?

2
Tất nhiên, bạn sẽ không khởi tạo các vars của mình thành các chuỗi trống. [ -z "$VAR" ]làm việc với một uninitialized VARquá. Việc khởi tạo chỉ là để thể hiện hành vi không mong muốn. Quan điểm của tôi là, nếu các vars của bạn đã được khởi tạo thành các chuỗi rỗng, bằng mọi cách, và bạn chạy rm -r "$PROJECT_HOME"/*sai dựa vào set -u, bạn sẽ có hành vi "tận thế". IHMO, tốt hơn hết là bạn nên an toàn hơn là xin lỗi khi bảo vệ toàn bộ nội dung trên máy tính của bạn. set -ukhông an toàn
PSkocik

3
"Nó rất dài"? Bạn không nên tìm kiếm một cách thuận tiện để thực hiện các thao tác nguy hiểm theo cách thủ công. Thay vào đó, bạn nên tạo một hàm, bí danh hoặc tập lệnh để làm những gì bạn muốn; trong trường hợp này, tạo một bí danh từ lệnh được đề xuất của @ PSkocik sẽ vừa an toàn thuận tiện.
Kyle Strand

1
Nếu người dùng đặt PROJECT_HOME=/etcthì sao? Chỉ kiểm tra một giá trị trống là không đủ để ngăn chặn thảm họa. Bạn không nên sử dụng các biến từ người dùng không tin cậy khi chạy bằng root.
Barmar

Câu trả lời:


27

Trong shell POSIX, bạn có thể sử dụng set -u :

#!/bin/sh

set -u
: "${UNSET_VAR}"

hoặc sử dụng mở rộng tham số :

: "${UNSET_VAR?Unset variable}"

Trong trường hợp của bạn, bạn nên sử dụng :?thay vì ?thất bại trên set nhưng biến rỗng:

rm -rf -- "${PROJECT_HOME:?PROJECT_HOME empty or unset}"/*

17
[ -z "$PROJECT_HOME" ] || rm -r "$PROJECT_HOME"/*

Điều này cũng sẽ bắt được trường hợp PROJECT_HOME được đặt nhưng không chứa bất cứ thứ gì.

Thí dụ:

1) Điều này sẽ xóa khá nhiều thứ bạn có thể xóa trên hệ thống của mình (chặn các dấu chấm bên trong /(thường không có)):

set -u
PROJECT_HOME=
rm -r "$PROJECT_HOME"/*

2) Điều này sẽ không làm gì cả:

PROJECT_HOME=
[ -z "$PROJECT_HOME" ] || rm -r "$PROJECT_HOME"/* 

Xóa hoàn toàn nhà dự án của bạn và tạo lại nó có thể là một tùy chọn khác (nếu bạn cũng muốn thoát khỏi dotfiles):

#no apocalyptic threats in this scenario
rm -r "$PROJECT_HOME"
mkdir "$_" 

1
-zlà ok, nhưng vì $PROJECT_HOMEđược coi là một thư mục, có lẽ -dsẽ tốt hơn. [[ -d $PROJECT_HOME ]] && rm -r "$PROJECT_HOME".
kojiro

2
Nếu PRO DỰ_HOME được đặt thành không điều kiện, thì đó là một lỗi không nghiêm trọng, có thể là do lỗi đánh máy. Việc -dkiểm tra sẽ che giấu lỗi đó. Tôi nghĩ sẽ tốt hơn nếu nó tiếp tục rmrmphàn nàn về điều đó.
PSkocik

2
Nếu PRO DỰ_HOME được đặt, nhưng tên không phải là thư mục, thì [[ -d $PROJECT_HOME ]] && rm -r "$PROJECT_HOME"sẽ không làm gì cả, âm thầm. Nhưng [[ -z $PROJECT_HOME ]] || rm -r "$PROJECT_HOME"sẽ âm thầm xóa "$ PRO DỰ_HOME", ngay cả khi đó là tệp không phải là thư mục. Nhận thông báo lỗi không bao giờ là vấn đề:if [[ -d $PROJECT_HOME ]]; then rm -r "$PROJECT_HOME"; else printf '%s is not a directory\n' "$PROJECT_HOME" >&2; fi
kojiro

1
Bây giờ "vô tình" thiết lập PROJECT_HOME="/."...
Hagen von Eitzen

1
@HagenvonEitzen Nếu PRO DỰ_HOME được đặt thành root, quy trình làm trống PRO DỰ_HOME sẽ trống gốc. Đó là hành vi được mong đợi và hoàn toàn hợp lý. Và bạn thậm chí không cần dấu chấm cuối cùng đó.
PSkocik

0

Một cách khác để làm điều này:

rm -r "${somevar:-/tmp/or_this_if_somevar_is_empty}"/*

Có nhiều sự thay thế khác nhau, cái ở trên là khi "somevar" trống rỗng (và trong trường hợp đó, nó cố gắng xóa /tmp/or_this_if_somevar_is_empty/*)


1
Hoặc: rm -fr ${ENV_VAR:?suitably caustic message here}/*, nhưng nó có thể vẫn có giá trị kiểm tra rằng giá trị không có bản đồ vào thư mục gốc, lưu ý rằng có rất nhiều cách để lật đổ các xét nghiệm đơn giản: //, /.., /usr/who/../.., ...
Jonathan Leffler

Vâng. Nếu bạn sẽ sử dụng một mở rộng tham số, bạn cũng có thể sử dụng một mở rộng thực sự gây ra lỗi
Chấn thương kỹ thuật số
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.