systemd的新特性与awk命令用法及示例

简述systemd的新特性及unit常见类型分析,能够实现编译安装的如nginx\apache实现通过systemd来管理

systemd是cenos7版本新引入的系统级服务管理工具,其主要的新特性如下:

  1. 系统引导时实现服务并行启动
  2. 按需激活进程(默认情况并没有实际启动进程)
  3. 支持系统状态快照
  4. 基于依赖关系来自定义服务的控制逻辑

systemd的核心概念就是unit(单元),将不同的管理资源称之为unit。通过配置文件来进行标识,识别和配置,文件包含了系统服务,监听的套接字文件(socket)及init相关的信息等等。配置文件主要有以下几下:

  1. /usr/lib/systemd/system
  2. /run/systemd/system
  3. /etc/systemd/system
  4. /lib/systemd/system

unit的常见类型:

Service unit:文件扩展名为.service,用于定义系统服务,如:httpd.service
Target unit:文件扩展为.target,用于模拟实现“运行级别”;
Device unit: .device,用于定义内核识别的设备;
Mount unit: .mount,定义文件系统挂载点;
Socket unit: .socket,用于标识进程间通信用到的socket(套接字)文件;
Snapshot unit: .snapshot, 管理系统快照;
Swap unit: .swap, 用于标识swap(交换分区)设备;
Automount unit: .automount,文件系统自动点设备;
Path unit: .path, 用于定义文件系统中的一文件或目录(在某些特殊的情况下使用
[root@zcy520ooooo ~]# ls /usr/lib/systemd/system
arp-ethers.service                      rhel-autorelabel-mark.service
auditd.service                          rhel-autorelabel.service
[email protected]                         rhel-configure.service
basic.target                            rhel-dmesg.service
basic.target.wants                      rhel-domainname.service
blk-availability.service                rhel-import-state.service
bluetooth.target                        rhel-loadmodules.service
brandbot.path                           rhel-readonly.service
brandbot.service                        rpcbind.target
......#以下省略

systemd关键特性工作原理:

1.基于sokcet的激活机制:
在系统引导时systemd会为所有支持激活该类型的服务分别创建一个socket,并在系统启动后将这个socket传给该服务,实现系统并行启动,并且可以在服务未启动时用systemd去监听这个socket的状态,当有进程访问这个socket时systemd在启动该服务,实现socket与服务程序的分离。
2. 基于bus的激活机制:
通过监听bus的状态来启动相应服务。
3. 基于device的激活机制:
在某个硬件设备激活或变为可用时,激活相应服务。
4. 基于Path的激活机制:
在文件路径变为可用或有文件时,激活相应服务。
5. 系统快照:
保存各unit的当前状态信息于持久存储设备中,随后服务启动时可用从快照开始继续运行。
6. 向后兼容sysv init脚本:
兼容性有限,不建议centos7中在使用init命令。
7. 不兼容:
systemctl的命令格式是固定不变的,不是由systemd启动的服务,systemd无法与之通信,systemctl不会与任何标准输入流有交流,自行控制其服务的启动。(不能通过交互方式去干涉systemd启动的服务,只能选择用systemd去开启,关闭服务等等。)

管理系统服务:
systemctl命令: Control the systemd system and service manager(控制systemd系统和其服务管理命令)
centos7:service类型的unit文件

systemctl  [OPTIONS...]  COMMAND  [NAME...].service
    COMMAND:
        启动: service  NAME  start  ==>  systemctl  start  NAME.service
        停止: service  NAME  stop  ==> systemctl  stop  NAME.service
        重启: service  NAME  restart  ==>  systemctl  restart  NAME.service
        状态: service  NAME  status  ==>  systemctl  status  NAME.service
        条件式重启:service  NAME  condrestart  ==>  systemctl  try-restart  NAME.service
        重载或重启服务: systemctl  reload-or-restart  NAME.servcie
        重载或条件式重启服务:systemctl  reload-or-try-restart  NAME.service
        查看某服务当前激活与否的状态: systemctl  is-active  NAME.service
        查看所有已激活的服务:systemctl  list-units  --type  service
        查看所有服务(已激活及未激活): chkconfig --lsit  ==>  systemctl  list-units  -t  service  --all 
        设置服务开机自启: chkconfig  NAME  on  ==>  systemctl  enable  NAME.service
        禁止服务开机自启: chkconfig  NAME  off  ==>  systemctl  disable  NAME.service 
        查看某服务是否能开机自启: chkconfig  --list  NAME  ==>  systemctl  is-enabled  NAME.service
        禁止某服务设定为开机自启: systemctl  mask  NAME.service
        取消此禁止: systemctl  unmask  NAME.servcie
        查看服务的依赖关系:systemctl  list-dependencies  NAME.service
[root@zcy520ooooo ~]# systemctl list-units -t service --all
  UNIT                                  LOAD      ACTIVE   SUB     DESCRIPTION
  auditd.service                        loaded    active   running Security Auditing Service
  chronyd.service                       loaded    active   running NTP client/server
  cpupower.service                      loaded    inactive dead    Configure CPU power related settin
  crond.service                         loaded    active   running Command Scheduler
  dbus.service                          loaded    active   running D-Bus System Message Bus
● display-manager.service               not-found inactive dead    display-manager.service
  dracut-shutdown.service               loaded    inactive dead    Restore /run/initramfs
  ebtables.service                      loaded    inactive dead    Ethernet Bridge Filtering tables
  emergency.service                     loaded    inactive dead    Emergency Shell
● exim.service                          not-found inactive dead    exim.service
  firewalld.service                     loaded    active   running firewalld - dynamic firewall daemo
  [email protected]                    loaded    active   running Getty on tty1
  httpd.service                         loaded    active   running The Apache HTTP Server
● ip6tables.service                     not-found inactive dead    ip6tables.service
● ipset.service                         not-found inactive dead    ipset.service
● iptables.service                      not-found inactive dead    iptables.service
  irqbalance.service                    loaded    active   running irqbalance daemon
● kdump.service                         loaded    failed   failed  Crash recovery kernel arming
  kmod-static-nodes.service             loaded    active   exited  Create list of required static dev
  microcode.service                     loaded    inactive dead    Load CPU microcode update
  network.service                       loaded    active   exited  LSB: Bring up/down networking
  NetworkManager-wait-online.service    loaded    active   exited  Network Manager Wait Online
  NetworkManager.service                loaded    active   running Network Manager
...#以下很多省略
============================================华丽的分割线===============================================
[root@zcy520ooooo ~]# systemctl status httpd
● httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2018-10-11 13:47:24 CST; 2h 34min ago
     Docs: man:httpd(8)
           man:apachectl(8)
 Main PID: 9184 (httpd)
   Status: "Total requests: 0; Current requests/sec: 0; Current traffic:   0 B/sec"
   CGroup: /system.slice/httpd.service
           ├─9184 /usr/sbin/httpd -DFOREGROUND
           ├─9186 /usr/sbin/httpd -DFOREGROUND
           ├─9187 /usr/sbin/httpd -DFOREGROUND
           ├─9188 /usr/sbin/httpd -DFOREGROUND
           ├─9189 /usr/sbin/httpd -DFOREGROUND
           └─9190 /usr/sbin/httpd -DFOREGROUND

10月 11 13:47:23 zcy520ooooo systemd[1]: Starting The Apache HTTP Server...
10月 11 13:47:24 zcy520ooooo httpd[9184]: AH00558: httpd: Could not reliably determine the ser...age
10月 11 13:47:24 zcy520ooooo systemd[1]: Started The Apache HTTP Server.
Hint: Some lines were ellipsized, use -l to show in full.

管理target units:
target units用来模拟实现运行级别,target units与init运行级别的对应关系,级别切换,查看等命令:

0  ==>  runlevel0.target,  poweroff.target
1  ==>  runlevel1.target,  rescue.target
2  ==>  runlevel2.tartet,  multi-user.target
3  ==>  runlevel3.tartet,  multi-user.target
4  ==>  runlevel4.tartet,  multi-user.target
5  ==>  runlevel5.target,  graphical.target
6  ==>  runlevel6.target,  reboot.target

级别切换: init  N  ==>  systemctl  isolate  NAME.target
查看级别: runlevel  ==>  systemctl  list-units  --type  target
查看所有级别: systemctl  list-units  -t  target  -a
获取默认运行级别:systemctl  get-default  
修改默认运行级别: systemctl  set-default   NAME.target
切换至紧急救援模式: systemctl  rescue
切换至emergency模式: systemctl  emergency
            
其它常用命令:
    关机: systemctl  halt,  systemctl  poweroff
    重启: systemctl  reboot
    挂起: systemctl  suspend
    快照: systemctl  hibernate 
    快照并挂起: systemctl  hybrid-sleep
[root@zcy520ooooo ~]# systemctl get-default
multi-user.target

service unit file:
文件通常由[Unit],[Service],[Install]三部分组成:

[root@zcy520ooooo ~]# cd /usr/lib/systemd/system
[root@zcy520ooooo system]# cat httpd.service 
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=man:httpd(8)
Documentation=man:apachectl(8)

[Service]
Type=notify
EnvironmentFile=/etc/sysconfig/httpd
ExecStart=/usr/sbin/httpd $OPTIONS -DFOREGROUND
ExecReload=/usr/sbin/httpd $OPTIONS -k graceful
ExecStop=/bin/kill -WINCH ${MAINPID}
# We want systemd to give httpd some time to finish gracefully, but still want
# it to kill httpd after TimeoutStopSec if something went wrong during the
# graceful stop. Normally, Systemd sends SIGTERM signal right after the
# ExecStop, which would kill httpd. We are sending useless SIGCONT here to give
# httpd time to finish.
KillSignal=SIGCONT
PrivateTmp=true

[Install]
WantedBy=multi-user.target

Unit:定义与Unit类型无关的通用选项;用于提供unit的描述信息、unit行为及依赖关系等

Unit段的常用选项:
    Description:描述信息; 意义性描述;
    After:定义unit的启动次序;表示当前unit应该晚于哪些unit启动;其功能与Before相反;
    Requies:依赖到的其它units;强依赖,被依赖的units无法激活时,当前unit即无法激活;
    Wants:依赖到的其它units;弱依赖;
    Conflicts:定义units间的冲突关系;

Service:与特定类型相关的专用选项;此处为Service类型

Service段的常用选项:
    Type:用于定义影响ExecStart及相关参数的功能的unit进程启动类型;
        类型:
            simple:由ExecStart启动的进程为该程序的主进程
            forking:由ExecStart指明的程序启动的进程的子进程会成为主进程,且生成之后主进程会退出
            oneshot:一次性的主进程类似simple,但启动后续unit之前主进程会退出
            dbus:类似simple,后续的unit在当前的unit得到dbus名称之后才能启动
            notify:类似于simple,后续的unit在通过sdnotify函数发送通知,才能启动
            idle:类似simple
    EnvironmentFile:环境配置文件;在ExecStart之前读取并为其提供某些变量
    ExecStart:指明启动unit要运行命令或脚本; 
    ExecStartPre:指明启动unit要运行之前命令或脚本
    ExecStartPost指明启动unit要运行之后命令或脚本
    ExecStop:指明停止unit要运行的命令或脚本;
    Restart:指明重启unit要运行的命令或脚本

Install:定义由“systemctl enable”以及"systemctl disable“命令在实现服务启用或禁用时用到的一些选项

Install段的常用选项:
    Alias:
    RequiredBy:被哪些units所依赖;
    WantedBy:被哪些units所依赖

注意:对于新创建的unit文件或,修改了的unit文件,要通知systemd重载此配置文件

systemctl  daemon-reload

实现编译安装的如nginx\apache实现通过systemd来管理:

  1. 安装编译安装依赖的类库和包
[root@zcy520ooooo ~]# yum install gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre-devel
#安装过程已省略
已安装:
  openssl-devel.x86_64 1:1.0.2k-12.el7                pcre-devel.x86_64 0:8.32-17.el7               

作为依赖被安装:
  keyutils-libs-devel.x86_64 0:1.5.8-3.el7            krb5-devel.x86_64 0:1.15.1-19.el7             
  libcom_err-devel.x86_64 0:1.42.9-12.el7_5           libselinux-devel.x86_64 0:2.5-12.el7          
  libsepol-devel.x86_64 0:2.5-8.1.el7                 libverto-devel.x86_64 0:0.2.5-4.el7           

作为依赖被升级:
  e2fsprogs.x86_64 0:1.42.9-12.el7_5              e2fsprogs-libs.x86_64 0:1.42.9-12.el7_5            
  libcom_err.x86_64 0:1.42.9-12.el7_5             libss.x86_64 0:1.42.9-12.el7_5                     

完毕!

  1. 下载并解压nginx
[root@zcy520ooooo ~]# wget http://nginx.org/download/nginx-1.11.10.tar.gz
--2018-10-17 18:01:22--  http://nginx.org/download/nginx-1.11.10.tar.gz
正在解析主机 nginx.org (nginx.org)... 206.251.255.63, 95.211.80.227, 2606:7100:1:69::3f, ...
正在连接 nginx.org (nginx.org)|206.251.255.63|:80... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度:967773 (945K) [application/octet-stream]
正在保存至: “nginx-1.11.10.tar.gz”

100%[===========================================================>] 967,773      369KB/s 用时 2.6s   

2018-10-17 18:01:25 (369 KB/s) - 已保存 “nginx-1.11.10.tar.gz” [967773/967773])
---------------------------------分割线----------------------------------------------------------------
[root@zcy520ooooo ~]# tar xf nginx-1.11.10.tar.gz 
[root@zcy520ooooo ~]# ls
nginx-1.11.10.tar.gz           nginx-1.11.10             
[root@zcy520ooooo ~]# cd nginx-1.11.10
[root@zcy520ooooo nginx-1.11.10]#

  1. 编译安装Nginx
