1、总结sed和awk的详细用法;
awk
Linux文本处理工具三剑客:grep、sed和awk。其中grep是一种文本过滤工具,sed是文本编辑器,而awk是一种报表生成器,就是对文件进行格式化处理的,这里的格式化不是文件系统的格式化,而是对文件内容进行各种“排版”,进而格式化显示。
在Linux之上我们使用的是GNU awk简称gawk,并且gawk其实就是awk的链接文件,因此在系统上使用awk和gawk是一样的。我们通过man gawk可以获得gawk的相关功能说明—gawk-paten scanning and processing language(模式扫描及处理语言),gawk是一种过程式编程语言,gawk还支持条件判断、数组、循环等各种编程语言中所有可以使用的功能,因此还可以把gawk称为一种脚本语言编辑器。
awk的运行方式有3种:
(1)awk命令行
#awk
(2)awk程序文件
#awk -f /path/from/awk_script
(3)awk脚本
#!/bin/awk -f
awk的基本用法:awk [OPTIONS] ‘program’ FILE1 FILE2 …
其中program:PATTERN{ACTION STATEMENT}
program:编程语言
PATTERN:模式
ACTION STATEMENT:动作语句,可以是由多个语句组成,各语句间使用分号隔开;如print,printf。
OPTIONS:
-F[]:指明输入字段分隔符;
-v VAR_NAME=VALUE:变量赋值;
-f /PATH/FROM/AWK_SCRIPT;
awk在处理文本时也是一次读取一行文本,然后根据输入分隔符(默认为空格字符)进行切片,切成n个片段,然后将每一片都赋予awk内部的一个变量当中进行保存,这些变量名为$1、$2、$3等一直到最后一个,awk就可以对这些片段单独处理,比如显示某一段、特定段、甚至可以对某些片段进行额外的加工处理,比如计数、运算等。
1、awk的输出命令之一:print
用法:print item1,items,…
item:字符串,用引号引用;
print “hello”,”world"
变量:显示变量的值,可以直接使用变量的名进行引用;
print name
数值:无需加引号
要点:
(1)各item之间需要使用逗号分隔;而输出时的分隔符默认为空白字符;
(2)输出的各item可以为字符串或数值、当前记录的字段($#)、变量或awk的表达式;数值会被隐式转换为字符串进行输出;
(3)print后面的item省略时,相当于运行“print $0”,用于输出整行;
(4)输出空白字符:print“ ”
2、变量
变量分为内建变量和自定义变量
2.1 内置变量
FS:input Field Seperator,输入字段分隔符,默认为空白;
如:-v FS=“[,;.]”也可以使用-F:
~]# head -3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
~]# awk -v FS=":" '{print $1,$2}' /etc/passwd | head -3
root x
bin x
daemon x
RS:input Record Seperator,输入时的行分隔符,默认为换行符;
OFS:output Field Separator,输出时的字段分隔符,默认为空白字符;
~]# awk -v FS=":" -v OFS="," '{print $1,$2}' /etc/passwd | head -3
root,x
bin,x
daemon,x
ORS:Output Record Separator,输出时的字段分隔符,默认为换行符;
NF:number of field in current record,当前行的字段数;
print NF:显示当前行的字段数
print $NF:显示当前行的第NF字段的值
~]# cat /etc/fstab | head -4
#
# /etc/fstab
# Created by anaconda on Sun Sep 11 12:00:46 2016
~]# awk '{print NF}' /etc/fstab | head -4
0
1
2
10
~]# awk '{print $NF}' /etc/fstab | head -4
#
/etc/fstab
2016
NR:number of record,行数:命令后跟的所有文件将统一合并计数;
~]# awk '{print NR}' /etc/fstab | head -4
1
2
3
4
FNR:行数,各文件单独统计:
FILENALE:当前正被awk读取的文件的文件名;
ARGC:awk命令运行中的参数个数;
ARGV:数字,保存了命令行参数本身;
ARGV[index]
ARGV[0],ARGV[1]
2.2自定义变量
(1)-v VAR_NAME=VALUE 变量名区分字符大小写;
~]# cat /etc/issue
\S
Kernel \r on an \m
~]# awk -v Final='Void' '{print Final}' /etc/issue
Void
Void
Void
虽然这里的对象文件/etc/issue内容没什么用,但是这里使用的文件行数,有多少行就显示多少个变量值。
(2)在program中自定义变量
~]# awk 'BEGIN{FS=":";f1=3}{print $f1}' /etc/passwd
3、awk的输出命令之二:printf 格式化输出
语法:printf FORMAT,item1,item2,…
要点:
(1)必须提供FORMAT;
(2)与print语句不同,printf不会自动换行,需要显示指定换行符:\n
(3)FORMAT中需要分别为后面的每个item指定一个格式符,否则item无法显示;
格式符:都以%开头,后跟单个字符;
%c:显示字符的ASCII码;
%d,%i:显示为十进制整数;
%e,%E:科学计数法显示数值;
%f:显示为浮点数;
%g,%G:以科学计数法或浮点数格式显示数值;
%s:显示为字符串;
%u:显示无符号整数;
%%:显示%符号本身;
~]# cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m
~]# awk -F: '{printf "USER:%s\n",$1}' /etc/issue
USER:CentOS release 6.5 (Final)
USER:Kernel \r on an \m
USER:
~]# awk '{printf "USER:%s\n",$1}' /etc/issue
USER:CentOS
USER:Kernel
USER:
USER:%s\n表示对$1的内容以字符串的形式显示,并且在其前面加上USER:字符串,同时在结尾添加换行符。
~]# awk -F' ' '{printf "USER:%s,UID:%d\n",$1,$3}' /etc/issue
USER:CentOS,UID:6
USER:Kernel,UID:0
USER:,UID:0
USER:%s,UID:%d\n表示对后面的$1的内容以字符串的形式显示,对后面的$2的内容以十进制的形式显示,同时在结尾添加换行符。
修饰符:每一种格式符都有一些修饰符
#[.#]:
左边的#:用于指定显示宽度;
右边的#:显示精度;
+:显示数值的符号
-:左对齐
~]# awk -F' ' '{printf "USER:%-15s,UID:%15d\n",$1,$3}' /etc/issue
USER:CentOS ,UID: 6
USER:Kernel ,UID: 0
USER: ,UID: 0
左边一栏以左对齐方式显示15个字符的长度,右边栏以默认对齐方式右对齐显示15个字符的长度。
4、awk的操作符
awk的操作符有:算数运算符、字符操作符、赋值操作符、比较运算符、模式匹配操作符、逻辑操作符、条件表达式和函数调用。
算数操作符:实现一些算数运算,如x+y,x-y,x*y,x/y,x^y,x%y
-x:负值
+x:转换为数值
字符操作符:字符串链接
赋值操作符:通常为变量的赋值,赋值操作符有以下几种
=,+=,-=,*=,/=,%=,^=
++,–
比较运算符:字符串或者数值的大小比较
>,>=,<,<=,!=,==
模式匹配符:根据右侧的模式进行匹配操作
~:是否能由右侧指定的模式所匹配
~!:是否不能由右侧指定模式所匹配
逻辑操作符:
&&
||
!
条件表达式:
selector?if-true-expression:if-false-expression
~]# awk -F: '{$3>=500?usertype="Common User":usertype="Sysadmin or SysUse
r";printf "%15s:%-s\n",$1,usertype}' /etc/passwd
root:Sysadmin or SysUser
bin:Sysadmin or SysUser
daemon:Sysadmin or SysUser
adm:Sysadmin or SysUser
lp:Sysadmin or SysUser
sync:Sysadmin or SysUser
shutdown:Sysadmin or SysUser
函数调用:调用函数来进行数据的处理
格式:function_name(argu1,argu2,…)
5、PATTERN模式:对哪些内容进行处理
(1)empty:空模式,匹配每一行;
(2)/regular expression/:仅将ACTION应用于能够被regular expression所匹配到的行;
~]# awk -F: '/^[ab]/{print $1,$3}' /etc/passwd
bin 1
adm 3
avahi-autoipd 170
abrt 173
apache 48
bash 500
basher 502
(3)relational expression:关系表达式,即结果为“真”、“假”的表达式,或者其结果能类同于“真”或“假”的表达式;一般来说,其结果为非0数值或非空字符串即可类同于“真”,否则,则类同为“假”;
~]# awk -F: '$3>=500{print $1,$3}' /etc/passwd
nfsnobody 65534
bash 500
testbash 501
basher 502
nologin 503
~]# awk -F: '$1~/root/{print $1,$3}' /etc/passwd
root 0
(4)line ranges:行范围,类似sed或vim中的地址定界方式如:
startline,endline: /pat1/,/pat2/
注意:不支持直接给出数字的格式
~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd
bin
daemon
adm
lp
sync
shutdown
halt
uucp
(5)BEGIN/END:两个特殊模式
BEGIN{}:在文件格式化操作开始之前事先执行的一次操作;通常用于输出表头或做出一个预处理操作;
END{}:在文件格式操作完成之后,命令退出之前执行的一次操作;通常用于输出表尾或做出清理操作;
6、常用ACTION
(1)EXPRESSIONS:例如变量赋值
(2)Control Statements:控制语句,如if,while等;
(3)Compound statements:组合语句;
(4)input statements
(5)output statements
7、控制语句
if(condition) {statments}
if(condition) {statments} else {statements}
while(conditon) {statments}
do {statements} while(condition)
for(expr1;expr2;expr3) {statements}
break
continue
delete array[index]
delete array
exit
{ statements }
7.1 if-else
语法:if(condition) statement [else statement]
~]# awk -F: '{if($3>=500) {printf "Common user:%s\n",$1} else {printf "root or Sysuser:%s\n",$1}}' /etc/passwd
root or Sysuser:root
…
Common user:nologin
…
~]# awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
root
bash
testbash
basher
~]# df -h | awk -F[%] '/^\/dev/{print $1}' | awk '{if($NF>=20) print $1}'
使用场景:对awk取得的整行或某个字段做添加判断
7.2 while循环
语法:while(condition) statement
条件为“真”时循环,为“假”时退出循环;
使用场景:通常用于在当前行的各字段进行循环;
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub2.cfg
~]# awk '/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}' /etc/grub2.cfg
~]# awk '{i=1;while(i<=NF){if(length($i)>=6){print $i};i++}}' /etc/issue
CentOS
release
(Final)
Kernel
7.3 do-while循环
语法:do {statement} while (condition)
意义:至少执行一次循环
7.4 for循环
语法:for(expr1;expr2;expr3) statement
for(variable assignment;condition;iteration process) {for-body}
~]# awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
~]# awk '{for(i=1;i<=NF;i++){if(length($i)>=6) print $i}}' /etc/issue
Kernel
特殊用法:
能够遍历数组中的元素;
语法:for(var in array) {for-body}
7.5 switch
语法:switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement}
7.6 break and continue
break[n]:退出当前循环,n是一个数字,用于指定退出几层循环;
continue:提前结束本轮循环而进入下一轮;
7.7 next:提前结束对本行文本的处理,而提前进入下一行的处理操作:
~]# awk -F: '{if($3%2==0) next;print $1,$3}' /etc/passwd
bin 1
adm 3
sync 5
halt 7
operator 11
nobody 99
systemd-bus-proxy 999
8、数组
关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号;
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”;
若要判断数组中是否存在某元素,要使用"index in array"格式进行;
weekdays[mon]="Monday"
若要遍历数组中的每个元素,要使用for循环;
for(var in array) {for-body}
~]# awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
注意:var会遍历array的每个索引;
state["LISTEN"]++
state["ESTABLISHED"]++
统计当前系统上所有的tcp连接的各种状态个数:
~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
~]# ss -tan | awk '!/^State/{state[$1]++}END{for(i in state) {print i,state[i]}}'
统计指定的web访问日志中各ip的资源访问次数:
~]# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
练习1:统计/etc/fstab文件中每个文件系统类型出现的次数;
~]# awk '/^UUID/{fs[$3]++}END{for(i in fs) {print i,fs[i]}}' /etc/fstab
练习2:统计指定文件中每个单词出现的次数;
~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
9、函数
9.1 内置函数
数值处理:
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所表示的数组中;
~]# netstat -tan | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}'
9.2 自定义函数
《sed和awk》
sed
文本处理三剑客:
grep, egrep, fgrep:文本过滤器
sed:Stream EDitor,流编辑器,行
awk:文本格式化工具,报告生成器
sed [OPTION]… 'script' [input-file] …
script:
地址定界编辑命令
常用选项:
-n:不输出模式空间中的内容至屏幕;
-e script, –expression=script:多点编辑;
-f /PATH/TO/SED_SCRIPT_FILE
每行一个编辑命令;
-r, –regexp-extended:支持使用扩展正则表达式;
-i[SUFFIX], –in-place[=SUFFIX]:直接编辑原文件 ;
~]# sed -e 's@^#[[:space:]]*@@' -e '/^UUID/d' /etc/fstab
地址定界:
(1) 空地址:对全文进行处理;
(2) 单地址:
#:指定行;
/pattern/:被此模式所匹配到的每一行;
(3) 地址范围
#,#:
#,+#:
#,/pat1/
/pat1/,/pat2/
$:最后一行;
(4) 步进:~
1~2:所有奇数行
2~2:所有偶数行
编辑命令:
d:删除;
p:显示模式空间中的内容;
a \text:在行后面追加文本“text”,支持使用\n实现多行追加;
i \text:在行前面插入文本“text”,支持使用\n实现多行插入;
c \text:把匹配到的行替换为此处指定的文本“text”;
w /PATH/TO/SOMEFILE:保存模式空间匹配到的行至指定的文件中;
r /PATH/FROM/SOMEFILE:读取指定文件的内容至当前文件被模式匹配到的行后面;文件合并;
=:为模式匹配到的行打印行号;
!:条件取反;
地址定界!编辑命令;
s///:查找替换,其分隔符可自行指定,常用的有s@@@, s###等;
替换标记:
g:全局替换;
w /PATH/TO/SOMEFILE:将替换成功的结果保存至指定文件中;
p:显示替换成功的行;
练习1:删除/boot/grub/grub2.cfg文件中所有以空白字符开头的行的行首的所有空白字符;
~]# sed 's@^[[:space:]]\+@@' /etc/grub2.cfg
练习2:删除/etc/fstab文件中所有以#开头的行的行首的#号及#后面的所有空白字符;
~]# sed 's@^#[[:space:]]*@@' /etc/fstab
练习3:输出一个绝对路径给sed命令,取出其目录,其行为类似于dirname;
~]# echo "/var/log/messages/" | sed 's@[^/]\+/\?$@@'
~]# echo "/var/log/messages" | sed -r 's@[^/]+/?$@@'
高级编辑命令:
h:把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g:把保持空间中的内容覆盖至模式空间中;
G:把保持空间中的内容追加至模式空间中;
x:把模式空间中的内容与保持空间中的内容互换;
n:覆盖读取匹配到的行的下一行至模式空间中;
N:追加读取匹配到的行的下一行至模式空间中;
d:删除模式空间中的行;
D:删除多行模式空间中的所有行;
示例:
sed -n 'n;p' FILE:显示偶数行;
sed '1!G;h;$!d' FILE:逆序显示文件的内容;
sed ’$!d' FILE:取出最后一行;
sed '$!N;$!D' FILE:取出文件后两行;
sed '/^$/d;G' FILE:删除原有的所有空白行,而后为所有的非空白行后添加一个空白行;
sed 'n;d' FILE:显示奇数行;
sed 'G' FILE:在原有的每行后方添加一个空白行;
2、删除/boot/grub/grub.conf文件中所有行的行首的空白字符;
~]# sed 's@^[[:space:]]\+@@' /boot/grub/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/mapper/VolGroup-lv_root
# initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title CentOS (2.6.32-431.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-431.el6.x86_64 ro root=/dev/mapper/VolGroup-lv_root rd_NO_LUKS rd_NO_MD rd_LVM_LV=VolGroup/lv_swap crashkernel=auto LANG=zh_CN.UTF-8 rd_LVM_LV=VolGroup/lv_root KEYBOAR
DTYPE=pc KEYTABLE=us rd_NO_DM rhgb quietinitrd /initramfs-2.6.32-431.el6.x86_64.im
3、删除/etc/fstab文件中所有以#开头,后跟至少一个空白字符的行的行首的#和空白字符;
~]# sed 's@^#[[:space:]]\+@@' /etc/fstab
#
/etc/fstab
Created by anaconda on Tue Dec 20 11:22:23 2016
#
Accessible filesystems, by reference, are maintained under '/dev/disk'
See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
#
/dev/mapper/VolGroup-lv_root / ext4 defaults 1 1
UUID=123bda7a-e4e5-4dc7-9d81-9bd5bcadd76f /boot ext4 defaults
1 2/dev/mapper/VolGroup-lv_swap swap swap defaults 0 0
tmpfs /dev/shm tmpfs defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
sysfs /sys sysfs defaults 0 0
proc /proc proc defaults 0 0
4、把/etc/fstab文件的奇数行另存为/tmp/fstab.3;
~]# sed 'n;d' /etc/fstab > /tmp/fstab.3
~]# cat /tmp/fstab.3
# /etc/fstab
#
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
/dev/mapper/VolGroup-lv_root / ext4 defaults 1 1
/dev/mapper/VolGroup-lv_swap swap swap defaults 0 0
devpts /dev/pts devpts gid=5,mode=620 0 0
proc /proc proc defaults 0 0
5、echo一个文件路径给sed命令,取出其基名;进一步地,取出其路径名;
~]# echo "/etc/fstab" | sed 's@^/.*/@@'
fstab
~]# echo "/etc/fstab" | sed -r 's@[^/]+/?$@@'
/etc/
6、统计指定文件中所有行中每个单词出现的次数;
~]# awk '{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}' /etc/fstab
7、统计当前系统上所有tcp连接的各种状态的个数;
~]# netstat -tan | awk '/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}'
~]# ss -tan | awk '!/^State/{state[$1]++}END{for(i in state) {print i,state[i]}}'
8、统计指定的web访问日志中各ip的资源访问次数:
~]# awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
9、写一个脚本:定义一个数组,数组元素为/var/log目录下所有以.log结尾的文件的名字;显示每个文件的行数;
#!/bin/bash
#
filelist=(/var/log/*.log)
for i in $(seq 0 $[${#filelist[@]}-1]);do ${#filelist[@]}表示数组中元素的个数
wc -l ${filelist[i]}
done
执行结果:
~]# bash countlog.sh
158 /var/log/boot.log
4 /var/log/wpa_supplicant.log
0 /var/log/yum.log
10、写一个脚本,能从所有同学中随机挑选一个同学回答问题;进一步地:可接受一个参数,做为要挑选的同学的个数;
#!/bin/bash
#
stu=(s1 s2 s3 s4 s5 s6)
num=${#stu[@]}
i=$[$RANDOM % $num]
echo "${stu[i]}"
执行结果
~]# bash stu.sh
s1
~]# bash stu.sh
s6
~]# bash stu.sh
s1
~]# bash stu.sh
s5
~]# bash stu.sh
s5
stu2.sh
#!/bin/bash
#
stu=(s1 s2 s3 s4 s5 s6)
stunumber=${#stu[*]}
read -p "please input the number of students to answer the question:[1-$stunumber]" num
if [[ $num -gt $stunumber || $num -eq 0 ]];then
echo "the number range is 1 – $stunumber"
exit 1
fi
for ((i=0;i<num;i++));do
j=$[$RANDOM % $stunumber]
echo ${stu[$j]}
unset stu[$j]
done
执行结果:
~]# bash stu2.sh
please input the number of students to answer the question:[1-6]0
the number range is 1 – 6
~]# bash stu2.sh
please input the number of students to answer the question:[1-6]11
the number range is 1 – 6
~]# bash stu2.sh
please input the number of students to answer the question:[1-6]3
s5
s4
s2
11、授权centos用户可以运行fdisk命令完成磁盘管理,以及使用mkfs或mke2fs实现文件系统管理;
/etc/sudoers的通用格式为:
user host=(run_as) [NOPASSWD:] command
user host run_as command
user:一位或几位用户,在/etc/group中可以用一个%代替它,组对象的名称一定要用百分号%开头。
host:一个或几个主机名;
run_as:作为哪个用户运行,常见选项是root和ALL
command:想让用户或组运行的一个或几个根级别命令。
Cmnd_Alias CMND_LVS:可以将命令集合为一个变量,之后直接引用。用户,主机都可以如此定义。
centos ALL=(root) NOPASSWD: /sbin/fdisk, /sbin/mke2fs, /sbin/mkfs
12、授权gentoo用户可以运行逻辑卷管理的相关命令;
Cmnd_Alias CMND_LVS = /sbin/lvm, /sbin/lvmchange, /sbin/lvmconf, /sbin/lvmdiskscan, /sbin/lvmdump, /sbin/lvmetad, /sbin/lvmsadc, /sbin/lvmsar
gentoo ALL=(root) NOPASSWD: CMND_LVS
13、基于pam_time.so模块,限制用户通过sshd服务远程登录只能在工作时间进行;
(1)在account required pam_nologin.so上添加一行:
~]# vim /etc/pam.d/sshd
account required pam_time.so
(2)编辑pam_time.so模块的配置文件
~]# vim /etc/security/time.conf
*;*;*;MoTuWeThFr0900-1800
14、基于pam_listfile.so模块,定义仅某些用户,或某些组内的用户可登录系统;
创建一个用户的列表文件,例如/etc/sshd_userlist,而后编辑文件 root centos gentoo 而后修正文件的权限和属主
# chmod 600 /etc/sshd_userlist
# chown root /etc/sshd_userlist
再编辑/etc/pam.d/sshd文件:
auth required pam_listfile.so item=user sense=allow file=/etc/sshd_userlist onerr=succeed
原创文章,作者:N23-苏州-void,如若转载,请注明出处:http://www.178linux.com/65936
评论列表(1条)
总结的grep,sed,awk比较详细,好多用法要能灵活用在实际工作中,继续加油。