支持版本:蘋(píng)果公司的GCC version 4.0.1
創(chuàng)新互聯(lián)是一家專(zhuān)業(yè)從事成都網(wǎng)站設(shè)計(jì)、做網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)的品牌網(wǎng)絡(luò)公司。如今是成都地區(qū)具影響力的網(wǎng)站設(shè)計(jì)公司,作為專(zhuān)業(yè)的成都網(wǎng)站建設(shè)公司,創(chuàng)新互聯(lián)依托強(qiáng)大的技術(shù)實(shí)力、以及多年的網(wǎng)站運(yùn)營(yíng)經(jīng)驗(yàn),為您提供專(zhuān)業(yè)的成都網(wǎng)站建設(shè)、營(yíng)銷(xiāo)型網(wǎng)站建設(shè)及網(wǎng)站設(shè)計(jì)開(kāi)發(fā)服務(wù)!
1
2
3
4
5
void runls()
{
[[NSTask launchedTaskWithLaunchPath:@"/bin/ls"
arguments:[NSArray array]] waitUntilExit];
}
如果希望調(diào)用系統(tǒng)命令,先執(zhí)行shell:
1
2
3
4
5
void runSystemCommand(NSString *cmd)
{
[[NSTask launchedTaskWithLaunchPath:@"/bin/sh"
arguments:[NSArray arrayWithObjects:@"-c", cmd, nil]]
waitUntilExit];
C程序調(diào)用shell腳本共同擁有三種法子 :system()、popen()、exec系列數(shù)call_exec1.c ,
system() 不用你自己去產(chǎn)生進(jìn)程。它已經(jīng)封裝了,直接增加自己的命令
exec 須要你自己 fork 進(jìn)程,然后exec 自己的命令
popen() 也能夠?qū)崿F(xiàn)運(yùn)行你的命令,比system 開(kāi)銷(xiāo)小
方法一、system()的使用。我直接上代碼吧
int system(const char *command);
我在/home/book/shell新建一個(gè)test.sh文件例如以下:
span style="font-size:18px;"span style="font-size:18px;"#!bin/bash
echo $HOME
echo "the is test!"/span/span
test.c文件例如以下:
span style="font-size:18px;"span style="font-size:18px;"#includestdlib.h
int main()
{
system("bash /home/book/shell/test.sh"); /* chmod +x test.sh ,路徑前面要加上bash */
return 0;
}/span/span
運(yùn)行例如以下命令來(lái)編譯:
span style="font-size:18px;"gcc test.c -o test
/span
測(cè)試命令:
span style="font-size:18px;"./test/span
結(jié)果例如以下:
span style="font-size:18px;"/root
the is test!/span
方法二:popen() 會(huì)調(diào)用fork()產(chǎn)生 子歷程,然后從子歷程中調(diào)用/bin/sh -c來(lái)履行 參數(shù)command的指令。參數(shù)type可應(yīng)用 “r”代表讀取?!皐”代表寫(xiě)入。遵循此type值。popen()會(huì)建立 管道連到子歷程的標(biāo)準(zhǔn) 輸出設(shè)備 或標(biāo)準(zhǔn) 輸入設(shè)備 ,然后返回一個(gè)文件指針。
隨后歷程便可利用 此文件指針來(lái)讀取子歷程的輸出設(shè)備 或是寫(xiě)入到子歷程的標(biāo)準(zhǔn) 輸入設(shè)備 中。此外,全部應(yīng)用 文 件指針(FILE*)操作的函數(shù)也都能夠應(yīng)用 ,除了fclose()以外。
返回值:若成功 則返回文件指針,否則返回NULL,差錯(cuò) 原因存于errno中。注意:在編寫(xiě)具SUID/SGID權(quán)限的程序時(shí)請(qǐng)盡量避免應(yīng)用 popen()。popen()會(huì)繼承環(huán)境變量。通過(guò)環(huán)境變量可能會(huì)造成系統(tǒng)安全的問(wèn)題
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
其它不用改變我們直接改動(dòng)test.c文件:
#includestdio.h
int main()
{
char buffer[80];
FILE *fp=popen("bash /home/book/shell/test.sh","r");
fgets(buffer,sizeof(buffer),fp);
printf("%s",buffer);
pclose(fp);
return 0;
}
方法三:exec函數(shù)簇 (我不太懂,copy別人的。也沒(méi)有驗(yàn)證。習(xí)慣方法一)
須要注意的是exec并非1個(gè)函數(shù), 事實(shí)上它僅僅是一組函數(shù)的統(tǒng)稱, 它包含以下6個(gè)函數(shù):
#include unistd.h
int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[];
能夠見(jiàn)到這6個(gè)函數(shù)名字不同, 并且他們用于接受的參數(shù)也不同.
實(shí)際上他們的功能都是幾乎相同的, 由于要用于接受不同的參數(shù)所以要用不同的名字區(qū)分它們, 畢竟c語(yǔ)言沒(méi)有函數(shù)重載的功能嘛..
可是實(shí)際上它們的命名是有規(guī)律的:
exec[l or v][p][e]
exec函數(shù)里的參數(shù)能夠分成3個(gè)部分, 運(yùn)行文件部分, 命令參數(shù)部分, 環(huán)境變量部分.
比如我要運(yùn)行1個(gè)命令 ls -l /home/gateman
運(yùn)行文件部分就是 "/usr/bin/ls"
命令參賽部分就是 "ls","-l","/home/gateman",NULL 見(jiàn)到是以ls開(kāi)頭 每1個(gè)空格都必須分開(kāi)成2個(gè)部分, 并且以NULL結(jié)尾的啊.
環(huán)境變量部分, 這是1個(gè)數(shù)組,最后的元素必須是NULL 比如 char * env[] = {"PATH=/home/gateman", "USER=lei", "STATUS=testing", NULL};
好了說(shuō)下命名規(guī)則:
e興許, 參數(shù)必須帶環(huán)境變量部分, 環(huán)境變零部分參數(shù)會(huì)成為運(yùn)行exec函數(shù)期間的環(huán)境變量, 比較少用
l 興許, 命令參數(shù)部分必須以"," 相隔, 最后1個(gè)命令參數(shù)必須是NULL
v 興許, 命令參數(shù)部分必須是1個(gè)以NULL結(jié)尾的字符串指針數(shù)組的頭部指針. 比如char * pstr就是1個(gè)字符串的指針, char * pstr[] 就是數(shù)組了, 分別指向各個(gè)字符串.
關(guān)于Linux命令的介紹,看看《linux就該這么學(xué)》,具體關(guān)于這一章地址3w(dot)linuxprobe/chapter-02(dot)html
p興許, 運(yùn)行文件部分能夠不帶路徑, exec函數(shù)會(huì)在$PATH中找
還有1個(gè)注意的是, exec函數(shù)會(huì)代替運(yùn)行它的進(jìn)程, 也就是說(shuō), 一旦exec函數(shù)運(yùn)行成功, 它就不會(huì)返回了, 進(jìn)程結(jié)束. 可是假設(shè)exec函數(shù)運(yùn)行失敗, 它會(huì)返回失敗的信息, 并且進(jìn)程繼續(xù)運(yùn)行后面的代碼!
通常exec會(huì)放在fork() 函數(shù)的子進(jìn)程部分, 來(lái)替代子進(jìn)程運(yùn)行啦, 運(yùn)行成功后子程序就會(huì)消失, 可是運(yùn)行失敗的話, 必須用exit()函數(shù)來(lái)讓子進(jìn)程退出!
system(執(zhí)行shell 命令)
相關(guān)函數(shù) fork,execve,waitpid,popen
表頭文件 #includestdlib.h
定義函數(shù) int system(const char * string);
函數(shù)說(shuō)明 system()會(huì)調(diào)用fork()產(chǎn)生子進(jìn)程,由子進(jìn)程來(lái)調(diào)用/bin/sh-c string來(lái)執(zhí)行參數(shù)string字符串所代表的命令,此命令執(zhí)行完后隨即返回原調(diào)用的進(jìn)程。在調(diào)用system()期間SIGCHLD 信號(hào)會(huì)被暫時(shí)擱置,SIGINT和SIGQUIT 信號(hào)則會(huì)被忽略。
返回值 如果system()在調(diào)用/bin/sh時(shí)失敗則返回127,其他失敗原因返回-1。若參數(shù)string為空指針(NULL),則返回非零值。如果system()調(diào)用成功則最后會(huì)返回執(zhí)行shell命令后的返回值,但是此返回值也有可能為system()調(diào)用/bin/sh失敗所返回的127,因此最好能再檢查errno 來(lái)確認(rèn)執(zhí)行成功。
附加說(shuō)明 在編寫(xiě)具有SUID/SGID權(quán)限的程序時(shí)請(qǐng)勿使用system(),system()會(huì)繼承環(huán)境變量,通過(guò)環(huán)境變量可能會(huì)造成系統(tǒng)安全的問(wèn)題。
范例 #includestdlib.h
main()
{
system(“l(fā)s -al /etc/passwd /etc/shadow”);
}
執(zhí)行 -rw-r--r-- 1 root root 705 Sep 3 13 :52 /etc/passwd
-r--------- 1 root root 572 Sep 2 15 :34 /etc/shadow
在c語(yǔ)言中調(diào)用shell命令的方法實(shí)現(xiàn)。
c程序調(diào)用shell腳本共有兩種方法
:system()、popen(),分別如下:
system()
不用自己去創(chuàng)建進(jìn)程,系統(tǒng)已經(jīng)封裝了這一步,直接加入自己的命令即可
popen()
也可以實(shí)現(xiàn)執(zhí)行的命令,比system
開(kāi)銷(xiāo)小
以下分別說(shuō)明:
1)system(shell命令或shell腳本路徑);
system()
會(huì)調(diào)用fork()產(chǎn)生
子歷程,由子歷程來(lái)調(diào)用/bin/sh-c
string來(lái)履行
參數(shù)string字符串所代表的命令,此命令履行
完后隨即返回原調(diào)用的歷程。在調(diào)用system()期間sigchld
信號(hào)會(huì)被暫時(shí)擱置,sigint和sigquit
信號(hào)則會(huì)被漠視
。
返
回值:如果system()在調(diào)用/bin/sh時(shí)失敗則返回127,其他失敗原因返回-1。若參數(shù)string為空指針(null),則返回非零值。
如果
system()調(diào)用成功
則最后會(huì)返回履行
shell命令后的返回值,但是此返回值也有可能為system()調(diào)用/bin/sh失敗所返回的127,因
此最好能再反省
errno
來(lái)確認(rèn)履行
成功
。
system命令以其簡(jiǎn)略
高效的作用得到很很廣泛
的利用
,下面是一個(gè)例子
例:在/tmp/testdir/目錄下有shell腳本tsh.sh,內(nèi)容為
#!/bin/sh
wget
$1
echo
"done!"
2)popen(char
*command,char
*type)
popen()
會(huì)調(diào)用fork()產(chǎn)生
子歷程,然后從子歷程中調(diào)用/bin/sh
-c來(lái)履行
參數(shù)command的指令。參數(shù)type可應(yīng)用
“r”代表讀取,“w”代表寫(xiě)入。遵循此type值,popen()會(huì)建立
管道連到子歷程的標(biāo)準(zhǔn)
輸出設(shè)備
或標(biāo)準(zhǔn)
輸入設(shè)備
,然后返回一個(gè)文件指針。隨后歷程便可利用
此文件指針來(lái)讀取子歷程的輸出設(shè)備
或是寫(xiě)入到子歷程的標(biāo)準(zhǔn)
輸入設(shè)備
中。此外,所有應(yīng)用
文
件指針(file*)操作的函數(shù)也都可以應(yīng)用
,除了fclose()以外。
返回值:若成功
則返回文件指針,否則返回null,差錯(cuò)
原因存于errno中。注意:在編寫(xiě)具suid/sgid權(quán)限的程序時(shí)請(qǐng)盡量避免應(yīng)用
popen(),popen()會(huì)繼承環(huán)境變量,通過(guò)環(huán)境變量可能會(huì)造成系統(tǒng)安全的問(wèn)題。
例:c程序popentest.c內(nèi)容如下:
#include
main
{
file
*
fp;
charbuffer[80];
fp=popen(“~/myprogram/test.sh”,”r”);
fgets(buffer,sizeof(buffer),fp);
printf(“%s”,buffer);
pclose(fp);
}
Linux C編程中,調(diào)用另一個(gè)可執(zhí)行文件或調(diào)用命令用system函數(shù)最簡(jiǎn)單了,這個(gè)函數(shù)原理是在你編寫(xiě)的那個(gè)程序的內(nèi)部啟動(dòng)另一個(gè)程序或命令,從而創(chuàng)建一個(gè)新進(jìn)程,并等待這個(gè)進(jìn)程執(zhí)行完畢退出。如果正常執(zhí)行,system函數(shù)將返回被執(zhí)行程序或命令的退出碼;如果無(wú)法運(yùn)行這個(gè)程序或命令,將返回錯(cuò)誤代碼127;如果是其他錯(cuò)誤,返回-1。這個(gè)函數(shù)的原型是:
#include stdlib.h
int system(const char *string);
參數(shù)string是將要執(zhí)行的程序文件名或路徑,如果是啟動(dòng)一個(gè)命令就是一個(gè)命令字符串。
還有一種執(zhí)行外部程序的方法是exec系列函數(shù),一般是在fork的子進(jìn)程里面調(diào)用exec系列函數(shù),那主進(jìn)程里直接調(diào)用exec系列不行嗎,為什么要fork再在子進(jìn)程里調(diào)用呢?因?yàn)閑xec系列的函數(shù)(包括execl函數(shù))是將當(dāng)前進(jìn)程替換成新進(jìn)程,這里的當(dāng)前進(jìn)程就是你編寫(xiě)的程序,也就是說(shuō)新進(jìn)程啟動(dòng)后調(diào)用exec函數(shù)的進(jìn)程就不存在了,所以exec系列函數(shù)調(diào)用之后的代碼就不會(huì)再執(zhí)行了。如果你不放在fork子進(jìn)程里面,那你編寫(xiě)的程序的主進(jìn)程在執(zhí)行execl函數(shù)后就完全不存在了,所以exec系列函數(shù)的使用都是先f(wàn)ork然后在子進(jìn)程里面調(diào)用。因?yàn)閑xec系列函數(shù)都要使用fork調(diào)用,所以我一般是用system函數(shù)。