3、自动化

脚本信号

信号基础

基础知识

简介

	当我们在构建一些更高级的脚本的时候,就会涉及到如何在linux系统上来更好的运行和控制它们,到目前为止,我们运行脚本的方式都是以实时的模式,在命令行来运行它。但是这并不是脚本唯一的运行方式,我们可以在linux系统中以更丰富的方式来运行它们,甚至在脚本遇到不可查的异常中止时候,以关闭linux终端界面的方式终止脚本。
	这些能力都是基于信号的机制来实现了

信号

	linux使用信号与系统上运行的进程进行通信,想要对shell的脚本控制,只需要传递相关信号给shell脚本即可。
信号 描述
1 SIGHUP 挂起进程
2 SIGINT 终止进程
3 SIGQUIT 停止进程
9 SIGKILL 无条件终止进程
15 SIGTERM 优雅的终止进程
17 SIGSTOP 无条件停止进程,不终止进程
18 SIGTSTP 停止或暂停进程,不终止进程
19 SIGCONT 继续运行停止的进程
    默认情况下,bash shell会忽略收到的任何SIGQUIT(3)和SIGTERM(15)信号(正因为这样交互式shell才不会被意外终止)。但是bash shell会处理收到的SIGHUP(1)和SIGINT(2)信号。

    如果bash shell收到SIGHUP信号,它会退出。但在退出之前,它会将信号传给shell启动的所有进程(比如shell脚本)。通过SIGINT信号,可以中断shell,Linux内核停止将CPU的处理时间分配给shell,当这种情况发生时,shell会将SIGINT信号传给shell启动的所有进程。

生成信号

终止进程:
	ctrl+c,
暂停进程:
	ctrl+z,停止的进程继续保留在内存中,并能从停止的位置继续运行
恢复进程:
	jobs查看运行任务,fg num 重新执行
杀死进程:
	kill -9 pid

简单实践

实践1-终止进程

[root@localhost ~]# sleep 1000
^C
[root@localhost ~]#

实践2-挂起进程

[root@localhost ~]# sleep 1000
^Z
[1]+  已停止               sleep 1000
[root@localhost ~]# ps aux  | grep sleep
root      39067  0.0  0.0 108052   360 pts/0    T    17:28   0:00 sleep 1000

实践3-恢复进程

查看所有挂起进程
[root@localhost ~]# jobs
[1]+  已停止               sleep 1000

恢复挂起进程的id
[root@localhost ~]# fg 1
sleep 1000
^C
[root@localhost ~]#

image

实践4-杀死进程

后台执行命令
[root@localhost ~]# sleep 1000 &
[1] 39074
[root@localhost ~]# ps aux  | grep sleep | grep -v grep
root      39074  0.0  0.0 108052   360 pts/0    S    17:30   0:00 sleep 1000

强制杀死进程
[root@localhost ~]# kill -9 39074
[root@localhost ~]#
[1]+  已杀死               sleep 1000
[root@localhost ~]# jobs

image

信号捕捉

基础知识

简介

	shell编程提供了一种方式,让我们可以随意的控制脚本的运行状态,这就需要涉及到信号的捕获操作。在shell编程中,我们可以借助于 trap命令实现指定shell脚本要watch哪些linux信号并从shell中拦截。如果脚本收到了trap命令中列出的信号,它会阻止它被shell处理,而在本地处理。

trap 命令格式

命令格式
	trap commands signals
	
命令示例:
	# 收到指定信号后,执行自定义指令,而不会执行原操作
    trap '触发指令' 信号
     
    # 忽略信号的操作
    trap '' 信号

    # 恢复原信号的操作,上一步指令
    trap '-' 信号
    
    # 列出自定义信号操作
    trap -p
    
    # 当脚本退出时,执行finish函数
    trap finish EXIT

简单实践

实践1-捕获终止信号

查看脚本内容
[root@localhost ~]# cat signal_trap_test1.sh
#!/bin/bash
# 功能:脚本信号捕捉

# 捕获关闭信号
trap "你敢关我,就不关,气死你" SIGINT SIGTERM
trap "走了,不送" EXIT

# 检测逻辑效果
while true
do
    read -p "请输入一个数据:" value
    echo "您输入的数据是: ${value}"
done
脚本执行效果
[root@localhost ~]# /bin/bash signal_trap_test1.sh
请输入一个数据:4
您输入的数据是: 4
请输入一个数据:^Csignal_trap_test1.sh:行1: 你敢关我,就不关,气死你: 未找到命令

