- A+
前几天用PHP做好了一个自动同步的功能
最近使用时发现,如果自动同步的文件过大时,脚本执行时间会很长,time_limit = 0 丫没有卵用。导致apache服务器直接报错。
没办法现在考虑用php的爸爸来做这个功能了。
2019-12-03先做准备
https://help.aliyun.com/document_detail/32134.html?spm=5176.8466049.0.0.204b1450IYQ0Lm
根据这篇文章先把功能安装好,再开始做自动同步吧。
过程中核心命令
gcc -Wall -O -g -I /usr/local/include/oss_c_sdk -I /usr/include/apr-1 -c main.c -o main.o
gcc main.o -o main -lpthread -L/usr/local/lib -loss_c_sdk -lcurl -lmxml -L/usr/local/apr/lib -lapr-1 -laprutil-1
安装流程
1.安装 CMake和第三方库 (centos)
安装CMake
yum install cmake
安装第三方库
sudo yum install curl-devel apr-devel apr-util-devel mxml mxml-devel
这里等下会出现错误(因为mxml版本过高)
2.安装SDK
如果 curl、apr、apr-util 和 mxml 第三方库安装在默认路径下时,安装方式如下:
cmake .
make
make install
如果 curl、apr、apr-util 和 mxml 第三方库不是安装在默认路径下,安装 SDK时,需要指定其安装路径,安装方式如下:
cmake -f CMakeLists.txt
// 编译类型为Release。常用的编译类型为:Debug、Release、RelWithDebInfo和MinSizeRel,默认使用Debug。
-DCMAKE_BUILD_TYPE=Release
// 自定义安装目录。
-DCMAKE_INSTALL_PREFIX=/usr/local/
// 指定curl、apr、apr-util和xml第三方库头文件和库文件的所在目录。
-DCURL_INCLUDE_DIR=/usr/include/curl
-DCURL_LIBRARY=/usr/lib64/libcurl.so
-DAPR_INCLUDE_DIR=/usr/include/apr-1
-DAPR_LIBRARY=/usr/lib64/libapr-1.so
-DAPR_UTIL_INCLUDE_DIR=/usr/include/apr-1
-DAPR_UTIL_LIBRARY=/usr/lib64/libaprutil-1.so
-DMINIXML_INCLUDE_DIR=/usr/include
-DMINIXML_LIBRARY=/usr/lib64/libmxml.so
// 编译时,如果报`Could not find apr-config/apr-1-config`,原因是在默认路径里面找不到apr-1-config文件,请添加该选项。
-DAPR_CONFIG_BIN=/path/to/bin/apr-1-config
// 如果报:Could not find apu-config/apu-1-config,请添加该选项。
-DAPU_CONFIG_BIN=/path/to/bin/apu-1-config
其他错误请看文章尾部
3.使用SDK
C/C++程序,从源代码到执行,需要经过编译、链接、运行三个步骤。OSS C SDK应用亦是如此,下面分别对这三个步骤详细说明。
编译
编译,将源代码编译成目标文件(*.obj),主要过程是预编译、语法检查、生成目标文件。预编译会对源代码中引用的头文件进行查找。语法检查即符号检查,对于函数,检查引用和原型是否匹配。编译时,有头文件即可编译通过,不需要查找库,所以也不需要指定库的位置。
GCC/G++搜索头文件的顺序如下:
编译源文件时指定的搜索路径,GCC/G++通过-I
指定;
环境变量C_INCLUDE_PATH/CPLUS_INCLUDE_PATH
指定的搜索路径
( 默认为空。 )
GCC/G++默认的头文件搜索路径;
包括`/usr/include`,`/usr/local/include` 和 `GCC/G++的头文件目录`。GCC/G\++的头文件目录,不同Linux系统下稍有不同。
GCC的头文件目录,通过如下命令查看
`gcc -print-prog-name=cc1` -v
G\+\+的头文件目录,通过如下命令查看
`g++ -print-prog-name=cc1` -v
OSS C SDK应用依赖的库,不指定安装目录,使用默认安装目录时,有以下两种安装方式:
- 使用apt-get、yum、rpm命令安装;
- 使用源代码安装且不指定安装路径。
使用默认安装目录时,对于不同的Linux,依赖库的头文件位置稍有不同。头文件路径是否在GCC/G++搜索路径中,如下表:
Linux | curl | apr/aprutil | mxml | sdk |
---|---|---|---|---|
Aliyun/Centos | 在 | 不在,默认安装路径 /usr/include/apr-1 | 在 | 不在,默认安装路径 /usr/local/include/oss_c_sdk |
Debian | 在 | 不在,默认安装路径 /usr/include/apr-1.0 | 在 | 不在,默认安装路径 /usr/local/include/oss_c_sdk |
Redhat | 在 | 不在,默认安装路径 /usr/local/apr/include/apr-1 | 在 | 不在,默认安装路径 /usr/local/include/oss_c_sdk |
SuSE | 在 | 不在,默认安装路径 /usr/include/apr-1 | 在 | 不在,默认安装路径 /usr/local/include/oss_c_sdk |
Ubuntu | 在 | 在 | 在 | 不在,默认安装路径 /usr/local/include/oss_c_sdk |
编译示例程序main.c,Ubuntu系统执行以下命令:
gcc -Wall -O -g -I. -I /usr/local/include/oss_c_sdk -c main.c -o main.o
Aliyun/Centos系统执行以下命令:
gcc -Wall -O -g -I /usr/local/include/oss_c_sdk -I /usr/include/apr-1 -c main.c -o main.o
注意:
- 编译、链接、运行小节中,第三方库和OSS C SDK库都采用不指定路径的方式安装,即使用默认安装目录;指定依赖库的安装路径,其编译、链接、运行的使用方法在 指定安装路径 小节中介绍。
链接
链接,把目标程序和依赖库链接成一个整体,生成可执行文件。对于静态库,链接时把整个库写入可执行文件;运行时不需要再指定,但是可执行程序会变大。动态库链接时,可执行程序中只记录库的信息(位置、大小、版本等)和调用的函数信息(名称、偏移等)。动态库是程序共享的,可执行程序也不会膨胀。
对于使用OSS C SDK的应用,推荐使用动态库。本文中和官网提供的示例,都使用动态库。GCC/G++对动态库的搜索路径如下:
- 链接目标文件时指定的搜索路径,GCC/G++通过
-L
指定; - 环境变量
LD_LIBRARY_PATH
指定的搜索路径;
默认是空的。 - 配置文件
/etc/ld.so.conf
中指定的搜索路径;/etc/ld.so.conf
内容是ld.so.conf.d/*.conf
,即包括/etc/ld.so.conf.d/*.conf
配置的路径。
可以使用命令ldconfig -v
查看所有可以使用的动态库;使用如下命令查看动态库的搜索路径
ldconfig -v | grep -v ^$'\t'
- 系统默认的动态库搜索路径/lib、/usr/lib或/lib64、/usr/lib64;
- GCC/G++的默认的搜索路径。
可以通过命令gcc -print-search-dirs
查看。
上面五部分组成了依赖库的搜索路径。如果依赖库不在上述路径中,链接时需要使用-L
指定。
对于不同的Linux系统,OSS C SDK应用依赖的库位置稍有不同,它们的路径是否在GCC/G++搜索路径中,如下表:
Linux | curl | apr/aprutil | mxml | sdk |
---|---|---|---|---|
Aliyun/Centos | 在 | 不在,默认安装路径/usr/local/apr/lib | 在 | 不在,默认安装路径/usr/local/lib |
Debian | 在 | 不在,默认安装路径/usr/local/apr/lib | 在 | 不在,默认安装路径/usr/local/lib |
Redhat | 在 | 不在,默认安装路径/usr/local/apr/lib | 在 | 不在,默认安装路径/usr/local/lib |
SuSE | 在 | 在 | 在 | 在 |
Ubuntu | 在 | 在 | 在 | 在 |
链接示例main.o
与依赖库 ,Ubuntu/SuSE执行以下命令:
gcc main.o -o main -lpthread -loss_c_sdk -lcurl -lmxml -lapr-1 -laprutil-1
Aliyun/Centos/Debian/Redhat执行以下命令:
gcc main.o -o main -lpthread -L/usr/local/lib -loss_c_sdk -lcurl -lmxml -L/usr/local/apr/lib -lapr-1 -laprutil-1
运行
运行,将可执行程序加载到内存并执行。执行时需要引用动态库。
运行时动态库搜索顺序如下:
- 环境变量
LD_LIBRARY_PATH
指定的搜索路径;
默认为空。 - 配置文件/etc/ld.so.conf中指定的搜索路径;
/etc/ld.so.conf
内容是ld.so.conf.d/*.conf
,即包括/etc/ld.so.conf.d/*.conf
配置的路径。
可以使用命令ldconfig -v
查看所有可以使用的动态库;使用如下命令查看动态库的搜索路径:
ldconfig -v | grep -v ^$'\t'
- 系统默认的动态库搜索路径/lib、/usr/lib或/lib64、/usr/lib64。
如果链接时用-L
指定了动态库的路径,且不在上述三类路径中,运行时需要使用LD_LIBRARY_PATH
指定。如果运行
示例main
时,报如下错误:
./main: error while loading shared libraries: liboss_c_sdk.so.3.0.0: cannot open shared object file: No such file or directory
说明运行时找不到动态库liboss_c_sdk。请使用LD_LIBRARY_PATH
指定,执行如下命令:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
提示:
- 示例代码中的OSS_ENDPOINT、ACCESS_KEY_ID、ACCESS_KEY_SECRET、BUCKET_NAME请更换成有效值。
指定安装路径
编译OSS C SDK应用的设备上,如果没有ROOT权限,安装第三方库和OSS C SDK时,需要指定安装目录。除非必要,不推荐安装依赖库时指定安装路径。
比如安装第三方库和OSS C SDK时,指定安装目录都是/home/your/oss/csdk,编译示例程序使用如下命令:
gcc -Wall -O -g -I. -I /home/your/oss/csdk/include -I /home/your/oss/csdk/include/oss_c_sdk -I /home/your/oss/csdk/include/curl -I /home/your/oss/csdk/include/apr-1 -c main.c -o main.o
链接示例程序使用如下命令:
gcc main.o -o main -lpthread -L/home/your/oss/csdk/lib -loss_c_sdk -lcurl -lmxml -lapr-1 -laprutil-1
执行示例程序使用如下命令:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/your/oss/csdk/lib
./main
三个命令
Linux使用依赖库,下面三个命令可能会用到,详细功能和参数请使用man cmd
查看。
ldconfig
动态库管理命令
ldd
显示可执行模块的依赖库
nm
显示可执行模块中符号的信息
目前根据上边的流程 oss_sdk已经安装成功
开始 编写shell
记录节点12月5号
oss_service.sh
#!/bin/bash
EXEC_PATH=/usr/local/oss
EXEC=oss
DAEMON=$EXEC_PATH/$EXEC
PID_FILE=/var/run/$EXEC.pid
test -f /etc/rc.d/init.d/functions && . /etc/rc.d/init.d/functions
if [ ! -f $DAEMON ] ; then
echo "ERROR: $DAEMON not found"
exit 1
else
chmod +x $DAEMON
fi
add(){
echo "oss add"
$DAEMON --add
echo -e " [ \033[36mOK\033[0m ]"
}
del(){
echo "oss del"
echo -e " [ \033[31mFailed\033[0m ]"
}
echo
case "$1" in
add)
add
;;
del)
del
;;
*)
echo "Usage: service $EXEC {add|del}"
exit 1
esac
echo
exit $?
oss.sh
#!/bin/sh
add(){
echo "i am oss_add function"
echo "第一个参数 $1"
echo "第二个参数 $2"
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
}
del(){
echo "i am oss_del function"
}
showhelp(){
echo "i am help"
}
while [ $1 ]; do
case $1 in
'-h' | '--help' | '?' )
showhelp
exit
;;
'--add' | '-add' )
add $2 $3
break;
;;
'--del' | '-del' )
del $2
break;
;;
*)
showhelp
exit
;;
esac
shift
done
ln -sf /usr/local/oss /bin/oss //类似加入 pathinfo
以上是笔记,以下是成功后的详细记录
整体思路
后台PHP 异步请求上传功能并传送一个回调地址,服务器端上传完成后再请求回调地址,后台php再改变MySQL is_oss(是否上传云端完成)状态改为1。
步骤一 制作一个公共命令,类似能在windows里的cmd窗口里直接敲出的命令。(原理该命令在 系统或用户path里即可 各种系统原理一样)
1.创建一个目录
mkdir /usr/local/oss
一般默认linux安装成功的软件都在这个位置
2.创建执行命令文件
cd /usr/local/oss
vim oss
3.oss的代码是
#!/bin/sh
add(){
echo "i am oss_add function"
echo "第一个参数 $1"
echo "第二个参数 $2"
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
#### centos7.6+ 的会报错 加上这句 再执行就不会
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
/home/tool/oss/shell/oss $1
echo "上传完成执行回调"
curl -i $2
}
del(){
echo "i am oss_del function"
}
showhelp(){
echo "i am help"
}
while [ $1 ]; do
case $1 in
'-h' | '--help' | '?' )
showhelp
exit
;;
'--add' | '-add' )
add $2 $3
break;
;;
'--del' | '-del' )
del $2
break;
;;
*)
showhelp
exit
;;
esac
shift
done
当前的版本比较简陋
4.放进 /bin下 让全局都可以使用到
ln -sf /usr/local/oss/oss /bin/oss
5.测试

说明成功了。
步骤二 制作上传到云端的程序
我这里直接在 SDK里边修改了
思路:
1.传递一个文件夹的绝对路径
2.遍历所有文件,遍历过程中直接上传
3.上传上去的新文件名称根据配置文件来替换(如 /data/www/www.shikexu.com/video/2019/12/06/d3sse12 源文件 新文件 video/2019/12/06/d3sse12/xxx.jpg 等等)
4.上传失败时写入日志(单个文件)
源码开始:
文件一 (配置文件 site.conf)
mkdir /usr/local/oss/config
vim /usr/local/oss/config/site.conf
site.conf 内容
site_path = /data/www/www.shikexu.com/
文件二(主文件 oss.c)
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "aos_log.h"
#include "aos_util.h"
#include "aos_string.h"
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include "aos_status.h"
#include "oss_auth.h"
#include "oss_util.h"
#include "oss_api.h"
#define MAX_PATH_LEN (256)
#define CONFIG_FILE "/usr/local/oss/config/site.conf"
const char OSS_ENDPOINT[] = "######";
const char ACCESS_KEY_ID[] = "######";
const char ACCESS_KEY_SECRET[] = "######";
const char BUCKET_NAME[] = "######";
const char OBJECT_NAME[] = "c_test.jpg";
char *site_path;
char *api_url;
void init_sample_request_options(oss_request_options_t *options, int is_cname);
void put_object_from_buffer();
void put_object_from_file();
void get_object_to_buffer();
void get_object_to_file();
void delete_object();
/* 读取配置文件 start */
char* Get_Config(char *Config_name)
{
char readbuf[512] = {0};
char findbuf[100] = {0};
char *retbuf;
retbuf = (char *)malloc(100);
strcpy(findbuf,Config_name);
int line = 0;
FILE *fp = fopen(CONFIG_FILE,"r");
if(fp == NULL)
{
perror("fopen");
return NULL;
}
while(fgets(readbuf,sizeof(readbuf),fp)) //逐行循环读取文件,直到文件结束
{
line++;
if(!strncmp(readbuf,"#",1) || !strncmp(readbuf,"\n",1)) //忽略注释(#)和空行
continue;
if(strstr(readbuf,findbuf)) //查找配置文件名
{
char *p=strchr(readbuf,'='); //确定“=”位置
do
{
p += 1;
}
while(*p == ' ');
sprintf(retbuf,"%s",p);
fclose(fp);
return retbuf;
}
}
return NULL;
}
/* 读取配置文件 end */
/* 中文名称的文件 start */
/* 中文名称的文件 end */
/* 字符串的替换 start */
char *strrpc(char *str,char *oldstr,char *newstr){
char bstr[strlen(str)];//转换缓冲区
memset(bstr,0,sizeof(bstr));
int i;
for(i=0;i<strlen(str);i++){
if(!strncmp(str+i,oldstr,strlen(oldstr))){
strcat(bstr,newstr);
i += strlen(oldstr) - 1;
}else{
strncat(bstr,str+i,1);
}
}
strcpy(str,bstr);
return str;
}
/* 字符串的替换 end */
static void trave_dir(char* path){
DIR *d = NULL;
char s_file[100];//源文件
char t_file[100];//临时的
char *n_file;//新的文件名
char s_path[100];//配置文件要存放的字符串
struct dirent *dp = NULL; /* readdir函数的返回值就存放在这个结构体中 */
struct stat st;
char p[MAX_PATH_LEN] = {0};
if(stat(path,&st) < 0 || !S_ISDIR(st.st_mode)){
printf("invalid path: %s\n",path);
return;
}
if(!(d = opendir(path))){
printf("opendir[%s] error: %m\n",path);
return;
}
while((dp = readdir(d)) != NULL){
/* 把当前目录. 上级目录 ..及隐藏文件都去掉 避免死循环 */
if((!strncmp(dp->d_name,".",1)) || (!strncmp(dp->d_name,"..",2)))
continue;
snprintf(p ,sizeof(p) - 1,"%s/%s",path,dp->d_name);
stat(p,&st);
if(!S_ISDIR(st.st_mode)){
printf("%s%s\n",path,dp->d_name);
printf("我是文件的记录\n");
/* 是文件而不是目录时 开始上传 start */
// /www/wwwroot/www.shikexu.com/video/m3u8/2019/12/05/4a44ssea 下的所有文件上传到
// video/m3u8/2019/12/05/4a44ssea/feng.jpg 每个独立的文件都需要去掉前缀
// 整理出来要上传原始文件路径 和上传后的文件名称
sprintf(s_file,"%s",p);
printf("源文件是%s\n",s_file);
strcpy(t_file,s_file);
sprintf(s_path,"%s",site_path);
printf("站点的路径是:%s\n",s_path);
s_path[strlen(s_path)-1] = 0;
/* 打印出配置文件的原型 start */
//int i;
//for(i=0;i<strlen(s_path);i++){
// printf("%c\n",s_path[i]);
//}
/* 打印出配置文件的原型 end */
n_file = strrpc(t_file,s_path,"");//替换求出上传上去的新的文件名
printf("新文件是%s\n",n_file);
//printf("站点路径是%s\n",site_path);
//printf("替换后源文件是%s\n",s_file);
//printf("临时的路径是%s\n",t_file);
/* 开始上传 start */
put_object_from_file(s_file,n_file);
/* 开始上传 end */
/* 是文件而不是目录时 开始上传 end */
}else{
printf("我是目录的记录\n");
printf("%s/\n",dp->d_name);
trave_dir(p);
}
}
closedir(d);
return;
}
int main(int argc, char *argv[])
{
/* 获取配置 start */
site_path = Get_Config("site_path");
printf("站点路径是%s\n",site_path);
// free(site_path); 释放防止内存泄露
/* 获取配置 end */
apr_file_t *output = NULL;
aos_pool_t *pool = NULL;
apr_status_t ret;
// initialize http io system, call it olny once
if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
exit(1);
}
aos_pool_create(&pool, NULL);
// open log file
ret = apr_file_open(&output, "oss-c-sdk.log", APR_FOPEN_CREATE | APR_FOPEN_WRITE | APR_FOPEN_APPEND, APR_OS_DEFAULT, pool);
if (APR_SUCCESS != ret) {
exit(1);
}
// set log file
aos_log_set_output(output);
// set log level
aos_log_set_level(AOS_LOG_INFO);
aos_info_log("start");
/* 开始根据目录来遍历文件 通过循环的方式来上传文件 start */
char *path = NULL;
if(argc !=2){
printf("Usage: %s [dir]\n",argv[0]);
printf("use DEFAULT option: %s .\n",argv[0]);
printf("------------------------------\n");
path = "./";
}else{
path = argv[1];
}
trave_dir(path);
/* 开始根据目录来遍历文件 通过循环的方式来上传文件 end */
// run samples
// put_object_from_buffer();
// char file_name = "我是中文.txt";
// put_object_from_file(file_name);
//get_object_to_buffer();
//get_object_to_file();
// delete_object();
// close log file
apr_file_close(output);
aos_pool_destroy(pool);
// deinitialize http io system, call it olny once
aos_http_io_deinitialize();
return 0;
}
void init_sample_request_options(oss_request_options_t *options, int is_cname)
{
options->config = oss_config_create(options->pool);
aos_str_set(&options->config->endpoint, OSS_ENDPOINT);
aos_str_set(&options->config->access_key_id, ACCESS_KEY_ID);
aos_str_set(&options->config->access_key_secret, ACCESS_KEY_SECRET);
options->config->is_cname = is_cname;
options->ctl = aos_http_controller_create(options->pool, 0);
}
void put_object_from_buffer()
{
aos_pool_t *p = NULL;
aos_string_t bucket;
aos_string_t object;
int is_cname = 0;
aos_table_t *headers = NULL;
aos_table_t *resp_headers = NULL;
oss_request_options_t *options = NULL;
aos_list_t buffer;
aos_buf_t *content = NULL;
char *str = "test oss c sdk";
aos_status_t *s = NULL;
aos_pool_create(&p, NULL);
options = oss_request_options_create(p);
init_sample_request_options(options, is_cname);
headers = aos_table_make(p, 1);
apr_table_set(headers, "x-oss-meta-author", "oss");
aos_str_set(&bucket, BUCKET_NAME);
aos_str_set(&object, OBJECT_NAME);
aos_list_init(&buffer);
content = aos_buf_pack(options->pool, str, strlen(str));
aos_list_add_tail(&content->node, &buffer);
s = oss_put_object_from_buffer(options, &bucket, &object,
&buffer, headers, &resp_headers);
if (aos_status_is_ok(s)) {
printf("put object from buffer succeeded\n");
} else {
printf("put object from buffer failed\n");
}
aos_pool_destroy(p);
}
void put_object_from_file(char *file_name,char *new_name)
{
// char file_name[100] = "我是中文.txt";
/* 转换中文的文件名 start */
/* 转换中文的文件名 end */
aos_pool_t *p = NULL;
aos_string_t bucket;
aos_string_t object;
int is_cname = 0;
aos_table_t *headers = NULL;
aos_table_t *resp_headers = NULL;
oss_request_options_t *options = NULL;
// char *filename = "1.txt";
aos_status_t *s = NULL;
aos_string_t file;
aos_pool_create(&p, NULL);
options = oss_request_options_create(p);
init_sample_request_options(options, is_cname);
headers = aos_table_make(options->pool, 1);
//apr_table_set(headers, OSS_CONTENT_TYPE, "image/jpeg");
aos_str_set(&bucket, BUCKET_NAME);
aos_str_set(&object, new_name);
aos_str_set(&file, file_name);
s = oss_put_object_from_file(options, &bucket, &object, &file,
headers, &resp_headers);
if (aos_status_is_ok(s)) {
printf("put object from file succeeded\n");
} else {
printf("put object from file failed, code:%d, error_code:%s, error_msg:%s, request_id:%s\n",
s->code, s->error_code, s->error_msg, s->req_id);
}
aos_pool_destroy(p);
}
void get_object_to_buffer()
{
aos_pool_t *p = NULL;
aos_string_t bucket;
aos_string_t object;
int is_cname = 0;
oss_request_options_t *options = NULL;
aos_table_t *headers = NULL;
aos_table_t *params = NULL;
aos_table_t *resp_headers = NULL;
aos_status_t *s = NULL;
aos_list_t buffer;
aos_buf_t *content = NULL;
char *buf = NULL;
int64_t len = 0;
int64_t size = 0;
int64_t pos = 0;
aos_pool_create(&p, NULL);
options = oss_request_options_create(p);
init_sample_request_options(options, is_cname);
aos_str_set(&bucket, BUCKET_NAME);
aos_str_set(&object, OBJECT_NAME);
aos_list_init(&buffer);
s = oss_get_object_to_buffer(options, &bucket, &object,
headers, params, &buffer, &resp_headers);
if (aos_status_is_ok(s)) {
printf("get object to buffer succeeded\n");
}
else {
printf("get object to buffer failed\n");
}
//get buffer len
aos_list_for_each_entry(aos_buf_t, content, &buffer, node) {
len += aos_buf_size(content);
}
buf = aos_pcalloc(p, (apr_size_t)(len + 1));
buf[len] = '\0';
//copy buffer content to memory
aos_list_for_each_entry(aos_buf_t, content, &buffer, node) {
size = aos_buf_size(content);
memcpy(buf + pos, content->pos, (size_t)size);
pos += size;
}
aos_pool_destroy(p);
}
void get_object_to_file()
{
aos_pool_t *p = NULL;
aos_string_t bucket;
char *download_filename = "SouthIsland_NewZealand_New.jpg";
aos_string_t object;
int is_cname = 0;
oss_request_options_t *options = NULL;
aos_table_t *headers = NULL;
aos_table_t *params = NULL;
aos_table_t *resp_headers = NULL;
aos_status_t *s = NULL;
aos_string_t file;
aos_pool_create(&p, NULL);
options = oss_request_options_create(p);
init_sample_request_options(options, is_cname);
aos_str_set(&bucket, BUCKET_NAME);
aos_str_set(&object, OBJECT_NAME);
headers = aos_table_make(p, 0);
aos_str_set(&file, download_filename);
s = oss_get_object_to_file(options, &bucket, &object, headers,
params, &file, &resp_headers);
if (aos_status_is_ok(s)) {
printf("get object to local file succeeded\n");
} else {
printf("get object to local file failed\n");
}
aos_pool_destroy(p);
}
void delete_object()
{
aos_pool_t *p = NULL;
aos_string_t bucket;
aos_string_t object;
int is_cname = 0;
oss_request_options_t *options = NULL;
aos_table_t *resp_headers = NULL;
aos_status_t *s = NULL;
aos_pool_create(&p, NULL);
options = oss_request_options_create(p);
init_sample_request_options(options, is_cname);
aos_str_set(&bucket, BUCKET_NAME);
aos_str_set(&object, OBJECT_NAME);
s = oss_delete_object(options, &bucket, &object, &resp_headers);
if (aos_status_is_ok(s)) {
printf("delete object succeed\n");
} else {
printf("delete object failed\n");
}
aos_pool_destroy(p);
}
其中 请将这四个替换成你自己的
OSS_ENDPOINT
ACCESS_KEY_ID
ACCESS_KEY_SECRET
BUCKET_NAME
替换后开始编译和运行测试
特别注意 ./oss /data/www/www.shikexu.com/video 这个后边的参数最后 不要带 /
看结果:

成功。
总结:
过程中遇到很多问题
问题1:(安装问题)安装OSS SDK时会出现 libmxml-dev 版本过高,然后具体会报什么错误我忘了。
出现原因 centos下 使用 yum自动安装导致的
sudo yum install curl-devel apr-devel apr-util-devel mxml mxml-devel
解决办法
用稍低的版本
rpm -qa | grep libxml //查看安装的包包
yum -y remove libxml* //删除刚才安装的 3.0
rpm -ql libxml2-2.9.1-6.el7_2.3.x86_64 //查看安装软件的路径
下载 这个 2.9版本的 然后
tar zxf mxml-2.9.tar.gz
./configure && make && sudo make install
cmake -DMINIXML_LIBRARY=/usr/local/lib/libmxml.a .
make
问题2 根据绝对路径获取 目录下的所有文件
解决办法
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#define MAX_PATH_LEN (256)
static void trave_dir(char* path){
DIR *d = NULL;
struct dirent *dp = NULL; /* readdir函数的返回值就存放在这个结构体中 */
struct stat st;
char p[MAX_PATH_LEN] = {0};
if(stat(path,&st) < 0 || !S_ISDIR(st.st_mode)){
printf("invalid path: %s\n",path);
return;
}
if(!(d = opendir(path))){
printf("opendir[%s] error: %m\n",path);
return;
}
while((dp = readdir(d)) != NULL){
/* 把当前目录. 上级目录 ..及隐藏文件都去掉 避免死循环 */
if((!strncmp(dp->d_name,".",1)) || (!strncmp(dp->d_name,"..",2)))
continue;
snprintf(p ,sizeof(p) - 1,"%s/%s",path,dp->d_name);
stat(p,&st);
if(!S_ISDIR(st.st_mode)){
// printf("%s%s\n",path,dp->d_name);
printf("%s\n",p);
}else{
printf("%s/\n",dp->d_name);
trave_dir(p);
}
}
closedir(d);
return;
}
int main(int argc,char **argv){
char *path = NULL;
if(argc !=2){
printf("Usage: %s [dir]\n",argv[0]);
printf("use DEFAULT option: %s .\n",argv[0]);
printf("------------------------------\n");
path = "./";
}else{
path = argv[1];
}
trave_dir(path);
return 0;
}
问题3 如何获取 根据配置文件来赋值
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#define FILENAME "./site.conf"
char* Get_Config(char *Config_name)
{
char readbuf[512] = {0};
char findbuf[50] = {0};
char *retbuf;
retbuf = (char *)malloc(50);
strcpy(findbuf,Config_name);
int line = 0;
FILE *fp = fopen(FILENAME,"r");
if(fp == NULL)
{
perror("fopen");
return NULL;
}
while(fgets(readbuf,sizeof(readbuf),fp)) //逐行循环读取文件,直到文件结束
{
line++;
if(!strncmp(readbuf,"#",1) || !strncmp(readbuf,"\n",1)) //忽略注释(#)和空行
continue;
if(strstr(readbuf,findbuf)) //查找配置文件名
{
char *p=strchr(readbuf,'='); //确定“=”位置
do
{
p += 1;
}
while(*p == ' ');
sprintf(retbuf,"%s",p);
fclose(fp);
return retbuf;
}
}
return NULL;
}
char* del_space(char *str){
int i = -1,j = strlen(str),cur=0;
char *fp = NULL;
char *fp_temp = NULL;
if(str == NULL){
return "error";
}
while(str[++i] == ' '){
}
while(str[--j] == ' '){
}
for(;i<=j;i++,++cur){
str[cur] = str[i];
}
str[cur] = '\0';
fp = fp_temp = str;//记录字符串
while(*str){
if(*str != ' '){
*fp_temp = *str;
fp_temp++;
}else{
if(*(fp_temp -1) != ' '){
*fp_temp = *str;
fp_temp++;
}
}
str++;
}
*fp_temp = '\0';
return fp;
}
char *strrpc(char *str,char *oldstr,char *newstr){
char bstr[strlen(str)];//转换缓冲区
memset(bstr,0,sizeof(bstr));
int i;
for(i = 0;i < strlen(str);i++){
if(!strncmp(str+i,oldstr,strlen(oldstr))){//查找目标字符串
strcat(bstr,newstr);
i += strlen(oldstr) - 1;
}else{
strncat(bstr,str + i,1);//保存一字节进缓冲区
}
}
strcpy(str,bstr);
return str;
}
void main1(){
char str[] = " sdfdsf sdfds sss sdfsd ";
char *p = del_space(str);
printf("%s",p);
}
int main(int argc, const char *argv[])
{
char *test = "/www/wwwroot/video.shikexu.com/";
char *site_path;
site_path = Get_Config("site_path");
printf("site_path:%s",site_path);
char s_path[100];
sprintf(s_path,"%s",site_path);
// strcpy(temp,site_path);
s_path[strlen(s_path)-1] = 0;
printf("s_path:%s\n",s_path);
free(site_path); //防止内存泄漏
printf("test:%s\n",test);
printf("test的长度为%d\n",strlen(test));
printf("s_path的长度为%d\n",strlen(s_path));
printf("对比结果%d\n",strcmp(s_path,test));
char str[] = "/www/wwwroot/video.shikexu.com/video/m3u8/2019/11/29/d23";
strrpc(str,s_path,"");
printf("last:%s\n",str);
return 0;
}
问题4 php脚本执行时间过长
解决办法异步执行 exec
$cmd = 'oss -add '.$task_path' "'.$api_url.'" >/dev/null &';
exec($cmd);
输出到 /dev/null 再加 & 后台执行。
至此结束,我现在还不会C,还需要继续学习。
转载请声明--原文地址
- 我的微信
- 这是我的微信扫一扫
-
- 我的微信公众号
- 我的微信公众号扫一扫
-