[root@zcy520ooooo nginx-1.11.10]# ./configure
checking for OS
 + Linux 3.10.0-862.el7.x86_64 x86_64
checking for C compiler ... found
 + using GNU C compiler
 + gcc version: 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) 
checking for gcc -pipe switch ... found
checking for -Wl,-E switch ... found
checking for gcc builtin atomic operations ... found
checking for C99 variadic macros ... found
#中间省略......
creating objs/Makefile

Configuration summary
  + using system PCRE library
  + OpenSSL library is not used
  + using system zlib library

  nginx path prefix: "/usr/local/nginx"
  nginx binary file: "/usr/local/nginx/sbin/nginx"
  nginx modules path: "/usr/local/nginx/modules"
  nginx configuration prefix: "/usr/local/nginx/conf"
  nginx configuration file: "/usr/local/nginx/conf/nginx.conf"
  nginx pid file: "/usr/local/nginx/logs/nginx.pid"
  nginx error log file: "/usr/local/nginx/logs/error.log"
  nginx http access log file: "/usr/local/nginx/logs/access.log"
  nginx http client request body temporary files: "client_body_temp"
  nginx http proxy temporary files: "proxy_temp"
  nginx http fastcgi temporary files: "fastcgi_temp"
  nginx http uwsgi temporary files: "uwsgi_temp"
  nginx http scgi temporary files: "scgi_temp

