bash scripting - đọc tarball từ stdin


7

Tôi có một nhiệm vụ tôi cần để viết kịch bản mà tôi cảm thấy nên đơn giản một cách ngu ngốc, nhưng tôi thực sự đang có một thời gian khá khó khăn.

Tôi có một tập lệnh bash ngắn có một loại ứng dụng cụ thể ở dạng tarball và xây dựng nó. Hiện tại nó chỉ cần hai đối số dòng lệnh: tên của ứng dụng và vị trí của tarball. Nhưng tôi đã sẵn sàng để triển khai tập lệnh xây dựng trên một hệ thống nhiều máy chủ, và thay vào đó tôi muốn tập lệnh này lấy tarball ứng dụng trên stdin, sẽ được chuyển qua ssh. Ví dụ, đây là cách tôi muốn gọi tập lệnh:

ssh build-host "/usr/local/bin/build-app.sh myapp" < /tmp/myapp.tar.gz

Khi được gọi như thế này, tập lệnh xây dựng sẽ cố gắng xây dựng một ứng dụng có tên là "myapp".

Tôi muốn tập lệnh xây dựng thực hiện một số kiểm tra độ tỉnh táo trước khi nó đọc trong tarball. Ngoài ra, nó nên thoát một cách duyên dáng nếu kiểm tra độ tỉnh táo thất bại. Vì vậy, đây là ý chính của nỗ lực đầu tiên của tôi tại tập lệnh xây dựng:

#!/bin/bash

appname=$1

# example sanity check
if [ ! -d "/apps/$appname" ]; then
    mkdir "/apps/$appname"
else
    echo "Error! The app already has been built."
    exit 1
fi

# more sanity checks...

# if passed all tests, then read stdin into tarfile
cat > "/apps/$appname/app.tar.gz"

# build app ...

Điều này gần như hoạt động. Vấn đề là tôi không thể tìm ra cách đọc từ stdin nửa chừng thông qua một tập lệnh bash. Thủ cat > filethuật chỉ hoạt động nếu tôi đặt nó ở dòng đầu tiên của kịch bản. Nhưng tôi không muốn làm điều đó. Ở dòng đầu tiên của kịch bản, không có kiểm tra độ tỉnh táo nào được chạy và không có cách nào để xác định nơi đặt tarfile. Tôi có thể có nhiều phiên bản tập lệnh chạy cùng một lúc và sẽ không có cách nào tốt để tránh va chạm.

(Ngoài ra cat > file, tôi cũng đã thử các thủ thuật như < /dev/stdin > filevới kết quả rất giống nhau.)

Vì vậy, tôi cũng đã thử như sau:

#!/bin/bash

tarball="$(cat)"
appname="$1"

# example sanity check
if [ ! -d "/apps/$appname" ]; then
    mkdir "/apps/$appname"
else
    echo "Error! The app already has been built."
    exit 1
fi

# more sanity checks...

# if passed all tests, then read stdin into tarfile
echo -n "$tarball" > "/apps/$appname/app.tar.gz"

# build app ...

Nhưng điều này cũng khá có vấn đề, vì hai lý do. Đầu tiên, nó không hoạt động. echo, ngay cả với -ncờ, dường như không được thiết kế cho dữ liệu nhị phân và tarfile kết quả đã bị hỏng. Thứ hai, điều này đòi hỏi phải lưu trữ toàn bộ tarball dưới dạng một biến như bước đầu tiên. Điều này không chỉ chậm hơn mong muốn, ngay cả đối với tarball thử nghiệm 5 MB, nhưng nó cũng có thể có nghĩa là tiêu thụ bộ nhớ cao, đặc biệt là đối với các ứng dụng lớn hơn mà tôi có thể sẽ xử lý.

Tôi thích ý tưởng đọc tarfile từ stdin. Điều này có nghĩa là tập lệnh bash có thể chỉ đơn giản là đóng ống nếu cảm thấy cần hủy bỏ và nó có thể cho phép tập lệnh bash quyết định nơi đặt tất cả các tarball ứng dụng, trái với phiên bản gốc của việc gọi tập lệnh xây dựng, mà trông như thế này:

scp /tmp/myapp.tar.gz build-host:/tmp/
ssh build-host /usr/local/bin/build-app.sh myapp /tmp/myapp.tar.gz

Phương pháp gọi này là có vấn đề vì (hy vọng) lý do rõ ràng.

Tôi thực sự hy vọng tôi có thể làm cho tập lệnh bash này hoạt động bằng cách đọc stdin hoặc một số dạng ống hoặc bộ đệm khác. Có bất kỳ ý tưởng làm thế nào để làm cho điều này để làm việc?

Câu trả lời:


6

Bạn cat > filenên làm việc bất kể khi nào bạn gọi nó, miễn là bạn không đọc từ đó trước đó và "sử dụng hết" luồng đầu vào hoặc đóng bộ mô tả tệp mà bạn không đọc. Đây là một lệnh hoàn toàn hợp pháp và bình thường và nó hoạt động, ít nhất là về phía tôi.


Đó là những gì tôi nghĩ. Nhưng điều đó không giải thích tại sao nó không làm việc cho tôi. Nếu, ở đầu tập lệnh bash của tôi, tôi chạy cat > filerồi chạy filetheo kết quả, tôi có thể thấy rõ kiểu tệp mong muốn là tar được mã hóa. Nhưng nếu tôi di chuyển catdòng xuống nơi tôi muốn chạy nó, kết quả là một tệp trống. Tôi không có bất cứ điều gì khác nên đọc từ (hoặc viết thành) stdin trong toàn bộ kịch bản của mình.
jayhendren

@jayhendren - Bạn có thể làm việc kịch bản gốc của bạn xuống một bằng chứng tối thiểu về khái niệm và đăng nó. Tôi cũng không thể tái tạo vấn đề của bạn.
grebneke

Đừng bận tâm. Tôi đã nhận nó để làm việc. Tôi không thực sự chắc chắn những gì tôi đã thay đổi để sửa nó hoặc tại sao nó không hoạt động trước đây, nhưng, ờ ... cảm ơn vì sự giúp đỡ của bạn? :)
jayhendren

Nó hoạt động tại địa phương (không có ssh)? Nếu bạn chỉ cần bỏ một số rác vào và kiểm tra tập tin đầu ra? Khả năng duy nhất tôi thấy là nếu bạn có một số lệnh uống tất cả các stdin hoặc đóng bộ mô tả tệp. Oh nevermind, miễn là nó hoạt động tốt.
orion

@jayhendren khi bạn nhận được một tập tin trống, bạn phải sử dụng một chương trình ở đâu đó tiêu thụ stdin, đó là lý do tại sao.
janos
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.