Khi bạn chạy một chương trình trên Linux hoặc macOS, nó chạy bên trong một tiến trình (process). Mỗi tiến trình đều có một tên. Tên đó chính là thứ bạn thấy khi chạy lệnh ps, top hoặc htop.
htop hiển thị tên tiến trình ở cột bên phải nhất.
Tên tiến trình mặc định có thể không hữu ích
Mặc định, tên tiến trình được lấy từ tên file thực thi chứa chương trình bạn đang chạy. Điều này hoạt động tốt với hầu hết các file thực thi.畢竟, việc tiến trình "less" có tên "less" là hợp lý.
Tuy nhiên, tên tiến trình mặc định kém hữu ích khi bạn chạy script Ruby từ dòng lệnh. Trong ví dụ dưới đây, tôi chạy một script Ruby ngủ 5 giây. Nếu chạy đồng thời lệnh "ps" ở cửa sổ terminal khác, tên tiến trình của script ngủ là "ruby sleep_5_seconds.rb". Nếu thêm đối số dòng lệnh, chúng cũng xuất hiện trong tên tiến trình, khiến việc tham chiếu tiến trình theo tên trở nên khó khăn.
Toàn bộ lệnh ruby được liệt kê làm tên tiến trình.
Cách thay đổi tên tiến trình
May mắn thay, bạn có thể dễ dàng đổi tên tiến trình hiện tại với Ruby. Đây là script đã cập nhật, đặt tên tiến trình thành "sleeper".
# `Process.setproctitle()` có sẵn từ Ruby >= 2.1
# Với các phiên bản Ruby cũ hơn, bạn có thể dùng:
# $PROGRAM_NAME = "sleeper"
# hoặc
# $0 = "sleeper"
Process.setproctitle("sleeper")
sleep 5
Bây giờ, khi chạy chương trình và dùng ps để hiển thị tiêu đề, ta được "sleeper".
Đổi tiêu đề tiến trình trong Ruby thay đổi đầu ra của ps và top.
Tốt hơn nữa, ta có thể dễ dàng tham chiếu tiến trình theo tên. Giả sử tôi chán chờ "sleeper" ngủ, có thể kill nó bằng lệnh killall sleeper.
Bạn có thể dùng lệnh killall để kết thúc tiến trình theo tên.
Hiển thị trạng thái server qua tên tiến trình
Một ứng dụng thú vị của việc đổi tên tiến trình là hiển thị thông tin trạng thái cho các tiến trình chạy lâu. Nếu bạn từng chạy Unicorn, hình ảnh sau sẽ quen thuộc:
\-+= 27185 deply unicorn master -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27210 deply unicorn worker[0] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27211 deply unicorn worker[1] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27212 deply unicorn worker[2] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27213 deply unicorn worker[3] -c simple_unicorn_config.rb -l0.0.0.0:8080
Đây là instance Unicorn với 4 tiến trình con. Giống ví dụ sleep_5_seconds.rb, tên tiến trình chỉ hiển thị lệnh dùng để khởi chạy.
Sẽ hữu ích nếu dòng trạng thái hiển thị worker đang bận (BUSY) hay rảnh (IDLE). Ví dụ:
\-+= 27185 deply unicorn master -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27210 deply unicorn worker[0] -c simple_unicorn_config.rb -l0.0.0.0:8080 BUSY
|--- 27211 deply unicorn worker[1] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27212 deply unicorn worker[2] -c simple_unicorn_config.rb -l0.0.0.0:8080
|--- 27213 deply unicorn worker[3] -c simple_unicorn_config.rb -l0.0.0.0:8080 BUSY
Bạn có thể làm điều này khá dễ dàng với một Rack middleware. Ví dụ:
class UpdateProcessTitle
def initialize(app)
@app = app
end
def call(env)
title = $0
$0 = $0 + " BUSY"
status, headers, body = @app.call(env)
$0 = title
[status, headers, body]
end
end
Tôi không biết ảnh hưởng hiệu năng của việc đặt tiêu đề tiến trình trên mỗi request web. Vì vậy hãy coi đây chỉ là ý tưởng thú vị.
Nếu muốn xem triển khai nâng cao hơn — đã dùng trong production — hãy đọc bài viết tuyệt vời của Thomas Varaneckas về Overriding Unicorn Worker Process Names.