[root@zcy520ooooo nginx-1.11.10]# make && make install
make -f objs/Makefile
make[1]: 进入目录“/root/nginx-1.11.10”
cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g  -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
    -o objs/src/core/nginx.o \
    src/core/nginx.c
cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g  -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
    -o objs/src/core/ngx_log.o \
    src/core/ngx_log.c
cc -c -pipe  -O -W -Wall -Wpointer-arith -Wno-unused-parameter -Werror -g  -I src/core -I src/event -I src/event/modules -I src/os/unix -I objs \
    -o objs/src/core/ngx_palloc.o \
#......中间过程省略

  1. 配置systemd Nginx服务和设置Nginx自启动
    创建systemd服务文件:/lib/systemd/system/nginx.service内容如下:
[root@zcy520ooooo system]# vim nginx.service

[Unit]
Description=nginx
After=network.target

[Service]
Type=forking
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/usr/local/nginx/sbin/nginx -s reload
ExecStop=/usr/local/nginx/sbin/nginx -s stop
PrivateTmp=true

[Install]
WantedBy=multi-user.target

  1. 重载配置文件并使用systemctl命令启动nginx服务
[root@zcy520ooooo system]# systemctl daemon-reload
[root@zcy520ooooo system]# systemctl start nginx.service 
[root@zcy520ooooo system]# systemctl status nginx.service
● nginx.service - nginx
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; disabled; vendor preset: disabled)
   Active: active (running) since 四 2018-10-18 10:02:50 CST; 1min 15s ago
 Main PID: 4853 (nginx)
   CGroup: /system.slice/nginx.service
           ├─4853 nginx: master process /usr/local/nginx/sbin/nginx
           └─4854 nginx: worker proces