您输入的数据是:
请输入一个数据:^Z
[1]+  已停止               /bin/bash signal_trap_test1.sh
[root@localhost ~]#
[root@localhost ~]# jobs
[1]+  已停止               /bin/bash signal_trap_test1.sh
[root@localhost ~]# fg 1
/bin/bash signal_trap_test1.sh

您输入的数据是:
请输入一个数据:3
您输入的数据是: 3
另开一个终端,直接kill进程
[root@localhost ~]# ps aux | grep sign
root      39142  0.0  0.0 113288  1460 pts/0    S+   17:43   0:00 /bin/bash signal_trap_test1.sh
[root@localhost ~]# kill -9 39142

回到之前的终端查看效果
[root@localhost ~]# fg 1
/bin/bash signal_trap_test1.sh

您输入的数据是:
请输入一个数据:3
您输入的数据是: 3
请输入一个数据:已杀死

实践2-捕获正常退出

查看脚本内容
[root@localhost ~]# cat signal_trap_test2.sh
#!/bin/bash
# 功能:脚本信号捕捉

# 捕获关闭信号
trap "echo '走了.不送'" EXIT

value="0"
# 检测逻辑效果
while true
do
    read -p "请输入一个数据:" value
    if [ ${value} == "9" ]
    then
        exit
    else
        echo "您输入的数据是: ${value}"
    fi
done
脚本执行效果
[root@localhost ~]# /bin/bash signal_trap_test2.sh
请输入一个数据:3
您输入的数据是: 3
请输入一个数据:9
走了.不送

image

实践3-移除捕获

查看脚本内容
[root@localhost ~]# cat signal_trap_test3.sh
#!/bin/bash
# 功能:移除脚本信号捕捉

# 捕获关闭信号
trap "echo '走了.不送'" EXIT

i=1
# 检测逻辑效果
while [ $i -le 3 ]
do
    read -p "请输入一个数据:" value
    if [ ${value} == "9" ]
    then
        exit
    else
        echo "您输入的数据是: ${value}"
    fi
    let i+=1
done

# 移除捕获信号
trap - EXIT
echo "移除了捕获信号"
脚本执行效果
[root@localhost ~]# /bin/bash signal_trap_test3.sh
请输入一个数据:9
走了.不送
[root@localhost ~]# /bin/bash signal_trap_test3.sh
请输入一个数据:1
您输入的数据是: 1
请输入一个数据:2
您输入的数据是: 2
请输入一个数据:3
您输入的数据是: 3
移除了捕获信号

结果显示:
	在没有走到信号捕获移除的时候,捕获仍然生效

expect基础

基础知识

场景需求

在日常工作中,经常会遇到各种重复性的"手工交互"操作,虽然没有什么技术含量,但是相当的重要。在实际的工作场景中,这种重复性的手工操作动作,非常的繁多,但是对于量大的工作来说,效率就非常低效了。所以我们就需要有一种工具,能够简化我们重复的手工操作。

expect简介

expect是一个免费的编程工具,由DonLibes制作,作为Tcl脚本语言的一个扩展,它可以根据程序的提示,模拟标准输入提供给程序,从而实现自动的交互式任务,而无需人为干预,可以用作Unix系统中进行应用程序的自动化控制和测试的软件工具。

说白了,expect就是一套用来实现自动交互功能的软件。它主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。在使用的过程中,主要是以脚本文件的样式来存在

官方网站:
	https://www.nist.gov/services-resources/software/expect
工具手册:
	man expect

软件部署

安装软件
[root@localhost ~]# yum install expect -y

查看效果
[root@localhost ~]# expect -v
expect version 5.45
进入专用的命令交互界面
[root@localhost ~]# expect
expect1.1>  ls
anaconda-ks.cfg
expect1.2> exit
命令帮助
    -c:	执行脚本前先执行的命令,可多次使用,多个命令之间使用;隔开
    -d:	debug模式,可以在运行时输出一些诊断信息,与在脚本开始处使用exp_internal 1相似。
    -D:	启用交换调式器,可设一整数参数。
    -f:	从文件读取命令,仅用于使用#!时。如果文件名为"-",则从stdin读取(使用"./-"从文件名为-的文件读取)。
    -i:	交互式输入命令,使用"exit"或"EOF"退出输入状态。
    --:	标示选项结束(如果你需要传递与expect选项相似的参数给脚本时),可放到#!行:#!/usr/bin/expect --。
    -v:	显示expect版本信息

