0%

函数式编程

函数式编程(英语:functional programming)或称函数程序设计,又称泛函编程,是一种编程典范,它将电脑运算视为数学上的函数计算,并且避免使用程序状态以及易变对象,函数编程语言最重要的基础是λ演算(lambda calculus,而且λ演算的函数可以接受函数当作输入(引数)和输出(传出值)

函数式编程范式相对命令式编程(Imperative programming),函数式编程更加强调程序执行的结果而非执行的过程,倡导利用若干简单的执行单元让计算结果不断渐进,逐层推导复杂的运算,而不是设计一个复杂的执行过程.而命令式编程使用各种变量以及复杂的控制语句来编写逻辑代码,最初图灵机的设计就是属于命令式编程,在纸带上面刻各种孔,然后机器根据纸带上的孔执行各种命令.C/C++ Java Python等各种面向对象编程其实都属于命令式编程范围,虽然现在这些高级语言或多或少都已经支持Lambda表达式以开始支持函数式编程,但是相比Lisp Haskell Clojure等这些纯正函数式语言,Python在函数式编程方面支持的相对少一点.

Python Lambda

λ演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义、函数如何被应用以及递归的形式系统。它由数学家阿隆佐·邱奇在20世纪30年代首次发表。Lambda演算作为一种广泛用途的计算模型,可以清晰地定义什么是一个可计算函数,而任何可计算函数都能以这种形式表达和求值,它能模拟单一磁带图灵机的计算过程;尽管如此,Lambda演算强调的是变换规则的运用,而非实现它们的具体机器。

说到Python支持函数式编程必须得说道Lambda表达式,Lambda按照wiki上说法比较复杂,其实简单的说Lambda表达式就是匿名函数

1
lambda argument: manipulate(argument)

1
2
squares = map(lambda x: x * x, range(9))
print squares

1
2
3
number_list = range(-5, 5)
less_than_zero = list(filter(lambda x: x < 0, number_list))
print(less_than_zero)

1
2
3
number_list = range(-5, 5)
less_than_zero = list(filter(lambda x: x < 0, number_list))
print(less_than_zero)

上面三个代码片段就是map/reduce/filter和lambda表达式结合的一个例子,python在支持lambda时,为了不让开发者乱用这个特性,lambda设计的比较简单,就是在lamba后面加函数以及操作,只要使用得当lambda可以让代码看起来更加简洁优雅,但是如果使用不当代码可读性会很差

Read more »

Rsync 使用

1、服务端与客户端的定义

​ A机器向B机器发送数据, 或者A机器向B机器拉取数据

​ 那么A均为客户端, B均为服务端

2、是否需要启动rsync服务

​ 客户端不需要, 服务端需要

​ 启动rsync进程: systemctl start rsyncd

​ 设置rsync开机自启动: systemctl enable rsyncd

3、rsync相关配置

​ 1)模块配置, 固定为/etc/rsyncd.conf, 权限644即可

​ 2)用户密码配置, 可以在/etc/rsyncd.conf配置该文件路径, 推荐使用/etc/rsyncd.secret, 权限必须为600

​ 3)日志回滚配置 /etc/logrotate.d/rsyncd.rotate, 按需添加

4、rsyncd.conf举例说明

###全局配置, 生效于每个模块, 并会被模块中相同的配置项覆盖

uid = root

gid = root

use chroot = no

pid file = /var/run/rsyncd.pid

#设置rsync用户密码配置文件路径

secrets file = /etc/rsyncd.secret

timeout = 300

read only = yes

write only = no

#设置最大连接数

max connections = 2048

dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

#设置rsync日志文件, 若未设置, 则默认将日志写入syslog, 即/var/log/message, 当前版本的rsync不支持关闭日志, 所以若设置了该项, 记得添加日志回滚, 避免日志文件挤爆磁盘

log file = /var/log/rsync.log

syslog facility = local3

###分模块配置, 注意rsync配置时,注释必须另起一行

#模块名

[test-module]

#模块根目录,注意该目录若不存在, rsync不会自动创建, 传输将报错

path = /mylog/test/ori_data/

#设置为可写

read only = no

#rsync用户名

auth users = mylog

5、rsyncd.secret举例说明

格式为 用户名:密码 , 例如

mylog:abc123

mylog2:abc456

6、rsync基础命令

