你这里面有两个问题:
关于问题1,首先yum没有直接用于检查所有使能的repo是否能正常访问的方法,所以需要一些别的方法来辅助判断。这样方式就有很多,比如yum update,yum list等方式会尝试先load所有repo源,进而检查这些repo是否正常。但是有些repo设置中,或全局设置中可能设置了诸如skip_if_unavailable的变量,达到如果repo不可用则直接跳过(不返回错误)的效果。可见这不是我们想要的,我们想要的是在发现不可用的repo时就返回错误。所以我们最好手动设置skip_if_unavailable=false,比如这样:
# yum --setopt=skip_if_unavailable=false list bash
当然,因为yum list会尝试list出所有软件包,但是我们其实不是想列出软件包,而只是想借助其list packages之前做的load repos的工作,所以我只让它列出一个最常见的软件包,如bash (换别的也可以),来减少运行时间。
我故意将系统其中一个repo地址改为一个无效地址,执行结果如下:
# yum --setopt=skip_if_unavailable=false list bash ... 70 B/s | 168 B 00:02 Errors during downloading metadata for repository 'xxxx': - Status code: 404 for http://xxx/xxxxxxx/xxxxx Error: Failed to download metadata for repo 'xxxx': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried # echo $? 1
现在第一个问题我们找到了一个差不多可行的方法(当然不排除有更合适的)。然后下面就是第二个问题。怎么用C语言来做这个检查?
一种方式是用C语言读取yum repo的配置文件,获取各个url,解析url,进而通过http/ftp等协议访问各个地址,尝试判断。这种方式显然比较原始,且有些复杂。
还有一种方式就是让C语言直接执行我们上面列出的命令。好在我们有一个可用的函数叫system(),可以让我们在C语言中执行一个shell命令,并且还能返回这个命令的执行结果,例子如下:
// mytest.c #include <stdlib.h> #include <stdio.h> int main(int argc, char *argv[]) { int ret; ret = system("yum --setopt=skip_if_unavailable=false list bash"); printf("ret=%d
", ret); return ret>>8; }
这就比第一种方式简单多了,第一种方式的很多细节直接交给yum程序去做了,省下很多事。执行效果如下:
# gcc -o mytest mytest.c -Wall # ./mytest ... 70 B/s | 168 B 00:02 Errors during downloading metadata for repository 'xxxx': - Status code: 404 for http://xxx/xxxxxxx/xxxxx Error: Failed to download metadata for repo 'xxxx': Cannot download repomd.xml: Cannot download repodata/repomd.xml: All mirrors were tried ret=256 # echo $? 1
当然,如果你嫌yum的输出很讨厌,还可以把输出过滤掉(如果结尾加上 >/dev/null 2>&1)。
我上面只是提供了一种解决问题的思路,并非“标准答案”。问题能否更好的解决有时还需要从问题本身分析入手,比如你面对的需求是否一定要以“用C语言判断yum源是否配好”来解决,是否有更好的设计,等等。这个问题我就写到这里,进一步的分析就是留给做项目的人自己需要承担的责任了。