Cho rằng sự đồng thuận dường như thích #sh
phương pháp của rake hơn , nhưng OP yêu cầu bash một cách rõ ràng, câu trả lời này có thể có một số công dụng.
Điều này có liên quan vì Rake#sh
sử dụng lệnh Kernel#system
gọi để chạy các lệnh shell. Ruby mã hóa cứng /bin/sh
, bỏ qua trình bao được định cấu hình của người dùng hoặc $SHELL
trong môi trường.
Đây là một cách giải quyết mà gọi bash từ /bin/sh
, cho phép bạn vẫn sử dụng sh
phương pháp:
task :hello_world do
sh <<-EOS.strip_heredoc, {verbose: false}
/bin/bash -xeu <<'BASH'
echo "Hello, world!"
BASH
EOS
end
class String
def strip_heredoc
gsub(/^#{scan(/^[ \t]*(?=\S)/).min}/, ''.freeze)
end
end
#strip_heredoc
được mượn từ đường ray:
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/string/strip.rb
Bạn có thể có được nó bằng cách yêu cầu active_support hoặc có thể nó được tự động tải khi bạn đang ở trong một dự án đường ray, nhưng tôi đang sử dụng đường ray bên ngoài này và vì vậy tôi phải tự gỡ bỏ nó.
Có hai heredocs, một bên ngoài với các điểm đánh dấu EOS
và một bên trong có các điểm đánh dấu BASH
.
Cách hoạt động của điều này là bằng cách cho heredoc bên trong giữa các điểm đánh dấu BASH để bash stdin. Lưu ý rằng nó đang chạy trong ngữ cảnh của /bin/sh
, vì vậy nó là một heredoc posix, không phải ruby. Thông thường, điều đó yêu cầu điểm đánh dấu kết thúc ở cột 1, điều này không xảy ra ở đây vì có thụt lề.
Tuy nhiên, vì nó được bọc bên trong một heredoc hồng ngọc, nên strip_heredoc
phương pháp được áp dụng ở đó sẽ khử lõm nó, đặt toàn bộ phần bên trái của heredoc bên trong vào cột 1 trước khi /bin/sh
nhìn thấy nó.
/bin/sh
cũng thường mở rộng các biến trong heredoc, điều này có thể ảnh hưởng đến tập lệnh. Các dấu nháy kép xung quanh điểm đánh dấu bắt đầu, 'BASH', yêu cầu /bin/sh
không mở rộng bất kỳ thứ gì bên trong heredoc trước khi nó được chuyển sang bash.
Tuy nhiên /bin/sh
, vẫn áp dụng thoát cho chuỗi trước khi chuyển nó đến bash. Điều đó có nghĩa là các lần thoát dấu gạch chéo ngược phải được nhân đôi để vượt qua /bin/sh
thành bash, tức là \
trở thành \\
.
Các tùy chọn bash -xeu
là tùy chọn.
Các -eu
đối số cho biết bash chạy ở chế độ nghiêm ngặt, chế độ này sẽ dừng thực thi khi có bất kỳ lỗi nào hoặc tham chiếu đến một biến không xác định. Điều này sẽ trả về một lỗi cho rake, điều này sẽ dừng tác vụ cào. Thông thường, đây là những gì bạn muốn. Các đối số có thể bị loại bỏ nếu bạn muốn hành vi bash bình thường.
Các -x
tùy chọn để bash và {verbose: false}
lập luận để #sh
làm việc trong buổi hòa nhạc để cào mà chỉ in các lệnh bash mà đang thực sự thực hiện. Điều này hữu ích nếu tập lệnh bash của bạn không có nghĩa là chạy toàn bộ, chẳng hạn như nếu nó có một bài kiểm tra cho phép nó thoát sớm một cách duyên dáng trong tập lệnh.
Hãy cẩn thận không đặt mã thoát khác 0 nếu bạn không muốn nhiệm vụ cào thất bại. Thông thường, điều đó có nghĩa là bạn không muốn sử dụng bất kỳ || exit
cấu trúc nào mà không đặt mã thoát rõ ràng, tức là || exit 0
.
%{
, nó%x(
và nó trả về stdout dưới dạng một chuỗi thay vì in nó.