接管子程式的標準輸入輸出
有這樣一種需求,希望讓程式呼叫fdisk、mysql、sqlplus這種可以互動的命令,執行一些操作後分析輸出結果,然後再根據這些結果決定如何執行下面的命令。這樣就可以代替人工的判斷和鍵盤輸入。
這種需求可以用管道來接管子程式的標準輸入輸出,甚至標準錯誤來完成。
具體方法是
1 用pipe(int)建立兩個管道,分別用於連線程式和要呼叫的命令的標準輸入和標準輸出。暫時叫他們“輸入管道”和“輸出管道”。
2 fork()一下,在父程式和子程式分別關閉兩個管道的一端。
輸入管道對主程式相當於鍵盤,因此關閉管道的讀端,而子程式關閉寫端。
輸出管道對主程式相當於顯示器,因此關閉管道的寫端,而子程式關閉讀端。
3 在子程式用dup2()。
將子程式的標準輸入複製為輸入管道的讀端。
將子程式的標準輸出複製為輸出管道的寫端。
4 在子程式呼叫execl來執行需要的命令。
5 在父程式寫入輸入管道的寫端,然後讀取輸出管道的讀端。
-
#include <stdio.h>
-
#include <unistd.h>
-
#include <errno.h>
-
#include <stdlib.h>
-
#include <fcntl.h>
-
#include <string.h>
-
-
int lsexec2(int* in, int* out, char* path, char* cmd, char* arg)
-
{
-
int fd_i[2];
-
int fd_o[2];
-
char buf[BUFSIZ];
-
int len = 0;
-
-
// 建立兩個管道,fd_i用於接管子程式的標準輸入,fd_o用於標準輸出
-
pipe(fd_i);
-
pipe(fd_o);
-
-
pid_t p = fork();
-
if(p < 0) return -1;
-
if(p > 0)
-
{ //parent
-
close(fd_i[0]); // 關閉輸入管道的讀端
-
*in = fd_i[1]; // 將寫端暴露給呼叫者,這樣呼叫者可以給子程式傳送命令
-
close(fd_o[1]); // 關閉輸出管道的寫端
-
*out = fd_o[0]; // 將讀端暴露給呼叫者,這樣呼叫者可以讀取子程式的輸出
-
return 0;
-
}
-
else
-
{ //child
-
close(fd_i[1]); // 關閉輸入管道的寫端
-
dup2(fd_i[0], STDIN_FILENO); // 將標準輸入複製到輸入管道的讀端,這樣就可以把父程式的輸入轉接到標準輸入
-
close(fd_o[0]); // 關閉輸出管道的讀端
-
dup2(fd_o[1], STDOUT_FILENO); // 將標準輸出複製到輸出管道的寫端,這樣父程式就可以透過讀端讀取標準輸出的內容
-
return execl(path, cmd, arg, (int*)0); // 執行需要的命令
-
}
-
}
-
-
int main(void)
-
{
-
int in, out;
-
char cmd[BUFSIZ];
-
memset(cmd, '\0', BUFSIZ);
-
-
if(lsexec2(&in, &out, "/sbin/fdisk", "fdisk", "/dev/sda") == -1)
-
{
-
printf("%s\n", strerror(errno));
-
exit(1);
-
}
-
strcpy(cmd, "p\nm\n");
-
write(in, cmd, strlen(cmd)); // 向in寫入指令,模擬人工鍵盤輸入
-
usleep(10000); // 由於只是demo,簡單等待10毫米,讓子程式輸出完整。正常應該是新開一個程式持續等待子程式輸出。
-
char buf[BUFSIZ];
-
int len = read(out, buf, BUFSIZ); // 讀取out的內容,讓程式看到命令的輸出內容
-
printf("%s", buf);
-
return 0;
- }
執行效果
[root@server2 c]# ./a
WARNING: DOS-compatible mode is deprecated. It's strongly recommended to
switch off the mode (command 'c') and change display units to
sectors (command 'u').
Command (m for help):
Disk /dev/sda: 34.4 GB, 34359738368 bytes
255 heads, 63 sectors/track, 4177 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000ac07a
Device Boot Start End Blocks Id System
/dev/sda1 1 1045 8388608 82 Linux swap / Solaris
/dev/sda2 * 1045 4178 25164800 83 Linux
Command (m for help): Command action
a toggle a bootable flag
b edit bsd disklabel
c toggle the dos compatibility flag
d delete a partition
l list known partition types
m print this menu
n add a new partition
o create a new empty DOS partition table
p print the partition table
q quit without saving changes
s create a new empty Sun disklabel
t change a partition's system id
u change display/entry units
v verify the partition table
w write table to disk and exit
x extra functionality (experts only)
Command (m for help): [root@server2 c]#
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26239116/viewspace-2120901/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java —— 標準輸入輸出Java
- 重定向子程式標準輸入輸出
- python 標準輸入輸出Python
- Linux的標準輸入、標準輸出和標準錯誤Linux
- 【C++】標準檔案的輸入輸出!!!C++
- C++名稱空間、標準輸入輸出、引用C++
- converter設計模式擴充套件,多種輸入輸出與標準輸入輸出的轉化方案設計模式套件
- python呼叫外部子程式,通過管道實現非同步標準輸入和輸出的Python非同步
- Linux循序漸進(20):標準輸入/輸出和重定向(轉)Linux
- C語言的本質(24)——C標準庫之輸入與輸出(下)C語言
- 指令碼日誌的標準輸出指令碼
- 用指標編寫程式將輸入的字串倒序輸出指標字串
- 使用shell tee 命令顯示及儲存標準輸出及標準錯誤輸出
- C++中的檔案輸入/輸出(4):檢測輸入/輸出的狀態標誌 (轉)C++
- 【Java基礎知識】IO流--標準輸入輸出流、列印流PrintStreamJava
- 015 Linux 標準輸入輸出、重定向、管道和後臺啟動程式命令Linux
- Shell標準輸出、標準錯誤 >/dev/null 2>&1devNull
- 輸入輸出
- c++builder中怎樣進行標準輸入、出C++UI
- java截獲標準輸出(2)(轉)Java
- java截獲標準輸出(1)(轉)Java
- Pr入門教程標準模板的使用方法及完成輸出
- shell程式設計(三)輸入輸出程式設計
- 輸入輸出流
- 資料的輸入輸出
- Python的輸入輸出Python
- 【C語言】編寫一個程式從標準輸入讀取字元,並把他們寫到標準輸出。除了大寫字母轉換成小寫字母之外,其他的原樣輸出。C語言字元
- 第13周-閱讀專案1-標準輸入輸出物件及文字檔案物件
- 標準化/結構化 JSON 輸出JSON
- linux中的輸入與輸出管理(重定向輸入,輸出,管道符)Linux
- C++中的檔案輸入/輸出(3):掌握輸入/輸出流 (轉)C++
- Go基礎系列:讀取標準輸入Go
- 怎麼提高go讀取標準輸入的速度Go
- 標準輸入輸出服從規則和fileno,freopen,fdopen,ftell,fseek,rewind幾個函式函式
- 【C++】輸入輸出C++
- Java 輸入輸出流Java
- 輸入輸出系統
- JAVA輸入輸出流Java