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

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

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

  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@localhost ~]# ls  /usr/lib/systemd/system
abrt-ccpp.service                        oddjobd.service
abrtd.service                            packagekit-offline-update.service
abrt-oops.service                        packagekit.service
abrt-pstoreoops.service                  paths.target
abrt-vmcore.service                      plymouth-halt.service
abrt-xorg.service                        plymouth-kexec.service
accounts-daemon.service                  plymouth-poweroff.service
alsa-restore.service                     plymouth-quit.service
alsa-state.service                       plymouth-quit-wait.service
alsa-store.service                       plymouth-read-write.service
anaconda-direct.service                  plymouth-reboot.service
anaconda-nm-config.service               plymouth-start.service
anaconda-noshell.service                 plymouth-switch-root.service
anaconda-pre.service                     polkit.service
anaconda.service                         postfix.service
anaconda-shell@.service                  poweroff.target
anaconda-sshd.service                    poweroff.target.wants
anaconda.target                          printer.target
anaconda-tmux@.service                   proc-fs-nfsd.mount
arp-ethers.service                       proc-sys-fs-binfmt_misc.automount
atd.service                              proc-sys-fs-binfmt_misc.mount
auditd.service                           psacct.service
auth-rpcgss-module.service               qemu-guest-agent.service
autovt@.service                          quotaon.service
avahi-daemon.service                     radvd.service
avahi-daemon.socket                      rasdaemon.service
basic.target                             ras-mc-ctl.service
basic.target.wants                       rc-local.service
blk-availability.service                 rdisc.service
bluetooth.service                        rdma-ndd.service
bluetooth.target                         rdma.service
brandbot.path                            realmd.service
brandbot.service                         reboot.target
..... #服务过多,省略了

systemd关键特性工作原理:

  1. 基于socket的激活机制:
    在系统引导时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启动的服务,systemctl无法与之通信,systemctl不会与任何标准输入流有交流,自行控制其服务的启动.(不能通过交互方式去干涉systemd启动的服务,只能选择用systemd去开启,关闭服务等等.)

管理系统服务:
syscemctl命令:控制systemd系统和其服务管理命令

systemctl  [OPTIONS...]  COMMAND  NAME.service
     COMMAND:
        start  开启服务  ==> service  NAME  start (init服务启动方式)
        stop  停止服务  ==> service  NAME  stop
        restart  重启服务  ==> service  NAME  restart
        status  查看服务当前状态  ==> service  NAME  status
        enable  开机自启  ==> chkconfig  NAME  on
        disable  开机不自启  ==> chkconfig  NAME  off
        is-enabled  查看服务是否能开机自启  ==> chkconfig  --list  NAME
        reload-or-restart  重载或重启服务  
        mask  禁止服务设定为开机自启
        unmask  取消此禁止
        list-dependencies  查看服务的依赖关系
        is-active  查看某服务当前激活与否的状态
 systemctl  list-units  -t  service  --all  ==> chkconfig --lsit  查看所有服务