简单实践

语法解读

	在进行expect脚本编写的时候,我们需要记住 -- expect 用的不是我们普通的shell或者python语法,它使用的是tlc语法。

	Tcl 全称是 Tool command Language。它是一个基于字符串的命令语言,基础结构和语法非常简单,易于学习和掌握。Tcl 语言是一个解释性语言,所谓解释性是指不象其他高级语言需要通过编译和联结,它象其他 shell 语言一样,直接对每条语句顺次解释执行。

	Tcl 数据类型简单。对 Tcl 来说,它要处理的数据只有一种——字符串。Tcl 将变量值以字符串的形式进行存储,不关心它的实际使用类型。

输出语法

输出:tcl使用”puts"关键字来作为输出语句
样式:puts <-nonewline> string
属性解析:
	如果string中间有特殊字符,可以使用 {} 或者 "" 将其作为一个小组,共同输出
	-nonewline 代表输出结果的时候,不输出换行符
	put 和 puts 都可以在命令行使用,但是脚本中,最好用puts
[root@localhost ~]# expect
expect1.1> puts hello				# 输出一个字符串内容
hello
expect1.2> puts "hello world"		# 输出包含特殊字符的字符串,不能用单引号
hello world
expect1.3> puts {hello world}		# 输出包含特殊字符的字符串
hello world
expect1.4> puts -nonewline "hello world"  # 输出内容的时候,不换行
hello worldexpect1.5>

image

脚本基础

1 文件名后缀   
	.expect 作为标识符
2 文件首行,要指定命令的执行解释器 
	#!/usr/bin/expect
3 脚本文件的执行
	expect 脚本名
脚本内容示例
[root@localhost ~]# cat expect_test.expect
#!/usr/bin/expect
# 设定一个环境变量
set var nihao
# 输出环境变量
puts $var

脚本执行效果
[root@localhost ~]# expect expect_test.expect
nihao

image

语法实践

基础知识

赋值语法

赋值:tcl 使用“set”关键字来定义参数,不必指定变量值的类型,因为变量值的类型仅一种——字符串
样式:set varName [value] 
注意:
	变量名是由 数字、下划线、字符组成,数字不能开头,大小写敏感。
expect1.7> set a Hello			# 设定一个变量名a
Hello
expect1.8> put $a				# 使用$ 符号获取变量名的存储值
Hello
expect1.9> put "$a"				# 使用 "" 方式打印变量的值
Hello
expect1.10> put {$a}			# {} 有别于"" 的特点在于原字符输出
$a
expect1.11> set b $a			# 变量的传递
Hello
expect1.12> puts $b
Hello

image

替换语法

替换(解析):
	- $符号可以实现引用替换,用于引用变量名代替的参数值,但是TCL对嵌套的”$”不于理睬
	- [] 方括号“[]”完成命令替换。用“[]”将一条命令括起来,命令执行完成后,返回结果
expect1.20> set b [set a 5]					# 相当于 set b $a,传递赋值
5
expect1.21> puts $b
5
expect1.22> set c [expr 5 * 10 ]			# expr是执行系统命令,将计算结果交给c
50
expect1.24> puts $c
50

image

注意事项

变量的设定
expect1.13> set var value					# 设定一个普通变量名
value
expect1.14> puts $var						# 获取变量名的值
value

不支持嵌套$
expect1.15> set var1 $$value				# TCL不支持嵌套的$
can't read "value": no such variable
    while executing
"set var1 $$value"
expect1.16> set var1 $$var					# 由于$var 已经是变量,所以前面的$就无效了
$value
expect1.17> puts $var1
$value

原字符输出
expect1.18> set var2 {$var1}				# {} 代表原字符输出
$var1
expect1.19> puts $var2
$var1

image

脚本实践

内置变量

对于tcl来说,它内部包含了大量的内置变量,可以让我们实现快速的功能操作。

常见的内置变量有:
	argc	指命令行参数的个数。等同于 $#
	argv	指包含命令行参数的列表。等同于 $@  $*
	argv0	是指被解释的文件或由调用脚本的名称的文件名。 等同于  $0
	env		用于表示是系统环境变量的内容,普通变量我们还是使用$即可 $env()
	tcl_version	返回Tcl解释器的最新版本,注意不是expect的版本号

