Read input in bash inside a while loop
(5个答案)
第一个帖子在这里!我真的需要帮助这一点,我在谷歌上看了这个问题,但找不到一个有用的答案。这就是问题所在。
我很喜欢在bash中编写一些类似框架的代码。每个人都可以创建自己的模块并将其添加到框架中。但是。为了知道脚本需要什么参数,我创建了一个“args.conf”文件,该文件必须位于每个模块中,如下所示:
LHOST;true;The IP the remote payload will connect to.
LPORT;true;The port the remote payload will connect to.
第一列是参数名,第二列定义是否需要,第三列是说明。总之,长话短说,框架应该逐行读取args.conf文件,以向用户询问每个参数的值。下面是一段代码:
info "Reading module $name argument list..."
trong khi đọc dòng;
echo $line > line.tmp
arg=`cut -d ";" -f 1 line.tmp`
requ=`cut -d ";" -f 2 line.tmp`
if [ $requ = "true" ]; then
echo "[This argument is required]"
khác
echo "[This argument isn't required, leave a blank space if you don't wan't to use it]"
fi
read -p " $arg=" answer
echo $answer >> arglist.tmp
done < modules/$name/args.conf
tr '\n' ' ' < arglist.tmp > argline.tmp
argline=`cat argline.tmp`
info "Đang khởi chạy mô-đun $name..."
mô-đun cd/$name
$thông dịch viên $file $argline
đĩa CD ../..
rm arglist.tmp
rm argline.tmp
dòng rm.tmp
thành công "Việc thực thi mô-đun $name đã hoàn tất."
Như bạn có thể thấy, nó sẽ hỏi người dùng một giá trị cho từng tham số. . . Nhưng:
1) Lệnh đọc dường như không được thực thi. Nó chỉ bỏ qua nó và tham số không có giá trị
2) Mặc dù tệp args.conf chứa 3 dòng, vòng lặp dường như chỉ thực thi một lần và tất cả những gì tôi thấy trên màn hình là "[Đối số này là bắt buộc]" một lần và mô-đun chỉ khởi động (và gặp sự cố vì không có đối số bắt buộc) luận cứ...) .
Thực sự không biết phải làm gì ở đây. . . Tôi hy vọng ai đó ở đây có câu trả lời.
Cảm ơn bạn trước!
(Xin lỗi vì sai lầm cuối cùng, tôi là người Pháp)
alpha.
Như @another đã chỉ ra trong phần nhận xét, vấn đề là tất cả đều nằm trong vòng lặpread
Các lệnh được đọc từ tệp args.conf chứ không phải từ người dùng. Cách tôi xử lý việc này là chuyển hướng tệp conf thông qua một bộ mô tả tệp khác với stdin (fd#0);
trong khi đọc dòng -u3;
...
đã hoàn thành 3< mô-đun/$name/args.conf
(Lưu ý: Nếu vỏ
read
lệnh không được hiểu
-u
tùy chọn, vui lòng sử dụng thay thế
đọc dòng <&3
. )
Tôi có rất nhiều gợi ý khác trong kịch bản này:
Tham chiếu biến không có dấu ngoặc kép, ví dụ:
tiếng vang $line
thay vì
tiếng vang "$line"
,cũng như
< module/$name/args.conf
thay vì
< "mô-đun/$name/args.conf"
. Tham chiếu biến không trích dẫn được chia thành các từ (nếu chúng chứa dấu cách) và mọi ký tự đại diện phù hợp với tên tệp sẽ được thay thế bằng danh sách các tệp phù hợp. Điều này gây ra lỗi rất lạ và không liên tục. Thật không may, sử dụng
$argline
Dựa vào cách phân đoạn từ để phân tách nhiều đối số nếu sử dụng;
bash
(không phải shell POSIX thông thường), bạn có thể sử dụng mảng; tôi sẽ thảo luận vấn đề này.
Bạn sử dụng đường dẫn tệp tương đối ở mọi nơi và trong tập lệnh của bạn
cd
ing. Điều này có xu hướng dễ vỡ và khó hiểu vì các đường dẫn tệp khác nhau ở các vị trí khác nhau trong tập lệnh và mọi đường dẫn tương đối được người dùng truyền vào sẽ trở nên không hợp lệ khi tập lệnh được truyền vào nơi khác lần đầu tiên. Điều tồi tệ hơn là ở
cd
Không có việc kiểm tra lỗi nên nếu có
cd
Nếu nó bị lỗi vì bất kỳ lý do gì thì toàn bộ phần còn lại của tập lệnh sẽ chạy sai vị trí và bị lỗi một cách kỳ lạ. Tốt hơn hết bạn nên tìm ra gốc của hệ thống của mình ở đâu (dưới dạng đường dẫn tuyệt đối) và sau đó tham chiếu mọi thứ trong đó (ví dụ:
cd
).
Trên thực tế, bạn không kiểm tra lỗi ở bất cứ đâu. Khi viết bất kỳ loại chương trình nào, nói chung bạn nên cố gắng nghĩ xem điều gì có thể xảy ra sai sót và cách chương trình sẽ phản hồi (đồng thời hy vọng rằng những điều bạn không mong đợi cũng sẽ xảy ra sai sót). Một số người thích sử dụng
< "$module_root/modules/$name/args.conf"
Làm cho tập lệnh của họ thoát nếu bất kỳ lệnh đơn giản nào không thành công nhưng
điều này không phải lúc nào cũng làm được những gì bạn mong đợi. Tôi muốn kiểm tra rõ ràng trạng thái thoát của lệnh trong tập lệnh, đại loại như:
lệnh1 || {
echo 'lệnh 1 thất bại!'
lối ra 1
}
nếu lệnh2 thì
echo 'lệnh2 đã thành công!'
khác
echo 'lệnh 2 thất bại!'
lối ra 1
fi
Bạn đang tạo các tệp tạm thời trong thư mục hiện tại, điều này có thể gây ra xung đột ngẫu nhiên (đồng thời với các lần chạy tập lệnh khác, bất kỳ tệp nào có tên bạn đang sử dụng, v.v.). Tốt hơn là tạo một thư mục tạm thời ngay từ đầu và lưu trữ mọi thứ trong đó (một lần nữa, bằng đường dẫn tuyệt đối):
module_tmp="$(mktemp -dt module-system)" || {
echo "Lỗi tạo thư mục tạm thời" >&2
lối ra 1
}
...
echo "$answer" >> "$module_tmp/arglist.tmp"
(BTW, xin lưu ý rằng tôi đang sử dụng
đặt -e
thay vì dấu gạch chéo ngược. Chúng dễ đọc hơn và không có một số dấu gạch ngang kỳ lạ về mặt ngữ pháp. Tôi khuyên bạn nên thay đổi nó sang một cái khác. )
Phải nói rằng, bạn đang lạm dụng các tệp tạm thời; rất nhiều điều có thể được thực hiện tốt bằng cách sử dụng các biến shell và các tính năng shell tích hợp. Ví dụ: thay vì đọc các dòng từ tệp cấu hình rồi lưu trữ chúng vào tệp tạm thời và sử dụng
$()
Việc chia chúng thành các trường cũng có thể bắt đầu đơn giản bằng
cắt
đến
tiếng vang
:
arg="$(echo "$line" | cut -d ";" -f 1)"
...hoặc tốt hơn nữa, hãy sử dụng
cắt
các chức năng tích hợp, theo
read
Đặt giá trị của trường phân tách thành:
trong khi IFS=";" đọc mô tả yêu cầu -u3;
(Xin lưu ý rằng do
IFS
Nhiệm vụ là
IFS
Tiền tố cho lệnh để nó chỉ ảnh hưởng đến những thay đổi chung của lệnh đó;
read
Có thể tạo ra những hiệu ứng lạ và nên tránh nếu có thể. )
Tương tự, lưu trữ danh sách đối số trong một tệp, chuyển đổi dòng mới thành dấu cách, sau đó đọc tệp. . . Bạn có thể bỏ qua bất kỳ hoặc tất cả các bước này. Nếu sử dụng
IFS
, vui lòng lưu trữ danh sách arg trong một mảng:
danh sách đối số=()
trong khi...
arglist+=("$answer") # hoặc ("#arg=$answer")? Bạn không chắc chắn về cú pháp của mình.
xong...
"$module_root/modules/$name/$interpreter" "$file" "${arglist[@]}"
(Cú pháp khó hiểu này, với dấu ngoặc kép, dấu ngoặc nhọn, dấu ngoặc vuông và ký hiệu at, thường được tìm thấy trong
bash
cách chính xác để mở rộng một mảng).
Nếu bạn không thể dựa vào các tiện ích mở rộng như mảng thì ít nhất bạn có thể làm điều đó với một biến thông thường:
danh sách đối số=""
trong khi...
arglist="$arglist $answer" # hoặc "$arglist $arg=$answer"? Bạn không chắc chắn về cú pháp của mình.
xong...
"$module_root/modules/$name/$interpreter" "$file" $arglist
... nhưng điều này có thể dẫn đến việc các tham số bị chia tách từ và/hoặc mở rộng vào danh sách tệp.
Tôi là một lập trình viên xuất sắc, rất giỏi!