[root@localhost nginx-1.11.10]# systemctl  list-units  -t  service  --all
  UNIT                                  LOAD      ACTIVE   SUB     DESCRIPTION
  abrt-ccpp.service                     loaded    active   exited  Install ABRT coredump hook
  abrt-oops.service                     loaded    active   running ABRT kernel log watcher
  abrt-vmcore.service                   loaded    inactive dead    Harvest vmcores for ABRT
  abrt-xorg.service                     loaded    active   running ABRT Xorg log watcher
  abrtd.service                         loaded    active   running ABRT Automated Bug Reporting Tool
  accounts-daemon.service               loaded    active   running Accounts Service
  alsa-restore.service                  loaded    inactive dead    Save/Restore Sound Card State
  alsa-state.service                    loaded    active   running Manage Sound Card State (restore a
● apparmor.service                      not-found inactive dead    apparmor.service
----------------分割线----------------
[root@localhost nginx-1.11.10]# systemctl status nfs-server.service 
● nfs-server.service - NFS server and services
   Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

管理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(比rescue切换更好)
    
    其它一些常用命令:
        关机: systemctl  halt,  systemctl  poweroff
        重启: systemctl  reboot
        挂起: systemctl  suspend
        快照: systemctl  hibernate 
        快照并挂起: systemctl  hybrid-sleep
[root@localhost nginx-1.11.10]# systemctl get-default 
graphical.target

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

[root@localhost system]# cat nfs-server.service 
[Unit]
Description=NFS server and services
DefaultDependencies=no
Requires= network.target proc-fs-nfsd.mount
Requires= nfs-mountd.service
Wants=rpcbind.socket network-online.target
Wants=rpc-statd.service nfs-idmapd.service
Wants=rpc-statd-notify.service

After= network-online.target local-fs.target
After= proc-fs-nfsd.mount rpcbind.socket nfs-mountd.service
After= nfs-idmapd.service rpc-statd.service
Before= rpc-statd-notify.service

# GSS services dependencies and ordering
Wants=auth-rpcgss-module.service
After=rpc-gssd.service gssproxy.service

Wants=nfs-config.service
After=nfs-config.service

[Service]
EnvironmentFile=-/run/sysconfig/nfs-utils

Type=oneshot
RemainAfterExit=yes
ExecStartPre=-/usr/sbin/exportfs -r
ExecStartPre=-/bin/sh -c '/bin/kill -HUP `cat /run/gssproxy.pid`'
ExecStart=/usr/sbin/rpc.nfsd $RPCNFSDARGS
ExecStop=/usr/sbin/rpc.nfsd 0
ExecStopPost=/usr/sbin/exportfs -au
ExecStopPost=/usr/sbin/exportfs -f

ExecReload=-/usr/sbin/exportfs -r

[Install]
WantedBy=multi-user.target

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

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

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

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

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

Install段的常用选项:
    Alias:当前uint的别名
    RequiredBy:被哪些units所依赖;
    WantedBy:被哪些units所依赖; 

注意:对于新创建的unit文件或修改了的unit文件,要使用以下命令通知systemd重载配置文件

systemctl daemon-reload

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

  1. 安装编译安装依赖的类库和包
 [root@localhost ~]# yum install gcc gcc-c++ autoconf automake zlib zlib-devel openssl openssl-devel pcre-devel
Loaded plugins: fastestmirror, langpacks
Repository epel is listed more than once in the configuration
Repository epel-debuginfo is listed more than once in the configuration
Repository epel-source is listed more than once in the configuration
base                                                                          | 3.6 kB  00:00:00     
epel                                                                          | 4.7 kB  00:00:00     
extras                                                                        | 3.4 kB  00:00:00     
updates                                                                       | 3.4 kB  00:00:00     


--> Processing Dependency: kernel-headers >= 2.2.1 for package: glibc-headers-2.17-196.el7_4.2.x86_64
--> Processing Dependency: kernel-headers for package: glibc-headers-2.17-196.el7_4.2.x86_64
---> Package keyutils-libs-devel.x86_64 0:1.5.8-3.el7 will be installed
---> Package libcom_err-devel.x86_64 0:1.42.9-10.el7 will be installed
---> Package libkadm5.x86_64 0:1.15.1-8.el7 will be installed
---> Package libselinux-devel.x86_64 0:2.5-11.el7 will be installed
--> Processing Dependency: libsepol-devel(x86-64) >= 2.5-6 for package: libselinux-devel-2.5-11.el7.x86_64
--> Processing Dependency: pkgconfig(libsepol) for package: libselinux-devel-2.5-11.el7.x86_64
---> Package libverto-devel.x86_64 0:0.2.5-4.el7 will be installed
--> Running transaction check
---> Package glibc-common.x86_64 0:2.17-196.el7 will be updated
---> Package glibc-common.x86_64 0:2.17-196.el7_4.2 will be an update
---> Package kernel-headers.x86_64 0:3.10.0-693.21.1.el7 will be installed
---> Package libsepol-devel.x86_64 0:2.5-6.el7 will be installed
--> Finished Dependency Resolution

# 过程过长省略掉了

Installed:
  autoconf.noarch 0:2.69-11.el7                      automake.noarch 0:1.13.4-3.el7                  
  gcc.x86_64 0:4.8.5-16.el7_4.2                      gcc-c++.x86_64 0:4.8.5-16.el7_4.2               
  openssl-devel.x86_64 1:1.0.2k-8.el7                pcre-devel.x86_64 0:8.32-17.el7                 
  zlib-devel.x86_64 0:1.2.7-17.el7                  

Dependency Installed:
  cpp.x86_64 0:4.8.5-16.el7_4.2                   glibc-devel.x86_64 0:2.17-196.el7_4.2             
  glibc-headers.x86_64 0:2.17-196.el7_4.2         kernel-headers.x86_64 0:3.10.0-693.21.1.el7       
  keyutils-libs-devel.x86_64 0:1.5.8-3.el7        krb5-devel.x86_64 0:1.15.1-8.el7                  
  libcom_err-devel.x86_64 0:1.42.9-10.el7         libkadm5.x86_64 0:1.15.1-8.el7                    
  libmpc.x86_64 0:1.0.1-3.el7                     libselinux-devel.x86_64 0:2.5-11.el7              
  libsepol-devel.x86_64 0:2.5-6.el7               libstdc++-devel.x86_64 0:4.8.5-16.el7_4.2         
  libverto-devel.x86_64 0:0.2.5-4.el7             m4.x86_64 0:1.4.16-10.el7                         
  perl-Test-Harness.noarch 0:3.28-3.el7           perl-Thread-Queue.noarch 0:3.02-2.el7             

Dependency Updated:
  glibc.x86_64 0:2.17-196.el7_4.2                 glibc-common.x86_64 0:2.17-196.el7_4.2            
  libgcc.x86_64 0:4.8.5-16.el7_4.2                libgomp.x86_64 0:4.8.5-16.el7_4.2                 
  libstdc++.x86_64 0:4.8.5-16.el7_4.2            

Complete!

  1. 下载和解压 Nginx
[root@localhost ~]# wget http://nginx.org/download/nginx-1.11.10.tar.gz
--2018-03-31 20:18:02--  http://nginx.org/download/nginx-1.11.10.tar.gz
Resolving nginx.org (nginx.org)... 206.251.255.63, 95.211.80.227
Connecting to nginx.org (nginx.org)|206.251.255.63|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 967773 (945K) [application/octet-stream]
Saving to: ‘nginx-1.11.10.tar.gz’

100%[===========================================================>] 967,773     78.6KB/s   in 13s    

2018-03-31 20:18:19 (73.3 KB/s) - ‘nginx-1.11.10.tar.gz’ saved [967773/967773]
[root@localhost ~]# tar -xzvf nginx-1.11.10.tar.gz
nginx-1.11.10/
nginx-1.11.10/auto/
nginx-1.11.10/conf/
nginx-1.11.10/contrib/
nginx-1.11.10/src/
nginx-1.11.10/configure
nginx-1.11.10/LICENSE
nginx-1.11.10/README
nginx-1.11.10/html/
nginx-1.11.10/man/
nginx-1.11.10/CHANGES.ru
....  #包显示过长忽略掉了

----------------------分割线----------------------
[root@localhost ~]# cd nginx-1.11.10/
[root@localhost nginx-1.11.10]# 

  1. 编译安装Nginx
[root@localhost nginx-1.11.10]# ./configure 
checking for OS
 + Linux 3.10.0-693.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-16) (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
checking for gcc variadic macros ... found
checking for gcc builtin 64 bit byteswap ... found
checking for unistd.h ... found
checking for inttypes.h ... found
checking for limits.h ... found
checking for sys/filio.h ... not found
checking for sys/param.h ... found
checking for sys/mount.h ... found
checking for sys/statvfs.h ... found
checking for crypt.h ... found
checking for Linux specific features
checking for epoll ... found
checking for EPOLLRDHUP ... found
checking for EPOLLEXCLUSIVE ... not found
checking for O_PATH ... found
checking for sendfile() ... found
checking for sendfile64() ... found
checking for sys/prctl.h ... found
checking for prctl(PR_SET_DUMPABLE) ... found
checking for sched_setaffinity() ... found
checking for crypt_r() ... found
checking for sys/vfs.h ... found
checking for nobody group ... found
checking for poll() ... found
checking for /dev/poll ... not found
checking for kqueue ... not found
checking for crypt() ... not found
checking for crypt() in libcrypt ... found
checking for F_READAHEAD ... not found
checking for posix_fadvise() ... found
checking for O_DIRECT ... found
checking for F_NOCACHE ... not found
checking for directio() ... not found
checking for statfs() ... found
checking for statvfs() ... found
checking for dlopen() ... not found
checking for dlopen() in libdl ... found
checking for sched_yield() ... found
checking for SO_SETFIB ... not found
checking for SO_REUSEPORT ... found
checking for SO_ACCEPTFILTER ... not found
checking for SO_BINDANY ... not found
checking for IP_BIND_ADDRESS_NO_PORT ... not found
checking for IP_TRANSPARENT ... found
checking for IP_BINDANY ... not found
checking for IP_RECVDSTADDR ... not found
checking for IP_PKTINFO ... found
checking for IPV6_RECVPKTINFO ... found
checking for TCP_DEFER_ACCEPT ... found
checking for TCP_KEEPIDLE ... found
checking for TCP_FASTOPEN ... found
checking for TCP_INFO ... found
checking for accept4() ... found
checking for eventfd() ... found
checking for int size ... 4 bytes
checking for long size ... 8 bytes
checking for long long size ... 8 bytes
checking for void * size ... 8 bytes
checking for uint32_t ... found
checking for uint64_t ... found
checking for sig_atomic_t ... found
checking for sig_atomic_t size ... 4 bytes
checking for socklen_t ... found
checking for in_addr_t ... found
checking for in_port_t ... found
checking for rlim_t ... found
checking for uintptr_t ... uintptr_t found
checking for system byte ordering ... little endian
checking for size_t size ... 8 bytes
checking for off_t size ... 8 bytes
checking for time_t size ... 8 bytes
checking for AF_INET6 ... found
checking for setproctitle() ... not found
checking for pread() ... found
checking for pwrite() ... found
checking for pwritev() ... found
checking for sys_nerr ... found
checking for localtime_r() ... found
checking for posix_memalign() ... found
checking for memalign() ... found
checking for mmap(MAP_ANON|MAP_SHARED) ... found
checking for mmap("/dev/zero", MAP_SHARED) ... found
checking for System V shared memory ... found
checking for POSIX semaphores ... not found
checking for POSIX semaphores in libpthread ... found
checking for struct msghdr.msg_control ... found
checking for ioctl(FIONBIO) ... found
checking for struct tm.tm_gmtoff ... found
checking for struct dirent.d_namlen ... not found
checking for struct dirent.d_type ... found
checking for sysconf(_SC_NPROCESSORS_ONLN) ... found
checking for openat(), fstatat() ... found
checking for getaddrinfo() ... found
checking for PCRE library ... found
checking for PCRE JIT support ... found
checking for zlib library ... 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@localhost nginx-1.11.10]# make && make install
make -f objs/Makefile
make[1]: Entering directory `/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 \
    src/core/ngx_palloc.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_array.o \
    src/core/ngx_array.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_list.o \
    src/core/ngx_list.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_hash.o \
    src/core/ngx_hash.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_buf.o \
    src/core/ngx_buf.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_queue.o \
    src/core/ngx_queue.c
......  #过程略掉
  1. 配置 systemd Nginx 服务和设置 Nginx 自启动
    创建 systemd 服务文件: /lib/systemd/system/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 i

  1. 重载配置文件并使用systemctl启动nginx服务
[root@localhost ~]# systemctl  daemon-reload
[root@localhost ~]# systemctl start nginx.service 
[root@localhost ~]# systemctl status nginx.service 
● nginx.service - nginx
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2018-03-31 20:35:58 CST; 19s ago
  Process: 4781 ExecStart=/usr/local/nginx/sbin/nginx (code=exited, status=0/SUCCESS)
 Main PID: 4782 (nginx)
   CGroup: /system.slice/nginx.service
           ├─4782 nginx: master process /usr/local/nginx/sbin/nginx
           └─4783 nginx: worker process

Mar 31 20:35:58 localhost.localdomain systemd[1]: Starting nginx...
Mar 31 20:35:58 localhost.localdomain systemd[1]: Started nginx.

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

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

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

gawk [options] 'program' FILE ...
    program: PATTERN{ACTION STATEMENTS}
            语句之间用分号分隔

    options:
        -F:指明输入时用到的字段分隔符
        -v var=value: 自定义变量,变量名严格区分字符大小写,并且可以program中直接定义
[root@localhost nginx-1.11.10]# tail -5 /etc/fstab | awk '{print $2,$4}'
/ defaults
/boot defaults
/home defaults
swap defaults
/mnt/media.repo defaults

1. print

        print item1, item2, ...

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

[root@localhost test]# awk '{print 222,$2,$4}' /etc/fstab | tail -5
222 / defaults
222 /boot defaults
222 /home defaults
222 swap defaults
222 /mnt/media.repo defaults

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@localhost nginx-1.11.10]# tail -5 /etc/passwd | awk -v FS=':' -v OFS=':' '{print  $2,$4}'
x:70
x:89
x:38
x:72
x:1000
------------------------分割线------------------------
[root@localhost nginx-1.11.10]# 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
6 0
------------------------分割线------------------------
[root@localhost nginx-1.11.10]# awk 'BEGIN{print ARGV[0]}' /etc/fstab 
awk    #把awk自身当做一个参数
[root@localhost nginx-1.11.10]# awk 'BEGIN{print ARGV[1]}' /etc/fstab 
/etc/fstab

3. printf命令

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

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

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

修饰符:
    #[.#]:第一个数字控制显示的宽度;第二个#表示小数点后的精度.例如:
    %3.1f :表示显示精度为1且用3个位数显示的浮点数.
    -: 左对齐
    +:显示数值的符号
[root@localhost test]#  awk -F: '{printf "%-10s:%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
abrt      :173.00
libstoragemgmt:998.00
rpc       :32.00
colord    :997.00
saslauth  :996.00
rtkit     :172.00
chrony    :995.00
qemu      :107.00
tss       :59.00
usbmuxd   :113.00
geoclue   :994.00
rpcuser   :29.00
nfsnobody :65534.00
radvd     :75.00
setroubleshoot:993.00
pulse     :171.00
gdm       :42.00
gnome-initial-setup:992.00
sshd      :74.00
avahi     :70.00
postfix   :89.00
ntp       :38.00
tcpdump   :72.00
456       :1000.00
named     :25.00
apache    :48.00


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

算术操作符:
    x+y, x-y, x*y, x/y, x^y, x%y
    -x
    +x: 转换为数值;

字符串操作符:默认没有符号的操作符(做字符串连接)

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

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

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

逻辑操作符:
    &&  与
    ||  或
    !   非
[root@localhost test]# awk -F: '{print $3,$4}' /etc/passwd | tail -5
38 38
72 72
1000 1000
25 25
48 48
[root@localhost test]# awk -F: '{print $3*$4}' /etc/passwd | tail -5
1444
5184
1000000
625
2304

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

[root@localhost ~]# awk -F: '{$1~"root"?usertype="root":usertype="common user";printf "%10s:%s\n",$1,usertype}' /etc/passwd
      root:root
       bin:common user
    daemon:common user
       adm:common user
        lp:common user
      sync:common user
  shutdown:common user
      halt:common user
      mail:common user
  operator:common user
     games:common user
       ftp:common user
    nobody:common user
systemd-network:common user
      dbus:common user
   polkitd:common user
      abrt:common user
libstoragemgmt:common user
       rpc:common user
    colord:common user
  saslauth:common user
     rtkit:common user
    chrony:common user
      qemu:common user
       tss:common user
   usbmuxd:common user
   geoclue:common user
   rpcuser:common user
 nfsnobody:common user
     radvd:common user
setroubleshoot:common user
     pulse:common user
       gdm:common user
gnome-initial-setup:common user
      sshd:common user
     avahi:common user
   postfix:common user
       ntp:common user
   tcpdump:common user
       456:common user

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

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

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

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

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

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

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

[root@localhost ~]# 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@localhost ~]# awk -F: '{for(i=1;i<NF;i++) {count[$i]++}}END{for(j in count) {print j,count[j]}}' /etc/passwd
rpc 1
 8
adm 2
/var/spool/postfix 1
990 1
/var/ftp 1
991 1
/etc/ntp 1
992 1
993 2
Privilege-separated SSH 1
994 1
/bin 1
65534 2
113 2
995 1
radvd 1
996 2
/var/lib/chrony 1
997 2
sync 2
998 2

$i表示该字段的值,如i=1,则$1=rpc,后面的j表示表示如果j在count[j]这个数组中,就打印以索引和对应的索引值,
如:i=1,count[$i]++相当于count[rpc]++,j in count表示j=rpc,并输出count[rpc]的值
......

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

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

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

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

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

do {statements} while(condition) :类此while,但至少执行一次循环体.

 do statement while(condition)
[root@localhost ~]# 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(expr1;expr2;expr3) {statements} :循环或遍历数组中的元素

for(expr1;expr2;expr3) statement
for(var in array) {for-body} 遍历数组中的元素
[root@localhost ~]# awk '/^[[:space:]]*save/{for(i=1;i<=NF;i++) {if(length($i)>10) {print $i,length($i)}}}' /etc/grub2.cfg 
saved_entry 11
prev_saved_entry 16
saved_entry="${chosen}" 23
saved_entry 11

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

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

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

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

[root@localhost ~]# awk -F: '{if ($NR%2!=0) next; print $1,$2,$3}' /etc/passwd
root x 0
bin x 1
daemon x 2
adm x 3
lp x 4
sync x 5
shutdown x 6
halt x 7
mail x 8
operator x 11
games x 12
ftp x 14
nobody x 99
systemd-network x 192
dbus x 81
polkitd x 999
abrt x 173
libstoragemgmt x 998
rpc x 32
colord x 997
saslauth x 996
rtkit x 172
chrony x 995
qemu x 107
tss x 59
usbmuxd x 113
geoclue x 994
rpcuser x 29
nfsnobody x 65534
radvd x 75
setroubleshoot x 993
pulse x 171
gdm x 42
gnome-initial-setup x 992
sshd x 74
avahi x 70
postfix x 89
ntp x 38
tcpdump x 72
456 x 1000

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

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

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

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

[root@localhost ~]# awk '{installed[$5]++}END{for(i in installed) {print i,installed[i]}}' /var/log/yum.log 
zlib-devel-1.2.7-17.el7.x86_64 1
glibc-headers-2.17-196.el7_4.2.x86_64 1
glances-2.5.1-1.el7.noarch 1
m4-1.4.16-10.el7.x86_64 1
libstdc++-4.8.5-16.el7_4.2.x86_64 1
python2-psutil-2.2.1-3.el7.x86_64 1
epel-release-7-9.noarch 1
pcre-devel-8.32-17.el7.x86_64 1
libverto-devel-0.2.5-4.el7.x86_64 1
glibc-devel-2.17-196.el7_4.2.x86_64 1
autoconf-2.69-11.el7.noarch 1
cpp-4.8.5-16.el7_4.2.x86_64 1
libmpc-1.0.1-3.el7.x86_64 1
1:openssl-devel-1.0.2k-8.el7.x86_64 1
kernel-headers-3.10.0-693.21.1.el7.x86_64 1
keyutils-libs-devel-1.5.8-3.el7.x86_64 1
perl-Test-Harness-3.28-3.el7.noarch 1
libcom_err-devel-1.42.9-10.el7.x86_64 1
libstdc++-devel-4.8.5-16.el7_4.2.x86_64 1
glibc-2.17-196.el7_4.2.x86_64 1
libselinux-devel-2.5-11.el7.x86_64 1
perl-Thread-Queue-3.02-2.el7.noarch 1
gcc-4.8.5-16.el7_4.2.x86_64 1
htop-2.1.0-1.el7.x86_64 1
gcc-c++-4.8.5-16.el7_4.2.x86_64 1
krb5-devel-1.15.1-8.el7.x86_64 1
libkadm5-1.15.1-8.el7.x86_64 1
glibc-common-2.17-196.el7_4.2.x86_64 1
automake-1.13.4-3.el7.noarch 1
libgomp-4.8.5-16.el7_4.2.x86_64 1
libgcc-4.8.5-16.el7_4.2.x86_64 1
dstat-0.7.2-12.el7.noarch 1
libsepol-devel-2.5-6.el7.x86_64 1
tree-1.6.0-10.el7.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@localhost ~]# awk '{for(i=1;i<length(NF);i++) print $1}' /etc/passwd
tss:x:59:59:Account

[root@localhost ~]# awk 'BEGIN{rd=int(100*rand());print rd}'
23

[root@localhost ~]# awk 'BEGIN{haha="AVfbsdfc12345ASDFvdf?";gsub(/[0-9]+/,"#_#!!!",haha);print haha}'
AVfbsdfc#_#!!!ASDFvdf?

[root@localhost ~]# awk 'BEGIN{haha="AV fb s d f c 1 23 4 5A SD F v df?";split(haha,Line," ");print length(Line);for(i in Line){print i,Line[i]}}'
14
4 d
5 f
6 c
7 1
8 23
9 4
10 5A
11 SD
12 F
13 v
14 df?
1 AV
2 fb
3 s

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容

  • muahao阅读 2,064评论 0 3
  • linux资料总章2.1 1.0写的不好抱歉 但是2.0已经改了很多 但是错误还是无法避免 以后资料会慢慢更新 大...
    数据革命阅读 12,131评论 2 34
  • systemd攻略 转自http://www.jianshu.com/p/d5305104d03a或者这个http...
    x1596357阅读 2,839评论 0 3
  • tl;dr应用场景:对日常系统启动过程进行管理,优化启动速度。 1. systemd原理 1.1 基础概念-Uni...
    mst7阅读 5,046评论 0 8
  • 训练营还未开营,就有这么一种声音,如果写的文不出彩,坚持365天日更也白费劲。 我还没有开始日更,觉得那些作者写得...
    溪水音阅读 380评论 10 11