内置参数实践

[root@localhost ~]# cat expect_test1.expect
#!/usr/bin/expect
# 查看当前文件传递的参数数量
puts "当前文件传递的参数数量: $argc"

# 查看当前文件传递的参数
puts "当前文件传递的参数: $argv"

# 查看当前文件名称
puts "当前文件名称: $argv0"

# 获取变量值
puts "当前系统变量PATH的值是: $env(PATH)"
set key value
puts "普通变量 key 的值是: $key"

# 查看版本信息
puts "当前tcl版本信息: $tcl_version"
脚本执行效果
[root@localhost ~]# expect expect_test1.expect
当前文件传递的参数数量: 0
当前文件传递的参数:
当前文件名称: expect_test1.expect
当前系统变量PATH的值是: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
普通变量 key 的值是: value
当前tcl版本信息: 8.5

expect交互基础

脚本基础

命令解释器

命令解释器
#!/usr/bin/expect
#!/usr/bin/expect -f    从文件中读取自动化命令
#!/usr/bin/expect -     如果文件名为 - ,那么从终端输入中读取
#!/usr/bin/expect -i	交互式输入命令
#!/usr/bin/expect -- 	脚本传递的选项参数和expect选项相似的参数给脚本
注意:
	#!是对脚本的解释器程序路径,脚本的内容是由解释器解释的
	
注释信息
# 被注释的信息

常见符号

{ }:
	作用1:保留所有字符原有的意思,而不做解释,类似于shell中的单引号
		样式:set var {"nihao hehehe"}
	作用2:代码块儿,但是两个 {} 边界必须在一起。
		正确样式:
		if {代码块1 } {
   			代码块2
			}
		错误示例:
		if {$count < 0}
        {
           break;
        }
	注意:
		无论什么时候,{}边界符号与其他内容都最好有空格隔开,尤其是边界外的内容
[]:
	作用:执行命令,类似shell中的 ``(反引号)或者 $()
	样式:set count [expr $count - 1 ]
	
注意:
	在expect 中,没有小括号的概念和应用

常用命令

set 		设定环境变量
				格式:set 变量名 变量值
				样式:set host "192.168.8.12"

				
spawn 		启动新的进程,模拟手工在命令行启动服务
				格式:spawn 手工执行命令
				样式:spawn ssh python@$host

expect 		接收一个新进程的反馈信息,我们根据进程的反馈,再发送对应的交互命令
				格式:expect "交互界面用户输入处的关键字"
				样式:expect "*password*"
				
send 		接收一个字符串参数,并将该参数发送到新进程。
				格式:send "用户输入的信息"	
				样式:send "$password\r"
				
interact 	退出自动化交互界面,进入用户交互状态,如果需要用户交互的话,这条命令必须在最后一行
				格式:interact
				样式:interact
				
其他命令
	exit		退出expect脚本
	expect eof	expect执行内容的结束标识符,退出当前脚本,与interact只能存在一个
	puts		输出变量的信息,相当于linux命令中的echo
	wait		退出程序后,等待时间,回收僵尸进程
	disconnect	断开一个进程连接,但让它在后台继续运行。
	exp_continue 	expect获取期望后,还会有另外的期望,那么我们就把多个期望连续执行

简单实践

实践1-简单的登录交互脚本

查看脚本内容
[root@localhost ~]# cat login_test.expect
#!/usr/bin/expect

# 1 设定环境变量
set username python

# 2 发起远程登录请求
spawn ssh $username@10.0.0.12

# 3 识别用户输入的位置关键字
expect "yes/no"

# 4 发送正确的信息
send "yes\r"

# 5 识别密码关键字,并传递密码信息
send "\r"
expect "password:"
send "123456\r"

# 6 切换回用户交互界面
interact

注意:
	由于password前面会涉及到一次Enter操作,所以在password匹配前,输入一次 \r
清理历史记录
[root@localhost ~]# rm -f .ssh/know_hosts

执行脚本内容
[root@localhost ~]# expect login_test.expect
spawn ssh python@10.0.0.12
The authenticity of host '10.0.0.12 (10.0.0.12)' can't be established.
ECDSA key fingerprint is SHA256:XUJsgk4cTORxdcswxIKBGFgrrqFQzpHmKnRRV6ABMk4.
ECDSA key fingerprint is MD5:71:74:46:50:3f:40:4e:af:ad:d3:0c:de:2c:fc:30:c0.
Are you sure you want to continue connecting (yes/no)? yes

