C语言代码由上到下依次执行,原则上函数定义要出现在函数调用之前,否则就会报错。但在实际开发中,经常会在函数定义之前使用它们,这个时候就需要提前声明。

函数声明(Declaration),就是告诉编译器我要使用这个函数,你现在没有找到它的定义不要紧,请不要报错,稍后我会把定义补上。

函数声明的格式非常简单,相当于去掉函数定义中的函数体,并在最后加上分号;,如下所示:

dataType functionName( dataType1 param1, dataType2 param2 ... );

也可以不写形参,只写数据类型:

dataType functionName( dataType1, dataType2 ... );

函数声明给出了函数名、返回值类型、参数列表(重点是参数类型)等与该函数有关的信息,称为函数原型(Function Prototype)。函数原型的作用是告诉编译器与该函数有关的信息,让编译器知道函数的存在,以及存在的形式,即使函数暂时没有定义,编译器也知道如何使用它。

有了函数声明,函数定义就可以出现在任何地方了,甚至是其他文件、静态链接库、动态链接库等。

实例1 定义一个函数 sum(),计算从 m 加到 n 的和,并将 sum() 的定义放到 main() 后面。

#include <stdio.h>//函数声明int sum(int m, int n); //也可以写作int sum(int, int);int main(){ int begin = 5, end = 86; int result = sum(begin, end); printf("The sum from %d to %d is %d\n", begin, end, result); return 0;}//函数定义int sum(int m, int n){ int i, sum=0; for(i=m; i<=n; i++){ sum+=i; } return sum;}

在 main() 函数中调用了 sum() 函数,编译器在它前面虽然没有发现函数定义,但是发现了函数声明,这样编译器就知道函数怎么使用了,至于函数体到底是什么,暂时可以不用操心,后续再把函数体补上就行。

实例2 定义两个函数,计算1! + 2! + 3! + … + (n-1)! + n!的和。

#include <stdio.h>// 函数声明部分long factorial(int n); //也可以写作 long factorial(int);long sum(long n); //也可以写作 long sum(long);int main(){ printf("1!+2!+...+9!+10! = %ld\n", sum(10)); return 0;}//函数定义部分//求阶乘long factorial(int n){ int i; long result=1; for(i=1; i<=n; i++){ result *= i; } return result;}// 求累加的和long sum(long n){ int i; long result = 0; for(i=1; i<=n; i++){ result += factorial(i); } return result;}

运行结果:

1!+2!+...+9!+10! = 4037913

对于单个源文件的程序,通常是将函数定义放到 main() 的后面,将函数声明放到 main() 的前面,这样就使得代码结构清晰明了,主次分明。

将函数定义放在最后,就是尽量屏蔽不重要的信息,凸显关键的信息。将函数声明放到 main() 的前面,在定义函数时也不用关注它们的调用顺序了,哪个函数先定义,哪个函数后定义,都无所谓了。

对于多个文件的程序,通常是将函数定义放到源文件(.c文件)中,将函数的声明放到头文件(.h文件)中,使用函数时引入对应的头文件就可以,编译器会在链接阶段找到函数体。

在使用 printf()、puts()、scanf() 等函数时引入了 stdio.h 头文件,我们认为 stdio.h 中包含了函数定义(也就是函数体),只要有了头文件就能运行,其实不然,头文件中包含的都是函数声明,而不是函数定义,函数定义都放在了其它的源文件中,这些源文件已经提前编译好了,并以动态链接库或者静态链接库的形式存在,只有头文件没有系统库的话,在链接阶段就会报错,程序根本不能运行。

除了函数,变量也有定义和声明之分。实际开发过程中,变量定义需要放在源文件(.c文件)中,变量声明需要放在头文件(.h文件)中,在链接程序时会将它们对应起来。

扫一扫获取更多精彩内容哟!!!


简介

rsync是实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息,该软件是通过ssh协议来传输文件。

rsync 命令的基本格式有多种,分别是:


[root@localhost ~]# rsync [OPTION] SRC DEST[root@localhost ~]# rsync [OPTION] SRC [USER@]HOST:DEST[root@localhost ~]# rsync [OPTION] [USER@]HOST:SRC DEST[root@localhost ~]# rsync [OPTION] [USER@]HOST::SRC DEST[root@localhost ~]# rsync [OPTION] SRC [USER@]HOST::DEST

针对以上 5 种命令格式,rsync 有 5 种不同的工作模式:

第一种用于仅在本地备份数据;

第二种用于将本地数据备份到远程机器上;

第三种用于将远程机器上的数据备份到本地机器上;

第四种和第三种是相对的,同样第五种和第二种是相对的,它们各自之间的区别在于登陆认证时使用的验证方式不同。


本文介绍利用rsync命令进行本地备份和还原操作,也是常用的linux系统进行备份还原的一种设计思路。