10月 18 10:02:50 localhost.localdomain systemd[1]: Starting nginx...
10月 18 10:02:50 localhost.localdomain systemd[1]: Started nginx.

提示:本实验只是演示如何用systemctl管理源码包编译的nginx服务,使用默认编译安装,uint配置文件也是相当简单,实际应用还需要做相应的调整

描述awk命令用法及示例(至少3例)

awk是文档的报告生成工具,主要用来格式化文本输出.有awk和gawk两个版本,linux上是gawk版本.awk一次从文本中读取一行,然后对该行按输入分隔符进行切片处理.默认分隔符为空白符.把分出来的每一片到保存到awk内建的变量中,1代表第一块切片....$n.最后对其中的某些片段进行过滤,显示等等其他一些操作.
基本用法:

gawk - pattern scanning and processing language
   gawk [options] 'program' FILE ...
        program: PATTERN{ACTION STATEMENTS}
            语句之间用分号分隔
    选项:
        -F:指明输入时用到的字段分隔符;
        -v var=value: 自定义变量,变量名严格区分字符大小写,并且可以program中直接定义。

[root@zcy520ooooo ~]# tail -4 /etc/fstab | awk ' {print $1,$3}'
UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 xfs
UUID=7b58779e-372e-4096-8bbd-625b09e1a14e xfs
UUID=e4af4f09-a39e-4acf-b85d-4d4d9b41f584 xfs
UUID=6206b8c1-adeb-4fef-b197-a97df129e85e swap

1. print

  print item1, item2, ...

使用要点:
(1)item之间用逗号分隔符
(2)输出的各item可以字符串,也可以是数值;当前记录的字段、变量或awk的表达式
(3)如省略item,相当于print $0
(4)awk中引用变量一般不用" "双引号或者$来引用

[root@zcy520ooooo ~]# tail -4 /etc/fstab | awk ' {print 123,$2,$3}'
123 / xfs
123 /boot xfs
123 /home xfs
123 swap swap

