wenmo8 发布的文章

在JavaScript中,有两种方式可以定义一个函数,一个是函数声明,一个是函数表达式。

一 函数声明

函数声明的语法如下:

function functionName(arg0, arg1, arg2) { //函数体}

函数声明的最重要的一个特征是函数声明提升,意思是在执行代码之前会先读取函数声明,所以函数声明可以放在调用函数语句之后。

sayHello();function sayHello(){    console.log("Hello");}


上述代码可以正常执行,不会报错。

二 函数表达式

函数表达式的语法形式如下:

var functionName = function(arg0, arg1, arg2) {    //函数体}

这种形式看起来像常规的变量赋值,先创建一个匿名函数,然后赋值给变量functionName。我们知道在JS中如果要想使用一个变量,必须先给这个变量赋值,所以函数表达式也不例外,在调用之前,必须先给它赋值。否则会报错。

sayHi(); //在这里调用会报错var sayHi = function(){console.log("Hi");}sayHi(); //Hi


函数声明和函数表达式都是用来定义一个函数的,区别就是函数声明存在函数声明,可以在声明前调用。而函数表达式则必须在赋值语句之后再调用。


1. 函数声明提升

func()function func () {}

上例不会报错,正是因为 ‘函数声明提升’,即将函数声明提升(整体)到作用域顶部(注意是函数声明,不包括函数表达式),实际提升后结果同下:

// 函数声明提升function func () {}func()

2. 变量声明提升(只有var声明的变量才有变量提升,let、const无;变量赋值无提升)

1. console.log(num) var num = 102. console.log(func) var func = function () { }

上两例均会打印出 'undefined',变量声明提升会将变量声明提升到作用域顶部,但只会提升声明部分,不会提升赋值部分,实际提升后结果如下:

1. var num console.log(num) num = 102. var func console.log(func) func = function () { }

3. 进阶举例(两者优先顺序、局部与全局变量):

var func = 10console.log(func && typeof(func))function func () {}-----console.log(func && typeof(func))function func () {}var func = 10

上两例将分别输出 ‘number’、'function',原因是 函数声明提升优先于变量提升,函数声明会被变量赋值影响,但不会被变量声明影响,实际提升后结果如下:

function func () {}var func = 10console.log(func && typeof(func))-----function func () {}var funcconsole.log(func && typeof(func))func = 10

    ②

num = 10function func () { window.num = 5 console.log(num) var num console.log(window.num)}func()

上例将会分别打印出 'undefined'、'5',第一处为局部变量,第二处为全局变量,实际提升后结果如下:

function func () { var num window.num = 5 console.log(num) console.log(window.num)}var numnum = 10func()


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 第一次编写