参数详解说明-v, --verbose详细模式输出。-q, --quiet精简输出模式。-c, --checksum打开校验开关,强制对文件传输进行校验。-a, --archive归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD。-r, --recursive对子目录以递归模式处理。-R, --relative使用相对路径信息。-b, --backup创建备份,也就是对于目的已经存在有同样的文件名时,将老的文件重新命名为~filename。可以使用–suffix选项来指定不同的备份文件前缀。–backup-dir将备份文件(如~filename)存放在在目录下。-suffix=SUFFIX定义备份文件前缀。-u, --update仅仅进行更新,也就是跳过所有已经存在于DST,并且文件时间晚于要备份的文件,不覆盖更新的文件。-l, --links保留软链结。-L, --copy-links想对待常规文件一样处理软链结。–copy-unsafe-links仅仅拷贝指向SRC路径目录树以外的链结。–safe-links忽略指向SRC路径目录树以外的链结。-H, --hard-links保留硬链结。-p, --perms保持文件权限。-o, --owner保持文件属主信息。-g, --group保持文件属组信息。-D, --devices保持设备文件信息。-t, --times保持文件时间信息。-S, --sparse对稀疏文件进行特殊处理以节省DST的空间。-n, --dry-run现实哪些文件将被传输。-w, --whole-file拷贝文件,不进行增量检测。-x, --one-file-system不要跨越文件系统边界。-B, --block-size=SIZE检验算法使用的块尺寸,默认是700字节。-e, --rsh=command指定使用rsh、ssh方式进行数据同步。–rsync-path=PATH指定远程服务器上的rsync命令所在路径信息。-C, --cvs-exclude使用和CVS一样的方法自动忽略文件,用来排除那些不希望传输的文件。–existing仅仅更新那些已经存在于DST的文件,而不备份那些新创建的文件。–delete删除那些DST中SRC没有的文件。–delete-excluded同样删除接收端那些被该选项指定排除的文件。–delete-after传输结束以后再删除。–ignore-errors及时出现IO错误也进行删除。–max-delete=NUM最多删除NUM个文件。–partial保留那些因故没有完全传输的文件,以是加快随后的再次传输。–force强制删除目录,即使不为空。–numeric-ids不将数字的用户和组id匹配为用户名和组名。–timeout=time ip超时时间,单位为秒。-I, --ignore-times不跳过那些有同样的时间和长度的文件。–size-only当决定是否要备份文件时,仅仅察看文件大小而不考虑文件时间。–modify-window=NUM决定文件是否时间相同时使用的时间戳窗口,默认为0。-T --temp-dir=DIR在DIR中创建临时文件。–compare-dest=DIR同样比较DIR中的文件来决定是否需要备份。-P 等同于 --partial。–progress显示备份过程。-z, --compress对备份的文件在传输时进行压缩处理。–exclude=PATTERN指定排除不需要传输的文件模式。–include=PATTERN指定不排除而需要传输的文件模式。–exclude-from=FILE排除FILE中指定模式的文件。–include-from=FILE不排除FILE指定模式匹配的文件。–version打印版本信息。–address绑定到特定的地址。–config=FILE指定其他的配置文件,不使用默认的rsyncd.conf文件。–port=PORT指定其他的rsync服务端口。–blocking-io对远程shell使用阻塞IO。-stats给出某些文件的传输状态。–progress在传输时现实传输过程。–log-format=formAT指定日志文件格式。–password-file=FILE从FILE中得到密码。–bwlimit=KBPS限制I/O带宽,KBytes per second。-h, --help显示帮助信息。实例解析 [root@localhost ~]# rsync -avzAXH --ignore-missing-args --exclude-from /backup/snapshots/.exclude --exclude-from /backup/snapshots/.excludeuser / /backup/snapshots/data

从/目录备份文件到/backup/snapshots/data下,同时不备份/backup/snapshots/.excludeuser和/backup/snapshots/.exclude目录文件


[root@localhost ~]# rsync -avzAXH --delete --exclude /data --exclude-from /backup/snapshots/.excludeuser /backup/snapshots/data /

从/backup/snapshots/data目录中恢复文件到/目录下


参数详解说明-a这是归档模式,表示以递归方式传输文件,并保持所有属性-v表示打印一些信息,比如文件列表、文件数量等-z加上该选项,将会在传输过程中压缩。-A, --aclsACLs权限控制-X, --xattrs文件系统扩展属性-H, --hard-links保留硬链结–delete删除 DEST 中 SRC 没有的文件–ignore-missing-args忽略缺少的源参数而不出错–exclude-from从文件中读取需要排除的文件


考虑到服务器数据的安全,我考虑增加一台备份服务器,通过数据同步,达到较好的冗余。

linux下有非常好的一个命令rsync可以实现差异备份,下面就说说它的用法:

