标签归档:Linux

时间同步客户端 – Chrony

Centos7.x中已经默认安装此时间同步客户端。

安装Chrony:

#ubuntu/debian:
apt-get install chrony

#Centos/redhat
yum install chrony

时间服务器删除添加:

#删除默认的Server
sed -i "/server/d" /etc/chrony.conf

#添加
#打开/etc/chrony.conf,新增一行:
server ntp.aliyun.com iburst

重启并检查:

/etc/init.d/chronyd restart
#或
systemctl restart chronyd

#查看是否正常
chronyc tracking

Reference ID    : CB6B0658 (203.107.6.88)
Stratum         : 3
Ref time (UTC)  : Mon Mar 12 02:01:35 2018
System time     : 0.000003723 seconds fast of NTP time
Last offset     : -0.003573318 seconds
RMS offset      : 0.003573318 seconds
Frequency       : 1.765 ppm slow
Residual freq   : +55.304 ppm
Skew            : 6.448 ppm
Root delay      : 0.064887173 seconds
Root dispersion : 0.001230678 seconds
Update interval : 2.1 seconds
Leap status     : Normal

其它说明—————————————————————–

rpm -qa | grep chrony
chrony-2.1.1-4.el7.centos.x86_64

rpm -ql chrony-2.1.1-4.el7.centos.x86_64
/etc/NetworkManager/dispatcher.d/20-chrony
/etc/chrony.conf   *****
/etc/chrony.keys
/etc/dhcp/dhclient.d/chrony.sh
/etc/logrotate.d/chrony
/usr/bin/chronyc  *****
/usr/lib/systemd/ntp-units.d/50-chronyd.list
/usr/lib/systemd/system/chrony-dnssrv@.service
/usr/lib/systemd/system/chrony-dnssrv@.timer
/usr/lib/systemd/system/chrony-wait.service
/usr/lib/systemd/system/chronyd.service
/usr/libexec/chrony-helper
/usr/sbin/chronyd  *****
/var/lib/chrony
/var/lib/chrony/drift
/var/lib/chrony/rtc
/var/log/chrony

主要三个文件,/etc/chrony.conf配置,/usr/bin/chronyc是客户端工具,/usr/sbin/chronyd是后台进程(使用/usr/lib/systemd/system/chronyd.service来管理)。

当Chrony启动时,它会读取/etc/chrony.conf配置文件中的设置。配置参数:

1 server – 该参数可以多次用于添加时钟服务器,必须以”server “格式使用。一般而言,你想添加多少服务器,就可以添加多少服务器。

    server 0.centos.pool.ntp.org
    server 3.europe.pool.ntp.org

2 stratumweight – stratumweight指令设置当chronyd从可用源中选择同步源时,每个层应该添加多少距离到同步距离。默认情况下,CentOS中设置为0,让chronyd在选择源时忽略源的层级。

3 driftfile – chronyd程序的主要行为之一,就是根据实际时间计算出计算机增减时间的比率,将它记录到一个文件中是最合理的,它会在重启后为系统时钟作出补偿,甚至可能的话,会从时钟服务器获得较好的估值。

4 rtcsync – rtcsync指令将启用一个内核模式,在该模式中,系统时间每11分钟会拷贝到实时时钟(RTC)。

5 allow / deny – 这里你可以指定一台主机、子网,或者网络以允许或拒绝NTP连接到扮演时钟服务器的机器。

    allow 192.168.4.5
    deny 192.168/16

6 cmdallow / cmddeny – 跟上面相类似,只是你可以指定哪个IP地址或哪台主机可以通过chronyd使用控制命令

7 bindcmdaddress – 该指令允许你限制chronyd监听哪个网络接口的命令包(由chronyc执行)。该指令通过cmddeny机制提供了一个除上述限制以外可用的额外的访问控制等级。

    bindcmdaddress 127.0.0.1
    bindcmdaddress ::1

8 makestep – 通常,chronyd将根据需求通过减慢或加速时钟,使得系统逐步纠正所有时间偏差。在某些特定情况下,系统时钟可能会漂移过快,导致该调整过程消耗很长的时间来纠正系统时钟。该指令强制chronyd在调整期大于某个阀值时步进调整系统时钟,但只有在因为chronyd启动时间超过指定限制(可使用负值来禁用限制),没有更多时钟更新时才生效。

也可以通过运行chronyc命令来修改设置,命令如下:
1 accheck – 检查NTP访问是否对特定主机可用
2 activity – 该命令会显示有多少NTP源在线/离线

chronyc> activity 
200 OK
4 sources online
0 sources offline
0 sources doing burst (return to online)
0 sources doing burst (return to offline)
0 sources with unknown address

3 add server – 手动添加一台新的NTP服务器。
4 clients – 在客户端报告已访问到服务器
5 delete – 手动移除NTP服务器或对等服务器
6 settime – 手动设置守护进程时间
7 tracking – 显示系统时间信息

chronyc> tracking
Reference ID    : 38.126.113.10 (38.126.113.10)
Stratum         : 3
Ref time (UTC)  : Mon Apr 24 06:29:55 2017
System time     : 0.000244395 seconds slow of NTP time
Last offset     : -0.000066831 seconds
RMS offset      : 0.000231604 seconds
Frequency       : 18.263 ppm fast
Residual freq   : -0.038 ppm
Skew            : 0.126 ppm
Root delay      : 0.012766 seconds
Root dispersion : 0.007974 seconds
Update interval : 518.7 seconds
Leap status     : Normal

CentOS 7.x 升级内核

默认,CentOS 7.x下,运行yum update会自动升级内核,不过一般都是非常保守的升级:

yum list kernel*
已安装的软件包
kernel.x86_64      3.10.0-514.el7                                         @anaconda     
kernel.x86_64      3.10.0-514.10.2.el7                                    @updates      
kernel.x86_64      3.10.0-514.16.1.el7                                    @updates 

这里可以看到,默认安装的是3.10.0-514.el7, 后来更新两次,分别安装了3.10.0-514.10.2.el7和3.10.0-514.16.1.el7。可见,内核版本号并没有发生任何改变,只是横杆后(-)的数字发生改变,这个应该是发行商维护的(非Linux内核维护),主要应该是一些补丁包添加。

如果要升级到最新的Linux内核,可以去kernel.org去下载源代码编译,不过随着内核越来越复杂,编译涉及到的内容非常多,所以注定是一件费时费力的事情。