2. 常用的内建变量:
FS:input field seperator,输入字段分隔符,默认为空白字符
OFS:output field seperator,输出字段分隔符,默认为空白字符
RS:input record seperator,输入时的换行符
ORS:output record seperator,输出时的换行符,默认是回车
NF:number of field,每行的字段数量,{print NF}表示字段数量, {print $NF}代表最后一个字段
NR:number of record, 行数
FNR:各文件分别计数;行数
FILENAME:当前文件名
ARGC:命令行参数的个数
ARGV:数组,保存的是命令行所给定的各参数

[root@zcy520ooooo ~]# awk -v FS=':' -v OFS=':' '{print $2,$4}' /etc/passwd | tail -5
x:983
x:982
x:70
x:16
x:72
[root@zcy520ooooo ~]# awk -v FS=':' '{print $2,$4}' /etc/passwd | tail -5
x 983
x 982
x 70
x 16
x 72
------------------------------------------分割线--------------------------------------------------------
[root@zcy520ooooo ~]# awk '{print NF,$NF}' /etc/fstab
0 
1 #
2 /etc/fstab
10 2018
1 #
9 '/dev/disk'
12 info
1 #
6 0
6 0
6 0
6 0
------------------------------------------分割线--------------------------------------------------------
[root@zcy520ooooo ~]# awk 'BEGIN{print ARGV[0]}' /etc/fstab
awk        #把awk自身当作一个参数
[root@zcy520ooooo ~]# awk 'BEGIN{print ARGV[1]}' /etc/fstab
/etc/fstab

3. printf命令

格式化输出:printf FORMAT, item1, item2, ...

(1) FORMAT必须给出; FORMAT为每个item提供一种格式,并对应给出一个字段
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FOMAT中需要分别为后面的每个item指定一个格式化符号

格式符:
    %c: 显示字符的ASCII码;
    %d, %i: 显示十进制整数;
    %e, %E: 科学计数法数值显示;
    %f:显示为浮点数;
    %g, %G:以科学计数法或浮点形式显示数值;
    %s:显示字符串;
    %u:无符号整数;
    %%: 显示%自身;

修饰符:
    #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度;
    %3.1f
    -: 左对齐
    +:显示数值的符号
[root@zcy520ooooo ~]# awk -F: '{printf "%-20s:%3.2f\n", $1,$3}' /etc/passwd
root                :0.00
bin                 :1.00
daemon              :2.00
adm                 :3.00
lp                  :4.00
sync                :5.00
shutdown            :6.00
halt                :7.00
mail                :8.00
operator            :11.00
games               :12.00
ftp                 :14.00
nobody              :99.00
systemd-network     :192.00
dbus                :81.00
polkitd             :999.00
sshd                :74.00
postfix             :89.00
chrony              :998.00
tss                 :59.00
apache              :48.00
1                   :1010.00
geoclue             :997.00
logstash            :1011.00
unbound             :996.00
rpc                 :32.00
gluster             :995.00
setroubleshoot      :994.00
libstoragemgmt      :993.00
usbmuxd             :113.00
qemu                :107.00
saslauth            :992.00
radvd               :75.00
ntp                 :38.00
rtkit               :172.00
abrt                :173.00
colord              :991.00
pulse               :171.00
gdm                 :42.00
rpcuser             :29.00
nfsnobody           :65534.00
sssd                :990.00
gnome-initial-setup :989.00
pcp                 :988.00
avahi               :70.00
oprofile            :16.00
tcpdump             :72.00

4. 操作符
awk支持常用的操作符,如:算术操作符,字符串操作符,赋值操作符,比较操作符,模式匹配符,逻辑操作符等等

算术操作符:
    x+y, x-y, x*y, x/y, x^y, x%y
    -x
    +x: 转换为数值
字符串操作符:没有符号的操作符,字符串连接

赋值操作符:
    =, +=, -=, *=, /=, %=, ^=
    ++, --

比较操作符:
    >, >=, <, <=, !=, ==

模式匹配符:
    ~:是否匹配
    !~:是否不匹配

逻辑操作符:
    &&
    ||
    !

函数调用:
    function_name(argu1, argu2, ...)

条件表达式:
    selector?if-true-expression:if-false-expression