▲合适系统:红旗DC 4.1 or 5.0或其他linux、FreeBSD系统

▲测试环境:红旗DC 5.0

一、通过rsh或ssh命令

在没有建立rsync服务器的情况下,我们可以利用rsync命令直接进行快速的差异备份:

命令格式:

#rsync [option] 源路径 目标路径

其中:

[option]:

a:使用archive模式,等于-rlptgoD,即保持原有的文件权限

z:表示传输时压缩数据

v:显示到屏幕中

e:使用远程shell程序(可以使用rsh或ssh)

--delete:精确保存副本,源主机删除的文件,目标主机也会同步删除

--include=PATTERN:不排除符合PATTERN的文件或目录

--exclude=PATTERN:排除所有符合PATTERN的文件或目录

--password-file:指定用于rsync服务器的用户验证密码

源路径和目标路径可以使用如下格式:

rsync://[USER@]Host[:Port]/Path    

[USER@]Host::Path                        

[USER@]Host:Path                          

LocalPath                                      

※需要注意的是,来源或目的路径最少要有一个是本地路径,如果忽略本地路径,则只会列出远端的文件列表。

例子:

#rsync -ave ssh test:/home/ftp/pub/ /home/ftp/pub/

把源路径中远端test机器上的/home/ftp/pub/目录中的内容,通过rsync同步到本地的/home/ftp/pub/目录下。

◎小心源路径结尾时候的/号,后缀/通知rsync复制该目录的内容,但不复制目录本身。例如:

#rsync -ave ssh test:/home/ftp/pub /home/ftp/

则会把pub目录整个同步到本地/home/ftp/路径中

#rsync -azv --delete rsync://linuxing@192.168.1.100/blog /var/www/html/

通过linuxing登陆到192.168.1.100中,同步rsync服务器的blog项到本地的/var/www/html/,并删除本地上源路径中不存在的文件或目录。

※千万要注意--delete参数,在使用此参数的时候,建议用绝对路径指定本地目录,防止清空当前目录。

二、建立rsync服务器

当服务器没有开通ssh,或备份方没有ssh权限的时候,我们可以通过建立rsync服务器,进行匿名的数据同步。

要使用rsync服务,需要建立服务端和客户端:

1、服务端

主配置文件:

#vi /etc/rsyncd.conf

log file = /var/log/rsyncd.log

pid file = /var/run/rsyncd.pid

lock file = /var/run/rsync.lock

[test]                                      #rsync区段的设定名称

path = /var/www/html/test       #需要同步的数据存放路径

comment =  test folder             #注释

uid = apache                           #采用什么身份进行文件读取

gid = apache                           #同上,必须是有读取path权限的用户、组

ignore errors                           #忽略错误

read only = yes                       #只读

list = no                                  #不能列表

auth users = linuxing                #连接rsync服务的帐号

secrets file = /etc/rsyncd.secrets    #指定存放帐号密码的位置

帐号密码文件:

#vi /etc/rsyncd.secrets

#格式:帐号:密码 (每行一组,帐号和密码用:号分开)

linuxing:backup

保存后,需要保证用户是root,权限是600

#chown root:root /etc/rsyncd.secrets

#chmod 600 /etc/rsyncd.secrets

启动服务:

#rsync --daemon

保证开机自动启动:

修改/etc/xinetd.d/rsync文件,把其中的disable=yes改为disable=no

#sed -i -e "/disable/{ s/yes/no/ }" /etc/xinetd.d/rsync

#service xinetd.d restart

2、客户端

使用用法一中涉及到rsync://的方法即可。

如果rsync服务器需要密码验证,可以增加--password-file参数:

#rsync -azv --delete rsync://linuxing@192.168.1.100/test /var/www/html --password-file=/etc/test

#vi /etc/test

#指定访问密码

bakcup

#chmod 600 /etc/test

3、定时

另外,由于rsync客户端没有定时功能,我们可以通过在crontab中增加计划任务实现定时的同步,如:(不要使用-v参数,防止刷屏)

#crontab -e

0 22 * * 1-5 /usr/彪壮的小霸王/rsync -az --delete rsync://linuxing@192.168.1.100/test /var/www/html --password-file=/etc/test

#指定星期一到五,每晚十点整进行同步

三、总结

使用rsync的优点:可通过ssh进行网络加密传输,也可以利用ssh客户端密钥建立信任关系。当在两台计算机之间保持大型、复杂目录结构的同步时候,比tar或wget等方式都要快。而且可以做到精确同步。

四、附录

如果是通过编译安装的rsync(如FreeBSD),路径有点不同:

服务器的配置文件在:/usr/local/etc/rsyncd.conf

启动文件:/usr/local/etc/rc.d/rsyncd.sh

命令文件:/usr/local/彪壮的小霸王/rsync

