【BASH】回顾与知识点梳理(二十五)

【BASH】回顾与知识点梳理 二十五

    • [二十五. 特殊shell、PAM 模块、讯息传递和大量建置账号](#二十五. 特殊shell、PAM 模块、讯息传递和大量建置账号)
      • [25.1 特殊shell](#25.1 特殊shell)
        • [特殊的 shell, /sbin/nologin](#特殊的 shell, /sbin/nologin)
      • [25.2 PAM模块](#25.2 PAM模块)
      • [25.3 Linux 主机上的用户讯息传递](#25.3 Linux 主机上的用户讯息传递)
        • [查询使用者: w, who, last, lastlog](#查询使用者: w, who, last, lastlog)
        • [使用者对谈: write, mesg, wall](#使用者对谈: write, mesg, wall)
        • [使用者邮件信箱: mail](#使用者邮件信箱: mail)
      • [25.4 CentOS 7 环境下大量建置账号的方法](#25.4 CentOS 7 环境下大量建置账号的方法)

该系列目录 --> 【BASH】回顾与知识点梳理(目录)

二十五. 特殊shell、PAM 模块、讯息传递和大量建置账号

25.1 特殊shell

我们前面一直谈到的大多是一般身份用户与系统管理员 (root) 的相关操作, 而且大多是讨论关于可登入系统的账号来说。那么换个角度想,如果我今天想要建立的, 是一个『仅能使用 mail server 相关邮件服务的账号,而该账号并不能登入 Linux 主机』呢?如果不能给予该账号一个密码,那么该账号就无法使用系统的各项资源,当然也包括 mail 的资源, 而如果给予一个密码,那么该账号就可能可以登入 Linux 主机啊!呵呵~伤脑筋吧~ 所以,底下让我们来谈一谈这些有趣的话题啰!

特殊的 shell, /sbin/nologin

在一开头的 passwd 文件结构里面我们就谈过系统账号这玩意儿,这玩意儿的 shell 就是使用/sbin/nologin ,重点在于系统账号是不需要登入的!所以我们就给他这个无法登入的合法 shell。 使用了这个 shell 的用户即使有了密码,你想要登入时他也无法登入,因为会出现如下的讯息喔:

bash 复制代码
This account is currently not available.

我们所谓的『无法登入』指的仅是:『这个使用者无法使用 bash 或其他 shell 来登入系统』而已,并不是说这个账号就无法使用其他的系统资源喔! 举例来说,各个系统账号,打印作业由lp这个账号在管理, WWW 服务由 apache 这个账号在管理, 他们都可以进行系统程序的工作,但是『就是无法登入主机取得互动的 shell』而已啦!^_^

换个角度来想,如果我的 Linux 主机提供的是邮件服务,所以说,在这部 Linux 主机上面的账号,其实大部分都是用来收受主机的信件而已,并不需要登入主机的呢! 这个时候,我们就可以考虑让单纯使用 mail 的账号以 /sbin/nologin 做为他们的 shell , 这样,最起码当我的主机被尝试想要登入系统以取得 shell 环境时,可以拒绝该账号呢!

另外,如果我想要让某个具有 /sbin/nologin 的使用者知道,他们不能登入主机时, 其实我可以建立『/etc/nologin.txt 』这个文件, 并且在这个文件内说明不能登入的原因,那么下次当这个用户想要登入系统时, 屏幕上出现的就会是 /etc/nologin.txt 这个文件的内容,而不是预设的内容了!

当使用者尝试利用纯 mail 账号 (例如 myuser3) 时,利用 /etc/nologin.txt 告知用户不要利用该账号登入系统。

答:直接以 vim 编辑该文件,内容可以是这样:

bash 复制代码
[root@study ~]# vim /etc/nologin.txt
This account is system account or mail account.
Please DO NOT use this account to login my Linux server.

想要测试时,可以使用 myuser3 (此账号的 shell 是 /sbin/nologin) 来测试看看!

bash 复制代码
This account is system account or mail account.
Please DO NOT use this account to login my Linux server.

结果会发现与原本的默认讯息不一样喔! ^_^

25.2 PAM模块

此处参考 linux PAM模块简介

25.3 Linux 主机上的用户讯息传递

谈了这么多的账号问题,总是该要谈一谈,那么如何针对系统上面的用户进行查询吧? 想几个状态,如果你在 Linux 上面操作时,刚好有其他的用户也登入主机,你想要跟他对谈,该如何是好? 你想要知道某个账号的相关信息,该如何查阅?呼呼!底下我们就来聊一聊~

查询使用者: w, who, last, lastlog

如何查询一个用户的相关数据呢?这还不简单,我们之前就提过了 id, finger 等指令了,都可以让您了解到一个用户的相关信息啦!那么想要知道使用者到底啥时候登入呢? 最简单可以使用last检查啊!

那如果你想要知道目前已登入在系统上面的用户呢?可以透过 w 或 who 来查询喔!如下范例所示:

bash 复制代码
[root@study ~]# w
01:49:18 up 25 days, 3:34, 3 users, load average: 0.00, 0.01, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
dmtsai tty2 07Jul15 12days 0.03s 0.03s -bash
dmtsai pts/0 172.16.200.254 00:18 6.00s 0.31s 0.11s sshd: dmtsai [priv]
# 第一行显示目前的时间、开机 (up) 多久,几个用户在系统上平均负载等;
# 第二行只是各个项目的说明,
# 第三行以后,每行代表一个使用者。如上所示,dmtsai 登入并取得终端机名 tty2 之意。
[root@study ~]# who
dmtsai tty2 2015-07-07 23:07
dmtsai pts/0 2015-07-22 00:18 (192.168.1.100)

另外,如果您想要知道每个账号的最近登入的时间,则可以使用 lastlog 这个指令喔! lastlog 会去读取 /var/log/lastlog 文件,结果将数据输出如下表:

bash 复制代码
[root@study ~]# lastlog
Username Port From Latest
root pts/0 Wed Jul 22 00:26:08 +0800 2015
bin **Never logged in**
....(中间省略)....
dmtsai pts/1 192.168.1.100 Wed Jul 22 01:08:07 +0800 2015
vbird1 pts/0 Wed Jul 22 01:32:17 +0800 2015
pro3 **Never logged in**
....(以下省略)....

这样就能够知道每个账号的最近登入的时间啰~

使用者对谈: write, mesg, wall

那么我是否可以跟系统上面的用户谈天说地呢?当然可以啦!利用 write 这个指令即可。 write 可以直接将讯息传给接收者啰!举例来说,我们的 Linux 目前有 vbird1 与 root 两个人在在线, 我的 root 要跟 vbird1 讲话,可以这样做:

bash 复制代码
[root@study ~]# write 使用者账号 [用户所在终端接口]
[root@study ~]# who
vbird1 tty3 2015-07-22 01:55 <==有看到 vbird1 在在线
root tty4 2015-07-22 01:56 
[root@study ~]# write vbird1 pts/2
Hello, there:
Please don't do anything wrong... <==这两行是 root 写的信息!
# 结束时,请按下 [crtl]-d 来结束输入。此时在 vbird1 的画面中,会出现:
Message from root@study.centos.vbird on tty4 at 01:57 ...
Hello, there:
Please don't do anything wrong...
EOF

怪怪~立刻会有讯息响应给 vbird1 !不过...当时 vbird1 正在查资料,哇! 这些讯息会立刻打断vbird1 原本的工作喔!所以,如果 vbird1 这个人不想要接受任何讯息,直接下达这个动作:

bash 复制代码
[vbird1@study ~]$ mesg n
[vbird1@study ~]$ mesg
is n

不过,这个 mesg 的功能对 root 传送来的讯息没有抵挡的能力!所以如果是 root 传送讯息, vbird1 还是得要收下。 但是如果 root 的 mesg 是 n 的,那么 vbird1 写给 root 的信息会变这样:

bash 复制代码
[vbird1@study ~]$ write root
write: root has messages disabled

了解乎?如果想要解开的话,再次下达『 mesg y 』就好啦!想要知道目前的 mesg 状态,直接下达『 mesg 』即可!瞭呼? 相对于 write 是仅针对一个使用者来传『简讯』,我们还可以『对所有系统上面的用户传送简讯 (广播)』哩~ 如何下达?用wall即可啊!他的语法也是很简单的喔!

bash 复制代码
[root@study ~]# wall "I will shutdown my linux server..."

然后你就会发现所有的人都会收到这个简讯呢!连发送者自己也会收到耶!

使用者邮件信箱: mail

使用 wall, write 毕竟要等到使用者在在线才能够进行,有没有其他方式来联络啊? 不是说每个Linux 主机上面的用户都具有一个 mailbox 吗? 我们可否寄信给使用者啊!呵呵!当然可以啊!我们可以寄、收 mailbox 内的信件呢! 一般来说, mailbox 都会放置在/var/spool/mail 里面,一个账号一个 mailbox (文件)。 举例来说,我的 vbird1 就具有 /var/spool/mail/vbird1 这个 mailbox 喔!

那么我该如何寄出信件呢?就直接使用 mail 这个指令即可!这个指令的用法很简单的,直接这样下达:『mail -s "邮件标题" username@localhost 』即可! 一般来说,如果是寄给本机上的使用者,基本上,连『 @localhost 』都不用写啦! 举例来说,我以 root 寄信给 vbird1 ,信件标题是『nice to meet you』,则:

bash 复制代码
[root@study ~]# mail -s "nice to meet you" vbird1
Hello, D.M. Tsai
Nice to meet you in the network.
You are so nice. byebye!
. <==这里很重要喔,结束时,最后一行输入小数点 . 即可!
EOT
[root@study ~]# <==出现提示字符,表示输入完毕了!

如此一来,你就已经寄出一封信给 vbird1 这位使用者啰,而且,该信件标题为: nice to meet you,信件内容就如同上面提到的。不过,你或许会觉得 mail 这个程序不好用~ 因为在信件编写的过程中,如果写错字而按下 Enter 进入次行,前一行的数据很难删除ㄟ! 那怎么办?没关系啦!我们使用数据流重导向啊!呵呵!利用那个小于的符号 ( < ) 就可以达到取代键盘输入的要求了。也就是说,你可以先用 vi 将信件内容编好, 然后再以 mail -s "nice to meet you" vbird1 < filename 来将文件内容传输即可。

  1. 请将你的家目录下的环境变量文件 (~/.bashrc) 寄给自己!

    答:mail -s "bashrc file content" dmtsai < ~/.bashrc

  2. 透过管线命令直接将 ls -al ~ 的内容传给 root 自己!

    答:ls -al ~ | mail -s "myfile" root

刚刚上面提到的是关于『寄信』的问题,那么如果是要收信呢?呵呵!同样的使用 mail 啊! 假设我以 vbird1 的身份登入主机,然后输入 mail 后,会得到什么?

bash 复制代码
[vbird1@study ~]$ mail
Heirloom Mail version 12.5 7/5/10. Type ? for help.
"/var/spool/mail/vbird1": 1 message 1 new
>N 1 root Wed Jul 22 02:09 20/671 "nice to meet you"
& <==这里可以输入很多的指令,如果要查阅,输入 ? 即可!

在 mail 当中的提示字符是 & 符号喔,别搞错了~输入 mail 之后,我可以看到我有一封信件, 这封信件的前面那个>代表目前处理的信件,而在大于符号的右边那个 N 代表该封信件尚未读过,如果我想要知道这个 mail 内部的指令有哪些,可以在 & 之后输入『?』,就可以看到如下的画面:

bash 复制代码
& ?
 mail commands
type <message list> type messages
next goto and type next message
from <message list> give head lines of messages
headers print out active message headers
delete <message list> delete messages
undelete <message list> undelete messages
save <message list> folder append messages to folder and mark as saved
copy <message list> folder append messages to folder without marking them
write <message list> file append message texts to file, save attachments
preserve <message list> keep incoming messages in mailbox even if saved
Reply <message list> reply to message senders
reply <message list> reply to message senders and all recipients
mail addresses mail to specific recipients
file folder change to another folder
quit quit and apply changes to folder
xit quit and discard changes made to folder
! shell escape
cd <directory> chdir to directory or home if none given
list list names of all available commands

25.4 CentOS 7 环境下大量建置账号的方法

系统上面如果有一堆账号存在,你怎么判断某些账号是否存在一些问题?这时需要哪些软件的协助处理比较好? 另外,如果你跟鸟哥一样,在开学之初或期末之后,经常有需要大量建立账号、删除账号的需求时,那么是否要使用 useradd 一行一行指令去建立? 此外,如果还有需要使用到下一章会介绍到的 quota (磁盘配额) 时,那是否还要额外使用其他机制来建立这些限制值?既然已经学过shell script 了, 当然写支脚本让它将所有的动作做完最轻松吧!所以啰,底下我们就来聊一聊,如何检查账号以及建立这个脚本要怎么进行比较好?

一些账号相关的检查工具

先来检查看看用户的家目录、密码等数据有没有问题?这时会使用到的主要有 pwck 以及 pwconv / pwuconv 等,让我们来了解一下先!

pwck/grpck

pwck 这个指令在检查 /etc/passwd 这个账号配置文件内的信息,与实际的家目录是否存在等信息,还可以比对 /etc/passwd /etc/shadow 的信息是否一致,另外,如果 /etc/passwd 内的数据字段错误时,会提示使用者修订。 一般来说,我只是利用这个玩意儿来检查我的输入是否正确就是了。

bash 复制代码
[root@study ~]# pwck
user 'ftp': directory '/var/ftp' does not exist
user 'avahi-autoipd': directory '/var/lib/avahi-autoipd' does not exist
user 'pulse': directory '/var/run/pulse' does not exist
pwck: no changes

瞧!上面仅是告知我,这些账号并没有家目录,由于那些账号绝大部分都是系统账号,确实也不需要家目录的,所以,那是『正常的错误!』呵呵!不理他。 ^_^。 相对应的群组检查可以使用 grpck 这个指令的啦!

pwconv

这个指令主要的目的是在『将 /etc/passwd 内的账号与密码,移动到 /etc/shadow 当中!』早期的 Unix 系统当中并没有 /etc/shadow 呢,所以,用户的登入密码早期是在 /etc/passwd 的第二栏,后来为了系统安全,才将密码数据移动到 /etc/shadow 内的。使用 pwconv 后,可以:

  • 比对 /etc/passwd 及 /etc/shadow ,若 /etc/passwd 内存在的账号并没有对应的 /etc/shadow 密码时,则pwconv 会去 /etc/login.defs 取用相关的密码数据,并建立该账号的 /etc/shadow 数据;
  • 若 /etc/passwd 内存在加密后的密码数据时,则 pwconv 会将该密码栏移动到 /etc/shadow 内,并将原本的/etc/passwd 内相对应的密码栏变成 x !

一般来说,如果您正常使用 useradd 增加使用者时,使用 pwconv 并不会有任何的动作,因为/etc/passwd 与 /etc/shadow 并不会有上述两点问题啊! ^_^。不过,如果手动设定账号,这个 pwconv 就很重要啰!

pwunconv

相对于 pwconv , pwunconv 则是『将 /etc/shadow 内的密码栏数据写回 /etc/passwd 当中, 并且删除 /etc/shadow 文件。这个指令说实在的,最好不要使用啦! 因为他会将你的 /etc/shadow 删除喔!如果你忘记备份,又不会使用 pwconv 的话,粉严重呢!

chpasswd

chpasswd 是个挺有趣的指令,他可以『读入未加密前的密码,并且经过加密后, 将加密后的密码写入 /etc/shadow 当中。』这个指令很常被使用在大量建置账号的情况中喔! 他可以由 Standard input 读入数据,每笔数据的格式是『 username:password 』。 举例来说,我的系统当中有个用户账号为vbird3 ,我想要更新他的密码 (update) , 假如他的密码是 abcdefg 的话,那么我可以这样做:

bash 复制代码
[root@study ~]# echo "vbird3:abcdefg" | chpasswd 

神奇吧!这样就可以更新了呢!在预设的情况中, chpasswd 会去读取 /etc/login.defs 文件内的加密机制,我们 CentOS 7.x 用的是 SHA512, 因此 chpasswd 就预设会使用 SHA512 来加密!如果你想要使用不同的加密机制,那就得要使用-c以及 -e 等方式来处理了! 不过从 CentOS 5.x 开始之后,passwd 已经默认加入了 --stdin 的选项,因此这个 chpasswd 就变得英雄无用武之地了! 不过,在其他非 Red Hat 衍生的 Linux 版本中,或许还是可以参考这个指令功能来大量建置账号喔!

大量建置账号模板(适用 passwd --stdin 选项)

由于 CentOS 7.x 的 passwd 已经提供了 --stdin 的功能,因此如果我们可以提供账号密码的话, 那么就能够很简单的建置起我们的账号密码了。底下鸟哥制作一个简单的 script 来执行新增用户的功能喔!

bash 复制代码
[root@study ~]# vim accountadd.sh
#!/bin/bash
# This shell script will create amount of linux login accounts for you.
# 1. check the "accountadd.txt" file exist? you must create that file manually.
# one account name one line in the "accountadd.txt" file.
# 2. use openssl to create users password.
# 3. User must change his password in his first login.
# 4. more options check the following url:
# http://linux.vbird.org/linux_basic/0410accountmanager.php#manual_amount
# 2015/07/22 VBird
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
# 0. userinput
usergroup="" # if your account need secondary group, add here.
pwmech="openssl" # "openssl" or "account" is needed.
homeperm="no" # if "yes" then I will modify home dir permission to 711
# 1. check the accountadd.txt file
action="${1}" # "create" is useradd and "delete" is userdel.
if [ ! -f accountadd.txt ]; then
echo "There is no accountadd.txt file, stop here."
 exit 1
fi
[ "${usergroup}" != "" ] && groupadd -r ${usergroup}
rm -f outputpw.txt
usernames=$(cat accountadd.txt)
for username in ${usernames}
do
 case ${action} in
 "create")
 [ "${usergroup}" != "" ] && usegrp=" -G ${usergroup} " || usegrp=""
 useradd ${usegrp} ${username} # 新增账号
 [ "${pwmech}" == "openssl" ] && usepw=$(openssl rand -base64 6) || usepw=${username}
 echo ${usepw} | passwd --stdin ${username} # 建立密码
 chage -d 0 ${username} # 强制登入修改密码
 [ "${homeperm}" == "yes" ] && chmod 711 /home/${username}
 echo "username=${username}, password=${usepw}" >> outputpw.txt
 ;;
 "delete")
 echo "deleting ${username}"
 userdel -r ${username}
 ;;
 *)
 echo "Usage: $0 [create|delete]"
 ;;
 esac
done

接下来只要建立 accountadd.txt 这个文件即可!鸟哥建立这个文件里面共有 5 行,你可以自行建立该文件!内容每一行一个账号。 而是否需要修改密码?是否与账号相同的信息等等,你可以自由选择!若使用 openssl 自动猜密码时,用户的密码请由 outputpw.txt 去捞~鸟哥最常作的方法,就是将该文件打印出来,用裁纸机一个账号一条,交给同学即可!

bash 复制代码
[root@study ~]# vim accountadd.txt
std01
std02
std03
std04
std05
[root@study ~]# sh accountadd.sh create
Changing password for user std01.
passwd: all authentication tokens updated successfully.
....(后面省略)....

该系列目录 --> 【BASH】回顾与知识点梳理(目录)

相关推荐
百事老饼干14 分钟前
Java[面试题]-真实面试
java·开发语言·面试
杨荧1 小时前
【JAVA毕业设计】基于Vue和SpringBoot的服装商城系统学科竞赛管理系统
java·开发语言·vue.js·spring boot·spring cloud·java-ee·kafka
白子寰1 小时前
【C++打怪之路Lv14】- “多态“篇
开发语言·c++
王俊山IT1 小时前
C++学习笔记----10、模块、头文件及各种主题(一)---- 模块(5)
开发语言·c++·笔记·学习
为将者,自当识天晓地。1 小时前
c++多线程
java·开发语言
小政爱学习!1 小时前
封装axios、环境变量、api解耦、解决跨域、全局组件注入
开发语言·前端·javascript
k09331 小时前
sourceTree回滚版本到某次提交
开发语言·前端·javascript
神奇夜光杯2 小时前
Python酷库之旅-第三方库Pandas(202)
开发语言·人工智能·python·excel·pandas·标准库及第三方库·学习与成长
Themberfue2 小时前
Java多线程详解⑤(全程干货!!!)线程安全问题 || 锁 || synchronized
java·开发语言·线程·多线程·synchronized·
plmm烟酒僧2 小时前
Windows下QT调用MinGW编译的OpenCV
开发语言·windows·qt·opencv