2014-11-27 11 views
5

Có một câu hỏi được trả lời trên Best Way to Gracefully Shutdown a Java Command Line Program. Một hook tắt sẽ thực hiện công việc trong trường hợp một chương trình bị chấm dứt bởi Ctrl + C.Làm thế nào để tắt một cách thủ công một ứng dụng Java được chấm dứt như là kết quả của việc đóng dòng lệnh mà từ đó nó đã được thực hiện?

Câu hỏi của tôi là cách thoát ra một cách duyên dáng nếu chính dòng lệnh được đóng trong khi thực hiện chương trình Java? Tôi đã thử nghiệm với móc tắt máy nhưng nó không hoạt động trong trường hợp này. Tôi không thể tìm hiểu điều gì sẽ xảy ra với máy ảo trong trường hợp này. Quá trình và tất cả các chủ đề của nó bị giết ngay lập tức? Loại tín hiệu nào đóng dòng lệnh?

Vì vậy, vấn đề cụ thể này có thể được giải quyết như thế nào?

EDIT: Vấn đề liên quan đến môi trường Windows.

+0

Trả lời http://stackoverflow.com/a/20568883/4428150 cho biết cách thực hiện điều đó từ C. – Gustave

Trả lời

2

Hợp lý, SIGHUP (treo thiết bị đầu cuối) nên được nâng lên.

Thực ra, tôi vừa kiểm tra phỏng đoán của mình bằng một tập lệnh shell đơn giản. Có, khi người dùng đóng một trình giả lập thiết bị đầu cuối trong đó một ứng dụng được khởi động (và từ đó nó không được tách ra), thì ứng dụng sẽ nhận được SIGHUP. Vì vậy, hãy thiết lập trình xử lý SIGHUP và phản ứng tương ứng. Hành vi thông thường là chấm dứt một ứng dụng, nhưng ý định của bạn có thể khác. Ngoài ra, nếu ứng dụng Java của bạn thực hiện bất kỳ hoạt động STDIN/STDOUT nào, nó sẽ bị đóng hoặc ít nhất được tái xác nhận khi nhận được HUP, vì nỗ lực đọc/ghi từ thiết bị đầu cuối không tồn tại sẽ dẫn đến SIGPIPE và/hoặc chương trình khối.

Đối với Windows hãy nhìn vào Catch Windows terminal closing on running process

+0

Tôi đã chỉnh sửa câu hỏi của mình. Ban đầu tôi trộn lẫn các lệnh diệt dựa trên Linux và Windows. Thực ra, tôi đặc biệt quan tâm đến phiên bản Windows của kịch bản này. –

+0

"Dòng lệnh của Windows" - cmd.exe? – user3159253

+0

Có, tôi đã tham khảo cmd.exe –

0

Chỉnh sửa cho các cửa sổ môi trường:

Tôi không có nhiều kinh nghiệm trên cửa sổ môi trường nhưng nếu bạn muốn ứng dụng của bạn để tiếp tục chạy, nó thường được triển khai như dịch vụ Windows (nó tương tự như daemon trên Linux). Bạn thường sẽ bắt đầu/dừng/khởi động lại dịch vụ thông qua một tiện ích liệt kê tất cả các dịch vụ (tôi nghĩ bạn sẽ vào được nó qua bảng điều khiển -> Administrative Tools -> Services. Tôi đoán rằng việc phát hành "stop" qua công cụ này sẽ báo hiệu một cách duyên dáng tắt máy. Và nếu bạn giết các dịch vụ qua trình quản lý tác vụ, sau đó nó sẽ không phải là một shutdown duyên dáng.


đây có phải là một môi trường Windows dựa Linux dựa hay? trong Linux, nếu bạn chạy chương trình ở chế độ nền (và thoát khỏi trình bao với lệnh 'thoát'), nó sẽ tiếp tục chạy. Bạn có thể đặt ứng dụng của mình ở chế độ nền bằng cách thêm một & ở cuối. Ngoài ra, rất nhiều ứng dụng/dịch vụ chạy trong nền. một tập lệnh khởi động Tomcat với lệnh startup.sh, nó sẽ tiếp tục chạy ở chế độ nền ngay cả khi bạn n bạn thoát khỏi thiết bị đầu cuối mà bạn đã khởi chạy nó từ đó. Trên cửa sổ quá, khái niệm nên tương tự.

Về mặt đóng ứng dụng, bạn sử dụng lệnh giết trên hệ thống Linux. lệnh kill trên một tiến trình gửi tín hiệu SIGTERM tới nó. Các ứng dụng có thể thực thi mã để chặn SIGTERM và tắt máy một cách duyên dáng khi phát hiện SIGTERM. Nếu ứng dụng không xử lý SIGTERM một cách duyên dáng, thì nó sẽ không trả lời SIGTERM/kill. Trong trường hợp đó, bạn cần phải cung cấp cho nó một SIGKILL (kill -9) để giết nó một cách rõ ràng. Trong trường hợp đó, tắt máy duyên dáng là không thể.

+0

"nếu bạn chạy chương trình ở chế độ nền, chương trình sẽ tiếp tục chạy ngay cả khi bạn đóng thiết bị đầu cuối" không nhất thiết phải như vậy. – user3159253

+0

bạn nói đúng. tôi sẽ cập nhật nhận xét của tôi. – Jigish

+0

Cho phép không quên nohup mà không có những gì bạn đề nghị sẽ không đúng sự thật. – Khanna111

0

Trong Java, có một phương pháp đặc biệt Runtime cho điều đó: addShutdownHook.

Điều này cho phép bạn khởi tạo một chuỗi mà JVM sẽ cố gắng chạy ngay trước khi dừng.Đó là các nơi để đặt bất kỳ dọn dẹp bạn muốn thực hiện ngay cả trong trường hợp Ctrl-C đóng cửa sổ cha mẹ. Trích xuất từ ​​javadoc: Móc tắt chỉ đơn giản là một chuỗi được khởi tạo nhưng chưa được bắt đầu. Khi máy ảo bắt đầu trình tự tắt máy của nó, nó sẽ bắt đầu tất cả các móc tắt đã đăng ký trong một số thứ tự không xác định và cho phép chúng chạy đồng thời. Khi tất cả các móc đã hoàn thành, nó sẽ chạy tất cả các finalizers chưa được giải quyết nếu finalization-on-exit đã được kích hoạt. Cuối cùng, máy ảo sẽ dừng lại.

Móc tắt máy sẽ gọi ngay cả khi chương trình kết thúc bình thường. Trong trường hợp đó, nó là sạch để loại bỏ các móc đăng ký trước khi thoát với removeShutdownHook (vẫn còn là một phương pháp từ Runtime)

EDIT:

Trong trường hợp của môi trường Windows, không có tín hiệu thật, nhưng callbacks đặc biệt khi hệ thống đang tắt. AFAIK, móc hệ thống được gọi chính xác trong trường hợp đó, nhưng tôi thừa nhận tôi chưa bao giờ thực sự thử nghiệm điều đó. Trong Windows, quá trình có thể được yêu cầu chấm dứt với 2 cách:

  • chức năng PostQuitMessage đăng bài viết WM_QUIT trong quá trình vòng lặp sự kiện - bình thường quá trình này nên thoát ra, nhưng nó có thể làm sạch nó (equivallent của Unix SIG_TERM)
  • TerminateProcess ngay lập tức dừng quá trình và tất cả các chủ đề của nó (equivallent của Unix SIG_KILL)

quá trình điều khiển có thể sử dụng một ConsoleControlHandler có thể đánh chặn Ctrl-C, Ctrl-break hoặc Ctrl-Đóng sự kiện. Đầu tiên hai được tạo ra thông qua bàn phím, cuối cùng được tạo ra khi người dùng đóng giao diện điều khiển. Nhưng thông thường, Oracle JVM nên sử dụng cơ chế móc hệ thống khi nhận được sự kiện Ctrl-Close được xử lý giống như SIGTERM.

+0

Tôi đã đề cập đến hook tắt máy trong câu hỏi của mình. Nó hoạt động trong trường hợp của Ctrl-C, nhưng không hoạt động trong trường hợp đóng cmd.exe –

Các vấn đề liên quan