如何通过管道立即捕获ping命令的输出?
这是我的代码:
int main ()
{
FILE *cmd = popen ( "ping -c 3 google.com | grep icmp", "r" );//ping google
char *s = malloc ( sizeof ( char ) * 200 );
while ( 1 )
{
fgets ( s, sizeof ( char )*200, cmd );
printf ( "%s", s);//show outcome
if ( strstr ( s, "icmp_req=3" ) != 0 )
break;
}
pclose ( cmd );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
程序完成后,将同时显示输出.但我想在程序执行时立即读取输出.
<stdio.h> 默认情况下是缓冲的,并且stdout是行缓冲的.
替换你printf("%s", s); 的printf("%s\n", s);(结束换行符将刷新stdout缓冲区)或fflush(NULL);在它之后添加一个调用.
实际上,你的问题与之无关ping,但管道是缓冲的.
你可能做的较低水平pipe,fork,dup2,read系统调用和显式管理管道上的缓冲.然后调用poll可能是有用的.
您可以考虑使用像liboping这样的ICMP pinging库,或者考虑改为执行HTTP请求(使用wget程序,或者最好使用libcurl ;也许一个简单的HTTP HEAD请求就足够了).作为一般建议,避免使用popen或分配进程system(因为目标计算机上可用的命令可能不同).
阅读一些很好的Linux编程书,比如http://advancedlinuxprogramming.com/
这是一个小代码,它使用liboping每秒 ping www.xively.com并显示延迟.您可以在ubuntu框上安装liboping静态/动态库文件和头文件,如下所示:sudo apt-get install liboping0 liboping-dev oping
然后使用上面的库(gcc -o test test.c -loping)编译以下程序.并以超级用户(sudo)身份运行可执行文件.
test.c的:
/*
* 1. install liboping, e.g. `sudo apt-get install liboping0 liboping-dev oping`
* 2. Compile with -loping, e.g. `gcc -o test test.c -loping`
* 3. Execute using sudo as super user, e.g. `sudo ./test`
*/
#include <stdlib.h>
#include <stdio.h>
#include <oping.h>
int main(int argc, char **argv) {
pingobj_t *ping;
pingobj_iter_t *iter;
if ((ping = ping_construct()) == NULL) {
fprintf(stderr, "ping_construct failed\n");
return -1;
}
printf("ping_construct() success\n");
if (ping_host_add(ping, "www.xively.com") < 0) {
const char * errmsg = ping_get_error(ping);
fprintf(stderr, "ping_host_add(www.xively.com) failed. %s\n", errmsg);
return -1;
}
printf("ping_host_add() success\n");
while (1) {
if (ping_send(ping) < 0) {
fprintf(stderr, "ping_send failed\n");
return -1;
}
printf("ping_send() success\n");
for (iter = ping_iterator_get(ping); iter != NULL; iter =
ping_iterator_next(iter)) {
char hostname[100];
double latency;
unsigned int len;
printf("ping_iterator_get() success\n");
len = 100;
ping_iterator_get_info(iter, PING_INFO_HOSTNAME, hostname, &len);
len = sizeof(double);
ping_iterator_get_info(iter, PING_INFO_LATENCY, &latency, &len);
printf("hostname = %s, latency = %f\n", hostname, latency);
}
sleep(1);
}
printf("exiting...\n");
ping_destroy( ping );
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
anurag@anurag-PC:~$ sudo ./test
ping_construct() success
ping_host_add() success
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 233.666000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 234.360000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 234.076000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 231.761000
ping_send() success
ping_iterator_get() success
hostname = www.xively.com, latency = 235.085000
^C
Run Code Online (Sandbox Code Playgroud)
如果你想从你的linux设备检查互联网连接,如果你的ISP或目标没有阻止ICMP数据包,那么liboping是好的.如果这些被阻止,您可以使用某个HTTP库尝试从www.google.com或任何其他网站获取index.html页面并检查是否成功