Warning: Permanently added '10.0.0.12' (ECDSA) to the list of known hosts.
python@10.0.0.12's password:
[python@localhost ~]$ id
uid=1000(python) gid=1000(python) 组=1000(python)

实践2-脚本结合

expect 除了使用专用的expect脚本来实现特定功能之外,它还可以与其他脚本嵌套在一起进行使用。最常用的结合方式就是 shell结合。

在于shell结合使用的时候,无非就是将expect的执行命令使用 <<-EOF  。。。 EOF 包装在一起即可。
样式:
/usr/bin/expect<<-EOF
spawn ...
...
expect eof 
EOF

注意:
	由于expect在shell中是作为一个子部分而存在的,所以,一般情况下,expect结束的时候,使用eof命令表示expect的内容到此结束
查看脚本内容
[root@localhost ~]# cat expect_auto_login.sh
#!/bin/bash
# 功能:shell自动登录测试
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 定制普通变量
host="$1"
username="$2"
password="$3"

/usr/bin/expect <<-EOF
# 发出连接进程
spawn ssh ${username}@${host}

# - 正常登陆
expect {
    "yes/no*" {  send "yes\n"; exp_continue  }
    "password:" {send "${password}\n";}
}
puts "测试完毕!!!"
expect eof
EOF
脚本测试效果
[root@localhost ~]# /bin/bash expect_auto_login.sh 10.0.0.12 python 123456
spawn ssh python@10.0.0.12
python@10.0.0.12's password: 测试完毕!!!

[python@localhost ~]$ exit
[root@localhost ~]#

综合案例

基础知识

简介

	当系统配置完毕后,我们可以采用fdisk命令对额外的磁盘进行磁盘分区。而expect可以实现这个效果。

手工演示

[root@localhost ~]# fdisk /dev/sdc
欢迎使用 fdisk (util-linux 2.23.2)。

更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。

Device does not contain a recognized partition table
使用磁盘标识符 0x17fc4c8a 创建新的 DOS 磁盘标签。

命令(输入 m 获取帮助):n					# 输入n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p				 # 输入p
分区号 (1-4,默认 1):					# 输入 Enter
起始 扇区 (2048-41943039,默认为 2048):# 输入 Enter
将使用默认值 2048
Last 扇区, +扇区 or +size{K,M,G} (2048-41943039,默认为 41943039):# 输入Enter
将使用默认值 41943039
分区 1 已设置为 Linux 类型,大小设为 20 GiB

命令(输入 m 获取帮助):wq				# 输入wq
The partition table has been altered!

Calling ioctl() to re-read partition table.
正在同步磁盘。
[root@localhost ~]# mkfs -t ext4 /dev/sdc
mke2fs 1.42.9 (28-Dec-2013)
/dev/sdc is entire device, not just one partition!
无论如何也要继续? (y,n) y
文件系统标签=
OS type: Linux
块大小=4096 (log=2)
分块大小=4096 (log=2)
Stride=0 blocks, Stripe width=0 blocks
1310720 inodes, 5242880 blocks
262144 blocks (5.00%) reserved for the super user
第一个数据块=0
Maximum filesystem blocks=2153775104
160 block groups
32768 blocks per group, 32768 fragments per group
8192 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
        4096000

Allocating group tables: 完成
正在写入inode表: 完成
Creating journal (32768 blocks): 完成
Writing superblocks and filesystem accounting information: 完成

[root@localhost ~]# mkdir /haha
[root@localhost ~]# mount /dev/sdc /haha
[root@localhost ~]# echo nihao > /haha/h.txt
[root@localhost ~]# ls /haha
h.txt  lost+found

脚本实践

查看脚本内容
[root@localhost ~]# cat expect_auto_partition.sh
#!/bin/bash
# 功能:shell自动磁盘分区格式化测试
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 定制普通变量
mount_dir='/disk_check'

# 检测基本环境
[ -f /usr/bin/expect ] && echo "expect 环境正常" || ("expect 环境异常" && exit)

# 查看磁盘列表
fdisk -l | grep "磁盘 /dev/s"

# 定制磁盘分区操作
read -p "请输入需要挂载得硬盘路径: " disk_name
	