首先了解一下kernel.org提供的Linux内核的版本(https://www.kernel.org/category/releases.html)。简单来说,RC版本就是预发布版本,Mainline主线版本,一般2-3月发布一次。Mainline之后就会释放稳定(Stable)版本。还有Longterm版本,表示是长期支持的版本。大部分发行版本Linux都会考虑使用Longterm版本的内核,比如CentOS中就使用3.10.0这个版本。

Longterm release kernels
Version Maintainer Released Projected EOL
4.9 Greg Kroah-Hartman 2016-12-11 Jan, 2019
4.4 Greg Kroah-Hartman 2016-01-10 Feb, 2018
4.1 Sasha Levin 2015-06-21 Sep, 2017
3.16 Ben Hutchings 2014-08-03 Apr, 2020
3.12 Jiri Slaby 2013-11-03 May, 2017
3.10 Willy Tarreau 2013-06-30 Oct, 2017
3.4 Li Zefan 2012-05-20 Apr, 2017
3.2 Ben Hutchings 2012-01-04 May, 2018

从这个表格看,3.10.0这个内核从2013年开始发布,到现在(2017年)已几年过去了,看起来稍微是有点旧了。而且2017年以后,至少需要使用4.4的内核。

为了便利地升级内核,可以使用elrepo(http://elrepo.org)这个软件源,以yum的方法快速安装:

# import key
rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org
# install elrepo repo
rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
# install kernel
yum --enablerepo=elrepo-kernel install  kernel-ml-devel kernel-ml -y
# modify grub
grub2-set-default 0
# reboot
reboot

以上安装的是最新的稳定版。源elrepo提供两个内核,kernel-ml中的ml是指mainline, 是mainline后的最新稳定版本;还有一个叫kernel-lt,它是基于长期支持版本的,比如当前kernel-lt就是指4.4版本的内核。

可以浏览如下链接,查看具体的软件包:
http://elrepo.org/linux/kernel/el7/x86_64/RPMS/

要确定可以使用哪些内核,可以使用:

yum --enablerepo=elrepo-kernel list kernel*

关于Grub2:
“Briefly, a boot loader is the first software program that runs when a computer starts. It is responsible for loading and transferring control to an operating system kernel software (such as Linux or GNU Mach). The kernel, in turn, initializes the rest of the operating system (e.g. a GNU system). ”

查看下安装:

rpm -qa | grep grub2
grub2-tools-2.02-0.44.el7.centos.x86_64
grub2-2.02-0.44.el7.centos.x86_64

rpm -ql grub2-2.02-0.44.el7.centos.x86_64
/boot/grub2/grub.cfg
/boot/grub2/grubenv
/etc/grub2.cfg  #软连接到/boot/grub2/grub.cfg

rpm -ql grub2-tools-2.02-0.44.el7.centos.x86_64
/etc/default/grub

/etc/grub.d
/etc/grub.d/00_header
/etc/grub.d/01_users
/etc/grub.d/10_linux
/etc/grub.d/20_linux_xen
/etc/grub.d/20_ppc_terminfo
/etc/grub.d/30_os-prober
/etc/grub.d/40_custom
/etc/grub.d/41_custom
/etc/grub.d/README

/etc/prelink.conf.d/grub2.conf
/etc/sysconfig/grub -> /etc/default/grub

/usr/bin/grub2-editenv
/usr/bin/grub2-file
/usr/bin/grub2-fstest
/usr/bin/grub2-glue-efi
/usr/bin/grub2-kbdcomp
/usr/bin/grub2-menulst2cfg
/usr/bin/grub2-mkfont
/usr/bin/grub2-mkimage
/usr/bin/grub2-mklayout
/usr/bin/grub2-mknetdir
/usr/bin/grub2-mkpasswd-pbkdf2
/usr/bin/grub2-mkrelpath
/usr/bin/grub2-mkrescue
/usr/bin/grub2-mkstandalone
/usr/bin/grub2-render-label
/usr/bin/grub2-script-check
/usr/bin/grub2-syslinux2cfg

/usr/sbin/grub2-bios-setup
/usr/sbin/grub2-get-kernel-settings
/usr/sbin/grub2-install
/usr/sbin/grub2-macbless
/usr/sbin/grub2-mkconfig
/usr/sbin/grub2-ofpathname
/usr/sbin/grub2-probe
/usr/sbin/grub2-reboot
/usr/sbin/grub2-rpm-sort
/usr/sbin/grub2-set-default
/usr/sbin/grub2-setpassword
/usr/sbin/grub2-sparc64-setup

Grub简单来说就是一个引导程序。机器子上电自检后,会从启动硬盘寻找引导程序,控制权交给引导程序后,由它负责系统引导,最关键的任务就是从什么地方载入内核。

配置文件/etc/grub2.cfg是一个软连接,指向/boot/grub2/grub.cfg,这个是主要的配置文件,其中有启动菜单项(多个,第一个标号为0,第二个为1,依次类推):

menuentry 'CentOS Linux (4.10.12-1.el7.elrepo.x86_64) 7 (Core)' --class centos --class gnu-linux --class gnu --class os --unrestricted $menuentry_id_option 'gnulinux-3.10.0-514.el7.x86_64-advanced-3f38705e-ad35-43b8-b624-4f021e320c87' {
	load_video
	set gfxpayload=keep
	insmod gzio
	insmod part_msdos
	insmod xfs
	set root='hd0,msdos1'
	if [ x$feature_platform_search_hint = xy ]; then
	  search --no-floppy --fs-uuid --set=root --hint-bios=hd0,msdos1 --hint-efi=hd0,msdos1 --hint-baremetal=ahci0,msdos1 --hint='hd0,msdos1'  f89b61bd-58b6-48c5-98db-ec8a00d84a3e
	else
	  search --no-floppy --fs-uuid --set=root f89b61bd-58b6-48c5-98db-ec8a00d84a3e
	fi
	linux16 /vmlinuz-4.10.12-1.el7.elrepo.x86_64 root=/dev/mapper/cl-root ro crashkernel=auto rd.lvm.lv=cl/root rd.lvm.lv=cl/swap rhgb quiet LANG=zh_CN.UTF-8
	initrd16 /initramfs-4.10.12-1.el7.elrepo.x86_64.img
}

一般,升级内核后会自动添加一个菜单项(在第0个位置)。默认,Grub取哪个菜单引导,取决于/boot/grub2/grubenv中的saved_entry配置:

saved_entry=0

这样表示取排在第0个位置的菜单作为默认引导。

也可以直接是菜单项名称,比如:

saved_entry=CentOS Linux (4.10.12-1.el7.elrepo.x86_64) 7 (Core)

可以直接编辑/boot/grub2/grubenv中的saved_entry,也可以使用工具grub2-editenv来编辑/boot/grub2/grubenv,不过如果仅仅想改变saved_entry这个环境变量,则可以使用grub2-set-default来进行,比如grub2-set-default 0就是把/boot/grub2/grubenv中的saved_entry设置为0。

为了防止载入不确定的内核(比如编辑了菜单),一般不建议使用索引号,可以如下设置,锁定默认到指定菜单:

grub2-set-default 'CentOS Linux (4.10.12-1.el7.elrepo.x86_64) 7 (Core)'

Ubuntu 16.x 装机参考

系统镜像可到:https://mirrors.aliyun.com/ubuntu-releases/下载

#更改限制
vi /etc/security/limits.conf
root soft nofile 65535
root hard nofile 65535
* soft nofile 65535
* hard nofile 65535

#解锁root
sudo passwd -u root
#为root设置密码
sudo passwd root

#切换到root
su root

为了避免麻烦,先关闭防火墙:

#查看启动了哪些服务
systemctl list-unit-files | grep enabled
systemctl stop ufw.service
systemctl disable ufw.service

默认没有安装openssh-server(Ubuntu 16.04默认安装时需要选中,否则需要自己安装)

apt install openssh-server

systemctl start sshd.service
systemctl enable sshd.service

默认安装的openssh-server是禁止root链接的,它的逻辑是先以一个普通用户登录,如果需要切换,再用su来进行。如果麻烦可以修改:

vi /etc/ssh/sshd_config

PermitRootLogin prohibit-password	#改为yes(prohibit-password禁止密码,就是使用公钥还是可以的)
PermitEmptyPasswords yes		#是否允许空密码,默认是no

#重启服务
systemctl restart sshd.service

更换软件源头,参考:http://wiki.ubuntu.org.cn/%E6%A8%A1%E6%9D%BF:16.04source

deb http://cn.archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse
deb http://cn.archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse
deb http://cn.archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe multiverse
deb http://cn.archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse
##测试版源
deb http://cn.archive.ubuntu.com/ubuntu/ xenial-proposed main restricted universe multiverse
# 源码
deb-src http://cn.archive.ubuntu.com/ubuntu/ xenial main restricted universe multiverse
deb-src http://cn.archive.ubuntu.com/ubuntu/ xenial-security main restricted universe multiverse
deb-src http://cn.archive.ubuntu.com/ubuntu/ xenial-updates main restricted universe multiverse
deb-src http://cn.archive.ubuntu.com/ubuntu/ xenial-backports main restricted universe multiverse
##测试版源
deb-src http://cn.archive.ubuntu.com/ubuntu/ xenial-proposed main restricted universe multiverse
# Canonical 合作伙伴和附加
deb http://archive.canonical.com/ubuntu/ xenial partner
deb http://extras.ubuntu.com/ubuntu/ xenial main

这里的http://cn.archive.ubuntu.com/ubuntu/是阿里云资源,可以替换为http://mirrors.163.com/ubuntu/

安装桌面

apt update
apt upgrade

apt-get install --no-install-recommends ubuntu-desktop

add-apt-repository ppa:embrosyn/cinnamon
apt install cinnamon

Bash Shell脚本实例

0 ——-

#!/bin/bash

#定位KILL命令
cmm="/usr/bin/kill"
if [ ! -f "$cmm" ]; then
    cmm="/bin/kill"
fi

#保持多少个进程
hold=2
if [ -n "$1" ]; then
    hold=$1
fi

#内存占用阈值(100M)
threshold=102400

#获取具体路径
pwd=$(cd `dirname $0`; pwd)

#搜索进程
search=$pwd'/artisan queue:work --queue=adc'

#循环杀掉超过阈值的进程
ps aux | grep $search | grep -v grep | awk '{print $2"|"$6}' | cat | while read line
do
    pid=`echo $line | cut -d "|" -f 1`
    rss=`echo $line | cut -d "|" -f 2`
    if [ $rss -gt $threshold ]; then
        kill=`$cmm -9 $pid`
        date=`date "+%Y-%m-%d %H:%M:%S"`
        echo $date' - 'PID:$pid' - RSS('$rss'K) > Threshold('$threshold'K) - Was Killed.'
    fi
done

#杀掉后维持进程数量
live=`ps -efH | grep $search | grep -v 'grep' | wc -l`
if [ $live -lt $hold ]; then
    for ((i=1; i<=$hold-$live; i=i+1))
    do
        php $search' --tries=3 --sleep=2 --timeout=300' 2>&1 >> /dev/null &
    done
fi

exit 0





#!/bin/bash

#定位KILL命令
cmm="/usr/bin/kill"
if [ ! -f "$cmm" ]; then
    cmm="/bin/kill"
fi

#操作系统位数
bit='32'
if [ $(getconf WORD_BIT) = '32' -a $(getconf LONG_BIT) = '64' ]; then
    bit='64'
fi

#端口
port=9515
if [ -n "$1" ]; then
    port=$1
fi

#获取具体路径
pwd=$(cd `dirname $0`; pwd)

#搜索进程
search=$pwd/chromedriver_linux$bit' --port='$port

#杀掉原来进程
ps aux | grep $search | grep -v grep | awk '{print $2}' | cat | while read pid
do
    kill=`$cmm -9 $pid`
    date=`date "+%Y-%m-%d %H:%M:%S"`
    echo $date' - 'PID:$pid' Was Killed.'
done

#重启进程
$pwd/chromedriver_linux$bit --port=$port 2>&1 >> /dev/null &

exit 0

##############################################################
##定时杀firefox

#!/bin/bash

#定位KILL命令
cmm="/usr/bin/kill"
if [ ! -f "$cmm" ]; then
    cmm="/bin/kill"
fi

#循环杀掉进程
ps aux | grep 'firefox/firefox' | grep -v grep | awk '{print $2"|"$6}' | cat | while read line
do
    pid=`echo $line | cut -d "|" -f 1`
    rss=`echo $line | cut -d "|" -f 2`

    kill=`$cmm -9 $pid`
    date=`date "+%Y-%m-%d %H:%M:%S"`
    echo $date' - 'PID:$pid' - RSS('$rss'K) Threshold('$threshold'K) - Firefox Was Killed.'
done

exit 0

1 内存监控,超过阀值则杀掉:

vi kill.sh

#!/bin/bash

#内存占用超过120M
threshold=120000
cmm="/usr/bin/kill"
if [ ! -f "$cmm" ]; then
    cmm="/bin/kill"
fi

ps aux | grep 'artisan queue:work' | grep -v grep | awk '{print $2"|"$6}' | cat | while read line
do
    pid=`echo $line | cut -d "|" -f 1`
    rss=`echo $line | cut -d "|" -f 2`

    if [ $rss -gt $threshold ]; then
        kill=`$cmm -9 $pid`
	date=`date "+%Y-%m-%d %H:%M:%S"`
        if [ $kill ]; then
            echo $date' -- 'PID:$pid' - RSS('$rss'K) > threshold('$threshold'K) - Was Killed.'
        elif
            ech $date' -- 'PID:$pid' - RSS('$rss'K) > threshold('$threshold'K) - Kill Failed.' 
        fi
    fi
done

这里被杀掉的进程由于有使用进程监控器监控,被杀掉后会自动重启。

2 内存监控,超过阀值则杀掉并重启

#!/bin/bash

#判断进程数量
live=`ps -efH | grep 'agent.js' | grep -v 'grep' | wc -l`
if [ $live -eq 0 ]; then
	/usr/local/bin/node /var/www/ebay-ap/agent.js 2>&1 >> /var/www/ebay-ap/log.txt &
fi

#判断是否超过阀值
threshold=204800

cmm="/usr/bin/kill"
if [ ! -f "$cmm" ]; then
    cmm="/bin/kill"
fi

ps aux | grep 'agent.js' | grep -v grep | awk '{print $2"|"$6}' | cat | while read line
do
    pid=`echo $line | cut -d "|" -f 1`
    rss=`echo $line | cut -d "|" -f 2`

    if [ $rss -gt $threshold ]; then
        date=`date "+%Y-%m-%d %H:%M:%S"`
        kill=`$cmm -9 $pid`
        if [ $kill ]; then
            echo $date -- PID: ${pid} Kill Failed [RSS: ${rss} gt ${threshold}]
        else
            echo $date -- PID: ${pid} Kill Success [RSS: ${rss} gt ${threshold}]
            /usr/local/bin/node /var/www/ebay-ap/agent.js 2>&1 >> /var/www/ebay-ap/log.txt &
        fi
    fi
done

如果进程异常退出了,则自动拉起。然后判断内存是否超标,如果超标则先杀掉然后再重启。这个方式看起来粗暴了一些,不过是非常有效的。

3 封杀某个区域的IP

#下载中国IP库
wget http://www.ipdeny.com/ipblocks/data/countries/cn.zone

#运行以下脚本
#!/bin/bash

COUNTRY = "cn"
IPTABLES = /sbin/iptables
EGREP = /bin/egrep

if [ "$(id -u)" != "0" ]; then
   echo "you must be root" 1>&2
   exit 1
fi

resetrules() {
    $IPTABLES -F
    $IPTABLES -t nat -F
    $IPTABLES -t mangle -F
    $IPTABLES -X
}

resetrules

for c in $COUNTRY
do
        country_file = $c.zone

        IPS = $($EGREP -v "^#|^$" $country_file)
        for ip in $IPS
        do
           echo "blocking $ip"
           $IPTABLES -A INPUT -s $ip -j DROP
        done
done

exit 0

4 防DD脚本

#!/bin/sh

IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"
IPT="/sbin/iptables"

KILL=1

# NO_OF_CONNECTIONS默认是150,这是一个经验值,如果服务器性能比较高,可以设置200以上,以避免误杀
NO_OF_CONNECTIONS=150

# 解锁的时间,单位为秒,可以设置更长时间
BAN_PERIOD=86400

# 解除对IP的封锁 过程就是运行一个睡眠脚本
unbanip()
{
	# 产生解除IP封锁时用到的随机脚本文件
        UNBAN_SCRIPT=`mktemp /tmp/unban.XXXXXXXX`

	# 临时文件
        TMP_FILE=`mktemp /tmp/unban.XXXXXXXX`

	# 将被解除封锁的IP
        UNBAN_IP_LIST=`mktemp /tmp/unban.XXXXXXXX`

	# 产生解除IP封锁的脚本内容
        echo '#!/bin/sh' > $UNBAN_SCRIPT
	# $BAN_PERIOD睡眠时间,表示$UNBAN_SCRIPT睡眠多久后继续
        echo "sleep $BAN_PERIOD" >> $UNBAN_SCRIPT

	# 输入重定向,行对于$line变量,是当前需要堵塞的IP,脚本运行过程中产生
	while read line; do
		# 解除IP封锁
		echo "$IPT -D INPUT -s $line -j DROP" >> $UNBAN_SCRIPT

		# 把将要解除堵塞的IP写入$UNBAN_IP_LIST
		echo $line >> $UNBAN_IP_LIST
	done < $BANNED_IP_LIST

        # 从$IGNORE_IP_LIST中去掉$UNBAN_IP_LIST,把结果写入$TMP_FILE(差集)
        echo "grep -v --file=$UNBAN_IP_LIST $IGNORE_IP_LIST > $TMP_FILE" >> $UNBAN_SCRIPT

	# 移动$TMP_FILE到$IGNORE_IP_LIST
        echo "mv $TMP_FILE $IGNORE_IP_LIST" >> $UNBAN_SCRIPT

	# 删除$UNBAN_SCRIPT
        echo "rm -f $UNBAN_SCRIPT" >> $UNBAN_SCRIPT
	# 删除$UNBAN_IP_LIST
        echo "rm -f $UNBAN_IP_LIST" >> $UNBAN_SCRIPT
	# 删除$TMP_FILE,经过上面的移动操作,$TMP_FILE其实已经不存在
        echo "rm -f $TMP_FILE" >> $UNBAN_SCRIPT

	# 在后台运行$UNBAN_SCRIPT
	. $UNBAN_SCRIPT &
}


TMP_PREFIX='/tmp/ddos'
TMP_FILE="mktemp $TMP_PREFIX.XXXXXXXX"

# 产生临时文件,存放已经被堵塞的IP
BANNED_IP_LIST=`$TMP_FILE`

# 产生临时文件,存放当前可能被堵塞的IP
BAD_IP_LIST=`$TMP_FILE`

#取回IP列表并按照数量从高到底排序
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LIST

# 如果配置为需要堵塞
if [ $KILL -eq 1 ]; then            
	# 超过100就记录
	NUM_CONNECTIONS=100  
	# 按照日期存放
	CNTS_LOG="/usr/local/ddos/$(date +%Y)/$(date +%m)/"
	mkdir -p $CNTS_LOG
	CNTS_LOG="$CNTS_LOG$(date +%Y%m%d).log"
	while read line; do
		CURR_CONN=$(echo $line | cut -d" " -f1)
		CURR_IP=$(echo $line | cut -d" " -f2)
		if [ $CURR_CONN -lt $NUM_CONNECTIONS ]; then
			break
		fi
		echo "$CURR_IP with $CURR_CONN connections at `date`" >> $CNTS_LOG
	done < $BAD_IP_LIST

        IP_BAN_NOW=0
        while read line; do
		# 当前这个IP有多少个连接
                CURR_LINE_CONN=$(echo $line | cut -d" " -f1)            
		# 当前IP
                CURR_LINE_IP=$(echo $line | cut -d" " -f2)          

		# 如果这个IP链接数小于预设,终止(因为数据经过排序)
                if [ $CURR_LINE_CONN -lt $NO_OF_CONNECTIONS ]; then     
			break
                fi

		# 计算当前IP在$IGNORE_IP_LIST出现了多少次
                IGNORE_BAN=`grep -c $CURR_LINE_IP $IGNORE_IP_LIST`
		# 如果当前IP已经在$IGNORE_IP_LIST,跳过,可以通过这个方式设置永不堵塞某些IP
                if [ $IGNORE_BAN -ge 1 ]; then
			continue
                fi

		# 进入到这里表示当前必定有IP要被堵塞
                IP_BAN_NOW=1

		# 添加堵塞了的IP到当前堵塞列表,$BANNED_IP_LIST会应用到unbanip函数
                # 如果不实现自动解锁,注释如下行
                echo $CURR_LINE_IP >> $BANNED_IP_LIST

		# 添加堵塞了的IP到$IGNORE_IP_LIST
                # 如果不实现自动解锁,注释如下行
                echo $CURR_LINE_IP >> $IGNORE_IP_LIST
                
		# 开始iptables封锁
                $IPT -I INPUT -s $CURR_LINE_IP -j DROP
                
        done < $BAD_IP_LIST

	# $IP_BAN_NOW等于1表示有IP被封锁了
        if [ $IP_BAN_NOW -eq 1 ]; then
		# 发送通知

		# 同时开始运行解除堵塞程序
                #unbanip                             
        fi
fi

# 清除临时产生的文件
rm -f $TMP_PREFIX.*

函数unbanip实际就是运行一个睡眠脚本,可以把其去掉(不自动解封):

#!/bin/sh

IGNORE_IP_LIST="/usr/local/ddos/ignore.ip.list"
IPT="/sbin/iptables"
KILL=1
NO_OF_CONNECTIONS=150

TMP_PREFIX='/tmp/ddos'
TMP_FILE="mktemp $TMP_PREFIX.XXXXXXXX"


BAD_IP_LIST=`$TMP_FILE`
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LIST

if [ $KILL -eq 1 ]; then
        IP_BAN_NOW=0
        while read line; do
		# 当前这个IP有多少个连接
                CURR_LINE_CONN=$(echo $line | cut -d" " -f1)            
		# 当前IP
                CURR_LINE_IP=$(echo $line | cut -d" " -f2)          

		# 如果这个IP链接数小于预设,终止(因为数据经过排序)
                if [ $CURR_LINE_CONN -lt $NO_OF_CONNECTIONS ]; then     
			break
                fi

		# 计算当前IP在$IGNORE_IP_LIST出现了多少次
                IGNORE_BAN=`grep -c $CURR_LINE_IP $IGNORE_IP_LIST`
		# 如果当前IP已经在$IGNORE_IP_LIST,跳过,可以通过这个方式设置永不堵塞某些IP
                if [ $IGNORE_BAN -ge 1 ]; then
			continue
                fi

		# 进入到这里表示当前必定有IP要被堵塞
                IP_BAN_NOW=1
                
		# 开始iptables封锁
                $IPT -I INPUT -s $CURR_LINE_IP -j DROP
        done < $BAD_IP_LIST

	# $IP_BAN_NOW等于1表示有IP被封锁了
        if [ $IP_BAN_NOW -eq 1 ]; then
		# 发送通知 CURL                           
        fi
fi

# 清除临时产生的文件
rm -f $TMP_PREFIX.*

如果仅仅希望监控一下哪些IP链接数过多,则可以如下改造:

#!/bin/sh

CNTS_LOG="/root/dd/log.txt"
IGNORE_IP_LIST="/root/dd/ignore.ip.list"
CONNECTIONS=5
 
TMP_PREFIX='/tmp/dd'
TMP_FILE="mktemp $TMP_PREFIX.XXXXXXXX"

BAD_IP_LIST=`$TMP_FILE`
netstat -ntu | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr > $BAD_IP_LIST

while read line; do
    CURR_CONN=$(echo $line | cut -d" " -f1)
    CURR_IP=$(echo $line | cut -d" " -f2)
    if [ $CURR_CONN -lt $CONNECTIONS ]; then
        break
    fi

    IGNORE=`grep -c $CURR_LINE_IP $IGNORE_IP_LIST`
    if [ $IGNORE -ge 1 ]; then
        continue
    fi

    echo "`date "+%Y-%m-%d %H:%M:%S"`|$CURR_IP|$CURR_CONN" >> $CNTS_LOG
done < $BAD_IP_LIST
 
rm -f $TMP_PREFIX.*

Linux Bash Shell编程

Bash Shell基础

1 Bash Shell

1.1 系统的合法shell与/etc/shells
Linux下可以使用的shell,可以检查一下/etc/shells这个文件,有下面几个可以用的shell:

#CentOS 7.X中的输出
cat /etc/shells

/bin/sh             #/bin/bash的链接
/bin/bash
/sbin/nologin       #用户不具备Shell环境(一般指无法登陆),指定这个值

/usr/bin/sh
/usr/bin/bash
/usr/sbin/nologin

/bin/tcsh
/bin/csh

系统某些服务在运行过程中,会去检查用户能够使用的Shell,而这些Shell的查询就是借助/etc/shells这个文件。在/etc/passwd这个文件内,每行的最后一个段指明了用户使用的shell(如果一个用户不能登录,通常是/sbin/nologin)。

1.2 Bash Shell功能
1) 命令记忆能力(history)
在用户的主文件夹内的.bash_history用来记录历史记录,但是它记录的是前一次登录以前所执行过得命令,而至于这一次登录所执行的命令都被暂存在临时内存中,当注销系统后,该命令记忆才会记录到.bash_history中。
2) 命令与文件补全功能
3) 命令别名设置功能(alias)
可以使用alias直接设置命令别名,直接输入alias可以输出当前存在的命令别名。

alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l.='ls -d .* --color=auto'
alias ll='ls -l --color=auto'
alias ls='ls --color=auto'
alias mv='mv -i'
alias rm='rm -i'
alias which='alias | /usr/bin/which --tty-only --read-alias --show-dot --show-tilde'

4) 作业控制、前台、后台控制(job control, foreground, background)
5) 程序脚本
6) 通配符(Wildcard)

1.3 Bash Shell的内置命令: type
为了方便Shell的操作,Bash已经内置了很多命令,利用type可以查看命令是否是内置命令。

2 Shell的变量

2.1 变量的显示与设置: echo unset
在Bash当中,当一个变量名称未被设置时,默认的内容是空的。变量的设置规则:
1) 变量与变量内容以一个等号连接,等号两边不能接空格,注意,如果有空格则是逻辑比较
2) 变量名称只能是英文字母和数字,但开头不能是数字
3) 变量内容如含有空格,需要使用单引号或双引号括起来(如没有引号括起来,但是包含了转义,最终会转义输出),但双引号内特殊字符保持本性,单引号内的任何字符都是一般文本
4) 可以使用转义符将特殊字符变成一般字符
5) 如需要引用其它命令的结果,可以使用反单引号或$()语法,比如`uname –r`和$(uname -r)等同
6) 如要为变量增加内容,可以使用$变量名或${变量名}累加内容(不需要所谓的连接符)
7) 如变量需要在其它子进程中执行,需要以export来使变量变成环境变量:export PATH。
8) 通常大写字符为系统默认变量
9) 取消变量的方法是使用unset 变量名称

2.2 环境变量

用env查看环境变量:

env

XDG_SESSION_ID=167086
HOSTNAME=xxxxx  #主机名
TERM=xterm
SHELL=/bin/bash  #使用的是哪个Shell
HISTSIZE=1000  #历史记录大小
SSH_CLIENT=113.88.168.31 17444 22
SSH_TTY=/dev/pts/3
USER=root
LS_COLORS=
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin  #执行文件查找的路径
PWD=/root
LANG=en_US.UTF-8 #语系数据,中文编码通常是zh_CN.UTF-8
HISTCONTROL=ignoredups
SHLVL=1
HOME=/root  #代表用户主文件夹
LOGNAME=root
SSH_CONNECTION=113.88.168.31 17444 120.24.42.192 22
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/0
_=/usr/bin/env

用set查看所有变量(含环境变量与自定义变量)

PS1     提示符号设置,可以man bash查询PS1的相关说明
$       当前的Shell的PID,$也是一个变量,要引用时使用$$
?       上个命令的回传码,一般,一个命令成功执行,则会回传一个0值
OSTYPE, HOSTTYPE, MACHTYPE 主机硬件与内核的等级

自定义变量转成环境变量
子进程会继承父进程的环境变量,不会继承自定义变量。直接执行export 变量名,可以把变量转成环境变量,如果要相反操作,用declare。

