c通过脚本实现一些操作
体会
当我们需要处理一些相对于c/c++比较麻烦的文件操作,可以通过调用shell脚本来实现相关c函数
(1) 函数原型:FILE * popen ( const char * command , const char * type )
int pclose ( FILE * stream );
(2) 需要头文件: #include <stdio.h>
(3) 函数说明
popen() 函数通过创建一个管道,调用 fork 产生一个子进程,
执行一个 shell 以运行命令来开启一个进程。
这个进程由 pclose() 函数关闭。
pclose() 函数关闭标准 I/O 流,等待命令执行结束,然后返回 shell 的终止状态。
如果 shell 不能被执行,则 pclose() 返回的终止状态与 shell 已执行 exit 一样。
(4) type 参数只能是读或者写中的一种,得到的返回值(标准 I/O 流)也具有和 type 相应的只读或只写
类型。如果 type 是 "r" 则文件指针连接到 command 的标准输出;如果 type 是 "w" 则文件指针连接到
command 的标准输入。
(5) command 参数是一个指向以 NULL 结束的 shell 命令字符串的指针。这行命令将被传到 bin/sh 并
使用-c 标志,shell 将执行这个命令。
(6) popen 的返回值是个标准 I/O 流,必须由 pclose 来终止。
前面提到这个流是单向的。所以向这个流写内容相当于写入该命令的标准输入;
命令的标准输出和调用 popen 的进程相同。
与之相反的,从流中读数据相当于读取命令的标准输出;
命令的标准输入和调用 popen 的进程相同。
代码实现
c/c++调用shell脚本实现这样一个功能:某个文件夹拥有一定数量的test_del开头的文件,优先级如下
第一,保证文件数大于10个
第二,删掉超过一周的文件
#c++文件, exec_text.cpp
#include <stdio.h>
#include <string.h>
#include <string>
#include <errno.h>
#define DPRINT printf //调试输出
#define EPRINT printf //错误输出
#define CMD_OUTPUT_LEN (1024)
/*
* 这个函数实现调用shell脚本, 并接收脚本输出的信息
* 参数1: 调用脚本的路径
* 参数2: 脚本输出的信息, 可以通过这个信息来判断调用脚本是否成功
* 惨呼3: 返回值int, 0表示成功, 其它表示失败
*/
int execCmd(const std::string& sCmd, std::string& sRes)
{
//参数合法性检查
if(sCmd.empty())
{
EPRINT("execCmd sCmd is empty \n");
return -1;
}
FILE* pFile = popen(sCmd.c_str(), "r");
if (!pFile)
{
EPRINT("exexCmd popen err(%d)", errno);
return -1;
}
char buffer[CMD_OUTPUT_LEN] = {0};
while(!feof(pFile))
{
//fget会自动加\0, 最多读sizeof(buffer)-1个字节
if (fgets(buffer, sizeof(buffer), pFile))
{
sRes = sRes + buffer;
}
}
pclose(pFile);
return 0;
}
#define SCRIPT_PATH "./script_text.sh"
#define SCRIPT_SUCCESS "success"
int main()
{
int nCode = -1;
std::string sRec;
nCode = execCmd(SCRIPT_PATH, sRec);
//这里执行脚本成功会输出success
if(0 != sRec.compare("success"))
{
EPRINT("call script(%s) failure, sRec=%s \n", SCRIPT_PATH, sRec.c_str());
}
else
{
DPRINT("call script(%s) success, sRec=%s \n", SCRIPT_PATH, sRec.c_str());
}
return 0;
}
#shell脚本文件, script_text.sh
#!/bin/sh
#说明:执行脚本成功,输出success
#日志文件, 一般都会有日志文件, 保存出错信息
log="/var/log/test_error.log"
date > $log
#更新操作保存最多文件数量
max=3
#操作目录
opr_dir="./"
#全局文件配置名字
file_name="test_del"
#当前时间和时间戳
current_time=`date "+%Y-%m-%d %H:%M:%S"`
current_ts=`date -d "$current_time" +%s`
#文件保存最长时间秒数
save_time=$(( 60 * 60 * 24 *7 ))
#操作函数,保留符合条件的配置文件,最少保留10个,超过10个的通过时间判断,超过最长时间则删除
update_test()
{
#to do
local num=0
for file in `ls -t | grep -e "^$file_name"`
do
if [ ! -f $file ]; then
continue
fi
((num++))
if [ $num -le $max ]; then
continue
fi
#获取文件创建时间,包含毫秒数
create_file_time_m=`stat $file|grep Modify|awk '{print $2" "$3}'`
#获取文件创建时间,去掉毫秒数
create_file_time=${create_file_time_m%%.*}
#获取文件创建时间戳
create_file_ts=`date -d "$create_file_time" +%s`
#获取文件创建时间和当前时间的时间差
time_diff=$(( $current_ts - $create_file_ts ))
if [ $save_time -lt $time_diff ]; then
`rm -rf $file`
fi
done
return 0
}
#程序开始的地方
start()
{
#opr directory
cd $opr_dir
update_test
echo -n "success"
return 0
}
#main start
start
#main end
exit 0