# expect自动分区操作
/usr/bin/expect << EOF
set timeout 30
spawn bash -c "fdisk ${disk_name}"
expect "命令*" {send "n\r"} 
expect "*default p*" {send "p\r"}
expect "*默认 1*" {send "\r"}
expect "起始 扇区*" {send "\r"}
expect "Last 扇区*" {send "\r"}
expect "命令*" {send "wq\r"} 
expect eof
interact	
EOF

# expect自动格式化操作
read -p "请输入硬盘的类型: " disk_type
/usr/bin/expect << EOF
set timeout 30
spawn bash -c "mkfs -t ${disk_type} ${disk_name}"
expect "*y,n*" {send "y\r"} 
expect eof
interact	
EOF

# 磁盘挂载测试
[ -d ${mount_dir} ] && rm -rf ${mount_dir} 
mkdir ${mount_dir}
mount ${disk_name} ${mount_dir}
echo disk_check > ${mount_dir}/check.txt
[ -f ${mount_dir}/check.txt ] && echo "${mount_dir} 挂载成功" || (echo "${mount_dir} 挂载失败" && exit)
umount ${mount_dir}
[ ! -f ${mount_dir}/check.txt ] && echo "${mount_dir} 卸载成功" || (echo "${mount_dir} 卸载失败" && exit)
rm -rf ${mount_dir}

创建用户实践

案例需求

	借助于expect实现在特定的主机上批量创建用户

脚本实践

查看脚本内容
[root@localhost ~]# cat expect_auto_register.sh
#!/bin/bash
# 功能:shell自动远程主机创建用户测试
# 版本:v0.1
# 作者:书记
# 联系:www.superopsmsb.com

# 定制初始变量
login_user='root'
login_pass='123456'
host_file='ip.txt'
new_user='shuji-1'
new_pass='123456'

# 批量创建用户
cat ${host_file} | while read ip
do
    expect <<-EOF
        set timeout 30
        spawn ssh $login_user@$ip
        expect {
            "yes/no" { send "yes\n";exp_continue }
            "password" { send "${login_pass}\n" }
        }

        expect "]#" { send "useradd ${new_user}\n" }
        expect "]#" { send "echo ${new_pass} |passwd --stdin ${new_user}\n" }
        expect "]#" { send "who\n" }
        expect "]#" { send "exit\n" }
        expect eof
	EOF
done
脚本执行后效果
[root@localhost ~]# /bin/bash expect_auto_register.sh
spawn ssh root@10.0.0.12
root@10.0.0.12's password:
[root@localhost ~]# useradd shuji-1
[root@localhost ~]# echo 123456 |passwd --stdin shuji-1
更改用户 shuji-1 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# who
root     pts/1        2022-06-26 08:47 (10.0.0.12)
root     pts/2        2022-06-26 07:15 (10.0.0.1)
[root@localhost ~]# exit
登出
Connection to 10.0.0.12 closed.
spawn ssh root@10.0.0.13
The authenticity of host '10.0.0.13 (10.0.0.13)' can't be established.
ECDSA key fingerprint is SHA256:XUJsgk4cTORxdcswxIKBGFgrrqFQzpHmKnRRV6ABMk4.
ECDSA key fingerprint is MD5:71:74:46:50:3f:40:4e:af:ad:d3:0c:de:2c:fc:30:c0.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '10.0.0.13' (ECDSA) to the list of known hosts.
root@10.0.0.13's password:
Last login: Sun Jun 26 07:16:20 2022 from 10.0.0.1
[root@localhost ~]# useradd shuji-1
[root@localhost ~]# echo 123456 |passwd --stdin shuji-1
更改用户 shuji-1 的密码 。
passwd:所有的身份验证令牌已经成功更新。
[root@localhost ~]# who
root     tty1         2022-06-25 23:57
root     pts/0        2022-06-26 08:47 (10.0.0.12)
root     pts/1        2022-06-26 07:16 (10.0.0.1)
[root@localhost ~]# exit
登出
Connection to 10.0.0.13 closed.
校验用户创建
[root@localhost ~]# id shuji-1
uid=1001(shuji-1) gid=1001(shuji-1) 组=1001(shuji-1)
[root@localhost ~]# ssh root@10.0.0.13 id shuji-1
root@10.0.0.13's password:
uid=1001(shuji-1) gid=1001(shuji-1) 组=1001(shuji-1)
posted @ 2023-01-16 22:28  aBiu--  阅读(34)  评论(0编辑  收藏  举报