Shell笔记¶
Linux系统介绍:内核、shell及软件包管理¶
Linux系统主要包括3层, 硬件(RAM、CPU、I/O设备等)、 Linux 内核和 用户进程。
Linux 内核最初由芬兰黑客 Linus Torvalds 开发,Linux内核是Linux操作系统的重要组成部分,是操作系统的核心,是系统硬件和进程之间的接口。内核提供内存管理、进程管理、设备驱动和各种系统调用。
Linux内核版本¶
Linux各个内核版本可以在https://www.kernel.org/ 上下载,一些社区组织或厂商将Linux内核与各种软件和文档包装起来,并提供系统安装界面和系统配置、设定与管理工具,就构成了 Linux 的发行版本。Linux有多个发行版本,常见的Linux系统有Centos和Ubuntu。
查看系统版本¶
cat /proc/version
uname -a
[root@iZ8vb54310gt89j8qct198Z ~]# cat /proc/version
Linux version 4.18.0-147.5.1.el8_1.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 8.3.1 20190507 (Red Hat 8.3.1-4) (GCC)) #1 SMP Wed Feb 5 02:00:39 UTC 2020
[root@iZ8vb54310gt89j8qct198Z ~]# uname -a
Linux iZ8vb54310gt89j8qct198Z 4.18.0-147.5.1.el8_1.x86_64 #1 SMP Wed Feb 5 02:00:39 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
4.18.0-147.5.1.el8_1.x86_64
:
4:内核主版本号
18:内核次版本号,偶数代表稳定版;奇数代表开发版
0:内核修订版本号,添加安全补丁,bug修复,新功能或驱动程序等
147.5.1:发行版本的补丁版本
el8_1:使用的内核是 RedHat / CentOS 系列发行版专用内核
x86_64:x86平台64位CPU
查看centos发行版本:
[root@iZ8vb54310gt89j8qct198Z ~]# cat /etc/redhat-release
CentOS Linux release 8.1.1911 (Core)
shell¶
常见 shell¶
Shell 是一种脚本编程语言,连接内核和用户。常见的 Shell 有 sh、bash、ksh、csh等。
Bourne Shell (/usr/bin/sh或/bin/sh)
Bourne Again Shell (/bin/bash):兼容 sh
C Shell (/usr/bin/csh)
K Shell (/usr/bin/ksh)
Shell for Root (/sbin/sh)
cat /etc/shells
命令查看系统可用shell:
[root@client ~]# cat /etc/shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
[root@client ~]#
运行 shell¶
使脚本具有执行权限
chmod +x ./test.sh
chmod 777 ./test.sh
执行脚本
./test.sh # 执行脚本
/bin/sh test.sh
查看Linux系统信息¶
查看系统位数¶
getconf LONG_BIT
file /bin/ls
[root@iZ8vb54310gt89j8qct198Z ~]# getconf LONG_BIT
64
[root@iZ8vb54310gt89j8qct198Z ~]# file /bin/ls
/bin/ls: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=937708964f0f7e3673465d7749d6cf6a2601dea2, stripped, too many notes (256)
[root@iZ8vb54310gt89j8qct198Z ~]#
查看内存信息¶
Linux 查看内存支持的最大内存容量
$ dmidecode|grep -P 'Maximum\s+Capacity'
Maximum Capacity: 8 GB
查看槽位上内存的速率,没插就是unknown。
dmidecode|grep -A16 "Memory Device"|grep 'Speed'
查看内存条厂家
dmidecode -t memory | grep Manufacturer
查看内存信息(显示插槽个数和每个插槽里内存条的大小)
$ dmidecode -t memory | grep Size
Size: 8192 MB
查看内存使用情况:
$free -h
total used free shared buff/cache available
Mem: 1.8G 1.4G 173M 764K 251M 268M
Swap: 2.0G 1.0G 1.0G
查看CPU信息¶
# CPU型号
$ cat /proc/cpuinfo | grep name | sort | uniq
model name : Intel Xeon Processor (Skylake, IBRS)
# 物理CPU个数
$ cat /proc/cpuinfo | grep "physical id"
physical id : 0
physical id : 1
physical id : 2
physical id : 3
physical id : 4
physical id : 5
physical id : 6
physical id : 7
# 每个物理CPU核数
$ cat /proc/cpuinfo| grep "cpu cores"| uniq
cpu cores : 1
# 逻辑CPU个数
$ cat /proc/cpuinfo| grep "processor"| wc -l
8
Linux软件包管理¶
Linux软件安装可以直接通过源码编译安装,一般源码包都打包成tar.gz压缩格式。源码包安装比较麻烦,容易出错,也可以使用包管理来软件包的管理,包管理工具是对软件工具的安装、卸载及其他管理, 常见的两类软件包管理工具是RPM 和 DPKG,RPM是Red Hat软件包管理器,DPKG的是Debian的Linux系列基本的包管理系统。
源码编译安装¶
源码编译安装步骤:
下载安装文件
解压
tar -xvzf xxx.tar.gz
检查编译 进入解压文件内
./configure
检查通过后,将生成用于编译的MakeFile文件。 4. 编译
make
安装
make install
安装完毕,应清除编译过程中产生的临时文件和配置过程中产生的文件。
make clean
make distclean
如果要卸载,则执行
make uninstall
RPM¶
RPM 全称为 Redhat Package Manager,最早由 Red Hat 公司制定实施,rpm包文件通常以.rpm结尾。
RPM包安装¶
下载rpm包后安装: 安装 RPM 包
rpm -ivh package.rpm
升级 RPM 包
rpm -Uvh package.rpm
卸载 RPM 包
rpm -ev package
rpm命令其它用法¶
查看是否安装了某个软件:
[root@Client ~]# rpm -qa | grep wireshark
wireshark-1.10.14-25.el7.x86_64
查询某个命令属于哪个软件:
[root@Client ~]# which scp
/usr/bin/scp
[root@Client ~]# rpm -qf /usr/bin/scp
openssh-clients-7.4p1-21.el7.x86_64
yum¶
rpm无法解决软件包与软件包之间的依赖问题,可以使用yum工具进行在线安装,yum(Yellowdog update Modifier)是RPM前端工具,操作对象为rpm包。由于网络问题,可以设置yum国内镜像源,也可以配置本地源。下面介绍yum安装方法: 搜索可用软件包:
yum search all 软件关键字
搜索已安装的软件:
yum list installed | grep 软件关键字
安装
yum install package-name
yum -y install package-name #接受所有互动问答
卸载
yum remove package-name
yum -y remove package-name
DPKG¶
DPKG全称为 Debian Package,功能与 RPM 相似,包文件通常以 .deb 扩展名结尾。Ubuntu系统使用此包管理工具。
DPKG 命令安装¶
安装 DEB 包
dpkg -i package.deb
升级 DEB 包
dpkg -i package.deb ( 和安装命令相同)
卸载 DEB 包
dpkg -r package.deb # 不卸载配置文件
dpkg -P package.deb # 卸载配置文件
apt¶
apt 全称 Advanced Packaging Tools,DPKG 前端工具, apt 的主要包管理工具为apt-get,实现功能和yum类似。
搜索可用软件包
apt-cache search 软件关键字
安装
apt-get install package-name
下载指定软件的源文件
apt-get source package-name
更新
apt-get upgrade # 更新软件
apt-get update # 更新软件列表
apt-get dist-upgrade # 更新所有软件
卸载
apt-get remove package-name
查看历史命令history¶
在Linux命令窗口可以查看执行过的历史命令,可以通过上/下方向键(或者Ctrl+ p / Ctrl+ n)显示相对于当前命令的上一条或下一条历史记录。或者通过Ctrl+ r
来搜索历史命令。
还有一种更为直观的方法是使用history命令,可以显示多个记录,默认情况下,历史命令存放在 ~/.bash_history
文件里面,也可以在/etc/bashrc
中设置历史命令存放路径,添加:export HISTFILE=存放路径
history命令格式如下:
history [-c] [-d offset] [n]
-c:清空历史命令
-d offset:删除历史命令中第offset个命令
n:显示最近的n条历史命令
显示最近的5个命令:
[root@server ~]# history 5
996 cat /etc/bashrc
997 vim /etc/bashrc
998 history --help
999 echo $HISTSIZE
1000 history 5
[root@server ~]#
Linux 文件句柄¶
由于UNIX/Linux系统中的资源都是以文件的形式存在的,可以限制用户进程可使用的系统资源数量,比如一个进程可以打开的文件数,用户可以创建多大的文件,以及进程可以使用多少内存。如果Linux在进行大量并发操作的时候,可能会报 "Too many open files" 错误,这是因为并发操作的文件数超过了限制,可以使用ulimit
命令查看:
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 7144
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 7144
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
open files 的最大限制为1024,可以使用ulimit命令进行修改:
ulimit –n 10000
这个命令不能保证永久生效,系统重启后会恢复原来的默认值。为了让ulimit在重启过程中持续存在,需要修改配置文件/etc/security/limits.conf
:
#<domain> <type> <item> <value>
#
#* soft core 0
#* hard rss 10000
#@student hard nproc 20
#@faculty soft nproc 20
#@faculty hard nproc 50
#ftp hard nproc 0
#@student - maxlogins 4
type可以设置为soft和hard:
soft:软件限制,用于警告
hard:硬件限制,设置实际的默认值
item选项包括:
core :core文件大小 (KB)
data :最大的数据大小 (KB)
fsize :最大文件大小 (KB)
memlock :最大锁定内存空间 (KB)
nofile :打开文件的最大数量
rss :最大Resident Set大小 (KB)
stack :堆栈大小 (KB)
cpu :最大CPU time (MIN)
nproc :最大进程数
as :最大地址空间 (KB)
maxlogins :此用户的最大登录数
maxsyslogins :系统的最大登录数
priority :运行用户进程的优先级
locks :用户最大文件锁定数
sigpending :最大被挂起/阻塞 (pending) 的信号数
msgqueue :POSIX消息队列使用的最大内存 (bytes)
nice :最大允许的 nice 优先级: [-20, 19]
rtprio :最大realtime优先级
打开文件的最大数量设置方法如下:
编辑配置文件 /etc/security/limits.conf
加入如下配置:
* soft nofile 10000
* hard nofile 10000
或者:
* - nofile 2000
保存退出。
Linux Bash编程¶
在《Linux系统介绍》中,介绍了shell的多个版本,现在的Linux发行版基本都默认使用bash(Bourne Again shell),兼容Bourne shell (sh),本文将简要介绍Bash编程语法。
变量¶
命名规则¶
只能使用英文字母,数字和下划线,首个字符不能以数字开头
中间不能有空格,可以使用下划线(_)
不能使用标点符号
不能使用bash里的关键字(可用help命令查看保留关键字) img
定义与使用变量¶
定义变量
your_name="abc"
echo $your_name
拼接字符串
your_name="world"
your_name2="hello,$your_name!"
echo $your_name2
数组
array_name=(value0 value1 value2 value3)
valuen=${array_name[n]} # 数组取值
array_name[0]=value0 # 赋值
length=${#array_name[@]} # 获取数组长度
数组实例:
my_array=(A B "C" D)
echo "第一个元素为: ${my_array[0]}"
my_array[1]=b
echo "数组的元素为:${my_array[*]}" # 打印所有元素
echo "数组的元素为:${my_array[@]}"
输出:
第一个元素为: A
数组的元素为:A b C D
数组的元素为:A b C D
只读变量¶
a="123"
readonly a
删除变量¶
unset variable_name #不能删除只读变量
不能删除只读变量
# b=10
# readonly b
# echo $b
10
# unset b
-bash: unset: b: cannot unset: readonly variable
#
环境变量¶
显示所有环境变量
env
# 或者
printenv
显示环境变量值
printenv LANG
# 或者
echo $LANG
控制语句¶
条件分支:if¶
if定义¶
if condition
then
command1
command2
...
commandN
fi
if和then写在同一行时,用分号分隔。
if [ 2==2 ]; then
echo "true";
else
echo "false";
fi
判断条件写法¶
# 写法一
test expression
# 写法二
[ expression ]
# 写法三
[[ expression ]]
if test 2==2; then echo "true"; fi
if [ 2>1 ]; then echo "true"; fi
if [[ 2>1 ]]; then echo "true"; fi
实例¶
比较两个变量的大小
a=10
b=20
if [ $a -eq $b ]; then
echo"equal";
elif [ $a -lt $b ]; then
echo "small";
elif [ $a -gt $b ]; then
echo "big";
fi
循环:for¶
for定义¶
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
实例¶
for和do写在同一行时,用分号分隔。
for Ioop in 1 2 3 4 5
do
echo "hello"
done
for Ioop in 1 2 3 4 5;do
echo "hello"
done
循环读取文件内容并输出
for i in $(cat test.txt); do echo $i; done
循环遍历列表
list=(value1 value2 value3)
for i in ${list[*]}; do echo $i; done
# 或者
for i in ${list[@]}; do echo $i; done
循环: while¶
while定义¶
while condition
do
command
done
实例¶
int=1
while(( $int<=5))
do
echo $int
let "int++"
done
循环读取文件内容并输出
while read line; do echo $line; done<test.txt
输出:
test1
test222
test3
test4
test5
read命令¶
read命令是用于从终端或者文件中读取输入的内部命令
读取整行输入
每行末尾的换行符不被读入
read命令使用¶
从标准输入读取输入并赋值给变量
read var
从标准输入读取多个内容
read varl var2 var3
不指定变量(默认赋值给 REPLY)
read
实例¶
# read a
123
# echo $a
123
# read a b c
1 2 3
# echo $a
1
# echo $b
2
# echo $c
3
#
默认变量
# read
456
# echo $REPLY
456
#
注释¶
# 注释
# 多行注释
:<<EOF
内容
.......
EOF
脚本参数传递¶
$0 脚本名称
$1~$n 获取第n个参数:
$# 传递到脚本的参数个数
$$ 脚本运行的当前进程ID号
$* 以一个单字符串显示所有向脚本传递的参数
$? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误
vim param.sh:
#!/bin/bash
echo "脚本名称:$0"
echo "脚本运行的当前进程ID号:$$"
echo "参数个数:$#"
echo "所有参数:$*"
echo "第1个参数:$1"
echo "第10个参数:${10}"
echo "return "$?
执行:
# chmod +x param.sh
# ./param.sh 1 2 3 4 5 6 7 8 9 10 1
脚本名称:./param2.sh
脚本运行的当前进程ID号:21097
参数个数:11
所有参数:1 2 3 4 5 6 7 8 9 10 1
第1个参数:1
第10个参数:10
return 0
#
基本运算¶
bash会把反引号里面当作一条命令来执行 In:
# echo `date +%y/%m/%d`
20/12/27
# echo `expr 2 + 2`
4
# a=10
# b=20
# echo expr $a + $b
30
# echo $(($a+$b))
30
# echo expr $a - $b
-10
# echo expr $a \* $b
200
# echo expr $b / $a
2
#
% 取余
= 赋值 a=$b 将把变量b的值赋给a
== 相等 相同则返回true
!= 不相等 不相同则返回true
# a=10
# b=20
# echo `expr $b % $a`
0
# echo $[$a == $b]
0
# echo $[$a != $b]
1
#
-eq 检测相等
-ne 检测不相等
-gt 检测左边是否大于右边
-lt 检测左边是否小于右边
-ge 检测左边是否大于等于右边
-le 检测左边是否小于等于右边
# vim test.sh
# cat test.sh
#!/bin/bash
a=10
b=20
if [ $a -lt $b ]
then
echo "equal"
fi
# chmod +x test.sh
# ./test.sh
equal
#
其它实例¶
内存统计¶
#!/bin/bash
# 内存使用百分比
free | sed -n '2p' | gawk 'x = int(( $3 / $2 ) * 100) {print x}' | sed 's/$/%/'
# 统计内存
for i in `ps aux | awk '{print $6}' | grep -v 'RSS'`; do
count=$[$count+$i]
done
echo "$count/kb"
# ./test.sh
16%
474608/kb
求阶乘¶
vim test.sh
read -p "Enter a number:"
factorial=1
for (( count=1; count<=$REPLY; count++))
do
factorial=$[ $factorial * $count ]
done
echo "The factorial of $REPLY is $factorial"
# chmod +x test.sh
# ./test.sh
Enter a number:6
The factorial of 6 is 720
Linux Bash编程二:shell语法及实用技巧¶
在Linux Bash编程中,介绍了Bash编程基本语法,本文记录一下Bash编程中使用到的相关shell 语法技巧。
字符串处理¶
在字符串中传递变量¶
$ num=8
# 方法1:双引号
$ text="There are $num ducks swimming in a pond"
$ echo $text
There are 8 ducks swimming in a pond
$
$ text="There are "$num" ducks swimming in a pond"
$ echo $text
There are 8 ducks swimming in a pond
# 方法2:单引号
$ text='There are $num ducks swimming in a pond'
$ echo $text
There are $num ducks swimming in a pond
$
$ text='There are '$num' ducks swimming in a pond'
$ echo $text
There are 8 ducks swimming in a pond
$ text="There are '$num' ducks swimming in a pond"
$ echo $text
There are '8' ducks swimming in a pond
tr命令¶
tr (translate) 命令用于删除或者转换字符,比如大小写转换,删除字符等。命令格式如下:
$ tr [OPTION] SET1 [SET2]
OPTION参数说明:
-c | --complement
:删除或者替换SET1以外的字符-d | --delete
:删除SET1以外的字符-s, --squeeze-repeats
:压缩连续重复的字符为单个字符-t, --truncate-set1
:截取 SET1 使之与 SET2 长度相等
1. 大小写转换¶
$ echo HELLO WORLD | tr "A-Z" "a-z"
hello world
$ echo HELLO WORLD | tr "[:upper:]" "[:lower:]"
hello world
$
$ echo hello world | tr "a-z" "A-Z"
HELLO WORLD
$ echo hello world | tr "[:lower:]" "[:upper:]"
HELLO WORLD
2. 替换¶
$ echo "(hello world)" | tr "()" "{}"
{hello world}
3. 压缩重复字符串¶
比如可以将多个连续空格压缩为一个空格
$ echo "hello world !" | tr -s [:space:] ' '
hello world !
4. 删除指定字符¶
$ echo "10MB" | tr -d MB
10
提取数字还可以这样:
$ echo "10MB" | tr -cd "[0-9]"
10
$ echo "10MB" | tr -cd [:digit:]
10
删除数字:
$ echo "10MB" | tr -d "[0-9]"
MB
$ echo "10MB" | tr -d [:digit:]
MB
字母字符用[:alpha:]
表示
判断字符串是否包含某个子串¶
使用通配符*
SIZE=10M
if [[ $SIZE == *M* ]]
then
echo "$SIZE include M"
fi
或者使用操作符~
if [[ $SIZE =~ M ]]
then
echo "$SIZE include M"
fi
数组操作¶
冒泡排序¶
#!/bin/bash
BubbleSort()
{
# 冒泡排序
# Performing Bubble sort
num_length=${#arry[*]}
for (( i = 0; i<$num_length; i++ ))
do
for (( j = 0; j<$num_length-i-1; j++ ))
do
if [[ ${arry[j]} -gt ${arry[$(( j+1 ))]} ]]
then
# swap
temp=${arry[j]}
arry[$j]=${arry[$((j+1))]}
arry[$(( j+1 ))]=$temp
fi
done
done
echo "Array in sorted order :"
echo -e "\E[1;31m${arry[*]} \033[0m"
}
arry=(9 8 5 6 2 4 7 1)
BubbleSort
执行结果:
$ sh BubbleSort.sh
Array in sorted order :
1 2 4 5 6 7 8 9
字体颜色¶
常用颜色格式:
normal='\033[0m' # 默认颜色
style='\033[1m' # 高亮
style='\033[4m' # 添加下划线
style='\033[7m' # 反显
color='\033[32m' # 绿色字体
color='\033[30m' # 黑色
color='\033[31m' # 红色
color='\033[33m' # 黄色
color='\033[34m' # 蓝色
color='\033[35m' # 紫色
color='\033[36m' # 深绿
color='\033[37m' # 白色
使用方法:
echo -e "\033[1m" "There are 8 ducks swimming in a pond"
echo -e "\033[0m" "There are 8 ducks swimming in a pond"
echo -e "\033[4m" "There are 8 ducks swimming in a pond"
echo -e "\033[7m" "There are 8 ducks swimming in a pond"
echo -e "\033[32m" "There are 8 ducks swimming in a pond"
文本处理¶
文件操作¶
sed -i '/^$/d' test.txt # 删除空行
sed -i 's/ *//g' test.txt # 删除空格
IFS=$'\n' # linux分隔符,默认是空格
for lines in `cat test.txt`; do # 循环读取每一行
pic=`echo $lines | grep '\!\[\]('` # 处理读取的内容:使用Linux三剑客进行文本处理
if [ "$pic" != "" ]
then
echo $pic >> new_file.txt
fi
# do something
done
清空文件内容¶
用于每次写文件时清空文件内容,下面介绍5种方法,前面4种方法中,如果文件不存在会创建文件。
$ cat /dev/null > test.txt
$ : > test.txt
$ > test.txt
$ true > test.txt
$ sed -i '1,$d' test.txt # 如果文件test.txt不存在会报错
使用SCP或Rsync实现Linux主机之间文件、目录的复制¶
我们知道Linux本机的文件拷贝可以使用cp
命令,它不能在Linux主机之间拷贝数据。本文介绍SCP和Rsync这两种实现Linux主机间的数据拷贝工具。
SCP 和 Rsync区别¶
SCP(secure copy) 是基于ssh协议的安全拷贝,用于将文件/目录安全地从本地主机传输到远程主机。
Rsync (remote synchronize)也可以实现同步本地主机和远程主机的文件/目录,和SCP不同之处在于,首次复制时,Rsync会复制整个目录,在后面的复制中,不会复制相同的内容,只对差异文件做更新,scp是把所有文件都复制过去。Rsync广泛用于备份和镜像。
下面介绍它们的简单使用方法。
SCP¶
一般情况下Linux服务器都有scp命令,如果没有,可通过如下方式安装:
yum -y install openssh-clients # centos
apt-get install openssh-client # Ubuntu
复制文件/目录到远程主机¶
scp source_file_name user@destination_host:destination_folder # 复制文件
scp -r source_directory user@destination_host:destination_folder # 复制目录
案例1:复制文件到远程主机
[root@Client ~]# scp text.txt root@192.168.20.40:/root
The authenticity of host '192.168.20.40 (192.168.20.40)' can't be established.
ECDSA key fingerprint is SHA256:tS6tueeKp9vBLDvxgsxIgCCaGMQWs9+5E167qz2ZB9c.
ECDSA key fingerprint is MD5:82:04:10:14:57:52:0a:05:d9:9b:ae:6e:3f:3f:68:98.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.20.40' (ECDSA) to the list of known hosts.
root@192.168.20.40's password:
test.txt 100% 12 6.0KB/s 00:00
[root@Client ~]#
从远程主机复制文件/目录¶
scp user@source_host:source_file_name local_destination_folder # 复制文件
scp -r user@source_host:source_file_name local_destination_folder # 复制目录
案例2:从远程主机复制文件
[root@Client ~]# scp root@192.168.20.40:/root/test40.txt /root
root@192.168.20.40's password:
test40.txt 100% 12 4.2KB/s 00:00
[root@Client ~]# ll | grep test40.txt
-rw-r--r-- 1 root root 12 7月 6 09:41 test40.txt
[root@Client ~]#
-r
参数用于递归的复制整个目录,SCP更多的参数使用方法可参考:https://manned.org/scp.1
本地文件/目录复制¶
如果不指定远程主机地址,可以实现和cp
目录一样的功能:
scp source_file destination_folder # 复制文件
scp -r source_directory destination_folder # 复制目录
案例3:本地文件复制
[root@Client ~]# mkdir test
[root@Client ~]# scp test40.txt /root/test
[root@Client ~]# ll /root/test/
总用量 4
-rw-r--r-- 1 root root 12 7月 6 09:49 test40.txt
[root@Client ~]#
Rsync¶
安装方法:
yum install rsync # centos
apt-get install rsync # Ubuntu
选项参数¶
Rsync可用的选项参数很多,下面介绍几个常用参数,更多参数使用方法可参考https://manned.org/rsync.1 ,或者使用rsync -h
、man rsync
命令查看文档说明。
选项 | 功能 |
---|---|
-t | 将源文件的修改时间(modify time)同步到目标机器 |
-I | --ignore-times,不跳过时间和大小都匹配的文件,也就是不检查是否有改动,直接复制 |
-r | 递归,用于目录复制 |
-a | 递归同步,还可以同步元信息(比如修改时间、权限等) |
-v | 打印复制过程 |
-l | 拷贝符号连接 |
--delete | 删除目标目录中多余的文件,也就是保持两个目录相同,使得目标目录成为源目录的镜像副本 |
复制文件/目录到远程主机¶
如果复制的目标目录不存在,会自动创建,语法格式和SCP一样:
rsync source_file_name/ user@destination_host:destination_folder # 复制文件
rsync -r source_file_name/ user@destination_host:destination_folder # 复制目录
案例1:复制文件、目录到远程主机
[root@Client ~]# rsync test.txt root@192.168.20.40:/root
root@192.168.20.40's password:
[root@Client ~]#
[root@Client ~]# rsync -rvl test/ root@192.168.20.40:/root/test222
root@192.168.20.40's password:
sending incremental file list
created directory /root/test222
./
test2.txt
test40.txt
sent 187 bytes received 93 bytes 62.22 bytes/sec
total size is 12 speedup is 0.04
从远程主机复制文件/目录¶
rsync user@source_host:source_file_name local_destination_folder # 复制文件
rsync -r user@source_host:source_file_name local_destination_folder # 复制目录
案例1:复制远程主机文件到本机
[root@Client ~]# rsync root@192.168.20.40:/root/test40.txt /root
root@192.168.20.30's password:
[root@Client ~]# ll test40.txt
-rw-r--r-- 1 root root 12 7月 8 11:11 test40.txt
[root@Client ~]#
其它用法¶
复制指定类型的文件¶
仅复制py文件:
rsync *.py user@destination_host:destination_folder
复制多个文件¶
[root@Client ~]# rsync test1.txt test2.txt test{5,6,7}.txt root@192.168.20.40:/root
root@192.168.20.40's password:
[root@Client ~]#
远程主机上查看是否复制成功
[root@Server ~]# ls | grep -E "test[0-9]{1}.txt"
test1.txt
test2.txt
test5.txt
test6.txt
test7.txt
[root@Server ~]#
从远程主机复制多个文件(先删除本地文件):
[root@Client ~]# rsync root@192.168.20.40:/root/test1.txt :test2.txt root@192.168.20.40:test{5,6,7}.txt /root
root@192.168.20.40's password:
[root@Client ~]# ls | grep -E "test[0-9]{1}.txt"
test1.txt
test2.txt
test5.txt
test6.txt
test7.txt
本地文件/目录复制¶
和scp命令一样,rsync也可以用于在本机进行文件复制。
rsync source_file destination_folder # 复制文件
rsync -r source_directory destination_folder # 复制目录
小结¶
rsync工具只对差异文件做更新的特性,在多个服务器之间同步文件非常有用,通常跳过写一个自动化脚本来实现批量同步,但是,你也许已经发现了,在执行同步命令时,需要输入目标主机的密码,在主机很多的情况下就不方便了。
一种解决方案是可以使用expect实现自动化交互,另一种方法是配置服务器之间ssh免密登录,因为scp和rsync默认使用ssh协议。ssh免密登录配置方法可参考配置多台服务器之间ssh免密登录
Linux三剑客grep、awk和sed介绍¶
grep,sed 和 awk是Linux/Unix 系统中常用的三个文本处理的命令行工具,称为文本处理三剑客。本文将简要介绍这三个命令的基本用法以及它们在Windows系统中的使用方法。
管道¶
在介绍这两个命令之前,有必要介绍一下Unix/Linux中管道(pipe)的概念。管道将一个命令/程序/进程的输出发送到另一个命令/程序/进程,以进行进一步处理。是一种进程间通信机制,使用管道符"|”将两个命令隔开,管道符左边命令的输出就会作为管道符右边命令的输入。
管道实现了数据在多个命令之间传递,不需要创建临时文件来传递,它是单向的,数据通过管道从左向右流动。
实例1:
cat test.txt | grep test1
$ cat test.txt | grep test1
test1
test111
test3 test1
test111
$ cat test.txt | grep test1 | grep test3
test3 test1
$
实例2:
$ cat test.txt | head -3
test1
test2
test3
$ cat test.txt | tail -5
test
test
test
rrrr
$
grep¶
定义¶
grep(Global Regular Expression Print) 命令用于搜索文件的特定模式,它不能增加、修改、删除文本内容,通常用于搜索过滤文本,显示被模式匹配到的行。使用正则表达式进行文本匹配(正则表达式参考文章《Python正则表达式》),它的使用权限是所有用户。
命令形式:
grep [OPTIONS] PATTERN [FILE...]
扩展正则表达式(egrep)添加
-E
参数:grep -E [OPTIONS] PATTERN [FILE...]
-P
参数可以让grep使用perl的正则表达式语法
选项参数¶
-v 或 --invert-match : 显示不被 pattern匹配到的行
-n 或 --line-number : 显示匹配的行号
-o 或 --only-matching :仅显示匹配到的字符串
-c 或 --count : 统计匹配的行数
-i 或 --ignore-case :忽略字符大小写
-m或--max-count:
-m 1
: 匹配到1行后停止匹配-A<显示行数> 或 --after-context=<显示行数> : 除了显示符合范本样式的那一列之外,并显示该行之后的内容。
-B<显示行数> 或 --before-context=<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前的内容。
-C<显示行数> 或 --context=<显示行数> : 除了显示符合样式的那一行之外,并显示该行之前和之后的内容。
or操作:
grep 'pattern1\|pattern2'
grep -E 'pattern1|pattern2'
egrep 'pattern1|pattern2'
实例1:查找文件内容,显示行号¶
查找文件内容包含'test1'的行,显示行数
$ grep -n test1 test.txt
1:test1
7:test111
9:test3 test1
11:test111
$ grep -o test1 test.txt
test1
test1
test1
test1
$ grep -no test1 test.txt
1:test1
7:test1
9:test1
11:test1
实例2:查找文件内容,不包含test1的行¶
$ grep -nv test1 test.txt
2:test2
3:test3
4:test4
5:test5
6:test6
8:test2
10:test
实例3:grep 正则表达式¶
查找test1开头的行
$ grep -n ^test1 test.txt
1:test1
7:test111
11:test111
查找以1结尾的行
$ grep -n 1$ test.txt
1:test1
7:test111
9:test3 test1
11:test111
实例4:判断或者提取数字¶
提取文本中的数字
$ cat test.txt
test123
456test
66
$ grep -Eo '[0-9]{1,}' test.txt
123
456
66
$ grep -o '[[:digit:]]*' <<< cat test.txt
123
456
66
$ cat test.txt | grep -o '[[:digit:]]*'
123
456
66
打印全为数字的行:
$ grep -Eo '^[0-9]{1,}*$' test.txt
66
$ grep -o '^[[:digit:]]*$' <<< cat test.txt
66
$ cat test.txt | grep -o '^[[:digit:]]*$'
66
判断某个变量是否为数字:
$ num='123'
$ grep '^[[:digit:]]*$' <<< $num
123
查看进程¶
$ ps -aux | grep chrome
root 5425 0.4 1.8 869280 34200 pts/0 Sl Dec22 11:31 /opt/google/chrome/chrome --no-sandbox
root 5439 0.0 0.0 563592 1132 pts/0 S Dec22 0:00 /opt/google/chrome/chrome --type=zygote --no-zygote-sandbox --no-sandbox
root 5440 0.0 0.1 563592 2836 pts/0 S Dec22 0:06 /opt/google/chrome/chrome --type=zygote --no-sandbox
root 5441 0.0 0.0 26452 208 pts/0 S Dec22 0:00 /opt/google/chrome/nacl_helper --no-sandbox
root 5442 0.0 0.0 26452 144 pts/0 S Dec22 0:00 /opt/google/chrome/nacl_helper --no-sandbox
sed¶
定义¶
sed(Stream Editor)是一种流编辑器,一次处理一行内容,将行存储在模式空间(临时缓冲区),然后用sed命令处理模式空间中的内容,处理完成后将内容送入屏幕,然后清除模式空间,继续读入下一行,执行下一个循环,直到文件末尾。这个过程中不会改变文件内容(除了 -i
选项)。
命令形式:
sed [选项] [sed命令] [-f <script FILE>] [FILE]
查看帮助文档:
man sed
sed -h
选项¶
-h: 显示帮助信息
-n: 仅显示 script处理后的结果,常与sed命令p连用:
sed -n 'p' test.txt
打印test.txt文件内容-e:直接在指令列模式上进行 sed 的动作编辑,不修改原文件,输出到终端
-i:修改文件内容,而不输出到终端
-f filename : sed 动作写在filename 内,执行 filename 内的sed 动作
-r∶扩展正规表达式
常用命令¶
a:append,新增:
sed -e '4 a newline' test.txt
c:change,取代:
sed -e '2,5c No 2-5 number' test.txt
d:delete,删除:
sed -e '2,5d' test.txt
sed -e '/^$/d' test.txt
:删除test.txt文件空行
i:insert,插入:
sed -e '2i newline' test.txt
p:print,打印:
sed -n 'p' test.txt
s:substitute,替换:
sed -e 's/old/new/g' test.txt
sed -e 's/$/%/' test.txt
:在每行末尾添加%sed -e 's/ *//g' test.txt
: 删除test.txt文件空格sed -e "4s;old;new;g" test.txt
或者sed -e '4s/old/new/g' test.txt
:替换第4行
N:将下一行添加到pattern space中,将当前读入行和用N命令添加的下一行看成“一行”
注意:
在替换操作中,替换时用的分割符 '/' 可以使用其它符号代替,特别是替换的内容中有 '/' 时,可以使用@、#、%等符号代替。
grep和sed命令的正则表达式中不支持
\d
,可使用如下方式匹配数字:sed -re 's/[0-9]+//g' test.txt
egrep '[0-9]+' test.txt
或grep -E '[0-9]+' test.txt
实例1:打印并输出数据¶
打印并输出第5行数据
$ sed -n '5p' test.txt
test5
$ cat -n test.txt | sed -n '5p'
5 test5
$
打印并输出第3-5行数据
$ sed -n '3,5p' test.txt
test3
test4
test5
取反,不选择第3到5行数据
$ sed -n '3,5!p' test.txt
test1
test2
隔行输出
$ sed -n '1~2p' test.txt
test1
test3
test5
$ sed -n '1~3p' test.txt
test1
test4
$
实例2:将匹配的行数据输出到指定文件¶
$ 累加
sed -n '1~2p' test.txt >> a.log
$ 覆盖
sed -n '1~3p' test.txt > a.log
$ sed -n '1~2p' test.txt>> a.log
$ cat a.log
test1
test3
test5
$ sed -n '1~3p' test.txt > a.log
$ cat a.log
test1
test4
$
实例3:新增、插入字符串¶
在第2行后加上 newLine
$ sed '2 a newline' test.txt
test1
test2
newline
test3
test4
test5
$
在第2行前加上 newline
$ sed '2 i newline' test.txt
test1
newline
test2
test3
test4
test5
实例4:删除匹配到的行或者匹配行后的n行¶
介绍两种方法来删除某一行的内容,一种是使用替代(substitute)的方法: 删除匹配到test3的那一行
$ sed -e 's/test3.*//g' test.txt
test1
test2
test4
test5
删除匹配行及后一行
$ sed -e 'N;s/test3.*//g' test.txt
test1
test2
test5
这种方法会留一个空行,可以进一步使用命令sed -e '/^$/d' test.txt
命令删除空行。
第二种方法是使用删除(delete)命令:
$ sed -e '/test3.*/d' test.txt
test1
test2
test4
test5
也可以删除匹配到的行及匹配行后的n行
$ sed -e '/test2.*/,+2d' test.txt
test1
test5
实例5:全局替换¶
将所有的test2替换为test222
$ sed -e 's/test2/test222/g' test.txt
test1
test222
test3
test4
test5
$ sed -e 's/test2/test222/' test.txt
test1
test222
test3
test4
test5
替换某一行:替换test1开头的所在行 test2.txt内容:
$ cat test2.txt
hello world !
test1 test2 test2
test1
test2
test3
# 方法1:c参数,替换某一行
$ sed "2c hello" test2.txt
hello world !
hello
test1
test2
test3
$ sed "3c hello" test2.txt
hello world !
test1 test2 test2
hello
test2
test3
# 方法2:s参数替换
$ sed 's/^test1.*$/hello/' test2.txt
hello world !
hello
hello
test2
test3
实例6:修改文件¶
前面的新增、替换操作都没有改变文件内容,如果要使文件修改生效,需要使用 -i
选项。
$ sed -i 's/test2/test222/' test.txt
$ cat test.txt
test1
test222
test3
test4
test5
$
实例7:横向连接¶
将匹配到的对象横向连接
比如我们需要杀掉某个服务有多个进程:
[root@Server ~]# ps -ef | grep named | grep -v grep
root 7136 1 0 1月22 ? 00:00:54 /var/bin/named -c /var/named/named.conf
root 7690 1 0 1月21 ? 00:01:02 /var/bin/named -c /var/named/named.conf
使用命令 kill -9 7136 7690
来杀掉这两个进程,使用如下命令实现连接这两个进程的ID:
kill -9 $(ps -ef | grep named | grep -v grep | awk '{print $2}') | sed ':1;N;s/\n/ /g;t1'
关键命令为 sed ':1;N;s/\n/ /g;t1'
,将换行替换为空格。
awk¶
定义¶
awk是一种文本模式扫描和处理的编程语言,由 Aho, Weinberger 和 Kernighan开发。awk功能强大,可用于数据提取和统计,常用在shell脚本中。awk逐行读入文件,以空格为默认分隔符将每行切片,切开的部分再进行后续处理。
命令形式:
awk [options] 'pattern action' [FILE(s)]
pattern:正则表达式
action:对匹配到的内容执行的命令(默认为输出每行内容)
常用参数¶
$0: 整条记录(当前行)
$1 - $n: 表示当前行的第n个域
FILENAME: awk浏览的文件名
BEGIN: 处理文本之前要执行的操作
END: 处理文本之后要执行的操作
FS: 设置输入域分隔符,等价于命令行
-F
选项,默认为空格“ ”awk -F: '{print $1}' test.txt
或者
awk 'BEGIN {FS = ":"} {print $1}' test.txt
NF: 浏览记录的域的个数/列数
NR: 已读的记录数/行数
FNR: 当前输入文件的记录数
OFS: 输出域分隔符,默认为空格“ ”
ORS: 输出记录分隔符,默认为“\n”
RS: 控制记录分隔符
exit:匹配到第一行内容后退出:
awk -F: '{print $2;exit}' test.txt
,grep使用-m
参数
实例1:查找、打印¶
搜索/etc/passwd有root关键字的所有行
$ awk -F : '/root/ {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
$
$ awk -F : '/root/ {print $7}' /etc/passwd
/bin/bash
/sbin/nologin
打印etc/passwd/的第二行信息
$ awk -F : 'NR==2 {print $0}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
$
实例2:BEGIN、END制表¶
使用 begin加入标题
$ awk -F : 'BEGIN {print "No", "User", "Auth"} {print NR "|" $1 "|" $2} END {print FILENAME}' /etc/passwd
No User Auth
1|root|x
2|bin|x
3|daemon|x
4|adm|x
5|lp|x
6|sync|x
7|shutdown|x
8|halt|x
9|mail|x
.................
28|nscd|x
29|exim|x
/etc/passwd
实例3:自定义分割符¶
$ echo "123|456|789"
123|456|789
$ echo "123|456|789" | awk 'BEGIN{RS="|"}{print $0}'
123
456
789
综合实例¶
找出log中的404 500的报错有多少条¶
$ grep -E ' 404 | 500 ' nginx.log | wc -l
267
$ grep -P ' 404 | 500 ' nginx.log | wc -l
267
$ grep -Pc ' 404 | 500 ' nginx.log
267
$ awk '$9~/404|500/' nginx.log | wc -l # {print}省略
267
$ awk '$9~/404|500/{print}' nginx.log | wc -l
267
$9表示查找第9列
波浪号~表示用来匹配后面的正则表达式,告诉awk后面开始是正则语法。
wc -l
:和-c
参数一样,统计匹配到的行数
访问量最高的ip¶
使用awk命令查找¶
$ awk '{print$1}' nginx.log | sort | uniq -c | sort -nr | head -3
282 216.244.66.241
130 136.243.151.90
110 127.0.0.1
$ awk '{print$1}' nginx.log | sort | uniq -c | sort -nr | head -3 | awk '{print $2}'
216.244.66.241
136.243.151.90
127.0.0.1
sort命令用于排序:
-r
:sort默认为升序,-r
参数表示降序-n
:以数值来排序,如果不使用这个参数就会出现10比2小的情况,因为把10当做字符来进行比较了。
uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用
-c
:在每列旁边显示该行重复出现的次数
head命令用于查看文件的开头部分的内容
使用grep查找¶
$ grep '^[0-9]*.[0-9]*.[0-9]*.[0-9]*' nginx.log #其中的点“.”为正则语法,表示匹配任意字符
123.127.112.18 - - [05/Dec/2018:00:09:18 +0000] "GET /cable HTTP/1.1" 101 1017 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36" 70.577 70.577 .
139.180.132.174 - - [05/Dec/2018:00:09:20 +0000] "GET /bbs.zip HTTP/1.1" 404 1264 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" 0.011 0.011 .
139.180.132.174 - - [05/Dec/2018:00:09:12 +0000] "GET /__zep__/js.zip HTTP/1.1" 500 2183 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36" 0.018 0.018 .
$ grep -o '^[0-9]*.[0-9]*.[0-9]*.[0-9]*' nginx.log
216.244.66.241
223.71.41.98
113.87.161.17
216.244.66.241
216.244.66.241
144.76.81.72
............
$ grep -o '^[0-9]*.[0-9]*.[0-9]*.[0-9]*' nginx.log | wc -l
2000
$ grep -o '^[0-9]*.[0-9]*.[0-9]*.[0-9]*' nginx.log | sort | uniq -c | sort -nr |head -3
282 216.244.66.241
130 136.243.151.90
110 127.0.0.1
......................
$
将 topics 后面的数字替换成numer¶
$ grep 'topics' nginx.log | sed 's#topics/[0-9]*#topics/number#g'
将ip地址横向打印¶
[root@centos7 tmp]# awk '{print $1}' nginx.log | sed ':1;N;s/\n/|/g;t1'
216.244.66.241|216.244.66.241|216.244.66.241|216.244.66.241|216.244.66.241|216.244.66.241|216.244.66.241|223.71.41.98|113.87.161.17|216.244.66.241|216.244.66.241|144.76.81.72
# :1
:标记 t1;
:把不同的命令分开
在Windows中使用grep、awk和sed¶
在Windows系统中也可以使用这3个命令,然而,windows cmd不支持这3个命令,因此需要下载对应的Win32版本文件,下面提供几种下载方法:
开源软件平台SourceForge:https://sourceforge.net/projects/gnuwin32/files/
安装Git Bash:安装方法可参考Git简易教程-安装及简单使用,Git Bash的安装目录
~\Git\usr\bin\
下有很多GNU工具。我把这三个工具放到了Github上:hiyongz/ShellNotes,可以在上面下载,注意对应的dll文件也需要下载。
安装使用:
在SourceForge上下载对应的setup文件安装,并添加到环境变量
或者直接下载对应的二进制文件,解压并添加到环境变量
测试文件test.log的内容:
log
log2
test
666 log
使用awk和grep命令查询log出现的行:
$ awk -F ' ' "/^log/ {print $0}" test.log
log
log2
$ grep -n "^log" test.log
1:log
2:log2
注意:正则表达式要用双引号。
使用bat脚本进行文本处理:
@echo off
set grep="D:/ProgramWorkspace/ShellNotes/grep/grep.exe"
set wc="D:/ProgramWorkspace/ShellNotes/wc/wc.exe"
set awk="D:/ProgramWorkspace/ShellNotes/awk/awk.exe"
set sed="D:/ProgramWorkspace/ShellNotes/sed/sed.exe"
%grep% -n "^log" test.log | %wc% -l > esult.log
%awk% -F ' ' "/^log/ {print $0}" test.log >> result.log
%sed% -n '1,3p' test.log >> result.log
pause
参考资料:
正则表达式30分钟入门教程:https://deerchao.cn/tutorials/regex/regex.htm
Linux常用命令:文件操作命令¶
Linux系统命令主要包括文件操作、网络命令和性能命令,本文介绍常用文件操作命令。
文件属性¶
文件类型:
普通文件:-
目录文件:d
块设备文件:b,硬盘
字符设备: c,串行端口的接口设备,例如键盘、鼠标
链接文件:l
套接字文件:s
管道文件:p
r 读权限read 4 w 写权限 write 2 x 操作权限 execute 1
常用命令:
chmod 777 test,修改test文件属性为可读,可写,可执行(4+2+1=7)
ls -l 查看文件属性(或者使用
ll
)ls -ld 查看当前目录的属性
ls -l 长模式,属性信息
ls -1 把文件一行一个的显示出来
ls -a 显示所有文件
ls -s 显示文件及文件大小
ls -l -a -s --> ls -las
ls -sh (h-human,显示文件大小单位)
基本终端操作命令¶
ls: 列出目录文件 pwd: 显示目前的目录 cd: 切换目录
cd - :切换到上次目录
cd .. :切换到上级目录
cd / :切换到根目录
cd ~ :切换到当前用户的home目录
cd start*end :目录名较长时可使用通配符"*",比如进入system目录,可以使用 cd s*m
man命令:可以通过 man + 命令
查看帮助文档:
j:下翻
k:上翻
空格键:翻页
q:退出
/-e:查找“-e”
n 下一个“-e”
N(shift+n) 上一个“-e”
[root@client ~]# ls
desktop.ini jenkins test.log test.txt t.txt
[root@client ~]# cd j*s
[root@client jenkins]# pwd
/root/jenkins
[root@client jenkins]# cd -
/root
[root@client ~]# pwd
/root
[root@client ~]# cd jenkins/
[root@client jenkins]# pwd
/root/jenkins
[root@client jenkins]# cd ..
[root@client ~]# pwd
/root
[root@client ~]#
/root
[root@client ~]# cd /
[root@client /]# pwd
/
[root@client /]# cd ~
[root@client ~]# pwd
/root
[root@client ~]#
文件、目录操作¶
touch:新建文件,或者使用vim命令创建文件:vim test.txt,保存 mkdir: 创建一个新的目录 rmdir: 删除一个空的目录 cp: 复制文件或目录 rm: 移除文件或目录 mv: 移动文件与目录,或修改文件与目录的名称
# 将目录A复制到目录B下
cp -r /etc/A /etc/B
# 将目录A的内容复制到目录B下
cp -r /etc/A/* /etc/B
cp -r /etc/A/. /etc/B
# 删除目录A及其下面的所有文件
rm -r /etc/A
rm -rf /etc/A #强制删除
# 移动目录A到目录B下
mv /etc/A /etc/B
# 移动目录A下的所有文件到目录B下
mv /etc/A/* /etc/B
文件内容显示¶
cat:显示文件内容,还可以将多个文件连接起来显示,适用于内容少的文件 more:以一页一页的显示内容,空格键下一页 less:支持向前翻,向后翻页 head:打印前面n行内容:head -2 test.txt tail:打印后面n行内容:tail -2 test.txt
向文件添加内容¶
将内容"TEST"添加到test.txt文件中
方法一:vi编辑法
打开终端,输入vi test.txt 回车,按a或i进入编辑模式 输入 TEST,然后按esc键退出编辑模式,输入
:wq
保存并退出。
方法二:echo命令法
# 追加
echo ‘TEST’ >> ./test.txt
# 覆盖
echo ‘TEST’ > ./test.txt
方法三:cat命令法
cat >> ./test.txt <<TEST
结尾的TEST要顶格。
方法四:cat编辑法
# 追加
cat >> ./test.txt
# 覆盖
cat > ./test.txt
回车后开始编辑输入内容:TEST,然后回车
按
ctrl+d
或者ctrl+c
组合键结束编辑。
清空文件内容¶
下面介绍几种清空文件内容的方式
> test.txt
: > test.txt
cat /dev/null > test.txt
echo -n "" > test.txt
也可以使用 dd
和 truncate
命令来清空内容:
dd of=test.txt count=0
dd if=/dev/null of=test.txt
truncate -s 0 test.txt
这两个命令可以用来生成指定大小的文件,具体使用方法可参考文章Linux和Windows创建指定大小文件方法。
还可以使用 sed
命令:
sed -i d test.txt
sed -i '/^$/d' test.txt # 删除空行
sed -i 's/ *//g' test.txt # 删除空格
find命令¶
用于查找文件,基本用法:find path -name‘xxx'
find / -name jenkins
:查找所有目录下的jenkins文件
[root@client ~]# find / -name jenkins
/root/jenkins
/var/lib/docker/overlay2/6cc1d9dcc70fed5dcc455ca4147a13f650724c2e8004a9c101b4e2130276241c/diff/usr/share/jenkins
/var/lib/docker/overlay2/9b98446d8cf91c4c8da9d8eab5cd6366ef2cec266615c1fe6ad4f4faa84f25a1/diff/usr/share/jenkins
/var/lib/docker/overlay2/f1f4123687b215d1eff46d989df6c9568be89c231a83ab6105dc22c136ccf24b/diff/usr/share/jenkins
[root@iZ8vb54310gt89j8qct198Z ~]#
限制搜索深度
-maxdepth
-mindefth
限制文件类型:文件类型有:普通文件f,目录d,符号链接 l,字符设备c,块设备b,套接字s,FIFO-p
-type f:搜索普通文件和目录 还有其他限制条件,可以通过命令
man find
查看
文件解压¶
tar -xvzf xxx.tar.gz
-x, --extract
:解压文件-v, --verbose
:显示解压日志-z, --gzip
:通过gzip支持压缩或解压缩-f, --file
:指定解压文件
du 命令:显示目录或文件的大小¶
du(disk usage)命令主要用于显示目录或文件的大小:
$ du
du
18760 ./node_exporter-1.1.2.linux-amd64
27792 .
下面介绍几个选项参数:
-a, --all
:显示目录下所有文件大小-b, --bytes
:以byte为单位-h, --human-readable
:文件大小以K,M,G为单位显示-H, --si
:文件大小以KB,MB,GB为单位(幂底数为1000)-k, --kilobytes
:以1024 bytes为单位-m, --megabytes
:以MB为单位-s, --summarize
:显示文件总大小
实例:
$du -hs
28M .
$ du -ah
8.9M ./node_exporter-1.1.2.linux-amd64.tar.gz
12K ./node_exporter-1.1.2.linux-amd64/LICENSE
4.0K ./node_exporter-1.1.2.linux-amd64/NOTICE
19M ./node_exporter-1.1.2.linux-amd64/node_exporter
12K ./node_exporter-1.1.2.linux-amd64/nohup.out
19M ./node_exporter-1.1.2.linux-amd64
28M .
Linux常用命令:网络命令¶
本文简要介绍Linux网络配置命令,包括 ip 地址、路由查看、配置等
ping¶
ping: 测试网络连接情况
-c
:回应的次数-i
:每次ping的时间间隔-I
:网卡名-t
:ttl 数值-s
:数据包的大小
# ping ipv6地址
ping -6 -I eth1 2001:db8::10
# ping ipv4地址
ping -I eth1 192.168.0.1
网络信息查询¶
netstat¶
netstat: 打印 Linux网络系统的状态信息
-t 列出所有tcp
-u 列出所有udp
-l 只显示监听端口
-n 以数字形式显示地址和端口号
-p 显示进程的pid和名字
netstat -t
netstat -ntlp
# 列出所有网络端口信息
netstat -a
# 列出所有tcp连接信息
netstat -at
# 列出所有udp连接信息
netstat -au
# 所有端口数据包统计信息
netstat -s
# 显示核心路由信息
netstat -r
# 或
route -n
route print # windows
# 显示网络接口列表
netstat -i
# 显示网络接口详细信息
netstat -ie
# 或
ifconfig
列出所有网卡信息¶
# 查看所有网卡信息
ifconfig -a
ip link
netstat -i
# 查看某一个网卡
ifconfig 网卡名字
路由配置¶
ipv4¶
route add/del -net 192.168.0.0/24 netmask 255.255.255.0 gw 192.168.0.1 dev eth1
route add/del -host 192.168.1.1 dev eth1
route add -net 23.23.23.0 netmask 255.255.255.0 reject # 屏蔽一条路由
route add/del default gw 192.168.0.1 #增加/删除默认网关
添加永久静态路由(centos7):
$ vim /etc/sysconfig/network-scripts/route-eth1
ADDRESS0=192.168.0.0/2
NETMASK0=255.255.255.0
GATEWAY0=192.168.0.1
0表示第一条静态路由。配置完成后重启网络:systemctl restart network
ipv6¶
ip -6 route add default via fe80::290:4cff:fe88:8888 dev eth1 # 配置默认网关
ip -6 route add 2001:db8:3333::/64 via fe80::ca3a:35ff:fe09:efa1 dev eth1 # 添加目的网络为2001:db8:3333::/64,下一跳网关为fe80::ca3a:35ff:fe09:efa1的静态路由
查看路由表¶
route -n
route -4 -n
route -6 -n
ip -6 route show default # 查看默认路由网关
禁用启用网卡¶
ifconfig eth1 up
ifconfig eth1 down
释放、更新地址¶
# ipv4
dhclient -r eth1
dhclient -v eth1
# ipv6
dhclient -6 -r eth1 //释放ipv6地址
dhclient -6 //重新获取ipv6地址
重启网络:
systemctl restart network
添加、删除IP地址¶
# 添加IPv4地址
ifconfig eth1 192.168.1.200 netmask 255.255.255.0
ip addr add 192.168.1.200/24 dev eth1
# 添加IPv6地址
ip -6 addr add 2001:db8:1111::20 dev eth1
# 删除IPv6地址
ip -6 addr del 2001:db8:1111::20 dev eth1
ip addr del 192.168.1.200/24 dev eth1
# 激活/禁用设备
ifconfig eth0 up
ifconfig eth0 down
修改MAC地址¶
ifconfig eth1 hw ether MAC地址 up
设置MTU值¶
ifconfig eth1 mtu 1500 up
配置arp信息¶
# arp缓存
arp -a
# 删除arp
arp -d IP
# 添加arp
arp -s IP MAC
设置无线网络¶
# 安装
sudo apt install wireless-tools
# 开启无线网卡wlan0
ifconfig wlan0 up
# 设置密码
iwconfig wlan0 key 12345678
# 设置SSID
iwconfig wlan0 essid "test"
# 加入无线网
iwconfig wlan0 ap auto
# 查看网卡信息
iwconfig wlan0
# 为无线网卡指定IP地址
ifconfig wlan0 192.168.1.30 netmask 255.255.255.0
# 用dhclient或dhcpcd获取ip
dhclient wlan0
# 或
dhcpcd wlan0
iwconfig 的弊端是只支持WEP认证方式,要想支持WPA,需要wpa_supplicant工具,wpa_supplicant支持4种认证方式:OPEN,WEP,WPA,WPA2
Linux常用命令:性能命令¶
本文介绍Linux常用性能统计分析命令,监控进程或者系统性能。主要包括CPU(top、mpstat)、内存(vmstat、free)、I/O(iostat)、网络性能(sar)、系统日志信息(demsg)、查看进程状态(pidstat)。下面简要介绍这些命令的使用方法。
mpstat、iostat、pidstat和sr命令需要安装sysstat软件包,sysstat包含了系统性能监测工具,安装方法如下:
yum install sysstat # CentOS
sudo apt-get install sysstat # Ubuntu
负载¶
CPU负载(cpu load)指的是某个时间点进程对系统产生的压力。表示特定时间间隔内运行队列中的平均进程数,如果一个进程满足以下条件则其就会位于运行队列中:
它没有在等待IO操作的结果
它没有主动进入等待状态(也就是没有调用'wait')
没有被停止(例如:等待终止)
单CPU满负荷运行时cpu_load为1,当多个CPU或多核时,相当于大桥有多个车道,满负荷运行时cpu_load值为CPU数或多核数;CPU负载的计算(以单CPU为例),假设一分钟内执行10个任务代表满负荷,当一分钟给出30个任务时,CPU只能处理10个,剩余20个不能处理,cpu_load=3;
单核CPU
cpu load = 1,满负载运行
cpu load = 0.5,半负载运行
cpu load = 1.7,超负载运行
一般来说,每个CPU内核当前活动进程数不大于3,则系统运行表现良好!
如果多核cpu,需要累加
4核cpu<12
uptime¶
uptime命令显示的平均负载包括了正在或准备运行在CPU上的进程和阻塞在不可中断睡眠状态(uninterruptible) I/O(通常是磁盘I/O)上的进程。
[root@server ~]# uptime
16:54:53 up 29 days, 2:02, 1 user, load average: 0.03, 0.03, 0.00
[root@server ~]# cat /proc/loadavg
0.03 0.03 0.00 3/166 16903
显示最近1分钟、5分钟、15分钟系统负载的移动平均值,它们共同展现了负载随时间变动的情况。
3:正在运行的进程数,166:总的进程数,16903:最近运行进程的ID。
ps和top命令¶
ps命令¶
ps命令是Process Status的缩写,用于查看系统进程信息
-e,-A:显示所有进程,包括其他用户的进程
-f:显示完整格式
-l:显示长列表
-a:所有进程,加上-x参数会显示没有控制终端的进程
-u:username,显示指定用户的进程,例如ps -u root
-x:显示当前用户在所有终端下的进程
-aux:显示所有进程,包括所有用户,分组情况
ps常用用法,通常与grep组合使用
显示dhcpd进程
ps ax | grep dhcpd | grep -v grep
ps -ef 显示所有进程
ps -aux 显示所有进程
ps -aux
按照CPU或者内存用量来筛选进程:
ps -aux --sort -pcpu
# 或
ps -aux --sort -pmem
终止进程¶
# 强制中断正在执行的命令,如,命令长时间没有响应的情况下
Ctrl+C组合键
# kill命令
kill -9 进程ID
# killall命令:终止指定名称的所有进程
killall -9 dhclient
top命令¶
ps命令列出的是当前进程的快照,top可用于持续监视系统性能, 动态显示进程信息。
-n 获取多次cpu的执行情况,top -n 4:只更新4次
-d 间隔时间,top -d 4:每隔4秒更新一次
-p 获取指定端口进程的数据,top -p 22
每隔1秒检测指定进程的cpu,检测20次
top -d 1 -n 20
示例¶
打印指定pid进程的cpu信息,间隔时间为1s,打印20次
查看进程的pid:
ps -ef | grep systemd
2. 循环打印
# 打印一次
top -p 1 -n 1 | grep systemd | awk '{print $10}'
# 循环打印20次
for i in {1..20};do top -p 1 -n 1 | grep systemd | awk '{print $10}';sleep 1s;done
for((i=0;i<20;i++));do top -p 1 -n 1 | grep systemd | awk '{print $10}';sleep 1s;done
dmesg | tail¶
默认显示最新的10个系统信息,可以查看导致性能问题的错误信息。
1. 显示最新的20个系统信息¶
[root@centos7 ~]# dmesg | tail -20
[ 15.356358] RPC: Registered named UNIX socket transport module.
[ 15.356360] RPC: Registered udp transport module.
[ 15.356361] RPC: Registered tcp transport module.
[ 15.356362] RPC: Registered tcp NFSv4.1 backchannel transport module.
[ 15.551529] type=1305 audit(1584428235.986:4): audit_pid=1054 old=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:auditd_t:s0 res=1
[ 19.223990] NET: Registered protocol family 40
[ 23.857606] ip6_tables: (C) 2000-2006 Netfilter Core Team
[ 24.130255] Ebtables v2.0 registered
[ 24.366128] Netfilter messages via NETLINK v0.30.
[ 24.418582] ip_set: protocol 7
[ 24.517273] IPv6: ADDRCONF(NETDEV_UP): ens33: link is not ready
[ 24.521156] e1000: ens33 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[ 24.524658] IPv6: ADDRCONF(NETDEV_UP): ens33: link is not ready
[ 24.524669] IPv6: ADDRCONF(NETDEV_CHANGE): ens33: link becomes ready
[ 24.528687] IPv6: ADDRCONF(NETDEV_UP): ens34: link is not ready
[ 24.532350] e1000: ens34 NIC Link is Up 1000 Mbps Full Duplex, Flow Control: None
[ 24.535760] IPv6: ADDRCONF(NETDEV_UP): ens34: link is not ready
[ 24.574912] IPv6: ADDRCONF(NETDEV_UP): ens34: link is not ready
[ 25.391535] nf_conntrack version 0.5.0 (16384 buckets, 65536 max)
[ 25.525351] IPv6: ADDRCONF(NETDEV_CHANGE): ens34: link becomes ready
[root@centos7 ~]#
2. 显示开始的20个系统信息¶
[root@centos7 ~]# dmesg | head -20
[ 0.000000] Initializing cgroup subsys cpuset
[ 0.000000] Initializing cgroup subsys cpu
[ 0.000000] Initializing cgroup subsys cpuacct
[ 0.000000] Linux version 3.10.0-1062.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC) ) #1 SMP Wed Aug 7 18:08:02 UTC 2019
[ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-3.10.0-1062.el7.x86_64 root=UUID=d7dc0c9e-a27d-4239-aba4-7c2e51d9fc93 ro crashkernel=auto spectre_v2=retpoline rhgb quiet LANG=en_US.UTF-8
[ 0.000000] Disabled fast string operations
[ 0.000000] e820: BIOS-provided physical RAM map:
[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009ebff] usable
[ 0.000000] BIOS-e820: [mem 0x000000000009ec00-0x000000000009ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000000dc000-0x00000000000fffff] reserved
[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x000000007fedffff] usable
[ 0.000000] BIOS-e820: [mem 0x000000007fee0000-0x000000007fefefff] ACPI data
[ 0.000000] BIOS-e820: [mem 0x000000007feff000-0x000000007fefffff] ACPI NVS
[ 0.000000] BIOS-e820: [mem 0x000000007ff00000-0x000000007fffffff] usable
[ 0.000000] BIOS-e820: [mem 0x00000000f0000000-0x00000000f7ffffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fec00000-0x00000000fec0ffff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fee00000-0x00000000fee00fff] reserved
[ 0.000000] BIOS-e820: [mem 0x00000000fffe0000-0x00000000ffffffff] reserved
[ 0.000000] NX (Execute Disable) protection: active
[ 0.000000] SMBIOS 2.7 present.
[root@centos7 ~]#
vmstat 1¶
全称 virtual memory stat,逐行输出虚拟内存状态统计信息
[root@centos7 ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1424832 2084 195100 0 0 47 4 45 55 0 0 99 1 0
vmstat 1
:每隔一秒打印一次
[root@centos7 ~]#
[root@centos7 ~]# vmstat 1 #1s打印一个
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 0 1424472 2084 195120 0 0 28 2 30 37 0 0 99 1 0
0 0 0 1424456 2084 195120 0 0 0 0 38 53 0 0 100 0 0
0 0 0 1424456 2084
参数解释:
r: 运行队列中进程数量
b: 等待IO的进程数量
swpd:使用的虚拟内存
free:可用内存
buff:用作缓冲的内存大小
cache:用作缓存的内存大小
us:用户进程执行时间(user time)
sy:系统进程执行时间(system time
id:空闲时间(包括IO等待时间),中央处理器的空闲时间
wa:等待IO时间
free -m¶
查看linux内存使用情况
[root@centos7 ~]# free -m
total used free shared buff/cache available
Mem: 1819 199 1471 9 148 1470
Swap: 4095 0 4095
Mem:物理内存
totel:总的物理内存 单位为:M
used:用掉的内存
free:空闲的物理内存
shared:共享内存
buff/cache:缓存内存
mpstat -P ALL 1¶
mpstat是Multiprocessor Statistics的缩写,实时监控CPU性能。
mpstat -P ALL 1 2
:间隔1s打印报告,共打印2个
-P ALL:监控所有CPU
1:间隔时间1s
2:打印次数2次
[root@centos7 ~]# mpstat
Linux 3.10.0-1062.el7.x86_64 (centos7) 03/18/2020 _x86_64_ (4 CPU)
04:41:47 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
04:41:47 AM all 0.66 0.00 1.39 2.65 0.00 0.01 0.00 0.00 0.00 95.28
[root@centos7 ~]#
[root@centos7 ~]# mpstat -P ALL 1
Linux 3.10.0-1062.el7.x86_64 (centos7) 03/18/2020 _x86_64_ (4 CPU)
04:44:11 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
04:44:11 AM all 0.39 0.00 0.82 1.54 0.00 0.01 0.00 0.00 0.00 97.24
04:44:11
[root@centos7 ~]#
%usr:间隔时间段内,用户态的CPU时间(%),不包含 nice值为负进程
%nice:nice值为负进程的CPU时间(%)
%sys:核心时间(%)
%iowait:硬盘IO等待时间(%)
%irq:硬中断时间(%)
%soft:软中断时间(%)
%steal:虚拟机管理器在服务另一个虚拟处理器时虚拟CPU处在非自愿等待下花费时间的百分比
%guest:运行虚拟处理器时CPU花费时间的百分比
%idle:CPU的空闲时间(%)
pidstat 1¶
pidstat用于监控全部或指定进程的资源占用情况,和top命令类似,但不覆盖输出,有利于观察数据随时间的变动情况,top会覆盖之前的输出
pidstat -p 1 1
:-p 指定进程号,间隔1s打印pid为1的进程
[root@centos7 ~]# pidstat
Linux 3.10.0-1062.el7.x86_64 (centos7) 03/18/2020 _x86_64_ (4 CPU)
04:52:29 AM UID PID %usr %system %guest %CPU CPU Command
04:52:29 AM 0 1 0.05 0.19 0.00 0.24 0 systemd
04:52:29 AM 0 2 0.00 0.00 0.00 0.00 3 kthreadd
04:52:29 AM 0 6 0.00 0.00 0.00 0.00 0 ksoftirqd/0
04:52:29
PID:进程ID
%usr:进程在用户空间占用cpu的百分比
%system:进程在内核空间占用cpu的百分比
%guest:进程在虚拟机占用cpu的百分比
%CPU:进程占用cpu的百分比,各个CPU上的使用量的总和
CPU:处理进程的cpu编号
Command:当前进程对应的命令
iostat 1¶
iostat用于显示CPU和块设备(磁盘I/O)相关的统计信息
[root@centos7 ~]# iostat 1
Linux 3.10.0-1062.el7.x86_64 (centos7) 03/18/2020 _x86_64_ (4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.15 0.00 0.34 0.60 0.00 98.92
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 9.46 158.59 15.05 142895 13561
scd0 0.02 1.14 0.00 1028 0
avg-cpu:总体cpu使用情况统计信息 linux各种设备文件在/dev目录下可以看到
tps:每秒进程向磁盘设备下发的IO读、写请求数量
kB_read/s:每秒从驱动器读入的数据量
kB_wrtn/s:每秒从驱动器写入的数据量
kB read:读入数据总量
kB wrtn:写入数据总量
sar命令¶
sar(System ActivityReporter):系统活动情况报告, 是Linux系统性能分析工具。可以用来分析磁盘I/O、CPU效率、内存使用等,下面介绍它的分析网络性能用法。
sar -n DEV 1¶
检查网络流量的工作负载,可用来检查网络流量是否已经达到限额。
[root@centos7 dev]# sar -n DEV 1
Linux 4.18.0-147.5.1.el8_1.x86_64 (iZ8vb54310gt89j8qct198Z) 12/19/2020 _x86_64_ (1 CPU)
08:08:37 PM IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s %ifutil
08:08:38 PM eth0 4.00 2.00 0.23 0.27 0.00 0.00 0.00 0.00
08:08:38 PM lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
08:08:38 PM docker0 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
sar -n TCP 1¶
显示TCP连接情况,可用来描述系统负载
[root@centos7 dev]# sar -n TCP,ETCP 1
Linux 4.18.0-147.5.1.el8_1.x86_64 (iZ8vb54310gt89j8qct198Z) 12/19/2020 _x86_64_ (1 CPU)
08:15:48 PM active/s passive/s iseg/s oseg/s
08:15:49 PM 0.00 0.00 1.00 1.00
08:15:48 PM atmptf/s estres/s retrans/s isegerr/s orsts/s
08:15:49 PM 0.00 0.00 0.00 0.00 0.00
active/s:主动连接数,本地每秒创建的TCP连接数
passive/s:被动连接数,远程每秒创建的TCP连接数
retrans/s:每秒TCP重传次数
Linux和Windows创建指定大小文件方法¶
在测试中有时需要创建不同大小的测试文件,用于测试上传下载性能以及以及其它文件传输功能,本文介绍几种Liunx和Windows系统下创建指定大小文件的方法。
Linux系统创建指定大小文件¶
下面介绍的dd 、fallocate和truncate命令包含于GNU coreutils软件包中,不需要单独安装。
dd命令¶
dd (device driver) 命令常用来复制备份文件,与cp命令具有以下区别:
dd是对块进行操作,操作磁盘的扇区字节,
cp操作文件或目录,对于不能以文件或目录格式呈现的数据cp无法复制。
dd是对磁盘连续的读取,也就是完全的数据搬移,cp复制的数据排列不是按顺序的。
也可以使用这个命令来创建特定大小的文件。
root@Server ~]# dd if=/dev/urandom of=testfile10MB_dd bs=10MB count=1
记录了1+0 的读入
记录了1+0 的写出
10000000字节(10 MB)已复制,0.124436 秒,80.4 MB/秒
root@Server ~]# ll testfile10MB_dd
-rw-r--r-- 1 root root 10000000 7月 7 11:56 testfile10MB_dd
[root@Server ~]# du testfile10MB_dd
9768 testfile10MB_dd
/dev/urandom
用于生成随机数据,也可以使用/dev/zero
来生成全0的文件:
[root@Server ~]# dd if=/dev/zero of=testfile10MB_dd0 bs=10MB count=1
记录了1+0 的读入
记录了1+0 的写出
10000000字节(10 MB)已复制,0.00799675 秒,1.3 GB/秒
[root@Server ~]# ll testfile10MB_dd0
-rw-r--r-- 1 root root 10000000 7月 7 13:57 testfile10MB_dd0
[root@Server ~]# od -c testfile10MB_dd0
0000000 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
*
46113200
[root@Server ~]#
/dev/urandom、/dev/random以及/dev/zero、/dev/null介绍:
/dev/urandom和/dev/random都可以产生随机的ASCII码字符流,其中/dev/random依赖系统中断,当系统中断不足时,/dev/random设备会“挂起”。/dev/urandom不依赖系统中断,所以在生成特定大小文件时一般使用/dev/urandom,不使用/dev/urandom。
/dev/zero “零”设备可以无限的提供空字符,产生二进制的零流
/dev/null “空”设备,像”黑洞“一样,所有写入它的内容都会永远丢失,也不会读取到任何内容。常用于禁止标准输出和标准错误的输出,比如抓包命令:
tcpdump -i eth1 -w /tmp/packet.pcap >/dev/null &
根据/dev/urandom的特性,也可以结合head命令来创建指定大小的文件:
head -c 10MB /dev/urandom > testfile10MB
# 或者
head -c 10MB /dev/zero > testfile10MB
bs
参数和truncate命令的size参数类似,默认单位为bytes,也支持以下单位:
c =1 bytes, w =2 bytes, b =512 bytes
K, M, G, T, P, E, Z, Y(幂底数为1024 bytes,如5M=5×1024×1024)
KB, MB, GB ...(幂底数为1000 bytes,如5MB=5×1000×1000)
fallocate命令¶
fallocate用于创建大文件(大于2G):
[root@Server ~]# fallocate -l 2G testfile2G_fal
[root@Server ~]# ll testfile2G_fal
-rw-r--r-- 1 root root 2147483648 7月 7 14:01 testfile2G_fal
-l
参数指定文件大小,默认单位为bytes,也可以指定单位:K, M, G, T, P, E, Z, Y以及KB, MB, GB等
truncate命令¶
truncate命令也可以用来创建指定大小的文件,下面创建一个10 MB大小的文件
[root@Server ~]# truncate -s 10M testfile10M
[root@Server ~]# ll testfile10M
-rw-r--r-- 1 root root 10485760 7月 7 10:45 testfile10M
[root@Server ~]#
[root@Server ~]# truncate -s 10MB testfile10Mb
[root@Server ~]# ll testfile10Mb
-rw-r--r-- 1 root root 10000000 7月 7 10:49 testfile10Mb
-s | --size
参数 用于指定要生成的文件大小,单位可以是:
K, M, G, T, P, E, Z, Y(幂底数为1024 bytes,如5M=5×1024×1024)
KB, MB, GB ...(幂底数为1000 bytes,如5MB=5×1000×1000)
dd 、fallocate和truncate的区别¶
truncate命令生成的是空洞文件,并不占用实际的磁盘空间,文件中间是用“\0”填充的,实际占用的空间为0。使用du命令查看truncate生成文件占用的磁盘空间:
[root@Server ~]# ll testfile10Mb
-rw-r--r-- 1 root root 10000000 7月 7 14:30 testfile10Mb
[root@Server ~]# du -sh testfile10Mb
0 testfile10Mb
[root@Server ~]# od -c testfile10Mb
0000000 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0 \0
*
46113200
[root@Server ~]#
fallocate命令为文件预分配物理空间,分配的空间在磁盘的扇区上是连续的,生成的不是空洞文件,不是空洞文件那样“假装”占有那么多空间:
[root@Server ~]# ll testfile2G_fal
-rw-r--r-- 1 root root 2147483648 7月 7 14:01 testfile2G_fal
[root@Server ~]# du -sh testfile2G_fal
2.0G testfile2G_fal
可以看到,和truncate不一样,用fallocate生成的文件在磁盘上确实占用了2.0G的空间。
dd命令生成的文件也不是空洞文件,使用它来生成大文件时速度较慢,而且使用dd以及提到的head命令生成文件时会进行大量IO操作,所以在Linux中生成文件时,建议使用fallocate命令。
Windows系统创建指定大小文件¶
fsutil工具¶
Windows中可以使用fsutil工具生成文件,命令语法格式如下:
fsutil file createNew test.txt 1024 # 文件大小单位为bytes
以管理员身份打开cmd,创建一个5M bytes的文件:5×1024×1024=5242880 bytes
C:\Users\DELL> fsutil file createNew test.txt 5242880
File C:\Users\DELL\test.txt is created
C:\Users\DELL> dir test.txt | findstr test.txt
2021/07/07 15:26 5,242,880 test.txt
Centos 虚拟机配置¶
克隆虚拟机后设置静态IP¶
克隆虚拟机后设置静态IP无效的解决方法
1. 获取虚拟机网卡的MAC地址¶
通过下面的其中一个命令获取要设置的网卡MAC地址
ip link show
ifconfig -a
ip address show
2. 修改70-persistent-ipoib.rules 文件¶
将eth0的MAC地址改为第一步获取到的地址
vim /etc/udev/rules.d/70-persistent-ipoib.rules
3. 修改网卡配置文件¶
将对于网卡配置文件的MAC地址也改为第一步获取到的地址
vim /etc/sysconfig/network-scripts/ifcfg-eth0
4. 重启¶
重启网络服务
systemctl restart network
systemctl restart network失败¶
systemctl restart network 重启网络失败
[root@haiyong rules.d]# systemctl restart network
Job for network.service failed because the control process exited with error code. See "systemctl status network.service" and "journalctl -xe" for details.
[root@haiyong rules.d]# journalctl -xe
--
-- The start-up result is done.
Jun 19 12:10:01 haiyong CROND[5949]: (root) CMD (/usr/lib64/sa/sa1 1 1)
Jun 19 12:10:10 haiyong polkitd[754]: Registered Authentication Agent for unix-process:
Jun 19 12:10:10 haiyong systemd[1]: Starting LSB: Bring up/down networking...
-- Subject: Unit network.service has begun start-up
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit network.service has begun starting up.
Jun 19 12:10:10 haiyong NetworkManager[939]: <warn> [1624075810.7721] ifcfg-rh: mi
Jun 19 12:10:10 haiyong network[5992]: Bringing up loopback interface: [ OK ]
Jun 19 12:10:10 haiyong NetworkManager[939]: <warn> [1624075810.8999] ifcfg-rh: mi
Jun 19 12:10:10 haiyong NetworkManager[939]: <info> [1624075810.9472] agent-manager: r
Jun 19 12:10:10 haiyong NetworkManager[939]: <info> [1624075810.9481] audit: op="conne
Jun 19 12:10:10 haiyong network[5992]: Bringing up interface ens33: Error: Connection
Jun 19 12:10:10 haiyong network[5992]: [FAILED]
Jun 19 12:10:11 haiyong NetworkManager[939]: <info> [1624075811.0139] agent-manager: r
Jun 19 12:10:11 haiyong NetworkManager[939]: <info> [1624075811.0152] audit: op="conne
Jun 19 12:10:11 haiyong network[5992]: Bringing up interface ens37: Error: Connection
Jun 19 12:10:11 haiyong network[5992]: [FAILED]
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong network[5992]: RTNETLINK answers: File exists
Jun 19 12:10:11 haiyong systemd[1]: network.service: control process exited, code=exite
Jun 19 12:10:11 haiyong systemd[1]: Failed to start LSB: Bring up/down networking.
-- Subject: Unit network.service has failed
-- Defined-By: systemd
-- Support: http://lists.freedesktop.org/mailman/listinfo/systemd-devel
--
-- Unit network.service has failed.
--
-- The result is failed.
Jun 19 12:10:11 haiyong systemd[1]: Unit network.service entered failed state.
Jun 19 12:10:11 haiyong systemd[1]: network.service failed.
Jun 19 12:10:11 haiyong polkitd[754]: Unregistered Authentication Agent for unix-proces
解决方法:
[root@haiyong rules.d]# systemctl stop NetworkManager
[root@haiyong rules.d]# systemctl disable NetworkManager
Removed symlink /etc/systemd/system/multi-user.target.wants/NetworkManager.service.
Removed symlink /etc/systemd/system/dbus-org.freedesktop.nm-dispatcher.service.
Removed symlink /etc/systemd/system/network-online.target.wants/NetworkManager-wait-online.service.
[root@haiyong rules.d]# systemctl restart network
关闭防火墙¶
查看防⽕火墙状态
systemctl status firewalld
systemctl status firewalld.service
停⽌止firewall
systemctl stop firewalld.service
禁止firewall开机启动
systemctl disable firewalld.service
关闭selinux¶
vi /etc/selinux/config
注释SELINUX=enforcing,添加SELINUX=disabled
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# SELINUX=enforcing
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
时钟同步¶
ntpdate是一个linux时间同步服务软件,一般默认情况下是未安装。
1. 配置时间服务器¶
使用root⽤户
[root@linux .ssh]# ntpdate
-bash: ntpdate: command not found
安装ntpdate:
yum -y install ntpdate
yum -y install ntp
[root@linux ~]# systemctl status ntpd.service
● ntpd.service - Network Time Service
Loaded: loaded (/usr/lib/systemd/system/ntpd.service; disabled; vendor preset: disabled)
Active: inactive (dead)
[root@linux ~]# rpm -qa | grep ntp
ntpdate-4.2.6p5-29.el7.centos.2.x86_64
ntp-4.2.6p5-29.el7.centos.2.x86_64
编辑/etc/ntp.conf
vim /etc/ntp.conf
restrict 127.0.0.1
restrict ::1
# Hosts on local network are less restricted.
restrict 192.168.183.0 mask 255.255.255.0 nomodify notrap
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
# server 0.centos.pool.ntp.org iburst
# server 1.centos.pool.ntp.org iburst
# server 2.centos.pool.ntp.org iburst
# server 3.centos.pool.ntp.org iburst
server 127.127.1.0 # local clock
fudge 127.127.1.0 stratum 10
保证BIOS与系统时间同步
vim /etc/sysconfig/ntpd ,添加:
# Command line options for ntpd
OPTIONS="-g"
SYNC_HWLOCK=yes
启动ntpd服务
systemctl start ntpd.service
设置ntpd的服务开机启动
chkconfig ntpd on
systemctl enable ntpd.service
设置时间同步:
# 通过⽹络连接外⽹进⾏时钟同步
ntpdate us.pool.ntp.org;
# 阿⾥云时钟同步服务器
ntpdate ntp4.aliyun.com
2. 其他机器配置¶
使用root⽤户
安装ntpdate:
yum -y install ntpdate
在其他机器配置10分钟与时间服务器同步⼀次 编写脚本
crontab -e
输入如下内容:
*/10 * * * * /usr/sbin/ntpdate 192.168.183.121
修改任意机器时间
date -s "2020-06-20 11:11:11"
查看crontab任务
crontab -l
查看crontab的执行日志
tail -n 30 -f /var/log/cron
安装jdk¶
查看系统⾃带的openjdk,如果有,卸载系统⾃带的openjdk
[root@linux ~]# rpm -qa | grep java
[root@linux ~]#
使用rz命令上传jdk-8u231-linux-x64.tar.gz文件,注意不要勾选Upload files as ASCII
解压jdk
tar -zxvf jdk-8u231-linux-x64.tar.gz -C ../servers/
配置环境变量
vi /etc/profile
export JAVA_HOME=/opt/bigdata/servers/jdk1.8.0_231
export PATH=:$JAVA_HOME/bin:$PATH
使配置文件生效
source /etc/profile
[root@linux software]# java -version
java version "1.8.0_231"
Java(TM) SE Runtime Environment (build 1.8.0_231-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.231-b11, mixed mode)
配置Linux主机名¶
为了方便区分局域网中的多个Linux主机,可以为每台机器设置主机名,本文介绍hostname配置方法。
1. 配置Linux hostname¶
下面配置两台centos7 虚拟机,主机名分别配置为client和server,它们主机IP 地址分别为192.168.30.8和192.168.30.9。
配置client主机¶
[root@client ~]# vi /etc/sysconfig/network
添加如下内容,保存:
# Created by anaconda
NETWORKING=yes
hostname=client
重启网络:
[root@client ~]# systemctl restart network
[root@client ~]# hostname
client
[root@client ~]#
如果不生效可以使用如下命令:
[root@client ~]# hostnamectl set-hostname client
配置server主机¶
[root@server ~]# hostnamectl set-hostname server
重启网络:
[root@server ~]# systemctl restart network
[root@server ~]# hostname
server
[root@server ~]# uname -n
server
2. 配置hostname与IP映射¶
配置client和server的hosts文件
vi /etc/hosts
添加如下内容:
192.168.30.8 client
192.168.30.9 server
3. 测试¶
通过ping hostname来测试是否配置成功:
client ping server:
[root@client ~]# ping server -c 3
PING server (192.168.30.9) 56(84) bytes of data.
64 bytes from server (192.168.30.9): icmp_seq=1 ttl=64 time=0.616 ms
64 bytes from server (192.168.30.9): icmp_seq=2 ttl=64 time=0.384 ms
64 bytes from server (192.168.30.9): icmp_seq=3 ttl=64 time=0.566 ms
--- server ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2001ms
rtt min/avg/max/mdev = 0.384/0.522/0.616/0.099 ms
[root@client ~]#
server ping client:
[root@Server ~]# ping client -c 3
PING client (192.168.30.8) 56(84) bytes of data.
64 bytes from client (192.168.30.8): icmp_seq=1 ttl=64 time=0.502 ms
64 bytes from client (192.168.30.8): icmp_seq=2 ttl=64 time=0.678 ms
64 bytes from client (192.168.30.8): icmp_seq=3 ttl=64 time=0.323 ms
--- client ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.323/0.501/0.678/0.144 ms
[root@Server ~]#
配置hostname与IP映射后,可以直接ping主机名而不用ping IP地址了。
4. 配置windows hosts¶
配置windows hosts,以便在windows下面能通过主机名进行访问。
编辑 C:\Windows\System32\drivers\etc\hosts文件,添加如下内容:
192.168.30.8 client
192.168.30.9 server
保存
5. windows测试¶
C:\Users\10287>ping client -n 3
正在 Ping client [192.168.30.8] 具有 32 字节的数据:
来自 192.168.30.8 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.30.8 的回复: 字节=32 时间<1ms TTL=64
来自 192.168.30.8 的回复: 字节=32 时间<1ms TTL=64
192.168.30.8 的 Ping 统计信息:
数据包: 已发送 = 3,已接收 = 3,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 0ms,最长 = 0ms,平均 = 0ms
配置多台服务器之间ssh免密登录¶
使用scp 或者 rsync命令在多台Linux服务器之间同步文件时需要输入密码,除了使用expect实现自动化交互以外,还有一种方法就是配置服务器之间ssh免密登录,本文记录一下具体配置过程。
1. 创建.ssh目录¶
假定有3台Linux主机,分别为A,B,C
在所有主机上创建ssh目录并赋予权限
mkdir /root/.ssh
chmod 700 /root/.ssh
2. 生成公钥与私钥¶
所有主机生成公钥与私钥,执行以下命令:
$ cd ~ # 进⼊入用户目录
$ ssh-keygen -t rsa -P "" # 生成ssh密码,-t 参数表示生成算法,可以选择rsa和dsa;-P表示使用的密码,""表示无密码。
4. 测试¶
ssh root@要进行链接的机器ip地址
主机A -> B:
[root@hostA ~]# ssh root@192.168.20.20
Last login: Sat Jul 10 10:17:34 2021 from hostA
[root@hostB ~]#
主机B -> A:
[root@hostB ~]# ssh root@192.168.20.10
Last login: Sun Jul 11 19:54:08 2021 from hostB
[root@hostA ~]#
使用samba实现linux和windows文件共享¶
Samba是用于Linux/Unix系统与Windows之间共享文件的软件,本文记录一下Samba的安装及使用方法。
samba简介¶
samba的功能都是通过一个CIFS(Common Internet File System)协议套件来管理的,这个名字是由微软引入的。
Samba是一个开源的CIFS实现,官网地址为 https://www.samba.org/samba/。
SMB (Server Message Block Protocol)协议是一种客户端/服务器通信协议,它主要包括smbd 和 nmbd,提供四种基本服务:
文件、打印服务:由SMB守护进程smbd提供
验证和授权:“共享模式”和“用户模式”
域解析:模拟Windows NT域系统,主要包括广播和点对点两种形式,还有一种是使用NBNS (NetBIOS Name Service)服务器,微软称为WINS服务(Windows Internet Name Service)
服务声明(浏览):声明网络上计算机提供的可浏览服务(文件和打印共享)列表。
前两个服务由smbd实现,后两个由nmbd来实现。
samba安装¶
centos7:
sudo yum install -y samba
sudo yum install -y samba-client
ubuntu:
sudo apt update
sudo apt install samba
sudo apt install samba-client
smbclient是一个smb服务器的客户端管理程序。
查看安装状态
$ whereis samba
samba: /usr/lib64/samba /etc/samba /usr/libexec/samba /usr/share/man/man7/samba.7.gz
$ rpm -qa | grep samba
samba-common-4.10.16-15.el7_9.noarch
samba-client-4.10.16-15.el7_9.x86_64
samba-client-libs-4.10.16-15.el7_9.x86_64
samba-common-libs-4.10.16-15.el7_9.x86_64
samba-libs-4.10.16-15.el7_9.x86_64
samba-common-tools-4.10.16-15.el7_9.x86_64
samba-4.10.16-15.el7_9.x86_64
$ smbd --version
Version 4.10.16
samba配置¶
1. 查看windows工作组¶
通过cmd命令 net config workstation
查看工作组:
C:\Users\10287>net config workstation
计算机名 \\DESKTOP-EHODIV3
计算机全名 DESKTOP-EHODIV3
用户名 Administrator
工作站正运行于
NetBT_Tcpip_{E484BACB-E20F-47EB-8727-EF799C2C041E} (0A0027000016)
软件版本 Windows 10 Home China
工作站域 WORKGROUP
登录域 DESKTOP-EHODIV3
COM 打开超时 (秒) 0
COM 发送计数 (字节) 16
COM 发送超时 (毫秒) 250
命令成功完成。
或者查看系统属性:此电脑 -> 属性 -> 高级系统设置 -> 计算机名 查看工作组
2. 关闭防火墙¶
配置之前先关闭linux防火墙
查看防⽕火墙状态
systemctl status firewalld
systemctl status firewalld.service
停⽌止firewall
systemctl stop firewalld.service
禁止firewall开机启动
systemctl disable firewalld.service
[root@Server apTest]# systemctl start smb.service
[root@Server apTest]#
[root@Server apTest]#
[root@Server apTest]# netstat -antpu| grep smb
tcp 0 0 0.0.0.0:139 0.0.0.0:* LISTEN 5164/smbd
tcp 0 0 0.0.0.0:445 0.0.0.0:* LISTEN 5164/smbd
tcp6 0 0 :::139 :::* LISTEN 5164/smbd
tcp6 0 0 :::445 :::* LISTEN 5164/smbd
[root@Server apTest]#
关闭selinux
vi /etc/selinux/config
注释SELINUX=enforcing,添加SELINUX=disabled
# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
# enforcing - SELinux security policy is enforced.
# permissive - SELinux prints warnings instead of enforcing.
# disabled - No SELinux policy is loaded.
# SELINUX=enforcing
SELINUX=disabled
# SELINUXTYPE= can take one of three values:
# targeted - Targeted processes are protected,
# minimum - Modification of targeted policy. Only selected processes are protected.
# mls - Multi Level Security protection.
SELINUXTYPE=targeted
3. 修改配置文件¶
先创建一个共享目录或者使用已有的目录。
$ mkdir -p /var/samba/share
$ touch /var/samba/share/test.txt
配置读写权限
chmod -R 777 /var/samba
配置smb.conf文件:vi /etc/samba/smb.conf
添加的共享名为myshare,这个名称是windows访问时会显示的名称,可以随意设置。
[global]
workgroup = WORKGROUP
security = user
passdb backend = tdbsam
printing = cups
printcap name = cups
load printers = yes
cups options = raw
[homes]
comment = Home Directories
valid users = %S, %D%w%S
browseable = No
read only = No
inherit acls = Yes
[printers]
comment = All Printers
path = /var/tmp
printable = Yes
create mask = 0600
browseable = No
[print$]
comment = Printer Drivers
path = /var/lib/samba/drivers
write list = @printadmin root
force group = @printadmin
create mask = 0664
directory mask = 0775
[myshare]
comment = my server share dir
path = /var/samba/share
public = yes
writable = yes
browseable = yes
guest ok = yes
guest only = yes
read only = no
4. 配置samba登录用户密码¶
可以使用groupadd
和 useradd
命令添加用户组,下面我直接使用root用户:
$ smbpasswd -a root
New SMB password:
Retype new SMB password:
Added user root.
新输的密码就是远程登录密码。
5. 启动服务¶
配置文件设置完成后启动samba服务,并设置开机启动
启动 smb.service 和 nmb.service两个服务
systemctl start smb.service
systemctl start nmb.service
重启smb服务命令:
systemctl restart smb.service
设置开机启动
systemctl enable smb.service
systemctl enable nmb.service
6. windows访问共享文件¶
win + r 输入samba服务器地址,访问samba共享文件
也可以在文件浏览器中输入地址
\\192.168.30.9
访问共享文件。
输入用户名密码后就可以访问Linux共享文件了!
可以对myshare中的文件进行读写操作以及文件创建。
smbclient使用¶
samba-client是linux中的客户端管理程序,如果要在linux/unix中访问samba文件可以使用smbclient工具。
登录samba服务器¶
$ smbclient //192.168.30.9/myshare
Enter SAMBA\root's password:
Try "help" to get a list of possible commands.
smb: \>
或者
$ smbclient //192.168.30.9/myshare/ -U root%12345678
Try "help" to get a list of possible commands.
smb: \>
登录成功后就可以对共享文件进行访问了:
smb: \> ls
. D 0 Sun Aug 22 10:17:09 2021
.. D 0 Sun Aug 22 09:03:44 2021
test.txt N 0 Sun Aug 22 09:30:59 2021
60273916 blocks of size 1024. 52785976 blocks available
smb: \>
下载¶
下载文件:
smb: \> get test.txt /root/samba/test.txt
getting file \test.txt of size 0 as /root/samba/test.txt (0.0 KiloBytes/sec) (average 0.0 KiloBytes/sec)
smb: \>
$ ll /root/samba/
total 0
-rw-r--r--. 1 root root 0 Aug 22 10:39 test.txt
指定日志存放目录
get test.txt /root/samba/test.txt -l /tmp/smb/smbalog
下载目录:
$ smbclient //192.168.30.9/myshare/ -U root%12345678 -c 'prompt OFF; recurse ON; cd /sambafolder/; lcd /tmp/smb/localfolder/; mget *' -l /tmp/smb/smbalog
上传¶
上传文件
smb: \> put /root/samba/test.txt test.txt
上传目录
$ smbclient //192.168.30.9/myshare/ -U root%12345678 -c 'prompt OFF; recurse ON; cd /sambafolder/; lcd /tmp/smb/localfolder/; mput *' -l /tmp/smb/smbalog
更多smbclient使用方法参考:https://www.samba.org/samba/docs/current/man-html/smbclient.1.html
参考文档:
Linux Bash编程:Fisher–Yates shuffle 洗牌算法¶
本文介绍使用shell语法来实现Fisher–Yates shuffle 洗牌算法。
Fisher-Yates shuffle 算法简介¶
Fisher–Yates shuffle 洗牌算法可以用于对数组进行随机排列,它的时间复杂度为O(n),伪代码如下:
To shuffle an array a of n elements (indices 0..n-1):
for i from n - 1 downto 1 do
j = random integer with 0 <= j <= i
exchange a[j] and a[i]
假定有一个数组a=[1, 2, 3, 4, 5, 6, 7, 8, 9],数组长度为n,打乱a中元素的具体迭代步骤如下:
生成一个[0, n-1]区间的随机数k;
将第k个元素和第n-1个元素进行交换;
进行下一轮迭代,生成一个[0, n-2]区间的随机数k,将第k个元素和第n-2个元素进行交换, 迭代次数为n-1次:从n-1取到1;
最终得到一个打乱的数组。
下表是一个数组的具体打乱过程,打乱后的数组是(9 4 8 1 2 3 5 6 7)
随机数 | 原数组 | 新数组 |
---|---|---|
0-8:6 | a = (1 2 3 4 5 6 7 8 9) | 交换a[8]和a[6] :(1 2 3 4 5 6 9 8 7) |
0-7:5 | a = (1 2 3 4 5 6 9 8 7) | 交换a[7]和a[5] :(1 2 3 4 5 8 9 6 7) |
0-6:4 | a = (1 2 3 4 5 8 9 6 7) | 交换a[6]和a[4] :(1 2 3 4 9 8 5 6 7) |
0-5:2 | a = (1 2 3 4 9 8 5 6 7) | 交换a[5]和a[2] :(1 2 8 4 9 3 5 6 7) |
0-4:1 | a = (1 2 8 4 9 3 5 6 7) | 交换a[4]和a[1] :(1 9 8 4 2 3 5 6 7) |
0-3:0 | a = (1 9 8 4 2 3 5 6 7) | 交换a[3]和a[0] :(4 9 8 1 2 3 5 6 7) |
0-2:2 | a = (4 9 8 1 2 3 5 6 7) | 交换a[2]和a[2] :(4 9 8 1 2 3 5 6 7) |
0-1:0 | a = (4 9 8 1 2 3 5 6 7) | 交换a[1]和a[0] :(9 4 8 1 2 3 5 6 7) |
shell实现¶
shuffle.sh :
#!/bin/bash
shuffle() {
local i tmp size max rand
# 打乱顺序
# Knuth-Fisher-Yates shuffle algorithm
size=${#my_array[*]}
max=$(( 32767 / size * size ))
# echo "max: $max"
for ((i=size-1; i>0; i--)); do
while (( (rand=$RANDOM) >= max )); do :; done
rand=$(( rand % (i+1) ))
# 交换
tmp=${my_array[i]}
my_array[i]=${my_array[rand]}
my_array[rand]=$tmp
echo ${my_array[*]}
done
}
my_array=(1 2 3 4 5 6 7 8 9)
shuffle
echo ${my_array[*]}
执行效果:
$ sh shuffle.sh
1 2 3 4 9 6 7 8 5
1 8 3 4 9 6 7 2 5
7 8 3 4 9 6 1 2 5
7 8 6 4 9 3 1 2 5
7 8 6 9 4 3 1 2 5
7 9 6 8 4 3 1 2 5
7 6 9 8 4 3 1 2 5
7 6 9 8 4 3 1 2 5
参考:
https://www.geeksforgeeks.org/shuffle-a-given-array-using-fisher-yates-shuffle-algorithm/
https://gaohaoyang.github.io/2016/10/16/shuffle-algorithm/#top
https://stackoverflow.com/questions/5533569/simple-method-to-shuffle-the-elements-of-an-array-in-bash-shell
随机数生成、对浮点数进行四舍五入运算¶
本文介绍使用shell实现随机数生成以及对浮点数进行四舍五入运算
随机数生成¶
生成0-1之间的随机数¶
生成0-1的随机数:
#!/bin/bash
random_number=`echo "scale=4 ; ${RANDOM}/32767" | bc -l` # 生成0-1的随机数
# random_number=`bc -l <<< "scale=4 ; ${RANDOM}/32767"`
echo $random_number
exit 0
执行:
$ sh random.sh
.8696
$ sh random.sh
.4517
$ sh random.sh
.5126
${RANDOM}
函数产生0 - 32767之间的伪随机整数。其中32767(2^15 - 1)是有符号16位整数的上限。scale=4
:保留4位小数
生成0-n之间的随机数¶
生成0-10之间的随机数:
#!/bin/bash
size=10
max=$(( 32767 / size * size ))
while (( (rand=$RANDOM) >= max )); do :; done
rand=$(( rand % (size+1) ))
echo $rand
生成1-10之间的随机数:
#!/bin/bash
size=10
max=$(( 32767 / size * size ))
while (( (rand=$RANDOM) >= max )); do :; done
rand=$(( rand % (size) + 1 ))
echo $rand
max=$(( 32767 / size * size ))
语句比较关键,这么处理的原因是${RANDOM}产生的最大数是32767,如果生成1-10之间的随机数,需要去掉32761-32767之间的数,否则会导致出现9和10的概率和其它数不一样。
对浮点数进行四舍五入运算¶
可以使用 printf "%.*f\n" [精度] [浮点数]
命令对浮点数进行四舍五入运算。
$ printf "%.*f\n" 0 6.666
7
$ printf "%.*f\n" 1 6.666
6.7
$ printf "%.*f\n" 2 6.666
6.67
bash脚本示例:
#!/bin/bash
random_number=`echo "scale=4 ; ${RANDOM}/32767" | bc -l` # 生成0-1的随机数
number=`echo "$random_number*100" | bc`
echo $number
number_round1=`echo $number | xargs printf "%.*f\n" 0`
echo $number_round1
number_round2=`echo $number | xargs printf "%.*f\n" 1`
echo $number_round2
exit 0
执行结果如下:
97.8900
98
97.9
参考:
https://unix.stackexchange.com/questions/167058/how-to-round-floating-point-numbers-in-shell
Linux Bash编程:将整数分解为n个随机数¶
本文介绍使用shell实现将一个整数m随机分解为n个数。
要求:
将一个整数m分解为n个随机数,n个随机数之和要等于m
指定随机数的最小值
分析:
这与leetcode上的两道题类似:
下面来介绍一种思路:
随机抽取
n-1
个区间为(0, m)
的数,得到数组a
将
0
和m
加入数组a
中对数组
a
进行升序排序按顺序计算数组
a
中相邻元素的差值:后一个元素减去前一个元素。差值组成的数组就是我们要的结果。
shell脚本SplitInteger.sh:
#!/bin/bash
SplitInteger()
{
let SIZE_BYTES=$SIZE_BYTES-$NUMBER*$minNum
declare -a num_list
num_list[0]=0
num_list[1]=$SIZE_BYTES
let num=$NUMBER
for i in $(seq 2 $num); do
random_rate=`echo "scale=4 ; ${RANDOM}/32767" | bc -l` # 生成0-1的随机数
# let random_bytes=$(( SIZE_BYTES*random_rate ))
random_bytes=`echo "$SIZE_BYTES*$random_rate" | bc` # 字符类型转换为数字类型进行运算
# echo "$random_bytes"
num_list[$i]=`echo $random_bytes | xargs printf "%.*f\n" 0` # 对结果进行四舍五入计算
done
# echo "Array in unsorted order :"
# echo ${num_list[*]}
num_length=${#num_list[*]}
BubbleSort # 排序
# 计算差值
let rand_len=$num_length-2
for i in $(seq 0 $rand_len); do
new_list[$i]=`echo "${num_list[$(( i+1 ))]}-${num_list[$i]}+$minNum" | bc`
done
# echo "Diff Array:"
echo "${new_list[*]}"
sum=0
for (( i=0;i<${#new_list[*]};i++ ))
do
let sum=sum+${new_list[$i]}
done
echo $sum
}
let SIZE_BYTES=100
let NUMBER=10
let minNum=5
SplitInteger
exit 0
执行:
$ sh SplitInteger.sh
8 12 6 16 9 12 11 9 5 12
100
BubbleSort
为冒泡排序方法,具体实现参考Linux Bash编程:字符串处理。
Linux Bash之getopt命令行参数解析¶
Unix shell 中内置了命令行参数解析函数getopts,但它仅支持简单的参数解析,不支持长参数,getopt是getopts的增强版,支持长参数。在Python笔记:命令行参数解析中介绍了Python中的命令行参数解析方法getopt(),本文介绍shell中如何使用getopt进行命令行参数解析。
先看下面脚本(test_getopt.sh):
#!/bin/bash
FIELD=unset
DF=unset
COUNT=unset
green='\033[32m'
help()
{
Usage="Usage: sh test_getopt.sh [OPTION] \n\
Options:\n\
[ -f | --field FIELD] \t\t-- 字段 \n \
[ -Y | --display-filter DF] \t-- 条件 \n \
[ -c | --count COUNT ] \t-- 计数 \n \
[ -h | --help ] \t\t-- 帮助信息 \n \
"
echo -e ${green} $Usage
exit 2
}
ARGS=$(getopt -a -n test_getopt.sh -o f:Y:ch --long field:,display-filter:,count,help -- "$@")
VALID_ARGS=$?
if [ "$VALID_ARGS" != "0" ]; then
help
fi
eval set -- "$ARGS"
while :
do
case "$1" in
-f | --field) FIELD="$2" ; shift 2 ;;
-Y | --display-filter) DF="$2" ; shift 2 ;;
-c | --count) COUNT=2 ; shift ;;
-h | --help) help; exit 0 ; shift ;;
--) shift; break ;;
esac
done
echo "FIELD : $FIELD"
echo "DF : $DF "
echo "COUNT : $COUNT"
echo "其余参数: $@"
exit 0
下面对脚本进行简要解释:
在开头可以定义脚本的全局变量,green用于设置字体颜色。
help()函数用于显示帮助信息,说明脚本的使用方法。
ARGS=$(getopt -a -n test_getopt.sh -o f:Y:ch --long field:,display-filter:,count,help -- "$@")
短参数一般在前面加单破折号(
-
),长参数使用双破折号(--
),-a
选项可以使长参数支持单破折号(-
)如果参数必须赋值,在后面加冒号(
:
),-n test_getopt.sh
:指定程序名为test_getopt.sh,如果不设置,默认使用getopt-o | --options
:短选项-l | --longoptions
:长选项
getopt接收所有输入后会返回一个状态码,0表示成功,其他值表示失败,状态码会传递给变量
$?
,对变量$?
做一个判断,如果不为0则打印帮助信息。eval set -- "$ARGS"
:eval 命令把字符串当做命令来执行,这里用于处理参数中的转义字符。
set 命令将命令行参数替换成getopt格式化后的命令行参数,也就是将getopt格式化的参数分配至位置参数($1,$2,...)
接下来就是对参数($1,$2,...)进行遍历处理
通过shift来移动获取参数,用它来实现移动一个或者多个位置(也就是弹栈)
每次循环,检查
$1
参数,对于必须赋值的参数,需要移动两位,因为它后面跟了一个参数值,需要移动两位才能到下一个参数。取值为$2
,因为第一个参数为选项名称,第二个参数才是参数值。移位到
--
后,表示所有参数解析完成,退出循环。
运行:
$ sh test_getopt.sh --help
Usage: sh test_getopt.sh [OPTION]
Options:
[ -f | --field FIELD] -- 字段
[ -Y | --display-filter DF] -- 条件
[ -c | --count COUNT ] -- 计数
[ -h | --help ] -- 帮助信息
$
$ sh test_getopt.sh -c -f test -Y hello test2
FIELD : test
DF : hello
COUNT : 2
其余参数: test2
Python正则表达式¶
正则表达式(Regular expression)是组成搜索模式的一组字符序列,是记录文本规则的代码,用来检查文本中是否包含指定模式的字符串,通过定义一个规则来匹配字符串。正则表达式广泛应用于在字符串查找和处理中,大多文本编辑器基本都支持正则表达式查找。本文将简要介绍正则表达式语法,然后介绍Python语言中正则表达式使用方法。
正则表达式¶
Unix之父Ken Tompson将正则表达式引入Unix,后面发展成了grep(Global Regular Expression Print)命令,由于grep不支持+
、|
与?
,且分组比较麻烦,AT&T的Alfred Aho开发了egrep命令。随着Unix的版本不断演化,Unix中的程序(比如Linux三剑客中的awk、sed)所支持的正则表达式有差异,比较混乱。在1986年制定了POSIX(Portable Operating System Interface)标准,其中统一了正则表达式的语法。
POSIX标准把正则表达式分为两种:BRE(Basic Regular Expressions)和ERE(Extended Regular Expressions )。BRE就是unix系统使用的grep命令,ERE对应egrep命令,是BRE的扩展。而linux系统使用的是GNU标准,linux发行版集成了GNU(Gnu’s Not Unix)套件,GNU在实现了POXIS标准的同时,做了一定的扩展。也包括GNU Basic Regular Expressions 和GNU Extends Regular Expressions。
正则表达式除了POSIX标准之外还有一个Perl分支,Perl与sed和awk兼容,后来演化成为PCRE(Perl Compatible Regular Expressions),是一个用C语言编写的正则表达式函数库,功能很强大,性能比POSIX正则表达式好。PCRE被引入了其他语言中,比如PHP, Tcl, Python, Ruby, C++, Java, R语言等等。
普通正则¶
代码 | 说明 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配字母或数字或下划线或汉字 |
\s | 匹配任意的空白符 |
\d | 匹配数字 |
\b | 匹配单词的开始或结束 |
^ | 匹配字符串的开始 |
$ | 匹配字符串的结束 |
* | 重复零次或更多次 |
扩展正则¶
扩展正则:grep加 -E
参数
grep -E ' 404 | 500' nginx.log
代码/语法 | 说明 |
---|---|
+ | 重复一次或更多次 |
? | 重复零次或一次 |
{n} | 重复n次 |
{n,} | 重复n次或更多次 |
{n,m} | 重复n到m次 |
| | 表示或 |
零宽断言¶
语法 | 说明 |
---|---|
(?=exp) | 匹配exp前面的位置 |
(?<=exp) | 匹配exp后面的位置 |
(?!exp) | 匹配后面不是exp的位置 |
(?<!exp) | 匹配前面不是exp的位置 |
正则表达式实例¶
正则表达式在线测试工具:
测试文本test.txt
$ cat test.txt
abc
bac
123456
bc
test123
12345678901234
023-12345678
123
GET 1
GET123
GET
test123test
1. 匹配以字母a开头的单词¶
$ grep '\ba\w*\b' test.txt
abc
2. 匹配刚好6个字符的单词¶
$ grep -E '\b\w{6}\b' test.txt
123456
GET123
3. 匹配1个或更多连续的数字¶
$ grep -Po '\d+' test.txt
123456
123
12345678901234
023
12345678
123
1
123
123
4. 5位到12位QQ号¶
$ grep -P '\d{5,12}' test.txt
123456
12345678901234
023-12345678
$ grep -P '^\d{5,12}$' test.txt
123456
5. 匹配电话号码¶
$ grep -P '0\d{2}-\d{8}' test.txt
023-12345678
6. 只匹配3位数字¶
$ grep -P '^\d{3}$' test.txt
123
7. 查找单词‘GET’¶
$ grep '\bGET\b' test.txt
GET 1
GET
$ grep '^GET$' test.txt
GET
8. 匹配两个字符之间的内容¶
$ grep -Eo "test(.+?)test" test.txt
test123test
$ grep -Po "(?<=test).*?(?=test)" test.txt
123
9. .*
和.+
的使用方法¶
$ text1="fn()"
$ text2="fn(6)"
$ echo $text1 | grep "fn\(.*\)"
fn()
$ echo $text2 | grep "fn\(.*\)"
fn(6)
$ echo $text1 | grep -E "fn\(.+\)"
$ echo $text2 | grep -E "fn\(.+\)"
fn(6)
Python正则表达式¶
Python有一个内置正则表达式模块 re
,可以使用它来进行字符串操作:
import re
re
模块提供了以下4种方法:
findall:返回所有匹配项
search:如果匹配到目标字符,返回一个匹配对象,用于判断是否存在目标字符串
split:分割
sub:替换
匹配数字、字母¶
text = '1&\nbsp;hour(s) 2&\nbsp;min 25&\nbsp;s'
re.findall(r'\d+',text) # 匹配时间(数字)
re.findall(r'\d+|(?<=;)\w+',text) # 匹配时间和单位
output:
['1', '2', '25']
['1', 'hour', '2', 'min', '25', 's']
re.findall(r'\d{2}+',text) # 匹配2位数字
查找替换两个字符串之间内容¶
替换字符target_text
:
xpath_path = '//*[contains(text(),"target_text")]/../td[5]/span' # xpath路径
repl = "需要替换成的字符串"
re.sub(r"(?<=\").*?(?=\")", repl, xpath_path) # 替换要查找的文本
output:
'//*[contains(text(),"需要替换成的字符串")]/../td[5]/span'
添加千位分割符¶
number = '12345678'
re.sub(r"\B(?=(?:\d{3})+(?!\d))", ",",number) # 替换要查找的文本
re.sub(r"\B(?:(?:\d{3})+(?!\d))", ",",number)
output:
'12,345,678'
'12,'
(?:\d{3})+(?!\d)
:
查找3n(数字) + 非数字 组合
(?:exp)
:
匹配exp,不捕获匹配的文本(非获取匹配),也不给此分组分配组号,当执行了第一次匹配时,匹配到了行尾,直接将345678替换成了“,”。
参考文档¶
正则表达式30分钟入门教程:https://deerchao.cn/tutorials/regex/regex.htm
github项目learn-regex:https://github.com/ziishaned/learn-regex
Linux cron定时介绍¶
定时任务的使用场景非常广泛,比如定时发送邮件,定时清理日志等等,在持续集成中,可以定时的触发测试任务,比如希望在每天晚上下班时间执行自动化用例。本文通过介绍Linux cron定时来了解cron定时相关概念。
Linux Crontab 定时任务¶
cron来源于希腊语chronos,意思是时间。在类Unix的操作系统中,可以使用cron 服务器来实现定时执行任务。crontab文件存放cron指令,执行周期命令的守护进程crond负责激活这些任务,定期检查是否有任务执行。
crond 服务¶
crond 服务是用来执行周期任务或等待处理某些事件的一个守护进程,crontab 命令需要 crond 服务支持。centos7中一般是默认安装的,可以使用 rpm
命令查看是否安装:
$ rpm -qa | grep crontab
crontabs-1.11-6.20121102git.el7.noarch
查看crond 服务状态:
# centos7
systemctl status crond.service
# centos6
service crond status
启动crond 服务:
# centos7
systemctl start crond.service
# centos6
service crond start
停止crond 服务:
# centos7
systemctl stop crond.service
# centos6
service crond stop
重启crond 服务:
# centos7
systemctl restart crond.service
# centos6
service crond restart
重载crond 服务:
# centos7
systemctl reload crond.service
# centos6
service crond reload
crontab相关文件¶
cron 服务主要包括以下文件目录:
/var/spool/cron
:用户定义的crontab文件存放目录/etc/cron.d
:存放要执行的crontab文件或脚本/etc/crontab
:系统任务调度的配置文件/etc/anacrontab
:anacron配置文件/etc/cron.deny
:列出不允许使用crontab命令的用户/etc/cron.daily
:每天执行一次的脚本/etc/cron.hourly
:每小时执行一次的脚本/etc/cron.monthly
:每月执行一次的脚本/etc/cron.weekly
:每星期执行一次的脚本
/etc/crontab
文件负责管理和维护任务:
$ cat /etc/crontab
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# For details see man 4 crontabs
# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed
其中:
SHELL
变量指定系统使用的shell版本PATH
指定系统执行命令的路径MAILTO
指定邮件发送的用户,如果为root,邮件会发送到/var/spool/mail/root
文件中
cron表达式¶
用户定义的crontab文件保存在 /var/spool/cron
目录中,每个crontab任务以创建者的名字命名。crontab文件中每一行都代表一项任务,每条命令包括6个字段,前5个代表时间,第6个字段是要执行的命令。
五颗星:* * * * *
第1颗星:分钟 minute,取值 0~59;
第2颗星:小时 hour,取值 0~23;
第3颗星:天 day,取值 1~31;
第4颗星:月 month,取值 1~12;
第5颗星:星期 week,取值 0~7,0 和 7 都表示星期天。
可以使用4种操作符:
*
:当前代表的所有取值范围内的数字/
:需要间隔的数字-
:某个区间,比如1-3表示1, 2, 3,
:分散的数字,可以不连续,比如1, 3, 5
下面举几个例子:
# 每5分钟构建一次
H/5 * * * *
# 每2小时构建一次
H H/2 * * *
# 每天8点到22点,每2小时构建一次
H 8-22/2 * * *
# 每天8点,22点各构建一次
H 8,22 * * *
crontab命令¶
crontab 命令用来配置定时任务,语法如下:
crontab [options] file
crontab [options]
常用options:
-u <user>
:定义用户-e
:编辑 crontab表-l
: 列出用户crontab表-r
:删除用户crontab表-i
:删除提示-n <hostname>
设置用户crontab主机名-c
:获取运行用户crontab的主机名-s
:selinux 上下文-x <mask>
:开启调试
crontab定时示例¶
先写一个用于采集CPU性能信息的脚本(cpu_Perf.sh):
#!/bin/bash
mpstat -P ALL 1 2 >> /var/cron/perf.log
下面来添加一个定时任务:
执行 命令crontab -e
,输入下面的cron表达式,每分钟执行一次CPU性能采集脚本:
* * * * * /var/cron/cpu_Perf.sh
保存。命令保存到了 /var/spool/cron/
目录下的root文件中(当前用户为root):
$ cat /var/spool/cron/root
* * * * * /var/cron/cpu_Perf.sh
$ crontab -l
* * * * * /var/cron/cpu_Perf.sh
保存成功后,每一分钟就会执行一次脚本。
Linux anacron 定时任务¶
如果服务器关机或者无法运行任务,定时任务就不会执行,服务器恢复后,定时任务不会执行没有执行的定时任务。这种场景下可以使用anacron命令,它与crond功能相同,增加了执行被跳过任务的功能。一旦服务器启动,anacron就会检查配置的定时任务是否错过了上一次执行,如果有,将立即运行这个任务,且只运行一次(不管错过了多少个周期)。
也就是说, anacron 是用来保证由于系统原因导致错过的定时任务可以在系统正常后执行的服务。
anacron命令¶
可以使用 anacron 命令来管理 anacron 服务,语法格式如下:
anacron [options] [job] ...
anacron -T [-t anacrontab-file]
options选项:
-s
:串行调用任务-f
:强制执行任务,忽略设置的周期-n
:没有delay执行任务,隐含调用了-s
参数-d
:把信息输出到标准输出设备和系统日志中-q
:禁止向标准输出发送消息,只能和-d选项配合使用。-u
:更新时间戳但不执行任务-V
:打印版本信息-h
:打印帮助信息-t <file>
:使用指定的配置文件,忽略默认的/etc/anacrontab文件。-T
:Anacrontab测试-S <dir>
:指定存放timestamp文件的路径
job
是 /etc/anacrontab
文件中定义的工作名 job-identifier
anacron执行过程¶
下面来介绍一下anacron的执行过程:
1、根据脚本需要执行的频率,将脚本安装到/etc/cron.[hourly|daily|weekly|monthly]
目录中:
/etc/cron.hourly
/etc/cron.daily
/etc/cron.monthly
/etc/cron.weekly
2、crond 服务会执行/etc/cron.d/0hourly
中指定的cron 任务,
$ cat /etc/cron.d/0hourly
# Run the hourly jobs
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
01 * * * * root run-parts /etc/cron.hourly
每小时运行一次 run-parts 程序,而 run-parts 程序执行 /etc/cron.hourly
中的所有的shell脚本。
/etc/cron.hourly
目录中包含 0anacron
脚本:
$ ls /etc/cron.hourly
0anacron mcelog.cron
3、 0anacron
脚本通过 /etc/anacrontab
配置文件来运行anacron程序。
$ cat /etc/anacrontab
# /etc/anacrontab: configuration file for anacron
# See anacron(8) and anacrontab(5) for details.
SHELL=/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root
# the maximal random delay added to the base delay of the jobs
RANDOM_DELAY=45
# the jobs will be started during the following hours only
START_HOURS_RANGE=3-22
#period in days delay in minutes job-identifier command
1 5 cron.daily nice run-parts /etc/cron.daily
7 25 cron.weekly nice run-parts /etc/cron.weekly
@monthly 45 cron.monthly nice run-parts /etc/cron.monthly
RANDOM_DELAY=45
:表示最大随机延迟时间为45分钟。START_HOURS_RANGE=3-22
: 执行的时间范围为03:00—22:00
/etc/anacrontab
配置文件执行cron.[daily|weekly|monthly]
目录中的可执行文件。
anacron的监测周期为每天、每周和每月,每天执行一次/etc/cron.daily
目录中的程序,每周执行一次 /etc/cron.weekly
中的程序,每月执行一次 /etc/cron.monthly
中的程序。
anacron不能在指定某个时间运行某个程序,它的设计目的是在特定的时间间隔运行某个程序,例如每天,每周日或者每月第一天的03:00运行某个程序。如果因为某种原因(关机或者服务器异常)没有执行,anacron会在服务器正常后运行一次错过的执行。
那么,anacron 是如何判断这些定时任务错过了执行呢?
其实是通过读取上次执行 anacron 的时间记录文件,通过两个时间的差值判断是否超过指定间隔时间(1天、1周和1月)。
/var/spool/anacron/
目录中的 cron.[daily|weekly|monthly]
文件记录了上一次执行 cron任务 的时间:
$ ls /var/spool/anacron/
cron.daily cron.monthly cron.weekly
$ cat /var/spool/anacron/cron.daily
20211123
cron表达式应用¶
前面介绍了在Linux中通常用 crond 服务来实现任务定时执行,在很多场景都会用到定时任务,比如定时提醒,定时发送邮件等。比如python中可以使用APScheduler库执行定时任务,Java可以使用Quartz框架实现,Go语言使用 github.com/robfig/cron 包。
在持续测试平台Jenkins中经常会配置定时执行任务,下面简单介绍一下Jenkins定时构建配置方法。
Jenkins定时构建¶
在配置Jenkins任务时,构建定时任务主要有两种形式:
一种是配置周期触发(Build periodically),在特定时间进行自动触发测试流程。
第二种是Poll SCM:定时检查源码变更,如果有更新就checkout新的代码下来,然后执行构建动作。
在【Build Triggers】中选择 Build periodically 或者 Poll SCM
在Schedule中输入cron表达式来配置定时任务。
Jenkins也可以创建多个定时,比如在每个工作日的9:30和每周五22:30构建:
30 9 * * 1-5
30 22 * * 5
Docker简介及安装¶
容器技术(Linux Container,LXC)是一种轻量级的虚拟化技术,容器镜像运行在一个隔离环境中,像集装箱一样,把应用封装起来,应用之间互不干扰,实现进程的隔离。Docker 是常用的一种容器技术,本文将简要介绍Docker及Docker安装方法。
Docker简介¶
Docker是什么¶
Docker基于Go语言开发,在2013年正式发布,是一个是用于构建、部署和管理容器化应用程序的开源平台,Docker 允许开发人员将应用程序打包到容器中,容器将应用程序源代码、操作系统库以及所需的依赖结合在一起,可以发布到任何流行的系统中。Docker具有以下优点:
使开发人员能够使用简单命令自动化构建、部署、运行、更新容器,缩短开发及运行代码之间的周期,快速交付应用。
应用隔离:不同软件运行环境兼容依赖问题,每个容器都可以看作是一个不同的微服务,容器之间互不影响。
轻量级,比创建虚拟机快得多
运行环境可移植,容器镜像将应用运行环境,包括代码、依赖、资源文件等打包。
Docker与虚拟机的区别¶
虚拟机(Virtual machine, VM)是对计算机系统的仿真,操作系统(OS)及其应用程序共享单个主机服务器的硬件资源,硬件是虚拟化的,每个虚拟机都有自己的底层操作系统。管理程序(hypervisor)位于硬件和虚拟机之间,负责创建和运行 VM 的软件、固件或硬件。
前面讲过,Docker也是一种虚拟化技术,它只虚拟化操作系统,而不像虚拟机那样虚拟化操作系统和硬件资源。主要区别如下:
容器与容器之间只是进程的隔离,通过名称空间隔离,而虚拟机是完全的资源隔离,可能更安全。
虚拟机的启动可能需要几分钟,Docker启动只需几秒钟甚至更短。
容器共享宿主操作系统的内核,而虚拟机使用完全独立的内核,需虚拟化内核。
虚拟机是操作系统和硬件的虚拟化,Docker是操作系统的虚拟化
Docker Engine¶
Docker Engine 是一个客户机/服务器 (C/S架构) 应用,主要包括三个部分:
server:守护进程(dockerd 命令),Docker Daemon
REST API:客户端与守护进程间的通信接口
CLI:command line interface (CLI) ,命令行接口客户端(docker 命令)
CLI 使用 REST API 与 Docker Daemon 进行通信,实现对Docker Daemon的控制和交互。也可以使用 UNIX 套接字、网络接口进行通信。守护进程构建、运行和管理 Docker 对象(镜像、容器、网络和volumes)。Docker 客户机和守护进程可以在同一个系统上运行,也可以将 Docker 客户机连接到远程 Docker 守护进程。
Docker daemon¶
Docker 守护进程(dockerd)是后台服务进程,是生存期较长的进程,负责监听 Docker API 请求,管理 Docker 对象。守护进程还可以与其他守护进程通信来管理 Docker 服务。
Docker client¶
Docker 客户端(docker)是 Docker 用户与 Docker 交互的主要方式,客户端将命令发送给守护进程,然后守护进程执行这些命令,Docker 客户端可以与多个守护进程进行通信。
Docker Images¶
Docker镜像是一个只读模板,其中包含创建 Docker 容器的说明。通常,一个镜像都可能依赖一个或多个下层的镜像组成的另一个镜像。Docker镜像可以从Docker仓库中下载,也可以自己创建(Dockerfile)。
Docker Registry¶
Docker仓库是集中存放Docker镜像的地方,默认公共仓库为 Docker Hub,也可以自己配置私人仓库。当使用 docker pull
或 docker run
命令时,将从配置的仓库中提取所需的镜像。使用 docker push
命令时,镜像将被推送到配置的仓库中。
Docker Containers¶
Docker容器是镜像运行后的进程,是镜像的可运行实例,默认情况下,容器之间是隔离的。
Docker安装¶
Docker安装可参考官方文档:https://docs.docker.com/engine/install/
Windows 10¶
下载地址 : https://hub.docker.com/editions/community/docker-ce-desktop-windows
Linux¶
安装方法有两种,一种是设置docker源进行安装(推荐方法),另一种是是下载安装包(CentOS和Ubuntu对应RPM、DEB包)进行手动安装,一般在安装主机没有网络的情况下使用这种方法。(RPM、DEB包介绍及安装方法可参考Linux系统介绍)
下面介绍一下CentOS下的docker安装方法(也可参考官方文档:https://docs.docker.com/engine/install/centos/),Ubuntu系统下docker的安装参考官方文档:https://docs.docker.com/engine/install/ubuntu/
要求CentOS 7 或者 CentOS 8
1. 卸载旧版本¶
$ sudo yum remove docker \
docker-client \
docker-client-latest \
docker-common \
docker-latest \
docker-latest-logrotate \
docker-logrotate \
docker-engine
2. 安装依赖、添加源¶
# 安装yum-utils包
$ sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 设置yum源
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# a
$ sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
3. 安装Docker Engine¶
安装最新版本的Docker Engine 和 containerd
$ sudo yum install docker-ce docker-ce-cli containerd.io
或者安装指定版本:
# 列出可用版本
$ yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64 3:20.10.2-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.2-3.el7 @docker-ce-stable
docker-ce.x86_64 3:20.10.1-3.el7 docker-ce-stable
docker-ce.x86_64 3:20.10.0-3.el7 docker-ce-stable
# 安装指定版本
$ sudo yum install docker-ce-20.10.2 docker-ce-cli-20.10.2 containerd.io
4. 启动Docker¶
# 启动
$ sudo systemctl start docker
# 开机启动
$ sudo systemctl enable docker
5. 检验Docker Engine是否安装成功¶
# 运行hello-world镜像
$ sudo docker run hello-world
# 或者 查看docker版本
$ docker version
配置阿里云镜像加速器¶
默认是从Docker Hub下载镜像,为了更快的下载docker镜像,可以配置国内的镜像服务器,下面介绍阿里云镜像配置方法。
阿里云控制台地址:https://homenew.console.aliyun.com/
进入容器镜像服务
设置登陆密码 首次使用需要设置密码:
设置镜像加速点击进入镜像加速器:https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors
选择对应的操作系统,按照操作步骤进行操作。
常见问题¶
报错信息:
Failed to Setup IP tables: Unable to enable SKIP DNAT rule: (iptables failed: iptables --wait -t nat -I DOCKER -i br-48bc3090b33e -j RETURN: iptables: No chain/target/match by that name.
原因是关闭防火墙之后docker需要重启:
service docker restart
参考:
Docker常用命令¶
本文介绍常用Docker命令,以搭建Web服务器Nginx为例介绍docker相关命令。
基本命令¶
查看Docker版本信息:
$ docker version
查看Docker系统信息:
$ docker info
从Docker Hub查找镜像
$ docker search 镜像名
# 搜索nginx镜像
$ docker search nginx
拉取镜像
$ docker pull nginx
[root@server server]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
a076a628af6f: Pull complete
0732ab25fa22: Pull complete
d7f36f6fe38f: Pull complete
f72584a26f32: Pull complete
7125e4df9063: Pull complete
Digest: sha256:10b8cc432d56da8b61b070f4c7d2543a9ed17c2b23010b43af434fd40e2ca4aa
Status: Downloaded newer image for nginx:latest
docker.io/library/nginx:latest
[root@server server]#
下载指定版本的镜像
$ docker pull nginx:1.19.6
镜像的可用版本可在docker hub中查看:https://hub.docker.com/ :
镜像管理¶
查看所有已下载镜像
$ docker images
[root@server server]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 3 weeks ago 133MB
app v1 db282454f6b3 7 months ago 83.1MB
<none> <none> 1acc89e1a291 7 months ago 152MB
bitnami/mariadb latest 08498502c6b7 7 months ago 319MB
bitnami/testlink latest 41feee91d195 7 months ago 826MB
prom/prometheus latest 39d1866a438a 7 months ago 142MB
mysql 5.7 9cfcce23593a 7 months ago 448MB
python 3.7-alpine 6a5ca85ed89b 8 months ago 72.5MB
jenkins/jenkins lts 5d1103b93f92 8 months ago 656MB
[root@server server]#
删除镜像
$ docker rmi nginx:latest
# 或者使用IMAGE ID
$ docker rmi f6d0b4767a6c
# 强制删除镜像
$ docker rmi -f f6d0b4767a6c
标记本地镜像
$ docker tag nginx:latest nginx:test
# 修改镜像名称
$ docker tag nginx:latest nginx_test
[root@server server]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 3 weeks ago 133MB
nginx test f6d0b4767a6c 3 weeks ago 133MB
[root@server server]# docker tag nginx:latest nginx_test
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest f6d0b4767a6c 3 weeks ago 133MB
nginx test f6d0b4767a6c 3 weeks ago 133MB
nginx_test latest f6d0b4767a6c 3 weeks ago 133MB
[root@server server]# docker rmi nginx:test
Untagged: nginx:test
[root@server server]# docker rmi nginx_test:latest
Untagged: nginx_test:latest
将指定镜像打包成 tar 归档文件
$ docker save nginx > nginx_test.tar
$ docker save nginx -o nginx_test.tar
导入打包的镜像
$ docker load < nginx_test.tar
查看镜像创建历史
$ docker history nginx
容器管理¶
运行容器
# 开启nginx服务
$ docker run -p 80:80 -d --name=nginx nginx:latest
-d: 后台运行容器,并返回容器ID --name: 为容器指定一个名称 -p: 指定端口映射:主机(宿主)端口:容器端口 **-v:**挂载目录,将主机的目录映射到容器目录
[root@server server]# docker run -p 80:80 -d --name=nginx nginx:latest
651ce76dd80fa58e3cdf2abeb9c08662bfcf68176738bb3881d0bcb851aa1a11
[root@server server]#
浏览器输入服务器IP地址
挂载目录
# 将主机目录/home/server/nginx/html映射到容器目录/usr/share/nginx/html
$ docker run -p 80:80 -d --name=nginx -v /home/server/nginx/html:/usr/share/nginx/html nginx:latest
在主机目录/home/server/nginx/html下新建一个index.html文件,输入内容:<h1>Hello World !</h1>
[root@server server]# cd /home/haiyong/nginx/html
[root@server html]# vim index.html
[root@server html]# cat index.html
<h1>Hello World !</h1>
[root@server html]#
浏览器刷新
查看运行的容器:
$ docker ps
$ docker ps -a
[root@server server]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
651ce76dd80f nginx:latest "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 0.0.0.0:80->80/tcp nginx
[root@server server]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
651ce76dd80f nginx:latest "/docker-entrypoint.…" 8 minutes ago Up 7 minutes 0.0.0.0:80->80/tcp nginx
3bab7ac2a2af jenkins/jenkins:lts "/sbin/tini -- /usr/…" 6 months ago Exited (255) 8 days ago 0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp jenkins
2c5ae10a7543 mysql:5.7 "docker-entrypoint.s…" 6 months ago Exited (255) 8 days ago 0.0.0.0:3306->3306/tcp, 33060/tcp mysql-test
[root@server server]#
查看容器中运行的进程
$ docker top nginx
[root@server server]# docker top nginx
UID PID PPID C STIME TTY TIME CMD
root 118225 118205 0 22:58 ? 00:00:00 nginx: master process nginx -g daemon off;
101 118284 118225 0 22:58 ? 00:00:00 nginx: worker process
实时监控容器资源消耗
$ docker stats nginx
[root@server server]# docker stats nginx
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
651ce76dd80f nginx 0.00% 1.492MiB / 1.777GiB 0.08% 3.97kB / 3.66kB 73.7kB / 24.6kB 2
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
651ce76dd80f nginx 0.00% 1.492MiB / 1.777GiB 0.08% 3.97kB / 3.66kB 73.7kB / 24.6kB 2
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
651ce76dd80f nginx 0.00% 1.492MiB / 1.777GiB 0.08% 3.97kB / 3.66kB 73.7kB / 24.6kB 2
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
查看容器日志
$ docker logs -f nginx
获取容器/镜像的元信息
$ docker inspect nginx
$ docker inspect -f '{{.Id}}' nginx
-f : 格式化字符串,输出格式使用Go语言模板。
[root@server server]# docker inspect nginx
[
{
"Id": "651ce76dd80fa58e3cdf2abeb9c08662bfcf68176738bb3881d0bcb851aa1a11",
"Created": "2021-02-02T14:58:47.047835997Z",
"Path": "/docker-entrypoint.sh",
"Args": [
"nginx",
"-g",
"daemon off;"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 118225,
"ExitCode": 0,
"Error": "",
"StartedAt": "2021-02-02T14:58:48.290043299Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
............................
[root@server server]# docker inspect -f '{{.Id}}' nginx
651ce76dd80fa58e3cdf2abeb9c08662bfcf68176738bb3881d0bcb851aa1a11
[root@server server]# docker inspect -f '{{.State.StartedAt}}' nginx
2021-02-02T14:58:48.290043299Z
docker inspect
返回的容器信息中记录了容器的磁盘挂载目录,可以使用grep命令筛选出Mounts
字段内容:
$ docker inspect nginx | grep Mounts -A 10
"Mounts": [
{
"Type": "bind",
"Source": "/home/server/nginx/html",
"Destination": "/usr/share/nginx/html",
"Mode": "",
"RW": true,
"Propagation": "rprivate"
}
],
"Config": {
查看容器内文件结构及更改
$ docker diff nginx
[root@server server]# docker diff webserver
C /etc
C /etc/nginx
C /etc/nginx/conf.d
C /etc/nginx/conf.d/default.conf
C /root
A /root/.bash_history
C /var
C /var/cache
C /var/cache/nginx
A /var/cache/nginx/client_temp
A /var/cache/nginx/fastcgi_temp
A /var/cache/nginx/proxy_temp
A /var/cache/nginx/scgi_temp
A /var/cache/nginx/uwsgi_temp
C /run
A /run/nginx.pid
**A:**添加了文件或目录 **B:**文件或目录被删除 **C:**文件或目录被修改
启动,停止容器
# 启动已经被停止的容器
$ docker start nginx
# 重启容器
$ docker restart nginx
# 暂停容器中所有的进程
$ docker pause nginx
# 恢复容器中所有的进程
$ docker unpause nginx
# 杀掉一个运行中的容器
$ docker kill nginx
# 停止一个运行中的容器
$ docker stop nginx
# 删除容器
$ docker rm nginx
# 强制删除容器
$ docker rm -f nginx
[root@server server]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
651ce76dd80f nginx:latest "/docker-entrypoint.…" 21 hours ago Up 21 hours 0.0.0.0:80->80/tcp nginx
[root@server server]# docker stop nginx
nginx
[root@server server]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@server server]# docker start nginx
nginx
[root@server server]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
651ce76dd80f nginx:latest "/docker-entrypoint.…" 21 hours ago Up 1 second 0.0.0.0:80->80/tcp nginx
[root@server server]# docker rm nginx
Error response from daemon: You cannot remove a running container 651ce76dd80fa58e3cdf2abeb9c08662bfcf68176738bb3881d0bcb851aa1a11. Stop the container before attempting removal or force remove
[root@server server]# docker stop nginx
nginx
[root@server server]# docker rm nginx
nginx
[root@server server]# docker start nginx
Error response from daemon: No such container: nginx
Error: failed to start containers: nginx
[root@server server]# docker run -p 80:80 -d --name=nginx nginx:latest
e0abbac7464794b5f2fbd328b841aaa83ffeff6c2072324b584cbbee4c68c36f
容器交互¶
在容器中执行命令
$ docker exec -it nginx ls
# 开启一个交互模式的终端,exit退出
$ docker exec -it nginx bash
# 使用root账号进入容器
$ docker exec -it -u root nginx bash
[root@server server]# docker exec -it nginx ls
bin docker-entrypoint.d home media proc sbin tmp
boot docker-entrypoint.sh lib mnt root srv usr
dev etc lib64 opt run sys var
[root@server server]# docker exec -it nginx echo "test"
test
[root@server server]# docker exec -it nginx bash
root@ad4c10c7cec2:/# ls
bin dev docker-entrypoint.sh home lib64 mnt proc run srv tmp var
boot docker-entrypoint.d etc lib media opt root sbin sys usr
root@ad4c10c7cec2:/# exit
exit
[root@haiyong haiyong]#
复制文件
# 将容器文件拷贝到主机
$ docker cp nginx:/etc/hosts hosts
# 将主机文件拷贝到容器中
$ docker cp hosts nginx:/etc/hosts
Dockerfile语法指令及Docker镜像构建¶
在工作中,通常会根据项目需要制作镜像,Docker可以通过读取Dockerfile文件中的指令来自动构建镜像,Dockerfile文本文件包含镜像构建的命令,通过 docker build
执行 Dockerfile中的一系列指令来自动构建镜像。除了Dockerfile的方式外,也可以使用Docker commit来制作镜像,本文将介绍Dockerfile语法Docker镜像的构建方法。
常用Dockerfile指令¶
Dockerfile官方文档:https://docs.docker.com/engine/reference/builder/
Docker 顺序执行Dockerfile文件中的指令,指令不区分大小写,为了区分,建议都大写。Dockerfile以 FROM
指令开始,FROM指令指定了构建的父镜像(基础镜像),Dockerfile使用 #
注释行,下面列出其它常用指令:
COPY:从本地复制文件,复制文件或者目录到容器里指定路径
ADD:可以从网络或者本地复制,将主机构建环境(上下文)目录中的文件和目录、以及一个URL标记的文件拷贝到镜像中,tar类型文件会自动解压。当需要从远程复制文件时,最好使用 curl 或 wget 命令来代替 ADD 命令。
LABEL:为镜像生成元数据标签信息
WORKDIR:指定工作目录,为后续的RUN、CMD、 ENTRYPOINT、ADD指令配置工作目录。
USER:指定运行容器时的用户名或UID,后续命令执行也会使用指定用户。
RUN:Dockerfile RUN命令是执行命令的核心部分,在
docker build
时执行。它接受命令作为参数并用于创建镜像。每条RUN命令在当前基础镜像上执行,并且会提交一个新镜像层:RUN pip install flask
CMD:容器运行
docker run
时执行的默认命令。ENV:容器启动的环境变量。
ARG:构建环境的环境变量。
ENTRYPOINT:指定容器的“入口”。
HEALTHCHECK:用于指定某个程序或者指令来监控 docker 容器服务的运行状态
Dockerfile构建容器¶
常用文件、命令:
.dockerignore:设置希望构建时需要忽略的文件,过滤指定文件
docker build -f Dockerfile文件名
:指定Dockerfile文件docker build -t 标签
:添加标签docker build --no-cache
:不使用缓存,也就是每次构建时,不管有没有安装过都进行重新构建docker build --build-arg
:传递ARG指令变量
1. 创建Dockerfile文件¶
构建一个dockerfile文件,定制一个Nginx镜像,添加容器健康检查。 Dockerfile:
# 基于 nginx:latest 镜像构建
FROM nginx:latest
# 指定信息
LABEL maintainer="test_dockerfile"
# 设置环境变量
ENV NGINX_VERSION latest
ARG workpath=/data/html/
# 切换root用户
USER root
# 执行命令,安装cur软件,设置软链接把ngin服务的日志显示到终端
RUN apt-get -yq update && apt-get install -y curl && \
ln -sf /dev/stdout /var/log/nginx/access.log && \
ln -sf /dev/stderr /var/log/nginx/error.log
# 挂载卷
VOLUME ["/data"]
# 设置工作目录
WORKDIR $workpath
# 复制 index.html 文件到nginx的html目录下
COPY index.html /usr/share/nginx/html
# 映射80端口
EXPOSE 80
# 此处CMD作为 ENTRYPOINT的参数。
CMD ["nginx","-g","daemon off;"]
# CMD ["-g","daemon off;"]
# CMD nginx -g daemon off
# 设置容器启动的命令
ENTRYPOINT ["nginx","-g","daemon off;"]
STOPSIGNAL SIGRTMAX
# 检查容器健康,通过访问 Nginx服务80端口,来判断容器服务是否健康
HEALTHCHECK --interval=5s --timeout=3s \
CMD curl -fs http://localhost/ || exit 1
index.html文件内容:
<h1>Hello World !</h1>
2. 构建镜像:docker build¶
在Dockerfile 文件目录下执行构建:
$ docker build -t nginx:testv1 -f Dockerfile .
nginx:testv1:镜像名称:镜像标签
Dockerfile:Dockerfile 文件名,默认文件名为Dockerfile
.
表示当前目录,代表本次执行的上下文路径
[root@server test_dockerfile]# pwd
/root/docker/test_dockerfile
[root@server test_dockerfile]# ls
Dockerfile index.html
[root@server test_dockerfile]# docker build -t nginx_demo:v1 .
Sending build context to Docker daemon 4.096kB
Step 1/13 : FROM nginx:latest
---> f6d0b4767a6c
Step 2/13 : LABEL maintainer="test_dockerfile"
---> Running in 6c4b611a19e9
Removing intermediate container 6c4b611a19e9
---> 6a6f12ed39ad
Step 3/13 : ENV NGINX_VERSION latest
---> Running in e9cfc405af5a
Removing intermediate container e9cfc405af5a
---> 6608a514dc4a
Step 4/13 : ARG workpath=/data/html/
---> Running in 31ec17310301
Removing intermediate container 31ec17310301
---> 04b7f5b51c63
Step 5/13 : USER root
---> Running in 1d6aaf7f9d13
Removing intermediate container 1d6aaf7f9d13
---> 3568d2cf3a36
Step 6/13 : RUN apt-get install -y curl && ln -sf /dev/stdout /var/log/nginx/access.log && ln -sf /dev/stderr /var/log/nginx/error.log
---> Running in fcf7a55bbb4a
Reading package lists...
Building dependency tree...
Reading state information...
curl is already the newest version (7.64.0-4+deb10u1).
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.
Removing intermediate container fcf7a55bbb4a
---> 20cb644a11c3
Step 7/13 : VOLUME ["/data"]
---> Running in ebaa3b7e6dbf
Removing intermediate container ebaa3b7e6dbf
---> 246093dbcc45
Step 8/13 : WORKDIR $workpath
---> Running in 494a62d4166b
Removing intermediate container 494a62d4166b
---> 2afb818a2a35
Step 9/13 : COPY index.html /usr/share/nginx/html
---> 1fee5e32c1fc
Step 10/13 : EXPOSE 80
---> Running in 2a80075b76f3
Removing intermediate container 2a80075b76f3
---> 3ef9846b592e
Step 11/13 : CMD ["nginx","-g","daemon off;"]
---> Running in db5ab895a85b
Removing intermediate container db5ab895a85b
---> 4e70e4e4ef95
Step 12/13 : STOPSIGNAL SIGRTMAX
---> Running in d7ceb8fdbd59
Removing intermediate container d7ceb8fdbd59
---> 68c8bb3b43f9
Step 13/13 : HEALTHCHECK --interval=5s --timeout=3s CMD curl -fs http://localhost/ || exit 1
---> Running in 3cb2690c7c13
Removing intermediate container 3cb2690c7c13
---> e20cc62ae3e5
Successfully built e20cc62ae3e5
Successfully tagged nginx_demo:v1
查看镜像:
[root@server test_dockerfile]# docker images | grep nginx_demo
nginx_demo v1 adfe6b7f7297 5 minutes ago 133MB
3. 运行镜像:docker run¶
[root@server test_dockerfile]# docker run -d --name=nginx-test -p 8080:80 nginx_demo:v1
b0bd21087663 nginx_demo:v1 "/docker-entrypoint.…" 6 minutes ago Up 6 minutes (unhealthy) 80/tcp admiring_swanson
[root@server test_dockerfile]#
docker ps 查看容器
[root@server test_dockerfile]# docker ps | grep nginx_demo
710628d0ad55 nginx_demo:v1 "/docker-entrypoint.…" 2 minutes ago Up 2 minutes (unhealthy) 0.0.0.0:8080->80/tcp nginx-test
[root@server test_dockerfile]#
浏览器输入:192.168.30.8:8080
可以进入容器查看设置的环境变量
[root@server test_dockerfile]# docker exec -it 710628d0ad55 bash
root@b0bd21087663:/data/html#
root@b0bd21087663:/data/html#
root@b0bd21087663:/data/html# pwd
/data/html
root@b0bd21087663:/data/html# ls
index.html
root@b0bd21087663:/data/html# env
HOSTNAME=b0bd21087663
PWD=/data/html
PKG_RELEASE=1~buster
HOME=/root
NJS_VERSION=0.5.0
TERM=xterm
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NGINX_VERSION=latest
_=/usr/bin/env
root@b0bd21087663:/data/html# id
uid=0(root) gid=0(root) groups=0(root)
root@b0bd21087663:/data/html# df -h
Filesystem Size Used Avail Use% Mounted on
overlay 45G 22G 24G 48% /
tmpfs 64M 0 64M 0% /dev
tmpfs 910M 0 910M 0% /sys/fs/cgroup
shm 64M 0 64M 0% /dev/shm
/dev/mapper/centos-root 45G 22G 24G 48% /data
tmpfs 910M 0 910M 0% /proc/asound
tmpfs 910M 0 910M 0% /proc/acpi
tmpfs 910M 0 910M 0% /proc/scsi
tmpfs 910M 0 910M 0% /sys/firmware
root@b0bd21087663:/data/html#
Docker commit¶
Docker commit一般用做从一个运行状态的容器来创建一个新的镜像,对外不可解释,不知道容器有什么应用,不方便排查问题,可维护性差。Dockerfile的方式更容易排查问题。
Docker commit构建命令:
$ docker commit 容器名 新镜像名:tag
对于上面构建的镜像,如果对index.html文件内容修改后重新打包一个镜像,我们可以使用Docker commit来构建:
[root@server ~]# docker commit nginx-test nginx_demo:v2
启动:
[root@server ~]# docker run -d --name=nginx-test2 -p 8080:80 nginx_demo:v2
常用Windows cmd命令¶
本文列出一些常用的 windows cmd命令,使用windows + r
键后输入命令或者打开cmd.exe命令提示符输入,其中cmd命令提示符可以通过使用windows + r
键后输入cmd打开
杀掉进程¶
$ taskkill /im chromedriver.exe /f
# 或者
$ wmic process where name="chromedriver.exe" call terminate
切换盘符目录¶
切换到其它盘
# 方法1
C:\Users\10287>d:
D:\>
# 方法2
C:\Users\10287>cd /d d:
D:\>
设置windows系统时区¶
参考:https://winaero.com/blog/set-time-zone-windows-10/
tzutil /l //查看所有可设置时区
tzutil /g //查看当前时区
tzutil /s "China Standard Time" //设置时区
tzutil /s "China Standard Time_dstoff" //关闭夏令时
打开资源管理器¶
explorer
关机重启¶
shutdown /?
查看帮助信息
关机
shutdown -s -t 60 # 60s 后关机
rononce -p # 15s 后关机
shutdown -s -t 0 # 立即关机
shutdown -p # 立即关机
或者使用wmic命令:
wmic process call create shutdown.exe
重启
shutdown -r -t 60 # 60s 后重启
shutdown -r -t 0 # 立即重启
休眠
shutdown -h
在rononce -p、shutdown -s或者shutdown -r倒计时结束之前执行shutdown -a可以取消关机或者重启操作
按住 shift 并点重启可以使重启后进入 BIOS
windows远程管理¶
mstsc
无法远程复制文件问题:
结束进程rdpclip.exe
重新开启进程:win + r 输入rdpclip.exe
windows计算器¶
calc
打开记事本¶
notepad
打开系统属性窗口¶
sysdm.cpl
打开系统属性窗口后,点击【高级】,可以打开【环境变量】设置系统环境变量
打开控制面板¶
control
打开剪贴板¶
Win10:windows + v
打开屏幕键盘¶
osk
服务设置¶
services.msc
注册表编辑¶
regedt32
任务管理器¶
taskmgr
写字板¶
write
画图板¶
mspaint
防火墙¶
firewall.cpl
其它¶
重置 Windows 10 本地帐户密码:https://support.microsoft.com/zh-cn/help/4028457/windows-10-reset-your-local-account-password
Windows 网络管理命令¶
本文列出一些常用的 Windows 网络管理命令。
ping¶
ping: 测试网络连接情况
-n
:要发送的回显请求数-t
:ping 主机直到中断-i
:生存时间ttl-6
:IPv6
$ ping 192.168.20.8 -n 3
Pinging 192.168.20.8 with 32 bytes of data:
Reply from 192.168.20.8: bytes=32 time<1ms TTL=64
Reply from 192.168.20.8: bytes=32 time<1ms TTL=64
Reply from 192.168.20.8: bytes=32 time<1ms TTL=64
Ping statistics for 192.168.20.8:
Packets: Sent = 3, Received = 3, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 0ms, Maximum = 0ms, Average = 0ms
网络信息查询¶
netstat¶
netstat: 协议统计和当前 TCP/IP 网络连接
-t
列出所有tcp连接-a
:显示所有连接和侦听端口-n
:以数字形式显示地址和端口号-o
:显示进程 ID-p proto
:显示指定的协议的连接,TCP、UDP、TCPv6 或 UDPv6-s
:显示每个协议的统计。默认情况下,显示IP、IPv6、ICMP、ICMPv6、TCP、TCPv6、UDP 和 UDPv6的统计信息,可使用-p
选项指定协议。-e
:显示以太网统计。此选项可以与 -s 选项结合使用。-r
:显示路由信息
$ netstat -ano -p tcp
Active Connections
Proto Local Address Foreign Address State PID
TCP 0.0.0.0:21 0.0.0.0:0 LISTENING 4896
TCP 0.0.0.0:135 0.0.0.0:0 LISTENING 1032
TCP 0.0.0.0:445 0.0.0.0:0 LISTENING 4
TCP 0.0.0.0:902 0.0.0.0:0 LISTENING 10388
TCP 0.0.0.0:912 0.0.0.0:0 LISTENING 10388
TCP 0.0.0.0:1080 0.0.0.0:0 LISTENING 11476
TCP 0.0.0.0:2425 0.0.0.0:0 LISTENING 7728
TCP 0.0.0.0:5040 0.0.0.0:0 LISTENING 7940
TCP 0.0.0.0:5357 0.0.0.0:0 LISTENING 4
查询5037端口占用:
$ netstat -ano | findstr 5037
TCP 0.0.0.0:5037 0.0.0.0:0 LISTENING 34212
找到对应进程(也可以在任务管理器中查看):
$ tasklist | findstr 34212
adb.exe 34212 Console 1 10,692 K
通过PID或者进程名杀死进程:
$ taskkill -pid 34212 -f -t # taskkill /pid 34212 /f /t
$ taskkill -f -im adb.exe # taskkill /f /im adb.exe
网卡信息¶
$ ipconfig
$ ipconfig /all
$ netsh interface ipv4 show config
$ netsh interface ipv6 show config
$ wmic nic list brief
路由配置¶
route add [Destination] mask [netmask] [gw] metric [测量值]
-p:添加永久路由
Destination: 指定该路由的网络目标。
mask:当添加一个网络路由时,需要使用网络掩码。
gw:路由数据包通过网关。注意,你指定的网关必须能够达到。
metric:设置路由跳数。
# ipv4
$ route -p add 23.23.23.0 mask 255.255.255.0 192.168.97.60
route delete 23.23.23.0
# ipv6
$ netsh interface ipv6 add/del route 2001::/64 "Local Area Connection 2" 2001::2
查看路由表¶
$ netstat -r
$ route print
$ route print -4
$ route print -6
$ netsh interface ipv4 show route
$ netsh interface ipv6 show route
禁用启用网卡¶
$ netsh interface set interface eth0 disabled # 禁用网卡
$ netsh interface set interface name="接口名称" admin=DISABLE
$ netsh interface set interface eth0 enabled #启用网卡
$ netsh interface set interface name="接口名称" admin=ENABLE
$ netsh interface ipv6 set interface name="接口名称" disable/enable
$ netsh interface show interface #显示接口
通过python脚本自动化控制:
import os
os.popen('netsh interface set interface name="接口名称" admin=DISABLE')
释放、更新地址¶
# ipv4
$ ipconfig /release
$ ipconfig /renew
# ipv6
$ ipconfig /release6
$ ipconfig /renew6
添加、删除IP地址¶
# ipv4
$ netsh interface ip add address "本地连接" 192.168.1.100 255.255.255.0
$ netsh interface ip delete address "本地连接" 192.168.1.100
## 设置静态IP地址
$ netsh interface ip set address name="eth1" source=static address=192.168.5.125 mask=255.255.255.0
# ipv6
$ netsh interface ipv6 delete address 本地连接 2001::1
$ netsh interface ipv6 add/del address 本地连接 2001::1
常用Windows 快捷键¶
windows 快捷键
打开 cmd¶
当前目录下打开cmd:Windows 文件资源管理器路径栏中输入 cmd
当前目录下打开cmd:在文件夹中,按shift键,点击右键,选择在此处打开cmd
user目录下:Windows+r,然后输入cmd
另外,在文件上shift+右键
会多出来一个 “复制为路径” 选项
cmd 命令窗口中输入start .
会打开处于当前目录的资源管理器
cmd 命令窗口按下 F7
可以显示历史命令记录
搜索¶
win + s
或直接 win键 打开开始菜单后输入名称快捷搜索打开应用和文件
记事本¶
打开,命令窗口输入:
notepad
记事本第一行写上.LOG
:关闭时会在最后一行插入编辑时间
文件资源管理器¶
Windows + e
:打开文件资源管理器
在路径栏输入shell:startup
或者启动
进入启动目录
路径栏输入shell:appsfolder
进入应用程序目录
选中文件ALT + 回车
或者 ALT + 双击文件
:查看文件属性
应用程序窗口¶
关闭Windows自带的程序窗口
点击右上角的叉关闭
双击窗口左上角的图标关闭
ALT + f4
,在桌面按下ALT + f4
会弹出关机菜单ALT + 空格 + c
Windows + ↑↓←→:调整窗口布局
ALT + TAB
:程序窗口切换
Windows + 1234等数字键:按任务栏上的顺序快捷切换窗口
Windows + g
打开Xbox便捷工具,比如截屏、录屏
Windows + d
:显示桌面或恢复桌面
Windows + m
:最小化所有窗口
Windows + Shift + m
:恢复最小化窗口
浏览器¶
清空浏览器缓存:Ctrl+Shift+Delete
VBSscript实现后台运行Windows bat脚本¶
VBScript 是Visual Basic 语言的轻量级版本,本文介绍使用VBS实现在后台运行bat脚本。
先编写一个简单的bat脚本(test_bat.bat):使用Python打开一个简单的 http 服务器
@echo off
echo start
cmd /k "python -m http.server 8100"
echo end
pause
下面来测试一下这个脚本,双击test_bat.bat,会打开如下窗口:
浏览器访问 http://127.0.0.1:8100/
可以看到HTTP服务搭建成功。
也可以使用 netstat
命令查看8100端口对应服务是否启动:
$ netstat -nao | findstr 8100
TCP 0.0.0.0:8100 0.0.0.0:0 LISTENING 17220
TCP 127.0.0.1:1024 127.0.0.1:8100 TIME_WAIT 0
$
$ tasklist | findstr 17220
python.exe 17220 Console 1 18,800 K
如何实现在后台运行呢?可以使用VBScript来实现。
编写vbs文件test_bat.vbs:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "test_bat.bat" & Chr(34), 0
0
表示后台运行,如果设置为1,会显示cmd窗口。
双击test_bat.vbs运行,浏览器访问 http://127.0.0.1:8100/ 查看服务是否启动 或者使用如下命令:
$ netstat -nao | findstr 8100
TCP 0.0.0.0:8100 0.0.0.0:0 LISTENING 1788
$ tasklist | findstr 1788
python.exe 1788 Console 1 18,680 K
可以看到HTTP server启动成功。
杀掉HTTP server:
$ taskkill -pid 1788 -f -t
SUCCESS: The process with PID 1788 (child process of PID 18576) has been terminated.
如果bat脚本需要传入参数怎么实现呢?可以使用WScript.Arguments对象获取参数,下面直接给出实现方式,将端口号作为参数传入:
test_bat2.bat:
@echo off
echo start
python -m http.server %1
echo end
pause
test_bat2.vbs:
dim args
Set args = WScript.Arguments
Set WshShell = CreateObject("WScript.Shell")
WshShell.run "cmd /c " &args(0) &args(1),0
cmd命令窗口运行
$ test_bat2.vbs test_bat2.bat " 8100"
在实际使用过程中,通常不会手动双击运行脚本,比如在自动化测试中,需要自动启动一个tshark抓包程序, 我们只需要它在后台运行。下面举一个Python运行bat脚本的示例程序。
def start_bat(self, port):
"""启动 HTTP server
:port: 服务端口号
"""
self.stop_process(port)
dir_path = os.path.dirname(os.path.realpath(__file__)) # 当前路径
print(dir_path)
os.system(f'{dir_path}/test_bat.vbs "{dir_path}/test_bat.bat" " {port}"')
for l in range(3):
sleep(3)
if self.check_process(port):
print("http server successfully")
return True
print("http server started failed")
return False
完整代码:https://github.com/hiyongz/ShellNotes/blob/main/test_vbs.py
通过bat脚本配置系统环境变量¶
本文介绍使用bat脚本添加系统环境变量
添加PATH环境变量¶
添加PATH环境变量,如果已经存在则不添加。
介绍2种方法来循环搜索路径是否已经存在:
@echo off
echo ---------------------------------------
set pan=%~d0
set filePath=%~p0
set filePath=%pan%%filePath%
echo current path: %filePath%
REM 添加PATH环境变量:如果已经存在则不添加
echo ---------------------------------------
SET add_path=
SET toAdd=D:\software\Nmap
SET MYPATHCOPY=%PATH%
call :search1
echo %add_path%
SET toAdd=C:\Program Files\Go\bin
SET MYPATHCOPY=%PATH%
call :search2
echo %add_path%
echo add the path: %add_path%
call set xx=%Path%;%add_path%
wmic ENVIRONMENT where "name='Path' and username='<system>'" set VariableValue="%xx%"
pause
REM TIMEOUT /T 10
REM 方法1
:search1
for /f "tokens=1* delims=;" %%a in ("%MYPATHCOPY%") do (
if "%toAdd%"=="%%a" (
goto :isFinded
)
set MYPATHCOPY=%%b
goto :search1
)
set add_path=%toAdd%;%add_path%
goto :EOF
REM 方法2
:search2
for /f "delims=; tokens=1,2*" %%p in ("%MYPATHCOPY%") do (
REM @echo %%~p
SET MYPATHCOPY=%%~q;%%~r
if "%toAdd%"=="%%p" (
REM echo %%p
goto :isFinded
)
goto :search2
)
set add_path=%toAdd%;%add_path%
goto :EOF
:isFinded
echo The path already exists: %toAdd%
goto :EOF
新建系统变量¶
1、使用 setx
来设置:
@echo off
set ENV_Path=%PYTHONPATH%
setx /M PYTHONPATH "D:\Anaconda3"
pause
2、使用 wmic
命令设置:
@echo off
::如果存在,先删除PYTHONPATH
wmic ENVIRONMENT where "name='PYTHONPATH'" delete
:: 创建系统变量PYTHONPATH
wmic ENVIRONMENT create name="PYTHONPATH",username="<system>",VariableValue="D:\Anaconda3"
一些windows批处理脚本¶
本文记录一些平时使用到的bat语法。
1. 获取当前目录¶
获取当前路径
@echo off
set DriveLetter=%~d0
echo %DriveLetter%
set filePath=%~p0
echo %filePath%
set filePath=%DriveLetter%%filePath%
echo current path: %filePath%
echo current path: %cd%
pause
执行结果:
D:
\ProgramWorkspace\ShellNotes\Windows\
current path: D:\ProgramWorkspace\ShellNotes\Windows\
current path: D:\ProgramWorkspace\ShellNotes\Windows
2. 获取目录中的文件和子目录¶
可以使用 dir
命令来获取某个目录下的文件或者子目录文件,使用 dir /?
命令查看帮助文档。
下面介绍几种使用方法:
# 显示当前目录下的文件、子目录以及子目录下的文件
dir /a /b /s
# 只显示当前目录下的文件
dir /b /a-d
# 从大到小排序
dir /b /a-d /o-s
# 显示后缀为bat的文件
dir /b /a-d /o-s *.bat
bat脚本打印当前目录下的bat文件:
@echo off
for /f "delims=\" %%a in ('dir /b /a-d /o-s "%cd%\*.bat"') do (
echo %%a
)
pause
3. 读取配置文件¶
创建一个配置文件 config.ini
:
host=192.168.0.1
port=8100
读取host和port的值:
@echo off
:: 读取配置
for /f "tokens=1,2 delims==" %%a in (config.ini) do (
if %%a==host set host=%%b
if %%a==port set port=%%b
)
echo host: %host%
echo port: %port%
pause
运行结果:
host: 192.168.0.1
port: 8100
4. 清空文件内容¶
清空 test.log 文件中的内容:
cd.>test.log
linux shell清空文件内容方法参考Linux常用命令:文件操作命令
5. 打印换行¶
使用 echo.
打印换行:
@echo off
echo hello
echo.
echo world
pause
6. 设置窗口显示颜色¶
语法:
COLOR [attr]
颜色属性 attr 可用于设置背景和前景的设置,可以设置的颜色:
0 = 黑色
1 = 蓝色
2 = 绿色
3 = 浅绿色
4 = 红色
5 = 紫色
6 = 黄色
7 = 白色
8 = 灰色
9 = 淡蓝色
A = 淡绿色
B = 淡浅绿色
C = 淡红色
D = 淡紫色
E = 淡黄色
F = 亮白色
例如设置窗口为白色背景,红色文字:
@echo off
color 74
echo Hello world !
pause
效果:
关注公众号【测试开发小记】及时接收最新技术文章!
