2010-08-09 24 views
10

Đây là mã của tôi:NSTask NSPipe - dòng khách quan c lệnh giúp đỡ

task = [[NSTask alloc] init]; 
[task setCurrentDirectoryPath:@"/applications/jarvis/brain/"]; 
[task setLaunchPath:@"/applications/jarvis/brain/server.sh"]; 

NSPipe * out = [NSPipe pipe]; 
[task setStandardOutput:out]; 

[task launch]; 
[task waitUntilExit]; 
[task release]; 

NSFileHandle * read = [out fileHandleForReading]; 
NSData * dataRead = [read readDataToEndOfFile]; 
NSString * stringRead = [[[NSString alloc] initWithData:dataRead encoding:NSUTF8StringEncoding] autorelease]; 

Vì vậy, tôi đang cố gắng để tái tạo này:

cd /applications/jarvis/brain/ 
./server.sh 

nhưng sử dụng NSTask trong Objective-C.

Vì một số lý do, khi tôi chạy mã này, stringRead, không trả về gì cả. Nó sẽ trả về terminal nào sẽ trả về khi tôi khởi chạy file .sh. Chính xác?

Bất kỳ ý tưởng nào?

Elijah

+0

Bạn có chắc là tập lệnh server.sh có tiêu chuẩn không? Có lẽ bạn nên treo lên stderr là tốt và xem nếu có chứa bất cứ điều gì. Bạn cũng có thể xem xét đọc dữ liệu từ đường ống khi tác vụ đang chạy, vì nếu nó cố gắng in quá nhiều vào đường ống trong khi bạn không đọc và bộ đệm sẽ đầy, tác vụ sẽ treo vào lần tiếp theo nó cố gắng xuất ra bất cứ thứ gì. –

+0

Tôi không chắc chắn. Bạn có thể chỉ cho tôi một ví dụ? Có, tôi đã xóa [release release] và [task waitUntilExit]. Cùng một vấn đề. – objectiveccoder001

+0

Bạn đang kiểm tra nội dung của stringRead theo chương trình (hoặc trong gdb), hoặc bạn đang cố gắng in chúng ra bằng cách sử dụng NSLog hay gì đó? Nếu bạn đang sử dụng NSLog và không thấy đầu ra nào, hãy kiểm tra Nhật ký Console trong Ứng dụng> Tiện ích cho đầu ra của bạn. Shell script chạy dưới dạng NSTask có thể làm cho đầu ra của bàn điều khiển Xcode ngừng hoạt động. Ngoài ra, tôi lấy ý kiến ​​của Kevin để kiểm tra xem có lỗi gì về lỗi chuẩn (chỉ cần thêm một đường ống thứ hai và đặt làm lỗi tiêu chuẩn cho công việc của bạn) và không dựa vào đường ống có thể đệm tất cả đầu ra của nhiệm vụ của bạn. – puzzle

Trả lời

19

Xcode Bug
Có một lỗi trong Xcode mà dừng nó từ in bất kỳ đầu ra sau một một nhiệm vụ mới sử dụng đầu ra tiêu chuẩn được đưa ra (nó thu thập tất cả các đầu ra, nhưng không còn in bất cứ điều gì). Bạn sẽ phải gọi [task setStandardInput:[NSPipe pipe]] để làm cho nó hiển thị đầu ra một lần nữa (hoặc, cách khác, có nhiệm vụ in để stderr thay vì stdout).


Đề xuất cho mã cuối cùng:

NSTask *server = [NSTask new]; 
[server setLaunchPath:@"/bin/sh"]; 
[server setArguments:[NSArray arrayWithObject:@"/path/to/server.sh"]]; 
[server setCurrentDirectoryPath:@"/path/to/current/directory/"]; 

NSPipe *outputPipe = [NSPipe pipe]; 
[server setStandardInput:[NSPipe pipe]]; 
[server setStandardOutput:outputPipe]; 

[server launch]; 
[server waitUntilExit]; // Alternatively, make it asynchronous. 
[server release]; 

NSData *outputData = [[outputPipe fileHandleForReading] readDataToEndOfFile]; 
NSString *outputString = [[[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding] autorelease]; // Autorelease optional, depending on usage. 
+0

Dường như điều này đang đóng băng mã của tôi ... huh ... bất kỳ ý tưởng nào khác? – objectiveccoder001

+0

Và, tôi đã cố gắng để đặt trong echo "hello thế giới" nó trở lại trống .... và ngày retured trống. – objectiveccoder001

+0

Ngay cả với '[server setStandardInput: [NSPipe pipe]]'? Đó là một chút lạ. Bạn đã sao chép nguyên văn mã của tôi chưa? Hãy thử nó, và xem nếu nó sẽ làm việc với một tập tin mà chỉ chứa 'echo" Hello World "; pwd | ls'. Nếu vẫn không hoạt động, vui lòng cho chúng tôi biết bạn đang sử dụng phiên bản Xcode nào và xem chuỗi ghi vào tệp có tạo ra bất kỳ đầu ra nào không (chỉ có thể là đầu cuối Xcode không in thêm đầu ra). –

9

Các giải pháp trên là đóng băng vì nó đồng bộ. Gọi tới [server waitUntilExit] chặn vòng lặp chạy cho đến khi hoàn thành công việc.

Đây là giải pháp không đồng bộ để nhận kết quả công việc.

task.standardOutput = [NSPipe pipe]; 
[[task.standardOutput fileHandleForReading] setReadabilityHandler:^(NSFileHandle *file) { 
    NSData *data = [file availableData]; // this will read to EOF, so call only once 
    NSLog(@"Task output! %@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); 

    // if you're collecting the whole output of a task, you may store it on a property 
    [self.taskOutput appendData:data]; 
}]; 

Có thể bạn muốn lặp lại tương tự ở trên cho task.standardError.

QUAN TRỌNG:

Khi tác vụ của bạn chấm dứt, bạn phải đặt khả năng đọcBộ chặn khối để không; nếu không, bạn sẽ gặp phải mức sử dụng CPU cao, vì việc đọc sẽ không bao giờ dừng lại.

[task setTerminationHandler:^(NSTask *task) { 

    // do your stuff on completion 

    [task.standardOutput fileHandleForReading].readabilityHandler = nil; 
    [task.standardError fileHandleForReading].readabilityHandler = nil; 
}]; 

Đây là tất cả không đồng bộ (và bạn nên làm không đồng bộ), vì vậy phương pháp của bạn phải có khối hoàn thành ^.

+0

Hoàn hảo. Đã tìm kiếm một ví dụ về API khối. – uchuugaka

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