Có ai biết làm thế nào để bắt đầu ra (tôi nghĩ rằng nó stdout) từ execvp
thay vì in hệ thống nó (trong c trên linux) trong thiết bị đầu cuối?Bắt stdout từ một ứng dụng thực hiện
Trả lời
execvp
thay thế quá trình hoạt động hiện tại trong bộ nhớ. Không có "đánh bắt" đầu ra.
Tôi nghi ngờ bạn đang cố gắng chạy một quy trình bên ngoài từ một quy trình hiện có và phân tích đầu ra của nó. Bạn cần sử dụng popen()
để thực hiện fork()
rồi exec()
, trả lại FILE *
để đọc (sẽ là stdout
của quá trình bạn vừa chạy).
Xem tài liệu của popen
, tôi nghĩ đó chính xác là những gì bạn cần.
Như những người khác đã nói, popen
là những gì bạn muốn sử dụng. Một cái gì đó như thế này ...
#include <iomanip>
#include <iostream>
using namespace std;
const int MAX_BUFFER = 255;
int main()
{
string cmd;
cout << "enter cmd: ";
cin >> cmd;
cout << endl << "running " << cmd << "…" << endl;
string stdout;
char buffer[MAX_BUFFER];
FILE *stream = popen(cmd.c_str(), "r");
while (fgets(buffer, MAX_BUFFER, stream) != NULL)
stdout.append(buffer);
pclose(stream);
cout << endl << "output: " << endl << stdout << endl;
}
tôi mất lòng tin popen/pclose
, như tôi đã làm việc trên quá nhiều hệ thống nơi SIGCHLD
đã được xử lý hơi khác nhau. Và tôi không tin tưởng việc phân tích cú pháp sh
-shell được sử dụng bởi popen
, vì tôi hiếm khi sử dụng nó.
Ngắn 22 tuổi O'Reilly cuốn sách Using C on the UNIX System, by Dave Curry vẫn là một rất tài liệu tham khảo tốt cho loại công cụ này.
Dù sao, đây là một số mã. Nó hơi dài, vì nó phân tích chuỗi mẫu "/bin/ls /etc"
thành mảng {"/bin/ls", "/etc", 0}
. Nhưng tôi thấy việc sử dụng định dạng chuỗi dễ dàng hơn và ngắn hơn 98% thời gian, mặc dù ví dụ này tuân theo điều đó.
Mã này tạo danh sách /etc.
Bạn cần phải thay đổi một số nội dung như ví dụ: NUMBER()
giống với XtNumber()
. Và bạn sẽ cần phải quyết định xem nó có phù hợp với việc xử lý của bạn là SIGCHLD
hay không.
int main(void) { // list the files in /etc
char buf[100];
FILE *fp;
int pid = spawnfp("/bin/ls /etc", &fp);
while (fgets(buf, sizeof buf, fp))
printf("%s", buf);
fclose(fp); // pclose() replacement
kill(pid, SIGKILL); // pclose() replacement
return 0;
}
Các thủ tục con ở đây là:
static int spawnpipe(const char *argv[], int *fd) // popen() replacement
{
int pid;
int pipe_fds[2];
if (pipe(pipe_fds) < 0)
FatalError("pipe");
switch ((pid = fork()))
{
case -1:
FatalError("fork");
case 0: // child
close(1);
close(2);
dup(pipe_fds[0]);
dup(pipe_fds[1]);
close(pipe_fds[0]);
close(pipe_fds[1]);
execv(argv[0], (char * const *)argv);
perror("execv");
_exit(EXIT_FAILURE); // sic, not exit()
default:
*fd = pipe_fds[0];
close(pipe_fds[1]);
return pid;
}
}
này chuyển đổi một chuỗi ascii vào một danh sách argv
, mà có lẽ là vô ích cho bạn:
Bool convertStringToArgvList(char *p, const char **argv, int maxNumArgs)
{
// Break up a string into tokens, on spaces, except that quoted bits,
// with single-quotes, are kept together, without the quotes. Such
// single-quotes cannot be escaped. A double-quote is just an ordinary char.
// This is a *very* basic parsing, but ok for pre-programmed strings.
int cnt = 0;
while (*p)
{
while (*p && *p <= ' ') // skip spaces
p++;
if (*p == '\'') // single-quote block
{
if (cnt < maxNumArgs)
argv[cnt++] = ++p; // drop quote
while (*p && *p != '\'')
p++;
}
else if (*p) // simple space-delineated token
{
if (cnt < maxNumArgs)
argv[cnt++] = p;
while (*p > ' ')
p++;
}
if (*p)
*p++ = 0; // nul-terminate
}
if (cnt < maxNumArgs)
argv[cnt++] = 0;
return cnt <= maxNumArgs; // check for too many tokens (unlikely)
}
này chuyển chuỗi lập luận để tokens và quan trọng hơn, số fd
đến số fp
, vì OP đã yêu cầu stdout
:
int spawnfp(const char *command, FILE **fpp)
{
const char *argv[100];
int fd, pid;
if (!convertStringToArgvList(strdupa(command), argv, NUMBER(argv)))
FatalError("spawnfp");
pid = spawnpipe(argv, &fd);
*fpp = fdopen(fd, "r");
return pid;
}
Tôi tìm thấy câu trả lời này, cung cấp cho popen
giao diện kiểu execvp
.
https://codereview.stackexchange.com/questions/31063/popen-with-array-of-arguments
- 1. Thực hiện một ứng dụng khác từ Java
- 2. Delphi - Bắt tất cả action.onexecute từ một ứng dụng
- 3. Bắt đầu/dừng một ứng dụng web từ chính nó?
- 4. Các chủ đề này là gì khi một ứng dụng Java bắt đầu thực hiện?
- 5. Bắt stdout từ một tiến trình con tcpdump sau khi chấm dứt nó
- 6. khởi chạy ứng dụng, chụp stdout và stderr bằng C++
- 7. Thực hiện một ứng dụng SAML trong Python
- 8. Thực hiện kết nối OAuth từ ứng dụng Windows với ứng dụng Google App Engine
- 9. hiện echo bằng fputs (STDout)?
- 10. Làm thế nào để nắm bắt đầu ra stdout từ một cuộc gọi hàm Python?
- 11. Bắt đầu twitter ứng dụng
- 12. Làm một hoạt động chỉ xuất hiện một lần, khi ứng dụng được bắt đầu
- 13. Nhận PID của ứng dụng hiện đang được thực hiện
- 14. Thực hiện một phân tích từ vựng
- 15. Chụp stdout từ lệnh system() tối ưu
- 16. Sử dụng Akka để thực hiện cuộc gọi dịch vụ web từ ứng dụng Play
- 17. Vấn đề thực hiện một tập tin thực thi trong một ứng dụng Java
- 18. Thực hành tốt nhất để bắt đầu ứng dụng xoay
- 19. Thực hiện cuộc gọi programatically từ ứng dụng iphone và trở lại ứng dụng sau khi kết thúc cuộc gọi
- 20. Ứng dụng web Clojure - tôi bắt đầu từ đâu?
- 21. in stdout trong thời gian thực từ một tiến trình con yêu cầu stdin
- 22. Bắt giữ/lấy cắp dữ liệu stdout trong haskell
- 23. Ứng dụng Android không bắt đầu từ phím tắt
- 24. Thực hiện Khóa mật khẩu cho ứng dụng Android
- 25. Thực hiện lại lệnh FLUSHALL trong ứng dụng đường ray
- 26. Gọi một ứng dụng từ một ứng dụng khác
- 27. Colorize stdout đầu ra cho Windows cmd.exe từ giao diện điều khiển C++ ứng dụng
- 28. Android: Bắt đầu Hoạt động mới từ Lớp Ứng dụng
- 29. bắt đầu ứng dụng erlang từ dòng lệnh
- 30. Làm thế nào để bắt đầu một hoạt động Android từ một ứng dụng Unity?
cũng sẽ hoạt động với đối số? – topherg
Vâng, cin sẽ làm giảm các đối số nhưng nếu bạn thu nhỏ chúng đúng cách, bạn có thể xử lý một thứ gì đó "ls -latr". – Ternary