在使用rsync传输之前, 需要在本机创建一个密码文件, 名称随意,例如命名为rsync.key, 权限必须是600, 并且内容只包含要使用的密码(例如 abc123)

  1. 这条命令, 表示将本机/home/test/目录下的所有内容,使用模块test-module传输到192.168.1.2, 根据模块配置, 这些内容将被传输到/mylog/test/ori_data/目录下

    1
    /bin/rsync-az–timeout=30–contimeout=15–password-file=rsync.key /home/test/ mylog@192.168.1.2::test-module
  2. 注意这里/home/test/改为/home/test , test-module模块名后面添加了一层子目录/test/ , 这条命令表示将本机的/home/test目录本身, 使用模块test-module传输到192.168.1.2, 根据模块配置, 这些内容将被传输到/mylog/test/ori_data/test/目录下

    1
    /bin/rsync-az–timeout=30–contimeout=15–password-file=rsync.key /home/test mylog@192.168.1.2::test-module/test/
  3. 相比于第一条命令, 这里修改了最后两个参数的顺序, 表示从192.168.1.2拉取数据到本机的/home/test/目录下

    1
    /bin/rsync-az–timeout=30–contimeout=15–password-file=rsync.key  mylog@192.168.1.2::test-module /home/test/

早点两年前就开始使用shadowsocks了,那时候买了搬瓦工一年19$的vps,由于搬瓦工数据中心比较少,且大部分位于美国,经过测试选了个在凤凰城的机房,但是网速一直不稳定时不时的断线,前阵子买了vultr位于东京数据中心的vps,网络稳定,看youtube 1080p 毫无压力.虽然用了很久的shandowsock5,但是一直对sock5协知之甚少,决定解下这个牛逼的翻墙协议,简单的说就是在墙外搭一个sock5服务器,墙内的客户端把tcp数据加密后发往墙外的服务器,server按照sock5协议解密后再发往目标机器

  1. PC客户端(即你的电脑)发出请求基于Socks5协议跟SS-Local端进行通讯,由于这个SS-Local一般是本机或路由器等局域网的其他机器,不经过GFW,所以解决GFW通过特征分析进行干扰的问题
  2. SS-Local和SS-Server两端通过多种可选的加密方法(“aes-256-cfb”等)进行通讯,经过GFW的时候因为是常规的TCP包,没有明显特征码GFW也无法对通讯数据进行解密
  3. SS-Server将收到的加密数据进行解密,还原初始请求,再发送到用户需要访问的服务网站,获取响应原路再返回SS-04,返回途中依然使用了加密,使得流量是普通TCP包,并成功穿过GFW防火墙
Read more »

守护进程

linux 服务端程序很多都是以守护进程的方式对外提供服务, linux 系统本身也有很多守护进程,例如kthreadd用来创建内核进程, kswapd是内存换页守护进程,flush是dump内存中的脏页面到磁盘,jbd提供ext4文件系统的日志日志功能…守护进程命名大部分都是以d结尾. 大部分守护进程都是以root方式运行,没有控制终端,运行在后台. 大部分守护进程都是进程组的组长进程以及会话的首进程,而且是进程组和会话中的唯一进程. 守护进程的父进程一般是系统1号进程,例如initd或者systemd.

编程规则

为了让守护进程在后台运行,减少不必要的交互,守护进程的编写有一套编程规则:

  • umask将文件模式创建屏蔽字设置一个已知值,通常是0. 由于继承得来的文件模式屏蔽字可能会被设置为拒绝某些权限.
  • fork() 然后父进程exit
    • 如果守护进程是以shell命令启动, 父进程exit会让shell认为这条命令已经执行完毕
    • 虽然子进程继承了父进程的进程组ID, 但获得了一个新的进程ID,这保证了子进程不是一个进程组的组长进程 (setid调用的条件)
  • 调用setid创建一个新会话, 如果调用setsid的进程不是一个进程组的组长,此函数创建一个新的会话期setid,setid会让子进程执行三个步骤
    • 让子进程成为新会话的首进程
    • 让子进程成为新进程组的组长进程
    • 让子进程没有控制终端,如果在调用setsid前,该进程有控制终端,那么与该终端的联系被解除。 如果该进程是一个进程组的组长,此函数返回错误
    • 为了保证这一点,我们先调用fork()然后exit(),此时只有子进程在运行
  • 再次fork, 这个步骤有些守护进程没有. 此时进程已经成为无终端的会话组长,但它可以重新申请打开一个控制终端,为了使进程不再成为会话组长来禁止进程重新打开控制终端, 再次fork然后父进程exit
  • 设置工作目录为根目录, 从父进程继承过来的当前工作目录可能在一个挂载的文件系统中
  • 关闭不再需要的文件描述符
  • 打开/dev/null, 让文件描述符0 1 2都指向/dev/null
  • 处理SIGCHLD信号, 处理SIGCHLD信号并不是必须的