[root@zcy520ooooo ~]# awk -F: '{print $3,$4}' /etc/passwd | tail -5
989 983
988 982
70 70
16 16
72 72
[root@zcy520ooooo ~]# awk -F: '{print $3+$4}' /etc/passwd | tail -5
1972
1970
140
32
144
------------------------------------------分割线--------------------------------------------------------
[root@zcy520ooooo ~]# awk -F: '{$1~"root"?usertype="root":usertype="common user or sysuser";printf "%
20s:%-s\n",$1,usertype}' /etc/passwd
                root:root
                 bin:common user or sysuser
              daemon:common user or sysuser
                 adm:common user or sysuser
                  lp:common user or sysuser
                sync:common user or sysuser
            shutdown:common user or sysuser
                halt:common user or sysuser
                mail:common user or sysuser
            operator:common user or sysuser
               games:common user or sysuser
                 ftp:common user or sysuser
              nobody:common user or sysuser
     systemd-network:common user or sysuser
                dbus:common user or sysuser
             polkitd:common user or sysuser
                sshd:common user or sysuser
             postfix:common user or sysuser
              chrony:common user or sysuser
                 tss:common user or sysuser
              apache:common user or sysuser
                   1:common user or sysuser
             geoclue:common user or sysuser
            logstash:common user or sysuser
             unbound:common user or sysuser
                 rpc:common user or sysuser
             gluster:common user or sysuser
      setroubleshoot:common user or sysuser
      libstoragemgmt:common user or sysuser
             usbmuxd:common user or sysuser
                qemu:common user or sysuser
            saslauth:common user or sysuser
               radvd:common user or sysuser
                 ntp:common user or sysuser
               rtkit:common user or sysuser
                abrt:common user or sysuser
              colord:common user or sysuser
               pulse:common user or sysuser
                 gdm:common user or sysuser
             rpcuser:common user or sysuser
           nfsnobody:common user or sysuser
                sssd:common user or sysuser
 gnome-initial-setup:common user or sysuser
                 pcp:common user or sysuser
               avahi:common user or sysuser
            oprofile:common user or sysuser
             tcpdump:common user or sysuser

5. PATTERN匹配模式
awk默认匹配每一行,启动地址定界的功能

(1) empty:空模式,匹配每一行;
(2) /regular expression/:仅处理能够被此处的模式匹配到的行;
(3) relational expression: 关系表达式;结果有“真”有“假”;结果为“真”才会被处理;
        (真:结果为非0值,非空字符串;)
(4) line ranges:行范围,
    startline,endline:/pat1/,/pat2/
        注意: 不支持直接给出数字的格式
(5) BEGIN/END模式
        BEGIN{}: 仅在开始处理文件中的文本之前执行一次;
        END{}:仅在文本处理完成之后执行一次;
[root@zcy520ooooo ~]# awk -F: '$NF~/bash$/ {print $1,$NF}' /etc/passwd
root /bin/bash
1 /bin/bash
logstash /bin/bash

#$NF~/bash$/:判断最后一个字段是否等于bash,等于则输出

------------------------------------------分割线--------------------------------------------------------
[root@zcy520ooooo ~]# awk -F: '/^h/,/^g/{print $1,$3}' /etc/passwd
halt 7
mail 8
operator 11
games 12

#匹配以h或以g开头的行

------------------------------------------分割线-------------------------------------------------------

[root@zcy520ooooo ~]# awk -F: 'BEGIN{print "      username        uid  \n====================="}/^h/,/^g/{print $1,$3}END{print "-----------------------\n end            "}' /etc/passwd
      username        uid  
=====================
halt 7
mail 8
operator 11
games 12
-----------------------
 end    

6. 常用的action

(1) Expressions
(2) Control statements:控制语句,if, while等;
(3) Compound statements:组合语句;
(4) input statements:输入语句
(5) output statements:输出语句(print,printf)
[root@zcy520ooooo ~]# awk -F: '{for(i=1;i

7. 控制语句
awk可以在处理动作中加入判断,循环等控制语句,来对匹配到的字段进行处理.常见的控制语句如下:

if(condition) {statments} :对awk取得的整行或某个字段做条件判断
if(condition) {statments} else {statements}同上

语法:if(condition) statement [else statement]
[root@zcy520ooooo ~]# awk -F: '{if($3<=1000) {printf "root or sys user: %10s\n",$1} else {printf "common user: %10s\n",$1}}' /etc/passwd
root or sys user:       root
root or sys user:        bin
root or sys user:     daemon
root or sys user:        adm
root or sys user:         lp
root or sys user:       sync
root or sys user:   shutdown
root or sys user:       halt
root or sys user:       mail
root or sys user:   operator
root or sys user:      games
root or sys user:        ftp
root or sys user:     nobody
root or sys user: systemd-network
root or sys user:       dbus
root or sys user:    polkitd
root or sys user:       sshd
root or sys user:    postfix
root or sys user:     chrony
root or sys user:        tss
root or sys user:     apache
common user:          1
root or sys user:    geoclue
common user:   logstash
root or sys user:    unbound
root or sys user:        rpc
root or sys user:    gluster
root or sys user: setroubleshoot
root or sys user: libstoragemgmt
root or sys user:    usbmuxd
root or sys user:       qemu
root or sys user:   saslauth
root or sys user:      radvd
root or sys user:        ntp
root or sys user:      rtkit
root or sys user:       abrt
root or sys user:     colord
root or sys user:      pulse
root or sys user:        gdm
root or sys user:    rpcuser
common user:  nfsnobody
root or sys user:       sssd
root or sys user: gnome-initial-setup
root or sys user:        pcp
root or sys user:      avahi
root or sys user:   oprofile
root or sys user:    tcpdump