2.3 影响显示结果的语系变量(locale)
可以使用locale来查询Linux支持多少语系。locale –a其实是列出/usr/lib/locale里面的文件。当设置了LANG或者是LC_ALL时,则其他的语系变量就会被这两个变量所替代。LC_ALL是整体的语系变量,它在/etc/sysconfig/i18n中设置:LANG=”zh_CN.UTF-8”。(CentOS 7.x中对应的配置文件是/etc/locale.conf文件)

2.4 变量键盘读取、数组与声明: read,array,declare
1) read

用法:
read [-pt] variable
参数:
-p 后面可以接提示符
-t 后面可以接等待秒数
 
例子:
read –p “Please putin your name:” –t 30 named
等待用户30秒输入它的名字赋值给named变量

2) declare / typeset
declare / typeset都用来声明变量的类型。

用法:
declare [-aixr] variable
参数:
-a 定义为数据
-i 定义为整数
-x 定义成环境变量
-r 定义变量为只读

默认Bash对于变量有几个基本定义:
变量类型默认为字符串,所以若不指定变量类型,则1+2为一个字符串而不是计算式
Bash环境中的数值运算,默认最多仅能到达整数,所以1/3结果是0

另,declare +x sum 把 – 换成 + 代表取消操作。一般,除非需要特别指定变量类型,否则都不需要使用declare关键字。

3) 数组变量类型
在Bash里,数组的设置方式:var[index]=content

2.5 与文件系统及程序的限制关系: ulimit
Bash是可以限制用户的某些系统资源的,包括可以打开的文件数量、可以使用的CPU时间、可以使用的内存总量等。

用法:
ulimit [-SHacdfltu] [配额]
-H hard limit
-S soft limit,可以超过,但有警告值,必须比hard小
-a 后面不接任何参数,可列出所有的限制额度
-f 此shell可以创建的最大文件容量
-d
-l 可用锁定的内存量
-t 可使用的最大CPU时间
-u 单用户可以使用最大进程数量

2.6 变量内容的删除、替代与替换

3 命令别名与历史命令

3.1 命令别名设置:alias, unalias
3.2 历史命令:history

4 Bash Shell的操作环境

4.1 路径与命令查找顺序
命令运行顺序:
1) 以相对/绝对路径执行命令,如 /bin/ls 或 ./ls (最优先)
2) 由alias找到该命令来执行
3) 由bash内置(bulitin)命令来执行
4) 通过$PATH变量的顺序找到第一个命令来执行

4.2 bash的登录与欢迎信息:/etc/issue, /etc/motd

#查看/etc/issue:
CeontOS release 5.6 (Final)
Kernel \r on an \m

#如同$PS1变量一样,issue这个文件的内容也可以使用反斜杠为变量调用:
\d  本地时间的日期
\l  显示第几个终端机接口
\m  显示硬件等级
\n  显示主机网络名称
\o  显示domain name
\r  操作系统的版本(相当于uname -r)
\t  显示本地端时间的时间
\s  操作系统名称
\v  操作系统版本

如果你想要让用户登录后取得一些信息,那么可以将信息加入/etc/motd里面,这样所有人登录后都会获取此信息。

4.3 Bash的环境配置文件

4.3.1 登录Shell 和 非登录Shell
登录Shell需要完整的登录流程,非登录Shell取得Bash接口的方法不需要重复登录的流程。

登录Shell 和 非登录Shell它们读取的配置文件数据并不一样。
登录Shell只会读取如下两个配置文件:
1) /etc/profile: 这是系统整体的设置,最好勿改动此文件
2) ~/.bash_profile 或 ~/.bash_login 或 ~/.profile: 属于用户个人设置,要改自己的数据就放这里。