Read more »

linux最大文件描述符数

前言

关于Linux下系统,进程能最大能打开的文件描述符数看过好多文章,但大都没有完整,详细说明每个值表示什么意思,在实践中该怎么设置.今天刚好有时间就通过Google来整理了如下的内容.如有错误请指出,谢谢.

系统级别

Linux系统级别限制所有用户进程能打开的文件描述符总数可以通过如下的命令查看

1
2
$ cat /proc/sys/fs/file-max 
2259544

有2中方法修改系统级别的限制:

  1. 通过命令动态修改(重启后失效)

    sysctl -w fs.file-max=102400

2.通过配置文件修改

1
2
3
4
vi /etc/sysctl.conf
在文件末尾添加
fs.file-max=102400
保存退出后使用sysctl -p 命令使其生效

fs.file-max有关的一个参数是file-nr, 该参数是只读的

1
2
$ cat /proc/sys/fs/file-nr 
3296 0 2259544

file-nr的值由3部分组成:1,已经分配的文件描述符数;2,已经分配但未使用的文件描述符数;
3,内核最大能分配的文件描述符数

注意: 只要你的内存足够大,file-max的值可以非常大。

用户级别

用户级别的限制是通过可以通过命令ulimit命令和文件/etc/security/limits.conf

1
2
3
4
5
6
7
8
9
10
$ ulimit  -n
655350
//查看硬件资源限制
$ ulimit -Hn
655350
//软件资源限制
$ ulimit -Sn
655350
//设置软/硬件资源限制
ulimit -Sn 655350 或 ulimit -Hn 655350

查看limits.conf文件

1
2
3
4
cat /etc/security/limits.conf
//输出
* hard nofile 655350
* soft nofile 655350

limits.conf 文件的格式是:

1
<domain> <type> <item> <value>

每个域的取值可以参考

如果domain的值是一个用户名,则可以限制该用户下的所有进程能打开的文件描述符总数,如果是*则表示针对每个用户都起作用

注意 针对同一个item取值, soft的值不能大于hard

nr_open

This denotes the maximum number of file-handles a process can
allocate. Default value is 1024*1024 (1048576) which should be
enough for most machines. Actual limit depends on RLIMIT_NOFILE
resource limit.

就是说nr_open表示一个进程做多能分配的文件句柄数,默认值是1048576。针对大多数的情况该值是足够的。

NR_FILE

NR_FILE is the limit on total number of files in the system at any given point in time

NR_FILE 是系统在某一给定时刻,限制的文件总数

While initializing the kernel we setup the vfs cache with start_kernel
vfs_caches_init(num_physpages);
files_init(mempages);
fs/file_table.c says
/* One file with associated inode and dcache is very roughly 1K.

  • Per default don’t use more than 10% of our memory for files.
    n = (mempages * (PAGE_SIZE / 1024)) / 10;
    this n can never be greater than NR_FILE

ulimit 命令

1.只对当前tty(终端有效),若要每次都生效的话,可以把ulimit参数放到对应用户的.bash_profile里面;
2.ulimit命令本身就有分软硬设置,加-H就是硬,加-S就是软;
3.默认显示的是软限制,如果运行ulimit命令修改的时候没有加上的话,就是两个参数一起改变.生效;

命令参数
-H 设置硬件资源限制.
-S 设置软件资源限制.
-a 显示当前所有的资源限制.
-c size:设置core文件的最大值.单位:blocks
-d size:设置数据段的最大值.单位:kbytes
-f size:设置创建文件的最大值.单位:blocks
-l size:设置在内存中锁定进程的最大值.单位:kbytes
-m size:设置可以使用的常驻内存的最大值.单位:kbytes
-n size:设置内核可以同时打开的文件描述符的最大值.单位:n
-p size:设置管道缓冲区的最大值.单位:kbytes
-s size:设置堆栈的最大值.单位:kbytes
-t size:设置CPU使用时间的最大上限.单位:seconds
-v size:设置虚拟内存的最大值.单位:kbytes
unlimited 是一个特殊值,用于表示不限制

总结 file-max, nr_open, nofile之间的关系

  1. 针对用户打开最大文件数的限制,可以通过修改文件limits.conf来实现
  2. nofile中soft的值小于hard, 最大值由nr_open来决定
  3. file-max表示内核针对整个系统,限制能所有进程能打开的文件描述符数
  4. nofile < nr_open < file-max