系统启动托管:/etc/rc.conf(增加rsyncd_enable="YES")

五、参考文章

http://rsync.samba.org/

帮助文件:man rsync 或 man rsyncd.conf

※2005-11-20 第一次编写


scp scp(全备份)1. 把本地文件复制到远程主机 (上传)2. 把远程文件复制到本地(下载) rsync和scp命令的对比rsync(支持增量备份)


实验环境:
我们需要两台主机,要保证两台主机是可以互相通信的。

配网,点击查看以前文章,不再复述。改主机名字,这一步可以省略。使用命令systemctl stop firewalld关闭两台主机的防火墙。做免密认证。 scp(全备份)

scp 本地文件 远程主机用户@远程主机ip:远程主机目录的绝对路径
scp 远程主机用户@远程主机ip:远程主机文件的绝对路径 本地文件

1. 把本地文件复制到远程主机 (上传)

scp file root@172.25.254.200:/root/Desktop
scp -r dir root@172.25.254.200:/root/Desktop   ## -r 表示复制目录
scp -q file root@172.25.254.200:/root/Desktop   ## -q 传输文件时不显示进度

2. 把远程文件复制到本地(下载)

scp root@172.25.254.200:/root/Desktop/file* .  ##最后的.表示下载到当前目录
先在lucky2这台主机建立三个文件

在lucky1这台主机执行命令成功!

rsync和scp命令的对比

用下图命令创建一个较大的文件

用du -sh /mnt/lucky可以看到文件大小

写一个脚本,多执行几次方便我们看效果

用scp可以看出时间都差不多

我们换用rsync看下效果

因为后边只做增量检测,没有增加所以不做重复传输

rsync(支持增量备份)

rsync用法:
rsync 文件 远程用户@远程主机ip:远程主机目录
rsync 远程用户@远程主机ip:远程主机目录 文件路径
为了看出命令效果,我们先做点准备工作:
先创建文件和文件夹

然后chmod 777 * 提权,再更改下用户和组:

再做个链接

下面开始执行命令,可看到效果:

上图可以看到执行命令后给的提示意思是跳过了链接文件,而且仔细观察可以发现,时间戳,用户用户组权限这些都不一样,加下边参数可以实现原样发送:
rsync
-r   ##复制目录
-l   ##复制链接,链接文件不会被跳过
-p   ##复制权限
-t   ##复制时间戳
-o   ##复制拥有者
-g   ##复制拥有组
-D   ##复制设备文件


//1、 编写程序输出ASCII码为32-127的字符。
#include
using namespace std;
int main()
{
for(int i=32;i<=127;i++)
cout<<“ASCII码是”
<<i<<“的字符是”<<(char)i<<endl;
return 0;
}
//2、 编写一个完整的C++程序,实现功能:向用户提问:“现在正在下雨吗?”,
//提示用户输入Y或N。若输入为Y,显示“现在正在下雨。”;若输入为N,显示“现在没有下雨。”;
//否则继续提问“现在正在下雨吗?”。
#include
using namespace std;
int main()
{
bool b=true;
while( b )
{
cout<<“现在正在下雨嘛?请输入’Y’或者‘N’”;
char c;
cin>>c;
switch©
{
case ‘Y’:
cout<<“现在正在下雨。”<<endl;
b=false;
break;
case ‘N’:
cout<<“现在没有下雨。”<<endl;
b=false;
break;
default:
cout<<“您输入了错误的字符!”<<endl;
}
}
return 0;
}
//3、 设计并测试一个名为Rectangle的矩形类,
//其属性为矩形的左下角和右上角两个点的坐标,能计算矩形的面积。
#include
using namespace std;
class Rectangle
{
public :
Rectangle()
{};
Rectangle(int iLeftX,int iLeftY,int iRightX,int iRightY)
{
this->iLeftX=iLeftX;
this->iLeftY=iLeftY;
this->iRightX=iRightX;
this->iRightY=iRightY;
}
int Area()
{
return (iRightX-iLeftX)(iRightY-iLeftY);
}
private:
int iLeftX;
int iLeftY;
int iRightX;
int iRightY;
};
int main()
{
Rectangle r(1,1,2,2);
cout<<“这个矩形的面积是:”<<r.Area()<<endl;
return 0;
}
//4、 定义一个Circle类,有数据成员Radius(半径),
//成员函数GetArea(),计算圆的面积,构造一个Circle的对象进行测试。
#include
using namespace std;
#define PI 3.1415926
class Circle
{
public :
Circle()
{};
Circle(double r)
{
Radius=r;
}
double GetArea()
{
return PIRadius*Radius;
}
private:
double Radius;
};
int main()
{
Circle c(2);
cout<<“这个圆的面积是:”<<c.GetArea()<<endl;
return 0;
}
C++控制台代码 全部经过测试通过
www.oolaile.com