4.3.2 /etc/profile
这个配置文件可以利用用户的标示符UID来决定很多重要的变量数据。每个用户登录取得Bash时一定会读取的配置文件。这个文件设置的变量主要有:PATH, MAIL, USER, HOSTNAME, HISTSIZE。 除此还调用外部数据:
1) /etc/inputrc
/etc/profile会主动判读用户有没有自定输入的按键功能,如果没有,它就会决定设置”INPUTRC=/etc/inputrc”这个变量。此文件内容为Bash的热键等数据。
2 /etc/profile.d/*.sh
这个目录下面的文件规定了Bash操作接口的颜色、语系、ll与ls命令的命令别名、vi的命令别名、which的命令别名等。如果需要帮所有用户设置一些共享的命名别名时,可以在这个目录下面创建.sh的文件,并写入数据。

4.3.3 /etc/sysconfig/i18n
这个文件是由/etc/profile.d/lang.sh调用的。bash默认使用何种语系的配置文件。

4.3.4 ~/.bash_profile
~/.bash_profile 或 ~/.bash_login 或 ~/.profile从左到右,只会读取其中一个。查看~/.bash_profile发现,它其实还运行了. ~/.bashrc

在CentOS的登录Shell环境下,最终被读取的配置文件是”~/.bashrc”这个文件。所以可以将自己的偏好设置写入该文件。

4.3.5 source: 读入环境配置文件的命令

用法:
source 配置文件名
例子:source ~/.bashrc 和 . ~/.bashrc一样

利用source或小数点都可以将配置文件的内容读进当前的shell环境中。

4.3.6 ~/.bashrc
非登录Shell仅会读取~/.bashrc。查看其内容发现它会主动调用/etc/bashrc,而它定义如下数据:
依据不同的UID规定umask的值和提示符(PS1)
调用/etc/profile.d/*.sh的设置

4.3.7 其它相关配置文件
/etc/man.conf
规定了使用man的时候man page的路径到哪里去寻找。
~/.bash_history
~/.bash_logout
当注销bash后系统再所完什么操作后才离开。

4.4 终端机的环境设置:stty, set

4.5 通配符与特殊符号

*       0个或多个
?       任意一个字符
[]      在其中的一个字符
[-]     如[a-z] [0-9]
[^]     排除之中的字符的一个字任意字符

#除了通配符,bash中的特殊符号:
#       注释
\       转移符号
|       管道
;       分隔符号
~       用户的主文件夹
$       变量引用符
&       后台运行
!       逻辑运算非
/       目录符
>, >>   数据流重定向,输出导向

5 数据流重定向

执行一个命令的时候,这个命令可能会由文件读入数据,经过处理之后,再将数据输出到屏幕上。标准输出与标准错误输出这两个命令默认都是输出到屏幕上面来。标准输出指的是命令执行所回传的正确的信息,而标准错误输出可理解为命令执行失败后,所回传的错误信息。

数据流重定向可以将stdout与stderr分别传送到其它的文件或设备去,所用到的特殊字符:
1) 标准输入(stdin): 代码为0,使用< 或 <<(指定结束输入的定界符); [bash] cat > catfile << "eof" [/bash] cat从标准输入接收输入然后显示,这里定位到catfile中,输入遇到定界符eof即刻结束输入。 2) 标准输出(stdout):代码为1,使用> 或 >>
3) 标准错误输出(stderr): 代码为2,使用2> 或 2>>

/dev/null垃圾桶设备与特殊写法
丢弃错误信息
2> /dev/null
如果所有信息都丢弃或都写入一个文件
> /dev/null 2>&1 或 &> /dev/null 此为特殊写法

标准输入: < 与<<
将原本需要有键盘输入的数据改由文件内容来替代。

命令执行的判断依据(; , && ||)
使用逗号可以在一行中连续执行多个命令
每个命令执行都有回传码,成功执行回传0,失败回传1,bash使用$?在动态记录这个这个值(?是一个变量,$也是变量,表示Bash的进程,使用$$来引用)。&& 和 ||可以用来分隔两个命令,使用&&时表示第一个命令执行成功则执行第二个,||表示第一个执行失败则执行第二个(判断依据是当前bash的$?的记录,所以当有多个&& 和 ||时需要注意,它判断的依据不是前面的命令,而是当前的bash记录的$?,当然,命令的执行会影响到$?值)

6 管道命令(pipe)

管道命令使用 | 界定符号。管道命令 | 仅能处理经由前面一个命令传来的正确信息,也就是标准输出的信息,对于标准错误输出并没有直接处理的能力。

在每个管道后面接的第一个数据必定是命令,而且这个命令必须要能接收标准输入的数据才行,这样的命令才可以是管道命令,管道命令有两个要注意的地方:
管道命令仅会处理标准输出,对于标准错误输出会予以忽略
管道命令必须要能够接收来自前一个命令的数据成为标准输入继续处理才行。

6.1 选取命令: cut, grep
一般,选取信息通常是针对行来分析的,并不是整篇信息分析的。

cut
主要用途在于将同一行里面的数据进行分解。

用法:
cut –d ‘分隔符’ -f fields
cut –c 字符范围
参数:
-d 后面接分隔字符,与-f 一起使用
-f 依据-d的分隔字符将一段信息切割为数段,用-f 取出第几段的意思
-c 以字符的单位取出固定字段区间
 
例子:
echo $PATH | cut -d ‘:’ -f 5 用:分割,取出第5段
echo $PATH | cut –d ‘:’ -f 3,5 用:分割,取出第3和第5段

cut在处理多空格相连的数据时比较困难。

grep
分析一行信息,如果符合条件则把整行信息输出。

用法:
grep [-acinv] [--color=auto] ‘查找字符串’ filename
参数:
-a 将binary文件以text文件的方式查找书籍
-c 计算找到’查找字符串’的次数
-i 忽略大小写
-n 输出行号
-v 反向选择,即显示出不符合的行
--color=auto 将找到的关键字部分加上颜色显示
 
例子:
last | grep ‘root’ | cut –d ‘ ’ -f 1
grep -n "conf" /etc/*  #找出文件含有conf字符串的行(文件)

6.2 排序命令:sort, wc, uniq

sort
对行进行排序,排序的字符与语系的编码有关,建议使用LANG=C来让语系统一。

用法:
sort [-fbMnrtuk] [file or stdin]
参数:
-f 忽略大小写
-b 忽略最前面的空格符
-M 以月份的名字来排序
-n 使用纯数字进行排序(默认以文字类型来排序)
-r 反向排序
-u 就是uniq,去重复
-t 分割符号,默认是用[Tab]来分隔
-k 以哪个区间来进行排序
 
例子:
cat /etc/passwd | sort -t ':' -k 3 –n
用冒号分隔取第三段当做纯数字来排序(-n 表示纯数字)

uniq
排序完成,将重复的行去掉。

用法:
uniq [-ic]
参数:
-i 忽略大小写
-c 进行计数
 
例子:
last | cut -d ‘ ‘ -f 1 | sort | uniq

wc

用法:
wc [-lwm]
参数:
-l 行数
-w 字数
-m 字符数

6.3 双向重定向: tee
tee会同时将数据流送到文件与屏幕,而输出到屏幕的,其实就是stdout,可以让下个命令继续处理。

用法:
tee [-a] file
参数:
-a 以累加(append)的方式将数据加入file当中
 
例子:
last | tee last.list | cut -d “ ” -f 1
利用tee保存一份数据到last.list并输出到屏幕。

6.4 字符转换命令:tr,col,join,paste,expand

tr

tr [-ds] SET1
参数:
-d 删除信息当中的SET1这个字符串
-s 替换掉重复的字符
 
例子:
last | tr ‘[a-z]’ ‘[A-Z]’
cat /root/passwd | tr –d ‘\r’

col

col [-xb]
参数:
-x 将tab键转换成对等的空格键
-b 在文字内有反斜杠(/)时,仅保留反斜杠最后接的那个字符

join

join [-ti12] file1 file2
参数:
-t join默认以空格符分割数据,并且对比第一个字段的数据,如两个文件相同,则将两条数据练成一行,且第一个字段放在第一个,-t指定分割符号
-i 忽略大小写
-1 数字1,代表第一个文件用药哪个字段来分析的意思
-2代表第二个文件用药哪个字段来分析
 
/etc/passwd的第四个字段是GID,哪个GID记录在/etc/group当中的第三个字段
join -t ‘:’ -1 4 /etc/passwd -2 3 /etc/group

相当关系数据库中的关联引用。注:在使用join之前,你所需要处理的文件应该要事先经过排序处理。

paste
直接将两行贴在一起,且中间以[tab]键隔开。

paste [-d] file1 file2
参数:
-d 后面可以接分隔符,模式是[tab]
- 如果file部分写成-,表示来自标准输入的数据
 
例子:
paste /etc/passed /etc/shadow
cat /etc/group | paste /etc/passwd /etc/shadow - | head –n 3
里面的横杆(-)表示来自cat的输出

expand
将[tab]按键转成空格键。

expand [-t] file
参数:
-t 后面可以接数字,一般,一个[tab]按键可以用8个空格键替换,也可以自行定义一个[tab]按键代表多少个字符。

6.5 切割命令:split
将大文件依据文件大小或行数来切割成小文件。

split [-bl] file PREFIX
参数:
-b 后接要切割成的文件大小,单位是b, k, m等
-l 以行数进行切割
PREFIX 代表前导符,可以作为切割文件的前导文字

6.6 参数代换:xargs
xargs再产生某个命令的参数。xargs可以读入stdin的数据,并且以空格符或断行字符进行分辨,将stdin的数据分割成arguments。使用xargs的原因是很多命令其实并不支持管道命令,因此可以通过xargs来提供该命令引用标准输入之用。

用法:
xargs [-0epn] command
参数:
-0 如果stdin含有特殊字符,这个参数可以将它还原成一般字符。
-e 这个是EOF意思。后面可以接一个字符串,当xargs分析道这个字符串时,就会停止工作。
-p 在执行每个命令的参数时,都会询问用户的意思
-n 后面接次数,每次command命令执行时,要使用几个参数的意思
 
例子:
cut –d ‘:’ –f1 /etc/passwd | xargs –p –n 5 finger
这样finger将从前面获取5个参数。
 
find /sbin –perm +7000 | xargs ls –l
通过xargs把前面的输出作为后面命令的参数,这个就是让ls原本不支持管道的命令间接支持管道的用法。

6.7 关于减号 – 的用途
在管道命令当中,经常会使用到前一个命令的stdout作为这次的stdin, 某些命令需要用到文件名来进行处理时,该stdin与stdout可以利用减号来替代(经过管道后前面的stdout就是后面的stdin,可以用-来引用前面的stdout或叫当前命令的stdin)。

tar –cvf – /home | tar –xvf –
前面把/home压缩到stdout,被管道带到下一个命令,下个命令使用减号引用管道带过来的前一个命令的stdout,作为其输入,然后再接压缩到stdout。

Bash Shell 正则表达式
1 基础正则表达式
1.1 语系对正则表达式的影响
使用正则表达式时,需要留意当时环境的语系,否则结果可能有差异。可以使用统一语系,比如LANG=C

[:alnum:]       英文大小写字符和数字,即0-9,a-z, A-Z
[:alpha:]       英文大小写字符,即a-z, A-Z
[:blank:]       空格和[Tab]
[:cntrl:]       键盘上控制键,即包括CR, LF, Tab, Del等
[:digit:]       数字,即0-9
[:graph:]       除了空格键以为所有按键
[:lower:]       小写字母
[:print:]       可以被打印的字符
[:punct:]       标点符号
[:upper:]       大写字母
[:space:]       空格
[:xdigit:]      十六进制的数字类型

1.2 基础正则表达式字符

^word        以word开头
word$        以word结尾
.        一个任意字符
\        转义字符
*        重复任意次
[list]       选取列出来的其中一个字符
[n1-n2]      选择n1到n2之间的一个字符,比如[0-9]
[^list]      选取排除了列出来的字符的其它任一字符
\{n,m\}      重复n次,最多不超m次,如果是\{n \}则表示重复n次,如果是\{n,\}则上重复n次以上

1.3 扩展正则表达式

+       重复一次或一次以上
?       重复零次或一次
|       用或的方式找出数个字符串
()      分组
()+     重复组

Bash Shell 工具- sed

rpm -qa | grep sed
sed-4.2.2-5.el7.x86_64

工具sed并不是Bash Shell的组成部分(grep cut等这些是内置命令),不过这个工具是Bash Shell编程不缺少的部分。

sed本身是一个管道命令,可以分析标准输入,而且sed还可以将数据进行替换、删除、新增、选取特定行等。

用法:
sed [-nefr] [动作]
参数:
-n 使用安静模式,一般,所有来自STDIN的数据都会列出到屏幕上,加入-n后,只有经过sed处理的那行才会被列出
-e 直接在命令行模式上进行sed的动作编辑
-f 直接将sed的动作写在一个文件内,-f filename则可以执行filename内的sed动作
-r sed的动作支持的是扩展正则语法
-i 直接修改读取的文件内容
 
动作说明:
[n1,[,n2]]function
n1, n2 选择进行动作的行数
 
function 参数
a 新增,a后可以接字符串
c 替换
d 删除
i  插入
p 打印
s 替换 通常可以搭配正则,如1,20s/old/new/g

例子:
1) 以行为单位的新增/删除
nl /etc/passwd | sed ‘2,5d’
将2~5行删除,d表示删除,sed后面接的动作务必用单引号括住,应该应该是sed –e,不用也可以。如果要删除3行以后所有行,nl /etc/passwd | sed ‘3,$d’,这个$表示最后一行,如果只要删除第二行,则nl /etc/passwd | sed ‘2d’

nl /etc/passwd | sed ‘2a vfeelit’
在第二行后加上vfeelit字符串,如果把a改成i,则是在第二行之前插入,如果要增加多行,每行后面需要使用转义字符分隔。

2) 以行为单位的替换与显示
nl /etc/passwd | sed ‘2,5c vfeelit’
这里的c表示替换,2到5行用给定的字符替换。

nl /etc/passwd | sed –n ‘5,7p’
这里的-n表示只有经过处理的打印出来(p),sed是把所有的都进行输出的,比如要列出11-20行,没有sed工具之前需要这样:head –n 20 | tail –n 10

3) 部分数据的查找并替换
sed的查找与替换与vi相当类似:
sed ‘s/查找字符串/新字符串/g’ 字母s前可以限定行数,比如2,10

cat /etc/man.config | grep ‘MAN’ | sed ‘s/#.*$//g’ | sed ‘/^$/d’

4) 直接修改文件内容
sed –s ‘s/\.$/\!/g’ regular.txt
直接在regular.txt中修改最后字符为.的修改为!

sed的”-i”参数可以直接修改文件内容。

Bash Shell 工具- awk

rpm -qa | grep awk
gawk-4.0.2-4.el7.x86_64

awk主要是处理每一行的字段内的数据,而默认的字段的分隔符为空格或[tab]键。

用法:
awk ‘条件类型1 {动作1} 条件类型2 {动作2} ..’ filename

注:注意其严格的格式,awk后接单引号,动作需要用大括号括起来。
例子:
last –n 5 | awk ‘{print $1 “\t” $3}’
显示每一行的第一和第三字段。

每一行的每个字段都是有变量名称的,那就是$1,$2 … 等变量名称。还有$0,表示整行数据的意思。

整个awk处理流程:
-读入一行,将数据填入$0,$1,$2这些变量中
-依据条件类型,判断是否执行后面的动作
-做完所有条件和动作
-如果还有后续行,重复

awk以行为单位,以字段为最小处理单位。至于数据有几行几列,则需要awk内置变量的支持:

NF      每一行拥有的字段总算
NR      带便目前处理的是第几行
FS      目前的分隔字符,默认是空格键

例子:
last –n 5 | awk ‘{print $1 “\t lines: “ NR “\t coleus:” NF}’

awk的逻辑运算符跟一般的没有差别,==表示判断是否等于,赋值使用=
例子:

cat /etc/passwd | awk ‘{FS=”:”} $3<10 {print $1 “\t ” $3}’

这里第一行没有正确显示,因为读入第一行时,那些$1,$2变量还是以空格作为分隔的,虽然用来FS=”:”,但是是从第二行开始生效的。可以使用BEGIN这个关键字预先设置awk的变量。

cat /etc/passwd | awk ‘BEGIN {FS=”:”} $3<10 {print $1 “\t ” $3}’

几个重要说明:
所有awk的动作,即在{}内的动作,如果有需要多个命令辅助时,可利用分号分隔
逻辑运行如果是等于判断务必使用==
格式化输出时,在printf的格式设置当中,务必加上\n才能进行分行
与bash shell变量不同,在awk中,变量可以直接使用,不需要加上$符号

Bash Shell 脚本
1 Shell Script入门
Shell Script编写注意事项:
1) 命令的执行从上而下,从左而右地分析与执行
2) 命令、参数间的多个空白会被忽略,空白行也被忽略,[tab]按键被视为空格键
3) 如果读取到一个Enter符号(CR),就尝试开始执行命令(以行为分隔)
4) #符号为注释

执行Shell Script方法:
1) 直接执行:Shell Script文件必须要具备可读可执行的权限,然后:
使用绝对路径来执行 比如/root/shell.sh
使用相对路径来执行 比如./shell.sh
变量PATH功能,将shell.sh放在PATH指定的目录内,如/bin/,然后让shell自动搜索PATH获取这个脚本并执行

2) 以bash进程来执行:通过bash shell.sh 或sh shell.sh来执行
如果shell.sh在/bin内具有rx的权限,那就直接输入shell.sh即可执行该脚本程序。因为/bin/sh是/bin/bash的链接文件,使用sh就是间接使用bash,此时shell.sh只要有r的权限即可被执行。

Shell Script组成部分
1) 第一行#!/bin/bash 声明这个script使用的shell名称,这样就能根据声明加载Shell(这里是bash)的相关环境配置文件(一般来说就是非登录Shell的~/.bashr)
2) 程序说明部分,以#开头,添加必要的说明信息
3) 主要环境变量声明
4) 程序部分
5) 告知执行结果
一个命令的执行是否成功,可以使用$?这个变量来查看。那么也可以利用exit这个命令来让程序中断,并且回传一个数值给系统。比如exit 0,这代表离开Script并且回传一个0给系统,如果执行echo $?则可得到0的值。利用exit n (n是数字)的功能,可以自定义错误信息。

范例:
1) 交互式脚本:变量内容由用户决定

#!/bin/bash
read –p “Please input you full name: ” fullname #提示用户输入
echo –e “\n Your full name is: $fullname”

2) 数值运算:简单的加减乘除
用declare来把变量定义成整数后才能进行加减运行,此外还可以利用$((计算式))来进行数值运算。Bash Shell里面仅支持整数。

#!/bin/bash
#
firstnu=10
secnu=6
total=$(($firstnu*$secnu))
echo –e “\n The result is: $total”

在数值运行上,也可以使用declare –i total=$firestnu*$secnu。

Shell Script的执行方式区别
脚本的执行除了以上提到的方式还可以利用source或小数点来执行。

1) 利用直接执行的方式来执行
直接命令执行(绝对路基、相对路径或$PATH内),或利用bash/sh来执行脚本时,该脚本都会使用一个新的bash环境来执行脚本内的命令。当子进程完成后,子进程内的各项变量或操作将会结束而不会传回到父进程中。
2) 利用source来执行脚本:在父进程中执行

2 判断式
2.1 利用test命令的测试功能
以下只列常用:

关于某个文件的“文件类型”判断,如test –e feliename表示是否存在

-e 		该文件是否存在
-f		该文件是否存在并且是文件
-d		该文件是否存在并且是目录

关于文件权限的检测,如test –r filename表示是否可读(但root除外)

-r		检测文件是否存在并且可读
-w 		检测文件是否存在并且可写
-x 		检测文件是否存在并且可执行
-u 		检测文件是否存在并且具有SUID属性
-g 		检测文件是否存在并且具有SGID属性
-k 		检测文件是否存在并且具有Sticky bit属性

关于两个整数之间的判断,如test n1 –eq n2

-eq		两数值相等 equal
-ne		两数值不等 not equal
-gt		n1大于n2 greater than
-lt		n1小于n2 less than
-ge		n1大于等于n2 grater than or equal
-le		n1小于等于n2 less than or equal

判定字符串的数据

test –z string	判定字符串是否为0,若string为空字符串,则为true
test –n string	判定字符串是否为非0,若string为空字符串,则为false
test str1=str2	判定str1是否等于str2,若相等,则回传ture
test str1!=str2	判定str1是否不等于str2,若相等,则回传false

多重条件判定,如test –r filename –a –x filename

-a		两个条件同时成立
-o		其中一个条件成立
!		取反,如test ! –x file,当file不具有x时,回传true

2.2 利用判断符号[]
可以使用[]来替代test,如[ -z “$HOME” ]; echo $?
注:在bash中用中括号作为shell的判断式时,必须要注意中括号的两端需要有空格符来分隔,如[空格”$HOME”空格==空格”$MAIL”空格]

2.3 Shell Script的默认变量($0,$1….)

Script针对参数已经设置好一些变量名称:

/path/to/scriptname  opt1  opt2  opt3
$0	             $1    $2    $3

执行的脚本文件名为$0变量,第一个接的参数就是$1。除此,还有一些特殊变量:

$#		代表后接的参数个数
$@		代表”$1”、 ”$2”、 ”$3”之意,每个变量是独立的(用双引号括起来)
$* 		代表”$1c$2c$3c$4”,其中c为分隔字符,默认为空格键

shift:造成参数变量号码偏移(**)
shift会移动变量,而且shift后面可以接数字,代表拿掉最前面几个参数的意思。

3 条件判断式
3.1 利用if..then
单层、简单条件判断式

if [ 条件判断式 ]; then
    内容
fi

如果有多个条件要判断时,可以有多个中括号来隔开,括号之间以&&或||隔开:
&&代表AND, ||代表or
比如:[ “$yn” == ”Y” –o “$yn” == ”y” ] 可以替代为:[ “$yn” == ”Y” ] || [ “$yn” == ”y” ]

多重、复杂条件判断式

if [ 条件判断式 ]; then
else
fi
 
if [ 条件判断式一 ]; then
elif [ 条件判断式二 ]; then
else
fi

elif也是个判断式,因此出现elif后面都要接then来处理。

3.2 利用case..esac判断
语法:

case $变量名称 in
    “第一个变量内容”)
        程序段
        ;;
    “第二个变量内容”)
        程序段
        ;;
    *)                  #最后一个变量内容都会用*来代表所有权其它值
        程序段
        exit 1
        ;;
esac

3.3 利用funtion功能
函数可以在Shell Script当中做出一个类似自定义执行命令的东西,因为Shell Script的执行方式是由上而下、由左而右的,因此在Shell Script当中的function的设置一定要在程序的最前面。

另外,function也是拥有内置变量的,它的内置变量与Shell Script很类似,函数名称代表$0,而后续接的变量也是以$1$2..来替代的(如果要向函数传递参数,对应位置的参数将替换$1$2..,比如一个函数叫getList,传递参数格式: getList aaa bbb, 这个函数内$1等于aaa,$2等于bbb)。

4 循环
4.1 while do done, until do done (不定循环)

while [ condition ]
do
    程序段
done
 
until [ condition ]
do
        程序段
done

#计算1+2+3+…+100
#!/bin/bash
#
s=0;
i=0
while [ “$i” != “100” ]
do
    i=$(($i+1))
    s=$(($s+$i))
done
echo “The result is: $s”

4.2 for..do..done(固定循环)

for var in con1 con2 con3 …
do
    程序段
done

4.3 for…do…done的数值处理

for ((初始值; 限制值; 执行步长))
do
    程序段
done

###
for ((i=1; i<=$nu; i=i+1))
do
    s=$(($s+$i))
done

4.4 Shell Script的追踪与调试

用法;
sh [-nvx] script.sh
参数:
-n 不要执行script,仅检查语法
-v 在执行script前先将其内容输出到屏幕上
-x 将使用到的script内容显示到屏幕上

由sh –x的方式来将命令执行过程也显示出来,如此用户可以判断程序代码执行到哪一段时会出现相关信息。

Linux 查看进程

杀掉登录用户:

w
 20:46:40 up 12 days,  4:28,  4 users,  load average: 0.30, 0.12, 0.07
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    112.97.63.53     20:28    0.00s  0.07s  0.00s w
root     pts/2    125.94.151.83    14:08    3:31m  0.04s  0.04s -bash

ps -ef | grep pts/2

#向上寻找父进程ID
kill -9 pid

动态查看进程CPU内存

#-d 1表示1秒刷新
top -d 1 -p pid

这个可以查看百分比,比如内存占用,如果要查看进程实际霸占的内存,可以通过ps命令。

查看进程霸占内存:

ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

RSS对应实际霸占的内存(KB),这里需要知道,进程占用内存一般是指堆内存(其它一般占比较少),而堆内存内中是有空闲的,不过这个都归到进程内存占用。另外,如果要查看进程更加详细的信息:

cat /proc/pid/status

Name:	node
State:	S (sleeping)
Tgid:	31897
Ngid:	0
Pid:	31897    进程号
PPid:	1        父进程
TracerPid:	0
Uid:	0	0	0	0
Gid:	0	0	0	0
FDSize:	256
Groups:	0 
VmPeak:	 1302912 kB
VmSize:	 1301888 kB
VmLck:	       0 kB
VmPin:	       0 kB
VmHWM:	  123372 kB
VmRSS:	  122772 kB实际霸占内存
VmData:	 1262976 kB
VmStk:	     136 kB
VmExe:	   19980 kB
VmLib:	    4056 kB
VmPTE:	     636 kB
VmSwap:	       0 kB
Threads:	9  线程数量
SigQ:	0/31225
SigPnd:	0000000000000000
ShdPnd:	0000000000000000
SigBlk:	0000000000000000
SigIgn:	0000000000001000
SigCgt:	0000000188004202
CapInh:	0000000000000000
CapPrm:	0000001fffffffff
CapEff:	0000001fffffffff
CapBnd:	0000001fffffffff
Seccomp:	0
Cpus_allowed:	7fff
Cpus_allowed_list:	0-14
Mems_allowed:	00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list:	0
voluntary_ctxt_switches:	1373
nonvoluntary_ctxt_switches:	4465

CentOS 7.X 装机参考

#查看文件描述符限制
ulimit -n

#调整文件描述符(文件最后添加内容)
vi /etc/security/limits.conf
* soft nproc 65535
* hard nproc 65535
* soft nofile 65535
* hard nofile 65535

#RAID卡查看
dmesg | grep -i raid
[    1.521079] Areca RAID Controller0: Model ARC-1200, F/W V1.49 2010-12-02
[    1.521203] scsi host0: Areca SATA RAID Controller (RAID6 capable)
[    1.648025] scsi 0:0:16:0: Processor         Areca    RAID controller  R001 PQ: 0 ANSI: 0

cat /proc/scsi/scsi
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
  Vendor: Areca    Model: ARC-1200-VOL#00  Rev: R001
  Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi0 Channel: 00 Id: 16 Lun: 00
  Vendor: Areca    Model: RAID controller  Rev: R001
  Type:   Processor                        ANSI  SCSI revision: 00
Host: scsi3 Channel: 00 Id: 00 Lun: 00
  Vendor: ATA      Model: ST1000NM0033-9ZM Rev: SN04
  Type:   Direct-Access                    ANSI  SCSI revision: 05

lspci | grep -i raid
03:00.0 RAID bus controller: Areca Technology Corp. ARC-1200 2-Port PCI-Express to SATA II RAID Controller


#查看版本
cat /etc/system-release
cat /etc/issue 	#CentOS 7下不会再输出版本

# 总核数 = 物理CPU个数 X 每颗物理CPU的核数 
# 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数
# 查看物理CPU个数
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
# 查看每个物理CPU中core的个数(即核数)
cat /proc/cpuinfo| grep "cpu cores"| uniq
# 查看逻辑CPU的个数
cat /proc/cpuinfo| grep "processor"| wc -l

#查看网卡
ip addr
ip link
ip -s link
ifconfig 	#CentOS 7下,默认不再安装此工具

#本机DNS配置,配置文件/etc/resolv.conf
options timeout:1 attempts:1 rotate
nameserver 192.168.1.1
nameserver 8.8.8.8

#CentOS 7下网卡命名发生了变化,以前的ethX这种命名不见
#如果要改回来,需要修改/etc/default/grub文件
#添加net.ifnames=0 biosdevname=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_DEFAULT=saved
GRUB_DISABLE_SUBMENU=true
GRUB_TERMINAL_OUTPUT="console"
GRUB_CMDLINE_LINUX="crashkernel=auto vconsole.font=latarcyrheb-sun16 vconsole.keymap=us net.ifnames=0 biosdevname=0 rhgb quiet"
GRUB_DISABLE_RECOVERY="true"

#修改网卡配置信息(注意网卡名称)
#CentOS 7中除了名称改变,其它几乎是一致的
vi vi /etc/sysconfig/network-scripts/ifcfg-eno16777736
TYPE=Ethernet
BOOTPROTO=static
IPADDR=192.168.1.168
NETMASK=255.255.255.0
GATEWAY=192.168.1.1
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
NAME=eno16777736
UUID=7f9bd132-fb60-4ec8-8021-734f15dc0ff2
DEVICE=eno16777736
ONBOOT=yes

#CentOS 7 主机名相关状态(相关信息可以通过hostnamectl完成)
[root@localhost ~]# hostnamectl status
   Static hostname: localhost.localdomain
         Icon name: computer
           Chassis: n/a
        Machine ID: 2c3cda62de28434a894128e7ade1627b
           Boot ID: bd5d076f8a8c42358fe8ef4dbc6f0929
    Virtualization: vmware
  Operating System: CentOS Linux 7 (Core)
       CPE OS Name: cpe:/o:centos:centos:7
            Kernel: Linux 3.10.0-229.el7.x86_64
      Architecture: x86_64

#查看主机名
hostname

#CentOS 7中修改主机名
vi /etc/hostname
localhost.localdomain

#CentOS 6.x中(CentOS中不存在/etc/sysconfig/network)
vi /etc/sysconfig/network
NETWORKING=yes		#ipv4网络
NETWORKING_IPV6=no	#ipv6网络
HOSTNAME=vfeelit	#主机名称

#CentOS 7时间相关
[root@localhost ~]# timedatectl
      Local time: Sat 2015-11-07 22:38:42 PST
  Universal time: Sun 2015-11-08 06:38:42 UTC
        RTC time: Sun 2015-11-08 06:38:42
        Timezone: America/Los_Angeles (PST, -0800)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: no
 Last DST change: DST ended at
                  Sun 2015-11-01 01:59:59 PDT
                  Sun 2015-11-01 01:00:00 PST
 Next DST change: DST begins (the clock jumps one hour forward) at
                  Sun 2016-03-13 01:59:59 PST
                  Sun 2016-03-13 03:00:00 PDT
# 列出所有时区
timedatectl list-timezones 

# 将硬件时钟调整为与本地时钟一致, 0 为设置为 UTC 时间
timedatectl set-local-rtc 1 

# 设置系统时区为上海
timedatectl set-timezone Asia/Shanghai 

# 也可以使用如下方法(CentOS 6.x中使用的方法)
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

##同步时间(yum install ntp)
ntpdate asia.pool.ntp.org

##查看当前时区的时间
date -R
Sun, 08 Nov 2015 14:45:07 +0800

#本地设置(修改为中文)
vi /etc/locale.conf
ANG="zh_CN.UTF-8"

#关闭Selinux
vi /etc/selinux/config
#关闭Selinux后可能无法开机,Ctrl+F1切换终端可以查看,编辑/etc/grub2.conf
#在语言设置之后添加selinux=0

#赋予rc.loal执行权限(CentOS 6.x中不需要)
ls -lha /etc/rc.d/rc.local 
-rw-r--r--. 1 root root 473 3月   6 2015 /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local

#查看当前运行级别(runlevel)
cat /etc/systemd/system/default.target
#修改运行级别(先删除/etc/systemd/system/default.target符合链接)
rm -f /etc/systemd/system/default.target
#运行级别3
ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target
#运行级别5
ln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target

#去掉一批自启动服务(systemctl list-unit-files|grep enabled)
#如果要停止当期服务,使用systemctl stop xxx 
systemctl disable auditd.service
systemctl disable avahi-daemon.service
systemctl disable firewalld.service
systemctl disable cups.service
systemctl disable irqbalance.service
systemctl disable iscsi.service
systemctl disable kdump.service
systemctl disable lvm2-monitor.service
systemctl disable mdmonitor.service
systemctl disable microcode.service
systemctl disable multipathd.service
systemctl disable NetworkManager.service
systemctl disable postfix.service
systemctl disable tuned.service
systemctl disable remote-fs.target
systemctl disable dm-event.socket
systemctl disable iscsid.socket
systemctl disable iscsiuio.socket
systemctl disable lvm2-lvmetad.socket

#安装
#使用系统默认安装的Chrony服务即可(http://blog.ifeeline.com/2554.html)
#1、ntpd.service #时间同步,不需要开机启动

2、nscd.service #缓存(默认没有DNS缓存)
有提供passwd, group, hosts, services,这里主要使用hosts
vi /etc/nscd.conf

#       logfile                 /var/log/nscd.log
        threads                 8
        max-threads             128
        server-user             nscd
#       stat-user               somebody
        debug-level             5
#       reload-count            5
        paranoia                no
#       restart-interval        3600


        enable-cache            hosts           yes
        positive-time-to-live   hosts           5
        negative-time-to-live   hosts           10
        suggested-size          hosts           211
        check-files             hosts           yes
        persistent              hosts           yes
        shared                  hosts           yes
        max-db-size             hosts           33554432
3、sysstat.service #系统性能
4、supervisord.service #进程监控

配置第三方YUM源:

#默认
yum repolist
base/7/x86_64        CentOS-7 - Base
extras/7/x86_64      CentOS-7 - Extras
updates/7/x86_64     CentOS-7 - Updates 

######
#安装epel,这个软件包,默认被extras收录,可以直接yum安装
yum install 
#也可以手动安装
wget http://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm
rpm -ivh epel-release-7-5.noarch.rpm
#确认
yum repolist
base/7/x86_64        CentOS-7 - Base
epel/x86_64          Extra Packages for Enterprise Linux 7 - x86_64
extras/7/x86_64      CentOS-7 - Extras 
updates/7/x86_64     CentOS-7 - Updates 

######
##-------ius源,它依赖epel(yum install epel-release)
#https://dl.iuscommunity.org/pub/ius/stable/CentOS/7/x86_64/repoview/
#来自这个源的软件包,习惯加一个u
wget https://rhel7.iuscommunity.org/ius-release.rpm
rpm -ivh ius-release.rpm

##--------Webtatic源,也依赖epel(yum install epel-release),这是一个理想的php(5.4-5.6,7),nginx的RPM源
#http://repo.webtatic.com/yum/el7/x86_64/RPMS/
#来自这个源的软件包,习惯加一个w
wget https://mirror.webtatic.com/yum/el7/webtatic-release.rpm
rpm -ivh webtatic-release.rpm

#安装PHP
yum install php71w-bcmath.x86_64 php71w-cli.x86_64 php71w-common.x86_64 php71w-fpm.x86_64 php71w-gd.x86_64 php71w-mbstring.x86_64 php71w-mcrypt.x86_64 php71w-mysqlnd.x86_64 php71w-opcache.x86_64 php71w-pdo.x86_64 php71w-pecl-apcu.x86_64 php71w-pecl-mongodb.x86_64 php71w-pecl-redis.x86_64 php71w-pgsql.x86_64 php71w-process.x86_64 php71w-recode.x86_64 php71w-soap.x86_64 php71w-tidy.x86_64 php71w-xml.x86_64 php71w-intl.x86_64 php71w-devel.x86_64

#安装PHP后修改对应文件权限
find . -user apache
/var/log/php-fpm		#要改
/var/cache/httpd
/var/cache/httpd/proxy
/var/lib/dav
/run/httpd/htcacheclean

find . -group apache
/usr/sbin/suexec
/var/cache/httpd
/var/cache/httpd/proxy
/var/lib/dav
/var/lib/php/wsdlcache		#要改	
/var/lib/php/session		#要改
/run/httpd
/run/httpd/htcacheclean


##--------remi源,也依赖epel(yum install epel-release)
##Remi源可以安装多个不同版本的PHP,而且扩展比较齐全,对于单一的服务部署,推荐使用Webtatic源
##否则可以用Remi源,安装完成后会自动添加服务管理脚本 /lib/systemd/system/php**-php-fpm.service
wget http://rpms.remirepo.net/enterprise/remi-release-7.rpm
rpm -Uvh remi-release-7.rpm
## 安装完成后,会对应多个仓库
-rw-r--r-- 1 root root  456 3月  21 06:28 remi-php54.repo
-rw-r--r-- 1 root root 1.3K 3月  21 06:28 remi-php70.repo
-rw-r--r-- 1 root root 1.3K 3月  21 06:28 remi-php71.repo
-rw-r--r-- 1 root root 1.3K 3月  21 06:28 remi-php72.repo
-rw-r--r-- 1 root root 2.6K 3月  21 06:28 remi.repo
-rw-r--r-- 1 root root  750 3月  21 06:28 remi-safe.repo
如果希望把某个版本作为主版本(就是安装到/usr/bin等目录),可以使用yum --enablerepo=remi-php71 install ****, 否则将独立安装。

// PHP 7.1
yum --enablerepo=remi install php71-php php71-php-bcmath php71-php-cli php71-php-common php71-php-devel php71-php-fpm php71-php-gd php71-php-intl php71-php-json php71-php-mbstring php71-php-mcrypt php71-php-mysqlnd php71-php-opcache php71-php-pdo php71-php-pecl-apcu php71-php-pecl-apcu-devel php71-php-pecl-crypto php71-php-pecl-igbinary php71-php-pecl-igbinary-devel php71-php-pecl-imagick php71-php-pecl-imagick-devel php71-php-pecl-mongodb php71-php-pecl-uuid php71-php-pecl-zip php71-php-pgsql php71-php-process php71-php-recode php71-php-soap php71-php-tidy php71-php-xml php71-php-xmlrpc php71-php-pecl-amqp php71-php-pecl-redis4 php71-php-pecl-swoole2 php71-php-pecl-uploadprogress php71-php-phalcon3

// PHP 5.4
// php54-php-pecl-swoole2 php54-php-phalcon3无对应
yum --enablerepo=remi install php54-php php54-php-bcmath php54-php-cli php54-php-common php54-php-devel php54-php-fpm php54-php-gd php54-php-intl php54-php-json php54-php-mbstring php54-php-mcrypt php54-php-mysqlnd php54-php-opcache php54-php-pdo php54-php-pecl-apcu php54-php-pecl-apcu-devel php54-php-pecl-crypto php54-php-pecl-igbinary php54-php-pecl-igbinary-devel php54-php-pecl-imagick php54-php-pecl-imagick-devel php54-php-pecl-mongodb php54-php-pecl-uuid php54-php-pecl-zip php54-php-pgsql php54-php-process php54-php-recode php54-php-soap php54-php-tidy php54-php-xml php54-php-xmlrpc php54-php-pecl-amqp php54-php-pecl-redis4 php54-php-pecl-uploadprogress 

// Remi源安装的配置放入到/opt/remi/php**/root/, 配置安装到了/etc/opt/remi/php**/(注:PHP5.5以下版本,配置在安装目录)