while(conditon) {statments}:对一行内的多个字段逐一类似处理时使用; 对数组中的各元素逐一处理时使用

语法:while(condition) statement
        条件“真”,进入循环;条件“假”,退出循环
[root@zcy520ooooo ~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-862.14.4.el7.x86_64 35
root=UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=zh_CN.UTF-8 16
linux16 7
/vmlinuz-3.10.0-862.el7.x86_64 30
root=UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=zh_CN.UTF-8 16
linux16 7
/vmlinuz-0-rescue-d5bf70a4141c42668b79f9b042c2b21e 50
root=UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5

do statement while(condition):类似while,但至少执行一次循环体.

语法:do statement while(condition)
[root@zcy520ooooo ~]# awk '/^[[:space:]]*save/{i=1;do {if(length($i)>10) {print $i,length($i)}; i++} while(i<=NF)}' /etc/grub2.cfg 
saved_entry 11
prev_saved_entry 16
saved_entry="${chosen}" 23
saved_entry 11

for循环:循环或遍历数组中的元素

语法:for(expr1;expr2;expr3) statement
      for(var in array) {for-body} 遍历数组中的元素
[root@zcy520ooooo ~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
linux16 7
/vmlinuz-3.10.0-862.14.4.el7.x86_64 35
root=UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=zh_CN.UTF-8 16
linux16 7
/vmlinuz-3.10.0-862.el7.x86_64 30
root=UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5
LANG=zh_CN.UTF-8 16
linux16 7
/vmlinuz-0-rescue-d5bf70a4141c42668b79f9b042c2b21e 50
root=UUID=17c90f0e-0bf0-40ea-8a5e-9598aa668053 46
ro 2
crashkernel=auto 16
rhgb 4
quiet 5

switch语句:控制开关语句,匹配到的字段符合某项进行处理

语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; ...; default: statement}

在if,while等控制语句中也可以使用中断,退出等.
break[n]:退出循环,在n退出循环
continue:结束当前循环并跳转到循环开始处
exit:返回状态码并退出循环

next:awk的特殊语句,提前结束对本行的处理而直接进入下一行

[root@zcy520ooooo ~]# awk -F: '{if($3%2!=1) next; print $1,$2,$3}' /etc/passwd
bin x 1
adm x 3
sync x 5
halt x 7
operator x 11
nobody x 99
dbus x 81
polkitd x 999
postfix x 89
tss x 59
geoclue x 997
logstash x 1011
gluster x 995
libstoragemgmt x 993
usbmuxd x 113
qemu x 107
radvd x 75
abrt x 173
colord x 991
pulse x 171
rpcuser x 29
gnome-initial-setup x 989


8. 关联数组:array[index-expression]
awk支持关联数组(自定义的数组)
index-expression:
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”

若要判断数组中是否存在某元素,要使用"index in array"格式进行;
若要遍历数组中的每个元素,要使用for循环:
for(var in array) {for-body}

[root@zcy520ooooo ~]# awk 'BEGIN{DAY["a"]="10.1";DAY["b"]="10.2";for(i in DAY) {print DAY[i]}}'
10.1
10.2
# 注意这里的i在后面输出是不用双引号或者$符号修饰,直接引用i就可以

注意var会遍历array的每个索引; state["a"]++表示数组索引的值进行自增DAY["a"]=3,DAY[a]++表示3自增

[root@zcy520ooooo ~]# awk '{installed[$5]++}END{for(i in installed) {print i,installed[i]}}' /var/log/yum.log
GConf2-3.2.6-8.el7.x86_64 1
gnome-color-manager-3.22.2-2.el7.x86_64 1
nss-3.36.0-7.el7_5.x86_64 1
gnome-shell-extension-apps-menu-3.26.2-3.el7.noarch 1
sane-backends-1.0.24-11.el7.x86_64 1
1:NetworkManager-libnm-1.10.2-16.el7_5.x86_64 1
colord-libs-1.3.4-1.el7.x86_64 1
unzip-6.0-19.el7.x86_64 1
cdparanoia-libs-10.2-17.el7.x86_64 1
xcb-util-wm-0.4.1-5.el7.x86_64 1
uom-se-1.0.4-3.el7.noarch 1
spice-gtk3-0.34-3.el7_5.2.x86_64 1
1:perl-Log-Message-0.08-3.el7.noarch 1
fontconfig-2.10.95-11.el7.x86_64 1
gcc-gfortran-4.8.5-28.el7_5.1.x86_64 1
httpd-2.4.6-80.el7.centos.1.x86_64 1
dejavu-sans-fonts-2.33-6.el7.noarch 1
freerdp-libs-1.0.2-15.el7.x86_64 1
1:librados2-0.94.5-2.el7.x86_64 1
python-enum34-1.0.4-1.el7.noarch 1
xdg-user-dirs-gtk-0.10-4.el7.x86_64 1
libreport-plugin-ureport-2.1.11-40.el7.centos.x86_64 1
libref_array-0.1.5-29.el7.x86_64 1
gnome-themes-standard-3.22.2-2.el7_5.x86_64 1
lsof-4.87-5.el7.x86_64 1
perl-Pod-Usage-1.63-3.el7.noarch 1
marisa-0.2.4-4.el7.x86_64 1
libvirt-python-3.9.0-1.el7.x86_64 1
libxml2-python-2.9.1-6.el7_2.3.x86_64 1
libwvstreams-4.6.1-11.el7.x86_64 1
scrub-2.5.2-7.el7.x86_64 1
perl-Exporter-5.68-3.el7.noarch 1
colord-1.3.4-1.el7.x86_64 1
perl-Module-Metadata-1.000018-2.el7.noarch 1
lohit-marathi-fonts-2.5.3-2.el7.noarch 1
jsr-311-1.1.1-6.el7.noarch 1
osinfo-db-20170813-6.el7.noarch 1
plymouth-plugin-label-0.8.9-0.31.20140113.el7.centos.x86_64 1
libsoup-2.56.0-6.el7.x86_64 1
qgnomeplatform-0.3-3.el7.x86_64 1
netcf-libs-0.2.8-4.el7.x86_64 1
xorg-x11-xinit-1.3.4-2.el7.x86_64 1
rarian-0.8.1-11.el7.x86_64 1
perl-Scalar-List-Utils-1.27-248.el7.x86_64 1
flatpak-libs-0.8.8-4.el7_5.x86_64 1
evolution-mapi-3.22.6-1.el7.x86_64 1
javassist-3.16.1-10.el7.noarch 1
sssd-ad-1.16.0-19.el7_5.8.x86_64 1
libvirt-client-3.9.0-14.el7_5.8.x86_64 1
firstboot-19.12-1.el7.x86_64 1
1:isomd5sum-1.0.10-5.el7.x86_64 1
libreport-plugin-mantisbt-2.1.11-40.el7.centos.x86_64 1
1:xorg-x11-xauth-1.0.9-1.el7.x86_64 1
xvattr-1.3-27.el7.x86_64 1
grilo-0.3.3-1.el7.x86_64 1
libraw1394-2.1.0-2.el7.x86_64 1
libdhash-0.5.0-29.el7.x86_64 1
lyx-fonts-2.2.3-1.el7.noarch 1
objectweb-asm-3.3.1-9.el7.noarch 1
mpfr-3.1.1-4.el7.x86_64 1
sil-nuosu-fonts-2.1.1-5.el7.noarch 1
pulseaudio-gdm-hooks-10.0-5.el7.x86_64 1
libchamplain-gtk-0.12.15-1.el7.x86_64 1
totem-pl-parser-3.10.7-1.el7.x86_64 1
libchamplain-0.12.15-1.el7.x86_64 1
libsss_autofs-1.16.0-19.el7_5.8.x86_64 1
abrt-libs-2.1.11-50.el7.centos.x86_64 1
plymouth-theme-charge-0.8.9-0.31.20140113.el7.centos.x86_64 1
librsvg2-2.40.16-1.el7.x86_64 1
libsmbclient-4.7.1-9.el7_5.x86_64 1
...#以下省略

描述awk函数示例(至少3例)

awk支持的内置函数主要有3种:算数函数、字符串函数、其他一般函数、时间函数;常用的内置函数如下:

内置函数
    数值处理:
        rand():返回0和1之间一个随机数;

字符串处理:
    length([s]):返回指定字符串的长度;
    sub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其第一次出现替换为s所表示的内容;
    gsub(r,s,[t]):以r表示的模式来查找t所表示的字符中的匹配的内容,并将其所有出现均替换为s所表示的内容;
    split(s,a[,r]):以r为分隔符切割字符s,并将切割后的结果保存至a所表示的数组中
[root@zcy520ooooo ~]# awk '{for(i=1;i
[root@zcy520ooooo ~]# awk 'BEGIN{rd=int(100*rand());print rd}'
23

[root@zcy520ooooo ~]# awk 'BEGIN{haha="ab cd e f gg ha2 1 23 4 5a SD F V df?";split(haha,line," ");print length(line);for(i in line){print i,line[i]}}'
14
4 f
5 gg
6 ha2
7 1
8 23
9 4
10 5a
11 SD
12 F
13 V
14 df?
1 ab
2 cd
3 e

你可能感兴趣的:(systemd的新特性与awk命令用法及示例)