多个UID为0的用户如何实现root用户的免密
文章目录
前言:
由于客户的机器都是suse的,并且uid为0的用户有 root、sysop、appadmin 三个用户,导致有的时候远程连接,即使是以 root 用户的身份登录,也会出现当前用户不是 root 的情况,以至于部署和免密脚本会失败
以下是通过注释
/etc/passwd
文件的方式,来暂时注销 sysop 和 appadmin 这两个用户,以此来达到当前uid为0的用户只有 root登陆 Linux 系统时,虽然输入的是自己的用户名和密码,但其实 Linux 并不认识你的用户名称,它只认识用户名对应的 ID 号(也就是一串数字)
Linux 系统将所有用户的名称与 ID 的对应关系都存储在
/etc/passwd
文件中
- ip:
- 192.168.72.12
- 192.168.72.13
- 192.168.72.14
- user:
- root
- appadmin
- sysop
创建用户
-m
创建用户的家目录(suse默认不会创建)
-U
创建用户的基本组(suse默认不会创建)
-o
允许创建重复的用户
-u
指定用户uid
useradd -mUo appadmin -u 0
useradd -mUo sysop -u 0
创建用户密码
创建用户密码,由于
suse
的passwd
命令没有--stdin
参数,没法使用echo '<user password>' | passwd --stdin <user name>
这个方式创建用户密码但是可以通过
echo '<user name>:<user password>' | chpasswd
的方式来创建用户密码这两种方式,是为了免交互为用户创建密码,直接使用
passwd
或者chpasswd
命令,是需要输入两次密码,对于写脚本不友好
echo 'appadmin:123.com' | chpasswd
echo 'sysop:123.com' | chpasswd
快速注释,方便快速回到root用户
for i in $(awk -F : '{if($3==0){print$1}}' /etc/passwd | grep -v root);do sed -i "/$i/s/^/#/g" /etc/passwd;done
快速取消注释
for i in $(awk -F : '{if($3==0){print$1}}' /etc/passwd);do sed -i "/$i/s/^#//g" /etc/passwd;done
免密脚本
我的用户密码全部设置为123.com了,需要使用下面的脚本,记得修改密码为自己的用户密码
#!/usr/bin/env bash
ips='
192.168.72.12
192.168.72.13
192.168.72.14
'
# 将上面的ip变量格式化成数组的形式
ip_arry=($(printf "%q\n" ${ips}))
# 备份root用户的.ssh目录
[[ -d "/root/.ssh" ]] && mv /root/.ssh{,-$(date +"%F_%T")}
# 生成新的公钥和私钥
ssh-keygen -t rsa -P "" -f /root/.ssh/id_rsa -q
for (( i=0; i<${#ip_arry[@]}; i++ ))
do
expect -c "
spawn ssh-copy-id -i /root/.ssh/id_rsa.pub root@${ip_arry[i]} -o \"StrictHostKeyChecking no\"
expect {
\"*assword*\" {send \"123.com\r\"; exp_continue}
\"*assword*\" {send \"123.com\r\";}
}"
done
当前主机用户不是root
通过
whoami
命令,确保当前的用户不是root
,可以使用ssh sysop@ip
来切换用户此时,执行上面的脚本会报错,如果
-f
指定的目录不是用户的家目录,ssh-keygen
无法自动创建,需要手动创建
/usr/bin/ssh-copy-id: ERROR: failed to open ID file '/root/.ssh/id_rsa.pub': No such file or directory
当前主机用户是root,远程主机多个用户uid为0
执行上面的脚本没有问题,可以实现root用户免密
但是连接远程主机,查看当前用户,显示为非root用户
ssh root@192.168.72.13 "whoami"
利用shell脚本实现远程主机uid为0的用户只有root一个
#!/usr/bin/env bash
ips='
192.168.72.12
192.168.72.13
192.168.72.14
'
ip_arry=($(printf "%q\n" ${ips}))
user_name=$(awk -F : '{if($3==0){print$1}}' /etc/passwd | grep -v root)
for (( i=0; i<${#ip_arry[@]}; i++ ))
do
for name in ${user_name}
do
j=($(printf "%q\n" ${name}))
ssh root@${ip_arry[i]} "sed -i \"/${name[j]}/s/^/#/g\" /etc/passwd"
done
done
当然,服务器是人家的,所以,自己的服务搞定以后,要取消sysop和appadmin的注释,不能影响客户的使用,使用一下脚本实现了取消注释
#!/usr/bin/env bash
ips='
192.168.72.12
192.168.72.13
192.168.72.14
'
ip_arry=($(printf "%q\n" ${ips}))
user_name=$(awk -F : '{if($3==0){print$1}}' /etc/passwd | sed 's/#//')
for (( i=0; i<${#ip_arry[@]}; i++ ))
do
for name in ${user_name}
do
j=($(printf "%q\n" ${name}))
ssh root@${ip_arry[i]} "sed -i \"/${name[j]}/s/^#//g\" /etc/passwd"
done
done
仅以此篇来记录自己的学习和成长的过程,虽然并不适用与大家的场景,不过用来练习shell脚本,还是可以的
---------------------------------更新时间:2021年11月22日---------------------------------
多个UID=0用户之间的免密
由于会有新场景上线,因此会有新机器需要做免密的情况,此时就要对所有UID=0的用户都完成免密才可以保证服务部署过程中,避免出现需要密码的情况,因此有了下面的脚本
- 脚本需要通过位置变量引入一个清单文件,清单文件名称以自己本地实际的为准,我这里使用的是list.txt来做参考
- 脚本执行方式:
bash same_uid_ssh.sh list.txt
- list.txt文件内的格式 [
以一个空格为分隔符
,依次为IP地址
、用户名
、用户密码
‘]:
192.168.70.26 sysop 123.com
192.168.70.88 sysop 234.com
192.168.70.89 sysop 345.com
- 脚本依赖
expect
和doc2unix
两个命令,执行前,建议先检查环境是否有这两个命令
#!/bin/bash
base_dir=$(cd `dirname $0`; pwd)
check_sanme_uid=$(awk -F ':' '{if ($3==0) {print $1}}' /etc/passwd | wc -l)
# 以数组的形式输出UID=0的所有用户
same_uid_user=($(awk -F ':' '{if ($3==0) {print $1}}' /etc/passwd))
# 脚本执行的时候没有带参数,则返回脚本执行方式
# list.txt非固定名称,只需要文件存在即可,文件内容以一个空格为分割,内容格式为: <ip地址> <用户名称> <用户密码>
if [[ "$#" == 0 ]];then
echo "Usage: bash $0 list.txt"
exit 0
fi
hosts_list=$1
user_host=($(awk '{print $1}' ${hosts_list}))
user_name=($(awk '{print $2}' ${hosts_list}))
user_pass=($(awk '{print $3}' ${hosts_list}))
if [[ "${check_sanme_uid}" > 1 ]];then
echo "system have ${check_sanme_uid} same uid users"
fi
# 生成ssh公钥
function make_ssh_pub () {
# 判断脚本所在路径下是否有 authorized_keys 文件,如果存在则清空文件内容
[[ ! -f "${base_dir}/authorized_keys" ]] || > ${base_dir}/authorized_keys
for (( i=0; i<${#same_uid_user[@]}; i++ ))
do
# 输当前循环的用户名
echo "now is ${same_uid_user[i]}"
# 通过for循环逐一注释 /etc/passwd 文件来达到当前UID=0的用户是唯一的
for change in $(awk -F ':' '{if ($3==0) {print $1}}' /etc/passwd | grep -v ${same_uid_user[i]})
do
sed -i "/${change}/s/^/#/g" /etc/passwd
done
# 判断用户是否为root来区分用户的家目录
# [只是注释 /etc/passwd 文件无法达到切换环境变量的效果,无法使用系统变量 $HOME 来指定用户的家目录]
if [[ "${same_uid_user[i]}"x == "root"x ]];then
user_home="/root"
else
user_home="/home/${same_uid_user[i]}"
fi
# 判断用户家目录下是否存在 .ssh 目录,存在则备份,后缀为: 年月日-时:分
[[ ! -d "${user_home}/.ssh" ]] || cp -r ${user_home}/.ssh{,.$(date +%Y%m%d-%H:%M)}
# 为了保证环境干净,删除用户家目录的 .ssh 目录
rm -rf ${user_home}/.ssh
# 静默生成用户ssh公钥,公钥格式为rsa
ssh-keygen -t rsa -P "" -f ${user_home}/.ssh/id_rsa -q
# 将用户的公钥追加到脚本所在路径下的 authorized_keys 文件内
# 后续只需要将脚本所在路径下的 authorized_keys 文件分发到其他节点指定用户家目录下的 .ssh 目录
# 以此来达到免密的效果
cat ${user_home}/.ssh/id_rsa.pub >> ${base_dir}/authorized_keys
# 取消之前的 /etc/passwd 文件的注释,进入下一层循环时,会重新注释其他用户,避免漏注释,造成公钥缺失
for change in $(awk -F ':' '{if ($3==0) {print $1}}' /etc/passwd | grep -v ${same_uid_user[i]})
do
sed -i "/${change}/s/^#//g" /etc/passwd
done
done
# 受到umask的影响,默认生成的文件权限为644,authorized_keys 文件默认权限为600,此处做一个赋权
chmod 600 ${base_dir}/authorized_keys
}
function make_ssh_auth () {
for (( host=0; host<${#user_host[@]}; host++ ))
do
# 判断脚本所在路径下是否有 user_list.txt 这个文件,有则清空文件内容
[[ ! -f "${base_dir}/user_list.txt" ]] || > ${base_dir}/user_list.txt
# 通过expect远程登录其他节点,查看UID=0的用户有哪些,避免环境差异,导致免密失败
# log_file将expect的输出重定向到指定文件中 [expect的log_file输出的文件格式不是unix的]
# expect内如果需要ssh到其他节点使用awk命令,需要使用花括号来代替双引号,并且$符号前面需要加上转义符(\)
expect -c "
spawn ssh ${user_name[host]}@${user_host[host]} {awk -F ':' '{if (\$3==0) {print \$1}}' /etc/passwd}
log_file ${base_dir}/user_list.txt
expect {
\"*es/no*\" {send \"yes\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\"; exp_continue}
}"
# 将dos格式的文件转换成unix格式的文件 [否则输出的内容会有dos文件的字符]
dos2unix -o ${base_dir}/user_list.txt
# 定义same_uid变量,以数组的形式定义从log_file文件内获取到的UID=0的用户
same_uid=($(printf "%q " `egrep -v 'spawn|assword' ${base_dir}/user_list.txt`))
for (( n=0; n<${#same_uid[@]}; n++ ))
do
# 定义用户的家目录,root用户与其他用户的家目录不同
if [[ "${same_uid[n]}"x == "root"x ]];then
user_home="/root"
else
user_home="/home/${same_uid[n]}"
fi
# 通过expect解决交互问题
# 在用户的家目录下创建.ssh目录,并赋权700
expect -c "
spawn ssh ${user_name[host]}@${user_host[host]} \"mkdir ${user_home}/.ssh -m 700\"
expect {
\"*es/no*\" {send \"yes\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\";}
}"
# 有些用户家目录下可能已经存在.ssh目录,这里重新赋权700,避免权限问题影响免密
expect -c "
spawn ssh ${user_name[host]}@${user_host[host]} \"chmod 700 ${user_home}/.ssh\"
expect {
\"*es/no*\" {send \"yes\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\";}
}"
# 判断用户家目录下的.ssh目录下是否已有 authorized_keys 免密文件,有则备份
# expect内如果用到'[]'来判断目录或文件是否存在,也需要用花括号来代替双引号
expect -c "
spawn ssh ${user_name[host]}@${user_host[host]} {[ ! -f ${user_home}/.ssh/authorized_keys ] || mv ${user_home}/.ssh/authorized_keys{,.bak}}
expect {
\"*es/no*\" {send \"yes\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\";}
}"
# 将脚本生成的 authorized_keys 免密文件分发到其他节点
expect -c "
spawn scp ${base_dir}/authorized_keys ${user_name[host]}@${user_host[host]}:${user_home}/.ssh/authorized_keys
expect {
\"*es/no*\" {send \"yes\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\"; exp_continue}
\"*assword*\" {send \"${user_pass[host]}\r\";}
}"
done
done
}
make_ssh_pub
make_ssh_auth
多个UID为0的用户如何实现root用户的免密的更多相关文章
- Ubuntu 增加新用户并赋予root权限及免密的方法
添加用户 添加一个名为hylink的用户 adduser hylink 修改密码 passwd hylink Changing password for user hylink. New UNIX p ...
- linux-shell 判断当前用户是否是root用户
环境变量UID中保存的是用户ID. root用户的UID是0. #! /bin/bash if [ $UID -ne 0 ]; then echo Non root user. Please run ...
- ubuntu首次给root用户设置密码和root用户登录设置
1 ubuntu首次给root用户设置密码 给root用户设置密码输入命令sudo passwd,然后系统会让你输入密码,这时输入的密码就是root用户的密码了,设置完成之后就可以切换root用户登录 ...
- 普通用户切换到root用户
普通用户切换到root用户首先按组合键 CTRL+ALT+T 进入终端界面,一般终端界面默认为普通用户权限模式,如何从普通用户进入root用户首先重置root密码输入 sudo passwd root ...
- Kali2.0的简单使用--开启root用户登录
1. 安装完kali之后 2. 修改/etc/ssh/sshd_conf的文件 将: #PasswordAuthentication no 修改为: PasswordAuthentication ye ...
- linux云计算集群架构学习笔记:用户管理和root用户密码重置
RHEL7用户管理 本节所讲内容: 用户和组的相关配置文件 管理用户和组 RHEL7破解root密码 与windows 相比 LINUX中的用户和账号的作用是一样的. 都是基于用户对访问的资源做控制, ...
- Linux脚本检测当前用户是否为root用户
#/bin/bash if [ $UID -ne 0 ]; then echo Non root user. Please run as root. else echo Root user fi
- Linux中查看你的用户是否为root用户
可以使用sudo -l命令: user@fafsf:/opt/user$ sudo -l [sudo] password for user: //这里是要输入你的密码 Sorry, user user ...
- 如何判断linux用户是否为root用户
看命令行提示符 ,如果是#,那就是root用户,如下图:[root@localhost /]# 如果是$,那就是普通用户,如下图:[test@localhost ~]$
随机推荐
- LINUX学习-Mysql安装
一.安装环境 操作系统CentOS6.8 关闭SeLinux和iptables防火墙 二.网络yum源 将下面的软件下载到 /etc/yum.repos.d/ 的目录下 官方基础:http:// ...
- HDU 1312 Red and Black (DFS & BFS)
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1312 题目大意:有一间矩形房屋,地上铺了红.黑两种颜色的方形瓷砖.你站在其中一块黑色的瓷砖上,只能向相 ...
- Keil MDK STM32系列(五) 使用STM32CubeMX创建项目基础结构
Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...
- Feed流系统重构-架构篇
重构,于我而言,很大的快乐在于能够解决问题. 第一次重构是重构一个c#版本的彩票算奖系统.当时的算奖系统在开奖后,算奖经常超时,导致用户经常投诉.接到重构的任务,既兴奋又紧张,花了两天时间,除了吃饭睡 ...
- 关于jar包和war读取静态文件
在war包中static中的静态文件,打成jar包后却读取不到,这是为什么呢,让我门看下两种读取的区别 一.war包中都取静态模板文件 public static void download(Stri ...
- Java代码批量插入数据到MySQL
1.批量插入 import java.io.BufferedReader; import java.io.FileInputStream; import java.io.FileNotFoundExc ...
- 【刷题-LeetCode】264. Ugly Number II
Ugly Number II Write a program to find the n-th ugly number. Ugly numbers are positive numbers whose ...
- VictoriaMerics学习笔记(2):核心组件
核心组件 1. 单机版 victoria-metrics-prod 单一二进制文件 读写都在一个节点上 作者推荐单机版 特性 merge方式配置 通过HTTP协议提供服务 内存限制(防止OOM) 使用 ...
- 一步一步超级详细的zabbix安装教程
安装说明: 1. 虚拟机上安装两台全新Linux: zabbix-server:192.168.255.128 zabbix-agent :192.168.255.129 2. zabbix-serv ...
- Error:(3, 21) java: 程序包javax.servlet不存在的解决方法
采用 https://blog.csdn.net/GK666_/article/details/106442929得到解决