// 添加服务启动脚本
cat php71-php-fpm.service
[Unit]
Description=The PHP FastCGI Process Manager
After=syslog.target network.target

[Service]
Type=notify
EnvironmentFile=/etc/opt/remi/php71/sysconfig/php-fpm
ExecStart=/opt/remi/php71/root/usr/sbin/php-fpm --nodaemonize
ExecReload=/bin/kill -USR2 $MAINPID
PrivateTmp=true

[Install]
WantedBy=multi-user.target

###### 
##为了避免意外更新,改为默认不启用
vi /etc/yum.repos.d/ius.repo	  #把ius的enable改为0
vi /etc/yum.repos.d/webtatic.repo #把webtatic的enable改为0
vi /etc/yum.repos.d/remi.repo	  #remi容器默认enable改为0

#######
##查看软件包的通用方法(先搜索,后安装)
yum repolist #查看启用仓库
yum --enablerepo=ius info php56u.x86_64 #查看某个源中的具体软件包信息
yum --disablerepo="*" --enablerepo="epel" list available | less #列出所有
yum --disablerepo="*" --enablerepo="ius" search php #源中搜索
yum install --enablerepo="ius" php56u.x86_64 #安装具体软件包

安装MySQL:(http://devdocs.magento.com/guides/v2.0/install-gde/prereq/mysql.html#instgde-prereq-mysql-centos)

#安装源
wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 
rpm -ivh mysql-community-release-el7-5.noarch.rpm
#从源安装MySQL
yum -y install mysql-server
#MySQL初始化
mysql_secure_installation
#开启服务
systemctl start mysqld.service

————————————————————–
CentOS 7.X的如下变化最让人不习惯:
一、CentOS的Services使用了systemd来代替sysvinit管理

systemd的服务管理程序:
systemctl是主要的工具,它融合之前service和chkconfig的功能于一体。可以使用它永久性或只在当前会话中启用/禁用服务。

直接运行systemctl可以列出正在运行的服务状态:

[root@vfeelit ~]# systemctl
UNIT                                         LOAD   ACTIVE SUB       DESCRIPTION
proc-sys-fs-binfmt_misc.automount            loaded active waiting   Arbitrary Executable File Formats File System
sys-devices-pl...serial8250-tty-ttyS0.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS0
sys-devices-pl...serial8250-tty-ttyS1.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS1
sys-devices-pl...serial8250-tty-ttyS2.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS2
sys-devices-pl...serial8250-tty-ttyS3.device loaded active plugged   /sys/devices/platform/serial8250/tty/ttyS3
sys-devices-vb...728-block-xvdb-xvdb1.device loaded active plugged   /sys/devices/vbd-51728/block/xvdb/xvdb1
sys-devices-vbd\x2d51728-block-xvdb.device   loaded active plugged   /sys/devices/vbd-51728/block/xvdb
sys-devices-vb...768-block-xvda-xvda1.device loaded active plugged   /sys/devices/vbd-768/block/xvda/xvda1
sys-devices-vbd\x2d768-block-xvda.device     loaded active plugged   /sys/devices/vbd-768/block/xvda
sys-devices-vif\x2d0-net-eth0.device         loaded active plugged   /sys/devices/vif-0/net/eth0
sys-devices-vif\x2d1-net-eth1.device         loaded active plugged   /sys/devices/vif-1/net/eth1
sys-module-configfs.device                   loaded active plugged   /sys/module/configfs
sys-subsystem-net-devices-eth0.device        loaded active plugged   /sys/subsystem/net/devices/eth0
sys-subsystem-net-devices-eth1.device        loaded active plugged   /sys/subsystem/net/devices/eth1
-.mount                                      loaded active mounted   /

## systemd-cgls树形方式展示
[root@vfeelit ~]# systemd-cgls
├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 23
├─user.slice
│ └─user-0.slice
│   └─session-5468.scope
│     ├─2837 sshd: root@pts/0    
│     ├─2845 -bash
│     ├─3003 systemd-cgls
│     └─3004 systemd-cgls
└─system.slice
  ├─php-fpm.service
  │ ├─ 2821 php-fpm: pool www              
  │ ├─ 2916 php-fpm: pool www              
  │ ├─ 2972 php-fpm: pool www              
  │ ├─32313 php-fpm: master process (/etc/php-fpm.conf
  │ ├─32316 php-fpm: pool www              
  │ ├─32317 php-fpm: pool www              
  │ ├─32318 php-fpm: pool www              
  │ ├─32319 php-fpm: pool www             
  │ ├─32320 php-fpm: pool www 

如何启动/关闭、启用/禁用服务
启动一个服务:systemctl start postfix.service
关闭一个服务:systemctl stop postfix.service
重启一个服务:systemctl restart postfix.service
显示一个服务的状态:systemctl status postfix.service
在开机时启用一个服务:systemctl enable postfix.service
在开机时禁用一个服务:systemctl disable postfix.service
查看服务是否开机启动:systemctl is-enabled postfix.service; echo $?
查看已启动的服务列表:systemctl list-unit-files | grep enabled

启用服务就是在当前“runlevel”的配置文件目录/etc/systemd/system/multi-user.target.wants/里,建立/usr/lib/systemd/system里面对应服务配置文件的软链接;禁用服务就是删除此软链接。(这种搞法非常常见)

[root@vfeelit multi-user.target.wants]# pwd
/etc/systemd/system/multi-user.target.wants
[root@vfeelit multi-user.target.wants]# ls -lah
crond.service -> /usr/lib/systemd/system/crond.service
nginx.service -> /usr/lib/systemd/system/nginx.service
nscd.service -> /usr/lib/systemd/system/nscd.service
ntpd.service -> /usr/lib/systemd/system/ntpd.service
php-fpm.service -> /usr/lib/systemd/system/php-fpm.service
rsyslog.service -> /usr/lib/systemd/system/rsyslog.service
sshd.service -> /usr/lib/systemd/system/sshd.service
supervisord.service -> /usr/lib/systemd/system/supervisord.service
sysstat.service -> /usr/lib/systemd/system/sysstat.service

CentOS 6.x中也是如此,但是语法已经不一样了。

二、修改系统运行级别

切换到运行级别
systemd使用比sysvinit的运行级更为自由的target替代。第3运行级用multi-user.target替代。第5运行级用graphical.target替代。runlevel3.target和runlevel5.target分别是指向 multi-user.target和graphical.target的符号链接。

可以使用下面的命令切换到“运行级别3 ”:
systemctl isolate multi-user.target或systemctl isolate runlevel3.target
可以使用下面的命令切换到“运行级别5 ”:
systemctl isolate graphical.target或systemctl isolate runlevel5.target

改变默认运行级别
systemd使用链接来指向默认的运行级别。在创建新的链接前,可以通过下面命令删除存在的链接: rm /etc/systemd/system/default.target

默认启动运行级别3 :
ln -sf /lib/systemd/system/multi-user.target /etc/systemd/system/default.target

默认启动运行级别5 :
ln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target

systemd不使用/etc/inittab文件。

查看当前运行级别
旧的runlevel命令在systemd下仍然可以使用。可以继续使用它,尽管systemd使用 ‘target’ 概念(多个的 ‘target’ 可以同时激活)替换了之前系统的runlevel。等价的systemd命令是systemctl list-units –type=target

其他配置工具:
1、setup和ntsysv工具还是保留了,但是功能已大大减弱,以前ntsysv工具可以控制所有系统服务的自启动,现在只能控制少部分服务。
2、/etc/resolv.conf这个DNS配置文件没变。
3、/etc/sysconfig/network-scripts/ifcfg-ens192网卡配置文件名字和一些选项有所变化。
4、引导方式改用grub2引导,grub2有如下特点:1、模块化设计;2、支持多体系硬件架构;3、支持国际化多语言;4、独立内存管理;5、支持脚本语言。

最后再稍作对比总结,三个基本任务,查看启动的服务,设置服务是否开机启动,当期关闭和启动服务

查看启动的服务
chkconfig –list -> systemctl list-unit-files|grep enabled(/etc/systemd/system/multi-user.target.wants)
设置服务是否开机启动
chkconfig –levels 35 xxxx off -> systemctl enable postfix.service
当期关闭和启动服务
service xxx stop -> systemctl start postfix.service

在Windows7下安装Linux(CentOS 6.x)

在Linux下,貌似无法识别NTFS,但可以识别FAT32,但是FAT32有个致命问题,就是单个文件无法大于4G,然而下载的CentOS 6.5 DVD1大于4G,所以这个方法不做考虑。

反过来思考,可以分一个EXT3分区,然后把其挂在Windows7下,这个是可行的,所以本文使用这个方法。

我的电脑C盘是一个SSD硬盘,只分一个区,这里把C盘压榨6G出来,用来安装CentOS到机械硬盘的空闲地方。这里使用一个叫分区助手的工具完成这个操作(直接360安装卫士的软件中搜索可下载):

先拆分分区,然后接着格式化(具体过程略)。
格式化分区

然后寻找一个叫ext2fsd的软件,用它可以把Ext3挂在到Windows里(http://www.ext2fsd.com)
EXT分区挂载到Windows

这里把这个EXT3分区映射为Windows下的X盘,接下就是拷贝文件进去:

CentOS-6.5-x86_64-bin-DVD1.iso
CentOS-6.5-x86_64-bin-DVD2.iso
images
isolinux

isolinux 和 images是从CentOS-6.5-x86_64-bin-DVD1.iso文件中提取出来的。

接下来就是要从这个EXT3分区引导安装,这个时候还需要一个叫EasyBCD的工具:
Windows下添加引导
这里配置一个启动项,这个配置项是需要正确指定刚刚配置的EXT3的对应编号,比如hd0表示第一个硬盘,后面的1表示这个硬盘的第二分区。
引导Linux分区启动
重新启动后就可以看到这个启动项,选择进入开始引导,选择镜像位置后就和用光盘安装没有什么区别了,所以后面的过程就省略了。安装完成后这个EXT3分区可以删掉,也可以挂到Linux中,使用它在Linux和Windows中共享文件。

原创文章,装载务必保留出处。
永久链接: http://blog.ifeeline.com/1090.html

GDB在调试程序时候提示Missing separate debuginfos, use: debuginfo-install glibc…

使用GDB调试C程序时:

gdb sum
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/the_c/sum...done.
(gdb) run
Starting program: /root/the_c/sum 
The sum of 1+2+3+...is 4950
Program exited with code 033.
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6_5.1.x86_64

提示使用debuginfo-install安装glibc。
在shell下运行:

debuginfo-install glibc-2.12-1.132.el6_5.1.x86_64
-bash: debuginfo-install: command not found

提示debuginfo-install命令不存在,那么必须还要安装个软件包。实际debuginfo-install是yum-utils软件包的一个工具,所以:

yum install yum-utils
...
rpm -ql yum-utils | grep debuginfo-install
/usr/bin/debuginfo-install
/usr/share/man/man1/debuginfo-install.1.gz

然后再次运行:

debuginfo-install glibc-2.12-1.132.el6_5.1.x86_64

Dependencies Resolved

===================================================================================
 Package                             Arch     Version              Repository
                                                                              Size
===================================================================================
Installing:
 glibc-debuginfo                     x86_64   2.12-1.132.el6_5.1   debug     8.7 M
 nss-softokn-debuginfo               x86_64   3.14.3-9.el6         debug     1.7 M
 yum-plugin-auto-update-debug-info   noarch   1.1.30-17.el6_5      updates    22 k
Installing for dependencies:
 glibc-debuginfo-common              x86_64   2.12-1.132.el6_5.1   debug     8.3 M

至此,问题解决。

原创文章,转载务必保留出处。
永久链接:http://blog.ifeeline.com/1079.html

Linux 作业管理(job control)

当登录系统取得bash shell之后,在单一终端机下同时进行多个作业的行为管理。

在进行作业管理的行为中,其实每个作业都是目前bash的子进程,即彼此之间是有相关性的。登录一个终端出现提示符让你操作的环境成为前台 (foreground),至于其它作业就可以放入后台(background)去暂停或运行。注意:放入后台的作业必须不能与用户互动。

Bash的作业控制必须要注意到的限制是:
这些作业所触发的进程必须来自于你shell的子进程
前台:你可以控制于执行命令的这个环境成为前台的作业
后台:可以自行运行的作业,你无法使用[ctrl+c]终止它,可使用bg/fg调用该作业
后台中执行的进程不能等待terminal/shell的输入

1 Job control管理 [作业管理]
Bash下面的Job分前台与后台,然后再后台里面的作业状态又可分为暂停与运行中。

直接将命令丢到后台中执行的&
例子:

tar –zpcf /tmp/etc/targ.gz /etc &

后面加入上&表示在后台处理,回车后看到bash会给予这个命令一个作业号码(job number),就是那个[1]。但是这个标准输出和错误输出还是都屏幕上。所以应该使用重定向处理。

tar –zpcf /tmp/etc.tar.gz /etc/ > /tmp/log.txt 2>&1 &

将目前的作业丢到后台中暂停:ctrl-z
比如正在使用vi,却发现有个文件不知道放在哪里,需要到bash环境下进行查找,此时只要将vi丢到后台当中等待即可。
例子:

vi ~/.bashrc
# 在vi的一般模式下,按下[ctrl]-z这两个键
[1]+ Stopped
# 顺利取得前台控制权

按下[ctrl]-z这两个键,屏幕上出现[1],表示这是第一个作业,而那个+代表最近一个被丢进后台的作业,且目前在后台下默认会被取用的那个作业(与fg这个命令有关)。而那个stopped则代表目前这个作业的状态。默认,使用[ctrl-z]丢到后台当中的作业都是暂停状态。

查看目前的后台作业状态:jobs
用法:

jobs [-lrs]
参数:
-l 除了列出job number与命令串之外,同时列出PID的号码
-r 仅列出正在后台run的作业
-s 仅列出正在后台当中暂停(stop)的作业

一般,直接执行jobs即可。如果还想知道该Job number的PID号码,可以加上-l这个参数。在输出的信息中,那个+代表默认的取用作业。如果目前有两个作业在后台当中,两个作业都是暂停的,而如果仅输入fg时,那么那个标志了+的作业会被拿到前台当中来处理。其实+代表最近被放到后台的作业号码,-代表最近第二个被放置到后台当中的作业号码。而超过最后第三个以后的作业,就不会有+/-符号存在了。

将后台作业拿到前台来处理:fg

fg %jobnumber
参数:
%jobnumber: jobnumber为作业号码(数字)。注意:%可有可无
如果fg –则把标志了-的那个作业拿出来。


让作业在后台下的状态变成运行中:bg

由于按下ctrl-z后作业会放到后台停止,如果要让其继续在后台运行起来,需要使用bg,它和fg的用法一样。

管理后台当中的作业:kill
如果需要删除某个作业,需要使用kill。

用法:
kill –signal %jobnumber
参数:
-l 列出目前能够使用的信号(signal)有哪些
signal 代表给予后面接的那个作业什么样的指示。
-1 重新读取一次参数的配置文件
-2 代表与由键盘输入ctrl-c同样的操作
-9 立刻强制删除一个作业
-15 以正常的程序方式终止一项作业

注意:-9通常是在强制删除一个不正常的作业时所使用的,-15则是以正常步骤接受一项作业(15也是默认值)
另外,kill后面接的数字默认是PID,如果想要管理bash的作业控制,就得要加上%数字了。

永久链接:http://blog.ifeeline.com/1052.html