需求描述
編寫程序,完成在主機上實現對備機上目錄及文件的操作。例如,主機為A,備機為B,要求編寫的程序運行在A機上,該程序實現在B機上創建文件目錄及拷貝文件的操作。
需求分析
我們先不考慮用程序實現需求,如果是讓我們用手工實現需求中描述的操作,我們會怎麼做呢?大家也許都會想到使用telnet的方式。也就是說,在A機上使用telnet遠程到B機上去,然後在B機上執行創建目錄和拷貝文件的操作。
我們也可以在程序中使用telnet來完成上述需求。
程序編寫
我們可以使用兩種方式來執行telnet命令,一種是直接使用系統提供的system函數,另一種是使用管道的方式。以下是這兩種方式編寫出來的程序:
1.使用system函數
/**********************************************************************
* 版權所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名稱:System.c
* 文件標識:無
* 內容摘要:測試system的用法
* 其它說明:利用system實現遠程操作
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20151225
*
**********************************************************************/
#include
#include
// 重定義數據類型
typedef unsigned char UINT8;
typedef signed int INT32;
// 函數聲明
void DealRemoteFile(void);
/**********************************************************************
* 功能描述:主函數
* 輸入參數:無
* 輸出參數:無
* 返 回 值:無
* 其它說明:無
* 修改日期 版本號 修改人 修改內容
* ---------------------------------------------------------------
* 20151225 V1.0 Zhou Zhaoxiong 創建
***********************************************************************/
INT32 main()
{
DealRemoteFile();
return 0;
}
/**********************************************************************
* 功能描述:處理遠端的文件
* 輸入參數:無
* 輸出參數:無
* 返 回 值:無
* 其它說明:無
* 修改日期 版本號 修改人 修改內容
* ---------------------------------------------------------------
* 20151225 V1.0 Zhou Zhaoxiong 創建
***********************************************************************/
void DealRemoteFile(void)
{
UINT8 szCmdBuf[1024] = {0};
UINT8 szResultBuf[1024] = {0};
snprintf(szCmdBuf, sizeof(szCmdBuf)-1, "(sleep 0.5; echo zhou; sleep 1; echo zhou; sleep 5; echo \"cd /home/zhou/zhouzx/Test;mkdir -p TestFile;cp TestFile.txt ./TestFile;\"; sleep 2) | telnet 10.10.10.10");
printf("DealRemoteFile: Cmd is %s\n", szCmdBuf);
system(szCmdBuf);
}
2.使用管道的方式
/**********************************************************************
* 版權所有 (C)2015, Zhou Zhaoxiong。
*
* 文件名稱:PipeOpenAndClose.c
* 文件標識:無
* 內容摘要:測試popen和pclose的用法
* 其它說明:利用popen和pclose處理遠端的文件
* 當前版本:V1.0
* 作 者:Zhou Zhaoxiong
* 完成日期:20151225
*
**********************************************************************/
#include
#include
// 重定義數據類型
typedef unsigned char UINT8;
typedef signed int INT32;
// 函數聲明
void DealRemoteFile(void);
/**********************************************************************
* 功能描述:主函數
* 輸入參數:無
* 輸出參數:無
* 返 回 值:無
* 其它說明:無
* 修改日期 版本號 修改人 修改內容
* ---------------------------------------------------------------
* 20151225 V1.0 Zhou Zhaoxiong 創建
***********************************************************************/
INT32 main()
{
DealRemoteFile();
return 0;
}
/**********************************************************************
* 功能描述:處理遠端的文件
* 輸入參數:無
* 輸出參數:無
* 返 回 值:無
* 其它說明:無
* 修改日期 版本號 修改人 修改內容
* ---------------------------------------------------------------
* 20151225 V1.0 Zhou Zhaoxiong 創建
***********************************************************************/
void DealRemoteFile(void)
{
UINT8 szCmdBuf[1024] = {0};
UINT8 szResultBuf[1024] = {0};
FILE *fpPipe = NULL;
snprintf(szCmdBuf, sizeof(szCmdBuf)-1, "(sleep 0.5; echo zhou; sleep 1; echo zhou; sleep 5; echo \"cd /home/zhou/zhouzx/Test;mkdir -p TestFile;cp TestFile.txt ./TestFile;\"; sleep 2) | telnet 10.10.10.10");
printf("DealRemoteFile: Cmd is %s\n", szCmdBuf);
fpPipe = popen(szCmdBuf, "r");
if (NULL == fpPipe)
{
printf("DealRemoteFile: fpPipe is NULL!\n");
return;
}
while (fgets(szResultBuf, sizeof(szResultBuf), fpPipe) != NULL)
{
if ('\n' == szResultBuf[strlen(szResultBuf)-1]) // 將換行符去掉
{
szResultBuf[strlen(szResultBuf)-1] = '\0';
}
printf("DealRemoteFile: ResultBuf is %s\n", szResultBuf);
}
pclose(fpPipe); // 關閉管道
fpPipe = NULL;
}
程序編譯及運行
將System.c和PipeOpenAndClose.c文件上傳到A機上,分別使用“gcc -g -o System System.c”和“gcc -g -o PipeOpenAndClose PipeOpenAndClose.c”命令對這兩個文件進行編譯,再分別運行“System”和“PipeOpenAndClose”命令,即可在B機上觀察到相關操作已執行成功(注意:要確保TestFile.txt文件存在於/home/zhou/zhouzx/Test目錄下)。
程序說明
1.以上兩個程序中的szCmdBuf中的命令是程序的核心,其模式是“shell命令 | telnet x.x.x.x”,其中“x.x.x.x”是B機的IP,shell命令中的“sleep”讓程序休眠,第一個echo後面的變量是用戶名,第二個echo後面的變量是密碼,第三個echo便執行具體的創建目錄和拷貝文件的操作。
2.popen和pclose配合來實現相關shell命令的執行。popen函數通過創建一個管道,調用fork產生一個子進程,這個進程必須由pclose函數來關閉。