2015-06-12 62 views
8

Tôi đã mã hóa một hàm sử dụng system() chức năng thư viện như sau:hệ thống() thỉnh thoảng trả 2

int execute(const char* cmd) 
{ 
    int ret = system(cmd); 

    if (ret != -1) 
    { 
    if (WIFEXITED(ret)) 
     ret = WEXITSTATUS(ret); 
    else 
     ret = -1; 
    } 

    LINFO("execute %s, ret = %d", cmd, ret); // logging 
    return ret; 
} 

Sau đó, tôi gọi nó với một kịch bản shell như sau:

#!/bin/sh 
PATH=$PATH:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin 
cd $(dirname $0) 

agent_name=`grep 'agent_name' ../etc/config.ini |awk '{ print $3 }'` 
py='../../python26/bin/python' 

check_alive() 
{ 
    status=`ps -ef | grep "$agent_name" | grep -v "grep" |wc -l` 

    if [ $status -ne 0 ]; then 
     # process exist 
     echo "$agent_name already exist" 
     exit 1 
    fi  

} 

check_alive 
eval '$py ../bin/agent.py -d' 

status=`ps -ef | grep "$agent_name" | grep -v "grep" |wc -l` 
if [ $status -lt 1 ] 
then 
    echo "run failed" 
    exit -1 
else 
    echo "run succ" 
    exit 0 
fi 

Nhưng đôi khi có là mã trả về kỳ lạ của 2, như sau:

[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 2 
[INFO]execute ./admin/trystart.sh, ret = 2 
[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 1 
[INFO]execute ./admin/trystart.sh, ret = 2 

Tôi muốn hiểu lý do tại sao là mã trả lại là 2.

================ mới 2015/06/12 13:54 ============== ==============

tôi đã phát hiện ra rằng khi hệ thống() trả về 2, đã có một thông báo lỗi của bash như sau:

bash: xmalloc: locale.c:73: cannot allocate 2 bytes (0 bytes allocated) 
+0

Đây là câu hỏi được định dạng rất tốt. Không cần cải thiện. Cũng giống như một lưu ý phụ, lý do có thể nằm sau 'return ret', trong đó' ret = system (cmd) '. 'system (cmd)' có thể là equsl '2'. – HyperNeutrino

+0

@JamesSmith Nếu 'system' trả về' 2' thì anh ta sẽ nhấn vào trường hợp '! = -1' và' WIFEXITED' sẽ trả về false và 'ret' nên được đặt thành' -1' tôi tin. –

+0

Là một sang một bên. Nhìn vào 'pgrep' thay vì đường ống của bạn và' eval' là hoàn toàn không cần thiết. –

Trả lời

8

các mã trạng thái của 2 đang được trả về bởi vỏ của bạn. Nếu không có nhiều chi tiết hơn, sẽ rất khó chẩn đoán. Việc thêm thông báo lỗi thực tế do trình bao tạo ra rất hữu ích.

Nếu bạn shell là bash - như bây giờ dường như là - sau đó mã trạng thái trở lại của 2 chỉ ra một lỗi cấp phát bộ nhớ, được xác nhận bởi các thông báo lỗi được tạo ra bởi bash:

bash: xmalloc: locale.c:73: cannot allocate 2 bytes (0 bytes allocated) 

Dòng 73, theo như tôi thấy, phân bổ bộ nhớ đầu tiên được thực hiện bởi một quá trình mới bắt đầu bash (được xác nhận bởi dấu hiệu của thông báo lỗi rằng không có byte nào được phân bổ), vì vậy có vẻ như vấn đề là malloc không thể cấp phát bộ nhớ.

Có thể thực sự không có bộ nhớ, đặc biệt nếu bạn đang chạy trên một hệ thống bị tắc nghẽn nặng mà không có cấu hình trao đổi. Nhưng có một vài gợi ý nằm rải rác trên internet cho thấy rằng điều này có thể phải làm với các tùy chọn bảo vệ bộ nhớ; đặc biệt, các cấu hình trong đó sbrk không khả dụng nhưng thư viện malloc hy vọng có thể sử dụng nó.

Bạn có thể muốn bắt đầu chẩn đoán hơn nữa bằng cách kiểm tra xem liệu chúng ta có thể chắc chắn bắt đầu vỏ mới:

for i in {0..999}; do sh -c 'exit 0' || echo Failure $?; done 

Dự đoán trước đó, mà có thể được sử dụng cho người khác. Việc sửa chữa yêu cầu exit được đề xuất, mặc dù nó có thể không liên quan gì đến vấn đề cụ thể trong câu hỏi này.

Vỏ dash, được sử dụng dưới dạng số /bin/sh thực hiện bởi một số bản phân phối, trả về mã trạng thái 2 khi vỏ thoát do điều kiện lỗi.

Một khả năng thủ phạm của kịch bản trên là

exit -1 

Mã trạng thái trở lại tám-bit giá trị unsigned; nói cách khác, mã trả về pháp lý nằm trong khoảng từ 0 đến 255. -1 không nằm trong phạm vi đó và bạn không nên sử dụng mã đó trong cuộc gọi đến exit.

Bash của exit dựng sẵn (như chức năng C exit) chỉ đơn giản là sử dụng các byte thứ tự thấp của mã trở lại cung cấp, vì vậy với bash mà bạn sẽ thấy một mã trở lại của 255. Tuy nhiên, dấu gạch ngang BUILTIN exit hy vọng đối số của nó là một số chưa ký và than phiền rằng -1 không phải là số hợp lệ.

Kể từ khi exit là nội trang đặc biệt và trình bao không tương tác, lỗi sẽ khiến vỏ thoát ra, theo the Posix standard. Dấu gạch ngang đặt mã thoát thành 2 khi thoát ra vì lỗi trình bao.

+0

Ah, tôi đã nghĩ rằng 255 đã cắt ngắn trước khi nó được đăng nhập. Điều đó có ý nghĩa hơn. –

+0

Nhưng ngay cả khi tôi đặt lại nội dung của tập lệnh ./admin/trystart.sh chỉ 'thoát 1', vấn đề lại xảy ra. – Hetiu

+0

Tôi đã thấy rằng khi hệ thống() trả về 2, có một thông báo lỗi của bash là: "bash: xmalloc: locale.c: 73: không thể cấp phát 2 byte (0 byte được phân bổ)" – Hetiu

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