一 软件包分类

Linux 系统和 Windows 系统之间的软件包是分开的。Windows 系统中的 .exe,.msi 是无法在Linux系统下运行。Linux 系统中的服务器应用是无法在 Windows 系统下运行。

Windows 下的 .exe 程序就是经过编译过后的二进制程序,类似于 Linux 下的 rpm 包。本质就是将源码包编译成二进制程序。反编译实现起来会非常困难。

1.1 软件包分类

  • 源码包(可以查看到源码信息,并且功能可以自定义)
  • 二进制包(无法查看到相应的源码信息)

(脚本安装包)

软件包选择建议:

源码包,如果服务是给大量客户端提供访问的,建议使用源码包,源码包效率更高(例如:LAMP)

RPM包,如果程序是给少量用户访问,或者本地使用的,建议RPM包,因为RPM简单,并且管理方便。

1.2 源码包

1.2.1 源码包什么样

~ vim hello.c
#include <stdin.h>
int main (void)
{printf ("hello world\n");
}
~ rpm -ivh /mnt/cdrom/Packages/gcc-4.4.6-4.el6.i686.rpm
~ gcc -c hello.c
# -c 生成".o"头文件。这里会生成 hello.o 头文件,但是不会生成执行文件
~ gcc -o hello hello.o
# -o 生成执行文件,并制定执行文件名。这里生成的hello就是可执行文件
~ ./hello
hello world
# 执行 hello 文件

1.2.2 源码包特点

源码包的优点是:

  • 开源,如果有足够的能力,可以修改源代码
  • 可以自由选择所需的功能
  • 软件是编译安装,所以更加适合自己的系统,更加稳定也效率更高
  • 卸载方便

源码包有缺点吗?

  • 安装过程步骤较多,尤其安装较大的软件集合时(如LAMP环境搭建),容易出现拼写错误
  • 编译过程时间较长,安装比二进制安装时间长
  • 因为是编译安装,安装过程中一旦报错新手很难解决

1.3 二进制包

1.3.1 二进制包分类

  • DPKG包:是由 Debian Linux所开发出来的包管理机制,通过 DPKG包,Debian Linux就可以进行软件包管理。主要应用在 Debian和 ubuntu中。
  • RPM包是由Red Hat公司所开发的包管理系统。功能强大,安装、升级、查询和卸载都非常简单和方便。目前很多Linux都在使用这种包管理方式,包括Fedora、Cent0S、SuSE等。我们学习的是 CentOS 6.3 | CentOS 7.9,所以我们将要学习RPM包管理系统

1.3.2 特点

RPM包的优点:

  • 包管理系统简单,只通过几个命令就可以实现包的安装、升级、查询和卸载。几乎不会在报错,因为厂家已经进行了相应的二进制编译。
  • 安装速度比源码包安装快的多

RPM包的缺点:

  • 经过编译,不再可以看到源代码
  • 功能选择不如源码包灵活
  • 依赖性。有时我们会发现需要安装软件包a时需要先安装b和c,而安装b时需要安装d和e。这是需要先安装d和e,再安装b和c,最后才能安装a包。比如说,我买了个漂亮的灯具,打算安装到我们家客厅,可是在安装灯具之前我们家客厅总要有顶棚吧,顶棚总要是做好了防水和刷好油漆了吧,这个装修和安装软件其实类似总要有一定的顺序的。可是有时依赖性会非常繁琐。有可能会需要解决相关的RPM包的依赖性问题。

1.3.3 RPM包依赖

  1. 手工命令安装(需要工程师手动安装)
  2. yum 在线安装

1)树形依赖:a-——->b–—->c

2)环形依赖:a-——->b-——->c-——->a(需要一条命令同时安装)

3)模块依赖:

什么是模块依赖?我们举一个例子,尝试安装以下文件:

[root@localhost Packages]# rpm -ivh mysql-connector-odbc-5.2.5-7.el7.x86_64.rpm
错误:依赖检测失败:libodbc.so.2()(64bit) 被 mysql-connector-odbc-5.2.5-7.e17.x86_64 需要libodbcinst.so.2()(64bit) 被 mysql-connector-odbc-5.2.5-7.el7.x86_64 需要

发现报错,需要安装“libodbc.so.2”函数库文件,这时会发现在光盘中根本找不到这个文件。那是因为函数库没有单独成包,是包含在某一个软件包中的。而如果要知道在哪个软件包中,需要查询网站 www. rpmfind.net,如图:

二 RPM 安装

2.1 rpm 包命名规则

包全名:httpd-2.2.15-15.el6.centos.i686.rpm

包名:httpd

  • 包全名:如果操作的是未安装软件包,则使用包全名,而且需要注意绝对路径
  • 包名:如果操作的是已经安装的软件包,则使用包名即可,系统会生产 RPM 包的数据库 /usr/lib/rpm ,而且可以在任意路径下操作

httpd :软件包名

2.2.15 :软件版本

15 :软件发布的次数

el6 :软件发行商。el6是RedHat公司发布,适合RHEL6.x(Red Hat Enterprise Linux)和CentOS6.x下使用

i686 :适合的硬件平台。RPM包可以在不同的硬件平台安装,选择适合不同CPU的软件版本,可以最大化的发挥CPU性能,所以出现了所谓的i386 (386 以上计算机都可以安装)、i586 (586以上的计算机都可以安装)、i686(奔腾II 以上计算机都可以安装,目前所有的CPU都是奔腾II以上,所以这个软件版本居多)、x86_64 (64位CPU可以安装)和noarch(没有硬件限制)等文件名了。

rpm :rpm包的扩展名。我们说过Linux下文件不是靠扩展名区分文件类型,也就是Linux中扩展名没有任何含义。可是这里怎么又出现了扩展名呢﹖原因很简单,如果我不把RPM的扩展名叫做“.rpm”,管理员很难知道这是一个RPM包,当然也就无法正确安装了。也就是说如果RPM包不用“.rpm”作为扩展名,系统可以正确识别没有问题,可是管理员很难识别这是个什么样的软件。

  • 包全名:如果操作的是未安装软件包,则使用包全名,而且需要注意绝对路径
  • 包名:如果操作的是已经安装的软件包,则使用包名即可,系统会生产 RPM 包的数据库(/var/lib/rpm/),而且可以在任意路径下操作。

2.2 依赖性

参考 1.3.3 RPM 包的依赖,不再重复

2.3 rpm 包手工命令安装/

2.3.1 默认安装位置

RPM 包默认安装路径
/etc/ 配置文件安装目录
/usr/bin/ 可执行的命令安装目录
/usr/lib/ 程序所使用的函数库保存位置
/usr/share/doc/ 基本的软件使用手册保存位置
/usr/share/man/ 帮助文件保存位置

2.3.2 RPM 包安装

1)安装命令

rpm -ivh 包全名
#注意一定是包全名。如果跟包全名的命令要注意路径,因为软件包在光盘当中
选项:
-i  :install安装(install)
-v  :显示更详细的信息(verbose)
-h  :打印#显示安装进度(hash)
  • –nodeps 不检测依赖性安装。软件时会检测依赖性,确定所需的底层软件是否安装。如果没有安装则会报错。如果我不管依赖性,想强行安装,可以使用这个选项。注意:这样不检测依赖性安装的软件基本是不能使用的,所以不建议这样做。
  • –replacefiles 替换文件安装。如果安装软件包,可是包中部分文件已经存在,那么正常安装时候,会报错“某个文件已经存在”从而导致软件无法安装,使用这个选项可以忽视这个报错,而覆盖安装
  • –replacepkgs 替换软件包安装。如果软件包已经安装,此选项可以把软件包重复安装一遍。
  • –force 强制安装。不管是否已经安装,都重新安装。就是–replacefiles 和 --replacepkgs 的综合。用于强制覆盖安装,适用于重要系统文件丢失的情况。
  • –test 测试安装。不会实际安装,只是检测一下依赖性。
  • –prefix 指定安装路径。为安装软件指定安装路径,而不使用默认安装路径。注意:如果指定了安装路径,软件没有安装到系统默认路径中的话,系统会找不到这些安装的软件,需要进行手工配置才能被系统识别。所以 rpm包 我们一般都采用默认路径安装。所以不建议这样做。

RPM 包建议安装在默认路径中(作者决定的)

1)默认安装位置是系统的习惯位置

2)RPM包管理系统是有 rpm -e 卸载命令的( 数据库记录安装位置 /var/lib/rpm )

源码包一定要指定安装位置的,源码包不指定安装位置,那么将会安装到Linux系统的各个目录下,但是源码包安装是没有数据库记录的,源码包的卸载直接卸载相关的目录即可。

~ rpm -ivh httpd-*
httpd-2.4.6-95.el7.centos.x86_64.rpm         httpd-manual-2.4.6-95.el7.centos.noarch.rpm
httpd-devel-2.4.6-95.el7.centos.x86_64.rpm   httpd-tools-2.4.6-95.el7.centos.x86_64.rpm
# 根据所需要的依赖进行依赖安装即可
yum localinstall -y httpd-2.4.6-95.el7.centos.x86_64.rpm \httpd-devel-2.4.6-95.el7.centos.x86_64.rpm \httpd-manual-2.4.6-95.el7.centos.noarch.rpm \httpd-tools-2.4.6-95.el7.centos.x86_64.rpm

2)服务启动

[root@localhost ~]# service 服务名 start|stop|restart|status
参数:
start       :启动服务
stop        :停止服务
restart :重启服务
status  :查看服务状态
~ systemctl start httpd
~ ss -ntlp | grep 80
LISTEN     0      128       [::]:80                    [::]:*                   users:(("httpd",pid=21546,fd=4),("httpd",pid=21545,fd=4),("httpd",pid=21544,fd=4),("httpd",pid=21543,fd=4),("httpd",pid=21542,fd=4),("httpd",pid=21541,fd=4))
~ curl localhost
# 可以显示相应的返回值

RPM 包安装的 Apache

  1. 启动

CentOS6 1)service httpd restart

CentOS6 2)/etc/rc.d/init.d/httpd start | restart | stop

CentOS7 1)systemctl restart httpd

  1. 网页的位置

/var/www/html :Apache 的网页路径

是否需要重启服务,唯一标准:就是是否修改了对应的配置文件。

~ echo "Hello world" > /var/www/html/index.html
~ curl localhost
Hello world
  1. 配置文件

/etc/httpd/conf/httpd.conf

2.3.3 PRM 包升级

[root@localhost~]# rpm -Uvh 包全名
选项:
-U(大写)      升级安装,如果没有安装过(可以代替 rpm -ivh),系统直接安装。如果安装过的版本较旧,则升级到新版本(upgrade),升级加安装。[root@localhost~]# rpm -Fvh 包全名
选项:
-F(大写)      升级安装,如果没有安装过,则不会安装。必须安装有较旧版本,才能升级(freshen)

2.3.4 RPM 卸载

RPM 卸载的时候会出现依赖性的问题。

[root@localhost ~]# rpm -e 包名
选项:
--nodeps    :不检查依赖性,生产环境下不能使用该参数
-e              :卸载# 不要使用 yum 命令进行卸载软件

2.3.5 查询

yum 可以取代 rpm 的安装,升级等操作,但是在查询中推荐使用 rpm 命令。

RPM 命令查询是客户端 本地软件包是否安装

YUM 命令查询时服务器端 服务端的软件包的信息

1)查询软件包是否安装

可以查询软件包是否安装,命令格式如下:

~ rpm -q 包名
选项:-q:查询(query)

范例:

~ rpm -q httpd
package httpd is not installed~ rpm -q httpd
httpd-2.2.15-69.el6.centos.x86_64

2)查询系统中的所有安装软件包

可以查询Linux系统中所有已经安装的软件包,命令格式如下:

~ rpm -qa
选项:-a:所有(all)

当然,可以用管道符来查看所需的内容,比如:

~ rpm -qa | grep http
httpd-tools-2.2.15-69.el6.centos.x86_64
httpd-2.2.15-69.el6.centos.x86_64

你会发现,使用“rpm -q包名”只能查看这个包是否安装,但是使用“rpm -qa / grep 包名”会把包含包名称的所有包都列出来。

3)查询软件包的详细信息

可以查询已经安装的某个软件包的详细信息,命令格式如下:

~ rpm -qi 包名
选项:-i:查询软件信息(information)

范例:

~ rpm -qi httpd
Name        : httpd                        Relocations: (not relocatable)
Version     : 2.2.15                            Vendor: CentOS
Release     : 69.el6.centos                 Build Date: Tue 19 Jun 2018 11:45:51 PM CST
Install Date: Sun 19 Jun 2022 05:22:02 PM CST      Build Host: x86-01.bsys.centos.org
Group       : System Environment/Daemons    Source RPM: httpd-2.2.15-69.el6.centos.src.rpm
Size        : 3170514                          License: ASL 2.0
Signature   : RSA/SHA1, Wed 20 Jun 2018 07:36:47 PM CST, Key ID 0946fca2c105b9de
Packager    : CentOS BuildSystem <http://bugs.centos.org>
URL         : http://httpd.apache.org/
Summary     : Apache HTTP Server
Description :
The Apache HTTP Server is a powerful, efficient, and extensible
web server.

也可以查询还没有安装的软件包的详细信息,命令格式如下:

~ rpm -qip 包全名
选项:-p:查询没有安装的软件包(Package)

范例:

~ rpm -qip httpd-2.2.15-69.el6.centos.x86_64.rpm
warning: httpd-2.2.15-69.el6.centos.x86_64.rpm: Header V3 RSA/SHA1 Signature, key ID c105b9de: NOKEY
Name        : httpd                        Relocations: (not relocatable)
Version     : 2.2.15                            Vendor: CentOS
Release     : 69.el6.centos                 Build Date: Tue 19 Jun 2018 11:45:51 PM CST
Install Date: (not installed)               Build Host: x86-01.bsys.centos.org
Group       : System Environment/Daemons    Source RPM: httpd-2.2.15-69.el6.centos.src.rpm
Size        : 3170514                          License: ASL 2.0
Signature   : RSA/SHA1, Wed 20 Jun 2018 07:36:47 PM CST, Key ID 0946fca2c105b9de
Packager    : CentOS BuildSystem <http://bugs.centos.org>
URL         : http://httpd.apache.org/
Summary     : Apache HTTP Server
Description :
The Apache HTTP Server is a powerful, efficient, and extensible
web server.

4)查询软件包中的文件列表

可以查询已经安装的软件包中的文件列表和安装的完整目录,命令格式如下:

  • rpm -ql 是知道软件包名 查询有软件包的文件列表
~ rpm -ql 包名
选项:-l:列出软件包中所有的文件列表和软件所安装的目录(list)

那么,可以查询还没有安装的软件包中的文件列表和打算安装的位置吗?答案是可以,命令格式如下:

~ rpm -qlp 包全名
选项:-p:查询没有安装的软件包(Package)

范例:

~ rpm -qlp httpd-2.2.15-69.el6.centos.x86_64.rpm

5)查询系统文件属于哪个RPM包

既然可以知道每个RPM包中的文件的安装位置,那么可以查询系统文件属于哪个RPM包吗?当然可以,不过需要注意的是,手工建立的文件是不能查询的,因为这些文件不是通过RPM包安装的,当然不能反向查询它属于哪个RPM包。命令格式如下:

  • rpm -qf 是知道文件列表查询 相关的软件包名
~ rpm -qf 系统文件名
选项:-f:查询系统文件属于哪个软件包(file)

范例:

~ rpm -qf /etc/fstab
setup-2.8.14-23.el6.noarch

6)查询软件包所依赖的软件包

查询系统中和已经安装的软件包有依赖关系的软件包,命令格式如下:

~ rpm -qR 包名
选项:-R:查询软件包的依赖性(requires)

可以查询没有安装的软件包的依赖性吗?加“-p”选项即可。例如,查看一下还没有安装的bind软件包的依赖包,可以执行如下命令:

~ rpm -qRp /mnt/cdrom/Packages/bind-9.8.2-0.68.rc1.el6.x86_64.rpm

小总结:

RPM 包:

  1. 手工命令安装

    1. 安装:rpm -ivh 包全名
    2. 升级:rpm -Uvh 包全名 或者 rpm -Fvh 包全名
    3. 卸载:rpm -e 包名
    4. 查询:
    1. 查询是否安装:rpm -q 包名 ; rpm -qa | grep 包名
    2. 查询包的信息:rpm -qi 包名
    3. 查询未安装包的信息:rpm -qip 包全名
    4. 查询安装位置:rpm -ql 包名
    5. 查询未安装包安装位置:rpm -qlp 包全名
    6. 查询系统文件属于哪个包:rpm -qf 系统文件名
    7. 查询依赖性:rpm -qR 包名
    1. 验证:rpm -V 包名
    2. 导入数字证书:rpm --import 数字证书
    3. 提取 RPM 包中的文件:rpm2cpio 包全名 | cpio -idv .文件绝对路径
  2. YUM 在线安装

    1. 安装:yum install -y 包名
    2. 升级:yum update -y 包名
    3. 查询可用的软件包:yum list
    4. 卸载:yum remove -y 包名
    5. 查询包:yum search 关键字
    6. 查找包的依赖:yum provides 系统文件名
    7. 包组信息:yum groupinfo
    8. 包组查询:yum groupsearch 关键字
    9. 包组安装:yum groupinstall 包组名
    10. 包组卸载:yum groupremove 包组名

2.3.6 验证

1)基本命令

~ rpm -Va
选项:-Va:校验本机已经安装的所有软件包~ rpm -V 已安装的包名
选项:-V:校验指定 PRM 包中的文件(verify)~ rpm -Vf 系统文件名
选项:-Vf:校验某个系统文件是否被修改

2)验证举例

~ rpm -V httpd
S.5....T.  c                    /etc/httpd/conf/httpd.conf
验证内容   文件类型      文件名

出现了提示信息,我们来解释下最前面共有8个信息内容,是表示验证内容的。文件名前面的c是表示这是个配置文件(configuration)。最后是文件名。那么验证内容中的8个信息的具体内容如下:

  • s 文件大小是否改变
  • M 文件的类型或文件的权限(rwx)是否被改变
  • 5 文件MD5校验和是否改变(可以看成文件内容是否改变)
  • D 设备的主从代码是否改变
  • L 文件路径是否改变
  • U 文件的属主(所有者)是否改变
  • G 文件的属组是否改变
  • T 文件的修改时间是否改变

软件包校验是跟软件包的原始值进行对比,就会有可能软件包的原始值会有问题,那么就可以在系统中事先安装好证书,该证书用来保证软件包的原始值是没有问题的。

只有到软件包的原始值通过证书的校验认证,才能允许安装该软件包,否则不通过。

apache配置文件的文件类型是c,那么还有哪些文件类型呢?

  • c:配置文件 (config file)
  • d:普通文档 ( documentation )
  • g:“鬼”文件 (ghost file),很少见,就是该文件不应该被这个RPM包包含
  • l:授权文件 (license file)
  • r:描述文件 (read me)

MD5 加密算法,会将文件利用 MD5 的加密算法得到一个结果为随机的 16 机制的MD5码。只要文件内容不变,无论在哪台电脑都不会改变。

MD5 只要用于做完整性的校验。

2.3.7 数字证书

刚刚的校验方法只能对已经安装的RPM包中的文件进行校验,但是如果RPM包本身就被动过手脚,那么校验就不能解决问题了。我们就必须使用数字证书验证了。

数字证书保证原始值的不变。

数字证书有如下特点:

  • 首先必须找到原厂的公钥文件,然后进行安装
  • 再安装RPM包是,会去提取 RPM包中的证书信息,然后和本机安装的原厂证书进行验证
  • 如果验证通过,则允许安装;如果验证不通过,则不允许安装并警告

1)数字证书位置

那么数字证书在哪里呢?其实在CentOS 6.3的第一张光盘中就有,当然它默认也会放在系统中。

~ ls -l /mnt/cdrom/RPM-GPG-KEY-CentOS-6
-r--r--r--. 2 root root 1706 Nov 27  2013 /mnt/cdrom/RPM-GPG-KEY-CentOS-6
# 光盘中的数字证书位置~ ls -l /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
-rw-r--r--. 1 root root 1706 Jun 26  2018 /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
# 系统中的数字证书位置

2)数字证书导入

~ rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
选项:--import:导入数字证书

我们如何查询系统中安装好的数字证书呢?命令如下:

~ rpm -qa | grep gpg-pubkey
gpg-pubkey-c105b9de-4e0fd3a3

2.3.8 RPM 包中文件的提取

修改配置文件一定要进行备份

1)cpio 命令

cpio命令主要有三种基本模式:“-o”模式指的是 copy-out 模式,就是把数据备份到文件库中;“-i”模式指的是 copy-in 模式,就是把数据从文件库中恢复;“-p”模式指的是复制模式,就是不把数据备份到cpio库中,而是直接复制为其他文件。命令如下:

~ cpio -o[vcB] > [文件|设备]
# 备份
选项:-o: copy-out模式,备份-v: 显示备份过程-c: 使用较新的portable format存储方式-B: 设定输入输出块为5120bytes,而不是模式的512butes~ cpio -i[vcdu] < [文件|设备]
# 还原
选项:-i: copy-in模式,还原-v:显示还原过程-c:使用较新的portable format存储方式-d:还原时自动新建目录-u:自动使用较新的文件覆盖较旧的文件~ cpio -p 目标目录

举几个例子吧,先来看看使用cpio备份数据的方法,命令如下:

# 例子:利用 find 命令找到文件,进行备份
~ find /etc/ -print | cpio -ocvB > /root/etc.cpio
# 利用 find 指定要备份 /etc 目录,使用 > 导出到 etc.cpio 文件~ ls -lh /root/etc.cpio
-rw-r--r-- 1 root root 32M Aug 10 11:01 /root/etc.cpio
# etc.cpio 文件生成

再来看看如何恢复 cpio 的备份数据,命令如下:

~ cpio -idvcu < /root/etc.cpio
#还原etc的备份
#但是如果大家查看下当前日录/root,会发现没有生成 etc目录。
#这是因为备份是/etc目录使用的是绝对路径,所以恢复的数据直接恢复到了/ete系统目录中,而没有生成在/root/etc中。

在Cent0S5.x的版本中,是可以利用上面的命令备份与恢复指定的文件。但是到CentOS6.x当中,需要更加严谨。如果备份时使用绝对路径,则恢复的数据会直接到绝对路径指定的路径中,如果需要把数据恢复到当前目录中,则需要使用相对路径,例如:

# 备份:
~ cd /etc/
# 进入到 /etc/ 目录
~ find . -print | cpio -ocvB > /root/etc.cpio
# 利用 find 指定要备份 /etc 目录,使用 > 导出到 etc.cpio 文件# 恢复:
~ cd /root
# 回到 /root 目录中
~ mkdir etc_test
# 建立恢复测试目录
~ cd etc_test
# 进入测试目录,数据恢复到此
~ cpio -idvcu < /root/etc.cpio
# 还原/ete目录的数据,因为备份时使用的是相对路径,则会还原到/root/ete_test/目录下

最后来演示一下cpio命令的“-p”复制模式,命令如下:

~ cd /tmp/
# 进入 /tmp 目录
~ rm -rf *
# 删除 /tmp 目录中所有数据
~ mkdir test
# 建立备份目录
~ find /boot/ -print | cpio -p /tmp/test
# 备份 /boot/ 目录到 /tmp/test 目录中
~ ls -l /tmp/test
total 4
dr-xr-xr-x 5 root root 4096 Aug 10 11:12 boot
# 在/tmp/test 目录中备份出了 boot 目录

2)提取 RPM 包中的文件

~ rpm2cpio 包全名 | cpio -idv .文件绝对路径rpm2cpio   将rpm包转换为cpi格式的命令cpio            是一个标准工具,它用于创建软件档案文件和从档案文件中提取文件

举个例子,现在我假设把系统中的 /bin/ls 命令不小心误删除了,那么我可以修复回来吗?这时有两种方法修复,要不就是使用 --force 选项覆盖安装一遍 coreutils-8.4-19.e16.i686包,要不就可以使用 cpio 命令提取出/bin/ls命令文件,再把它拷贝到对应位置就可以了。不过我是怎么知道/bin/ls命令是属于 coreutils-8.4-19.e16.i686 这个软件包的呢?还记得 -qf 选项吗?命令如下:

~ rpm -qf /bin/ls
coreutils-8.4-47.el6.x86_64
# 查看 ls 文件属于哪个软件包

那么我们在讲RPM包中文件提取,所以我们使用第二章方法,cpio命令提取出ls命令文件,然后拷贝到对应位置,命令如下:

~ mv /bin/ls /root/
# 把 /bin/ls 命令移动到 /root/ 目录下,造成误删除的假象~ ls
-bash: /bin/ls: No such file or directory
# 此时执行 ls 命令,系统会报错"命令没有找到"~ rpm2cpio /mnt/cdrom/Packages/coreutils-8.4-47.el6.x86_64.rpm | cpio -idv ./bin/ls
./bin/ls
25240 blocks
# 提取 ls 命令文件到当前目录下~ cp /root/bin/ls /bin/
# 把提取ls 命令文件复制到 /bin/ 目录下~ ls -l
total 120
drwxr-xr-x. 2 root root   4096 Aug  4 06:32 bin
-rwxr-xr-x. 1 root root 117048 Jun 19  2018 ls

2.4 RPM 包在线安装(yum安装)

2.4.1 yum 源文件解析

yum 源配置文件保存在/etc/yum.repos. d/目录中,文件的扩展名一定是“.repo”。也就是说,yum源配置文件只要扩展名是“.repo”就会生效。

~ ls -l /etc/yum.repos.d/
total 28
-rw-r--r--. 1 root root 1991 Jun 26  2018 CentOS-Base.repo
-rw-r--r--. 1 root root  647 Jun 26  2018 CentOS-Debuginfo.repo
-rw-r--r--. 1 root root  289 Jun 26  2018 CentOS-fasttrack.repo
-rw-r--r--. 1 root root  630 Jun 26  2018 CentOS-Media.repo
-rw-r--r--. 1 root root 8854 Jun 26  2018 CentOS-Vault.repo

这个目录中有5个yum源配置文件,默认情况下Cent0S-Base.repo文件生效。我们打开这个文件看看,命令如下:

~ vim /etc/yum.repos.d/CentOS-Base.repo[base]
name=CentOS-$releasever - Base
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6#released updates
[updates]
name=CentOS-$releasever - Updates
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras&infra=$infra
#baseurl=http://mirror.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
...省略部分输出...

在CentOS-Base.repo文件中有5个yum源容器,这里只列出了base容器,其他容器和 base容器类似。我们解释一下base这个容器。

  • [base]:容器名称,一定要放在 [] 中。
  • name:容器说明,可以自己随便写。
  • mirrorlist:镜像站点,这个可以注释掉。
  • baseurl:我们的yum源服务器的地址。默认是Cent0S官方的yum源服务器,是可以使用的。如果你觉得慢,则可以改成你喜欢的yum源地址。
  • enabled:此容器是否生效,如果不写或写成 enabled=1 则表示此容器生效,写成 enabled=0 则表示此容器不生效。
  • gpgcheck: 如果为1则表示RPM的数字证书生效;如果为0则表示RPM的数字证书不生效。
  • gpgkey:数字证书的公钥文件保存位置。不用修改。

2.4.2 搭建本地光盘源

第一步:放入 CentOS 安装光盘,并挂载光盘到指定位置。命令如下:

~ mkdir -pv /mnt/cdrom
# 创建 cdrom 目录,作为光盘的挂载点
~ mount /dev/cdrom /mnt/cdrom
# 挂载光盘到/mnt/cdrom 目录下

第二步:修改其他几个yum源配置文件的扩展名,让它们失效,因为只有扩展名是“*.repo”的文件才能作为yum源配置文件。当然也可以删除其他几个yum源配置文件,但是如果删除了,当你又想用网络作为yum源时,就没有了参考文件,所以最好还是修改扩展名。命令如下:

~ cd /etc/yum.repos.d
~ mv CentOS-Base.repo CentOS-Base.repo.bak
~ mv CentOS-Debuginfo.repo CentOS-Debuginfo.repo.bak
~ mv CentOS-Vault.repo CentOS-Vault.repo.bak

第三步:修改光盘yum源配置文件CentOS-ISO.repo,参照以下方法修改:

~ vim CentOS-ISO.repo
[CentOS-ISO]
name=CentOS-ISO
baseurl=file:///mnt/cdrom
# 地址为你自己的光盘挂载地址
# file:///media/cdrom/
# file:///media/cdrecorder/
# 注释掉两个不存在的地址
enabled=1
# 把 enabled=0 改为 enabled=1,让这个 yum 源配置文件生效
gpgcheck=1
gpgfile=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-6
# 将软件包信息提前在本地索引缓存,用来提高搜索安装软件的速度
~ yum makecache fast
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
CentOS-ISO                                                                    | 4.0 kB     00:00 ...
CentOS-ISO/group_gz                                                           | 242 kB     00:00 ...
CentOS-ISO/filelists_db                                                       | 6.3 MB     00:00 ...
CentOS-ISO/other_db                                                           | 2.8 MB     00:00 ...
Metadata Cache Created
# 显示所有仓库
~ yum repolist
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
repo id                                        repo name                                       status
CentOS-ISO                                     CentOS-ISO                                      6,713
repolist: 6,713
# 详细信息内容显示
~ yum list

2.4.3 yum 命令

1)查询

  • 查询 yum 源服务器上所有可安装的软件包列表。
~ yum list
# 查询所有可用软件包列表
Installed Packages
# 已经安装的软件包
ConsoleKit.x86_64                        0.4.1-6.el6                 @anaconda-CentOS-201806291108.x8
6_64/6.10
ConsoleKit-libs.x86_64                   0.4.1-6.el6                 @anaconda-CentOS-201806291108.x8
6_64/6.10
...省略部分输出...
Available Packages
# 还可以安装的软件包
389-ds-base.x86_64                       1.2.11.15-95.el6_9          CentOS-ISO
389-ds-base-devel.i686                   1.2.11.15-95.el6_9          CentOS-ISO
# 软件包                                                                   版本                                               所在位置(光盘)
...省略部分输出...
  • 查询 yum 源服务器中是否包含某个软件包
~ yum list 包名
# 查询单个软件包
# 例如:
~ yum list samba
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
Available Packages
samba.x86_64                                 3.6.23-51.el6                                 CentOS-ISO
  • 搜索 yum 源服务器上所有和关键字相关的软件包
~ yum search 关键字
# 搜索服务器上所有和关键字相关的软件包
# 例如
~ yum search ifconfig
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
========================================= Matched: ifconfig =========================================
net-tools.x86_64 : Basic networking tools

yum search 搜索可以用于确定某个软件在哪个相关包当中。此例子可以确定“ifconfig”命令需要安装“net-tools”包。

  • 查询指定软件包的信息
~ yum info 包名~ yum info samba
# 查询 samba 软件包的信息
Loaded plugins: fastestmirror, refresh-packagekit, security
Loading mirror speeds from cached hostfile
Available Packages                  # 还没有安装
Name        : samba                 # 包名
Arch        : x86_64                # 适合的硬件平台
Version     : 3.6.23                # 版本
Release     : 51.el6                # 发布版本
Size        : 5.1 M                 # 大小
Repo        : CentOS-ISO        # 在光盘上
...省略部分输出...
  • (1)安装
~ yum install -y 包名
选项:install 安装-y          自动回答yes,如果不加 -y,那么每个安装的软件都需要手工回答 yes
# 例如
~ yum install -y gcc
# 使用 yum 自动安装 gcc
  • (2)升级
~ yum update -y 包名
# 升级指定的软件包
选项:update:升级-y       :自动回答 yes

注意:在进行升级操作时,yum源服务器中软件包的版本要比本机安装的软件包的版本高。

~ yum update -y
# 升级本机所有软件包

这条命令会升级系统中所有的软件包。不过我们的生产服务器是稳定优先的,所以这种全系统升级的情况并不多见。包括升级内核。

  • (3)卸载

再次强调一下,除非你确定卸载的软件的依赖包不会对系统产生影响,否则不要执行 yum的卸载,因为很有可能在卸载软件包的同时卸载的依赖包也是重要的系统文件,这就有可能导致系统崩溃。卸载命令如下:

~ yum remove 包名
# 卸载指定的软件包
# 例如
~ yum remove -y samba
# 卸载 samba 软件包

2.4.4 yum 组管理命令

  • yum 查询可以安装的软件组
~ yum grouplist
# 列出所有可用的软件组列表
  • 查询软件组内包含的软件
~ yum groupinfo 软件组名
# 列出软件组中包含的软件
# 例如:
~ yum groupinfo "Web Server"
# 查询软件组"Web Server"中包含的软件
  • 安装软件组
# CentOS6.3之前的版本是不支持中文
~ yum groupinstall 软件组名
# 安装指定软件组,组名可以由 grouplist 查询出来
# 例如:
~ yum groupinstall -y "Web Server"
# 安装网页服务软件组
  • 卸载软件组
~ yum groupremove -y 软件组名
# 卸载指定软件组

三 源码包安装

3.1 注意事项

3.1.1 应该选择那种软件包?

  • 如果软件包是给大量客户提供访问,建议使用源码包安装,如LAMP环境搭建,因为源码包效率更高。
  • 如果软件包是给Linux底层使用,或只给少量客户访问,建议使用rpm包安装,因为rpm包简单。

3.1.2 源码包是从哪里来的?

rpm包是光盘中直接包含的,所以不需要用户单独下载。而源码包是通过官方网站下载的,如果需要使用,是需要单独下载的。

3.1.3 是否可以在系统中即安装 RPM 包的Apache,又安装源码包的 Apache?

原因:RPM包安装和源码安装的安装路径各不相同。答案是可以,因为两种安装方法安装的Apache,安装位置是不一样的,例如:

# RPM包:不建议指定安装位置的,建议安装在默认位置(RPM包安装的服务有标准卸载命令,不怕文件到处安装)
配置文件:/etc/httpd/conf/httpd.conf
网页位置:/var/www/html/
日志位置:/var/log/httpd/
启动方法:1)service httpd restart2)/etc/rc.d/init.d/httpd restart# 源码包:必须指定安装位置(源码包没有安装数据库,没有删除命令)
配置文件:/usr/local/apache2/conf/httpd.conf
网页文件:/usr/local/apache2/htdocs/
日志文件:/usr/local/apache2/logs/
启动方法:/usr/local/apache2/bin/apachectl start

3.1.4 生产服务器上,是否会同时安装两种Apache?

当然不会啊,因为系统中只有一个80端口,所以你只能启动一个Apache,装多个只能浪费资源。我们建议安装源码包的 Apache。

小总结:

服务是否可以修改端口:

  • 如果服务是给大量客户端访问,不建议更换端口,因为用户就找不到了
  • 如果服务是给内部人员使用,建议改换端口,因为更加安全(SSH 22)

3.2 安装过程

我们来解释一下源码包安装的具体步骤。

(1)下载软件包。

(2)解压缩。

(3)进入解压目录。

(4)./configure 编译前准备。

这一步主要有三个作用:

  1. 在安装之前需要检测系统环境是否符合安装要求。
  2. 定义需要的功能选项。“./configure”支持的功能选项较多,可以执行“./configure --help”命令查询其支持的功能。一般都会通过“./configure --prefix=安装路径”来指定安装路径。
  3. 把系统环境的检测结果和定义好的功能选项写入Makefile文件,后续的编译和安装需要依赖这个文件的内容。

需要注意的是,configure不是系统命令,而是源码包软件自带的一个脚本程序,所以必须采用“./configure”方式执行(“./”代表在当前目录下。./是执行可执行程序的意思。shell脚本也可以直接这么用)。

(5)make 编译

make 会调用gcc编译器,并读取 Makefile 文件中的信息进行系统软件编译。编译的目的就是把源码程序转变为能被Linux 识别的可执行文件,这些可执行文件保存在当前目录下。编译过程较为耗时,需要有足够的耐心。

(6)make clean 清空编译内容(非必需步骤)

如果在“./configure”或“make”编译中报错,那么我们在重新执行命令前一定要记得执行make clean命令,它会清空Makefile文件或编译产生的“.o”头文件。

(7)make install 编译安装

这才是真正的安装过程,一般会写清楚程序的安装位置。如果忘记指定安装目录,则可以把这个命令的执行过程保存下来,以备将来删除使用。

小总结:

configure 和 make 是都不会硬盘写入任何数据的,只要以上两条命令有任何的报错,则就可以使用 make clean 清空编译内容。

make install 会向硬盘写入数据。

源码包和 RPM 包的管理方法尽量不要放在一块。

源码包:

  • ./configure --prefix=/usr/loca/apache2/
  • make && make install

源码包报错:

1)安装过程必须停止

2)是否出现 no、warning、error 关键字

范例:

# 启动Apache2
~ /usr/local/apache2/bin/apachectl start
~ ps -aux | grep apache2
Warning: bad syntax, perhaps a bogus '-'? See /usr/share/doc/procps-3.2.8/FAQ
root      52603  0.0  0.1  35484  2172 ?        Ss   11:45   0:00 /usr/local/apache2/bin/httpd -k start
daemon    52604  0.0  0.0  35484  1572 ?        S    11:45   0:00 /usr/local/apache2/bin/httpd -k start
daemon    52605  0.0  0.0  35484  1572 ?        S    11:45   0:00 /usr/local/apache2/bin/httpd -k start
daemon    52606  0.0  0.0  35484  1572 ?        S    11:45   0:00 /usr/local/apache2/bin/httpd -k start
daemon    52607  0.0  0.0  35484  1572 ?        S    11:45   0:00 /usr/local/apache2/bin/httpd -k start
daemon    52608  0.0  0.0  35484  1572 ?        S    11:45   0:00 /usr/local/apache2/bin/httpd -k start
root      52622  0.0  0.0 103324   852 pts/1    S+   11:48   0:00 grep --color=auto apache2~ curl localhost
<html><body><h1>It works!</h1></body></html>

3.3 删除

源码包没有删除命令,如果需要删除,直接删除安装目录即可。

3.4 补丁

3.4.1 补丁的生成

~ diff 选项 old new
# 比较 old 和 new 文件的不同
# 选项
-a  将任何文档当做文本文档处理
-b  忽略空格造成的不同
-B  忽略空白行造成的不同
-I  忽略大小写造成的不同
-N  当比较两个目录时,如果某个文件只在一个目录中,则在另一个目录中视作空文件
-r  当比较目录时,递归比较子目录
-u  使用同一的输出格式

举例:

~ mkdir -pv test
# 建立测试目录
~ cd test
# 进入测试目录
~ cat > old.txt <<EOF
our
school
is
kubesphere
EOF
# 文件 old.txt,为了一会输出便于比较,每行分开
~ cat > new.txt <<EOF
our
school
is
kubesphere
in
Shenzhen
EOF

比较下两个文件的不同,并生成补工文件“txt.patch”,命令如下:

~ diff -Naur /root/test/old.txt /root/test/new.txt
~ diff -Naur /root/test/old.txt /root/test/new.txt > txt.patch
# 比较两个文件的同步,同时生成 txt.patch 补丁文件
--- /root/test/old.txt  2022-08-04 11:59:55.259294777 +0800
+++ /root/test/new.txt  2022-08-04 12:00:09.229909280 +0800
@@ -2,3 +2,5 @@schooliskubesphere
+in
+Shenzhen# 查看下这个文件
~ vi txt.patch
--- /root/test/old.txt  2022-08-04 11:59:55.259294777 +0800
# 前一个文件
+++ /root/test/new.txt  2022-08-04 12:00:09.229909280 +0800
# 后一个文件
@@ -2,3 +2,5 @@schooliskubesphere
+in
+Shenzhen

#后一个文件比前一个文件多两行(+表示)

3.4.2 打入补丁

~ patch -pn < 补丁文件
# 按照补丁文件就行更新
选项:-pn :n为数字。代表按照补丁文件中的路径,指定更新文件的位置

“-pn”不好理解,我们说明下。补丁文件是要打入旧文件的,但是你当前所在的目录和补丁文件中的记录的目录是不一定匹配的,所以就需要“-pn”来同步两个目录。

比如我当前是在“/root/test”目录中(我要打补丁的旧文件就在当前目录下),补丁文件中记录的文件目录为“/root/test/old.txt”,这时如果写入“-p1”(在补丁文件目录中取消一级目录)那么补丁文件就会打入“/root/test/root/test/old.txt”文件中,这显然是不对的。那如果写入的是“-p2”(在补丁文件目录中取消二级目录)那么补丁文件打入的就是“/root/test/test/old.txt”,这显然也不对。如果写入的是“-p3”(在补丁文件目录中取消三级目录)那么补丁文件就是打入的“/root/test/old.txt”,我们的old.txt文件就在这个目录下,所以就应该是“-p3”。

那么我们更新下“old.txt”文件,命令如下:

~ patch -p3 < txt.patch
patching file old.txt
# 给 old.txt 文件打入补丁~ cat old.txt
# 查看以下 old.txt 的内容
our
school
is
kubesphere
in
Shenzhen
# 多出来了 in Shenzhen 两行

四 脚本安装程序

4.1 脚本程序简介

脚本程序包并不多见,所以在软件包分类中并没有把它列为一类。它更加类似于Windows下的程序安装,有一个可执行的安装程序,只要运行安装程序,然后进行简单的功能定制选择(比如指定安装目录等),就可以安装成功,只不过是在字符界面下完成的。

目前常见的脚本程序以各类硬件的驱动居多,我们需要学习一下这类软件的安装方式,以备将来不时之需。

4.2 Webmin 安装

4.2.1 简介

我们来看看脚本程序如何安装和使用。安装一个叫作 Webmin的工具软件,Webmin是一个基于Web的系统管理界面。借助任何支持表格和表单的浏览器(和file Manager模块所需要的Java),你就可以设置用户账号、apache、DNS、文件共享等。Webmin包括一个简单的Web服务器和许多CGI程序,这些程序可以直接修改系统文件,比如 /etc/inetd.conf 和 /etc/passwd。Web服务器和所有的 CGI程序 都是用 Perl 5 编写的,没有使用任何非标准 Perl 模块。也就是说,Webmin是一个用 Perl 语言写的、可以通过浏览器管理 Linux 的软件。

Webmin 本质就是使用 Web 浏览器来管理 Linux 系统的软件。

4.2.2 安装步骤

首先下载Webmin软件,地址为 http://sourceforge.net/projects/webadmin/files/webmin/,这里下载的是 webmin-1.610.tar.gz。

接下来解压缩软件,命令如下:

wget --no-check-certificate https://sourceforge.net/projects/webadmin/files/webmin/1.610/webmin-1.610.tar.gz/download
tar -zxvf webmin-1.610.tar.gz

进入解压目录,命令如下:

cd webmin-1.610

执行安装程序 setup.sh 并指定功能选项,命令如下:

~ ./setup.sh
***********************************************************************
*            Welcome to the Webmin setup script, version 1.610        *
***********************************************************************
Webmin is a web-based interface that allows Unix-like operating
systems and common Unix services to be easily administered.Installing Webmin in /root/webmin-1.610 ...***********************************************************************
Webmin uses separate directories for configuration files and log files.
Unless you want to run multiple versions of Webmin at the same time
you can just accept the defaults.Config file directory [/etc/webmin]:
# 选择安装位置,默认安装在 /etc/webmin 目录下,如果安装到默认位置,则直接回车
Log file directory [/var/webmin]:
# 日志文件保存位置,直接回车,选择默认位置
***********************************************************************
Webmin is written entirely in Perl. Please enter the full path to the
Perl 5 interpreter on your system.Full path to perl (default /usr/bin/perl):
# 指定 Perl 语言的安装位置,直接回车,选择默认位置,Perl 默认就安装在这里
Testing Perl ...
Perl seems to be installed ok***********************************************************************
Operating system name:    CentOS Linux
Operating system version: 6.10***********************************************************************
Webmin uses its own password protected web server to provide access
to the administration programs. The setup script needs to know :- What port to run the web server on. There must not be anotherweb server already using this port.- The login name required to access the web server.- The password required to access the web server.- If the webserver should use SSL (if your system supports it).- Whether to start webmin at boot time.Web server port (default 10000):
# 指定Webmin 监听的端口,直接回车,默认选定10000
Login name (default admin):
# 输入登录Webmin 的用户名
Login password:
Password again:
# 输入登录密码
The Perl SSLeay library is not installed. SSL not available.
# Apache 默认没有启动SSL功能,所以SSL没有被激活
Start Webmin at boot time (y/n):y
...省略部分内容...Attempting to start Webmin mini web server..
Starting Webmin server in /root/webmin-1.610
Pre-loaded WebminCore
..done***********************************************************************
Webmin has been installed and started successfully. Use your web
browser to go tohttp://10.0.0.40:10000/and login with the name and password you entered previously.

五 用户管理

个人电脑 和 服务器级别的用户管理和用户权限管理是不一样的。Windows 的权限是绑定在用户组上的,用户拥有什么权限,不取决于该用户,而是取决于该用户所属于的用户组。默认Windows 添加的新用户都是属于 User 组中。

  • Windows 的权限是绑定在用户组中的,Linux 的权限是绑定在用户 UID 中的。

权限分割 主要规范内部人员。

系统权限 ROOT 给了运维同学,ROOT 权限给运维主管,普通权限给普通运维。MySQL 给了 DBA 普通权限进行处理。在 数据库 ROOT 权限是 DBA 使用。

5.1 用户相关文件

5.1.1 /etc/passwd 用户信息文件

root❌0:0:root:/root:/bin/bash

第一列:用户名

第二列:密码位

第三列:用户ID

  • 0 超级用户UID。如果用户UID为0,代表这个账号是管理员账号。那Linux中如何把普通用户升级成为管理员呢?就是把其他用户的UID修改为0就可以了,这点和Windows是不同的。不过不建议建立多个管理员账号。

  • 1-499 系统用户(伪用户)UID。这些UID账号是系统保留给系统用户的UID,也就是说UID是1-499范围内的用户是不能登录系统的,而是用来运行系统或服务的。其中 1-99是系统保留的账号,系统自动创建。100-499是预留给用户创建系统账号的。

  • 500-65535普通用户UID。建立的普通用户UID 从500开始,最大到65535。这些用户足够使用了,但是如果不够也不用害怕,2.6.x内核以后的Linux系统用户UID已经可以支持 2^32 这么多了。

  • CentOS 7 之后,系统用户是在 1-999 系统用户(伪用户)UID。理论上每个服务都需要有各自服务的伪用户。

第四列:组ID、GID添加用户时,如果不指定用户所属的初始组,那么会建立和用户名相同的组

第五列:用户说明

第六列:用户家目录 ~

第七列:登录Shell /bin/bash

如何把普通用户变成超级用户:把用户 UID 改为 0。

5.1.2 /etc/shadow 影子文件

RHEL 5 之前的用户密码加密算法是 MD5,RHEL 6 之后的用户密码加密算法是 SHA512

root: 6 6 6SckntYMN$xhj0yVZ8U4rTQDkZQnrxd0aU42iXFjMu9KIbpsuyG2WRBVI6zTBTcvCxua4BveAL0qvj7IuhDr2tFhBFGCXZ6/:19188:0:99999:7:::

第一列:用户名

第二列:加密密码

我们也可以在密码前人为的加入“!”或“*”改变加密值让密码(暂时失效)-,使这个用户无法登陆,达到暂时禁止用户登录的效果。

注意所有伪用户的密码都是“!!”或“*”,代表没有密码是不能登录的。当然我新创建的用户如果不设定密码,它的密码项也是“!!”,代表这个用户没有密码,不能登录

第三列:密码最近更改时间,1970年1月1日作为标准时间

时间截转日期

~ date -d "1970-01-01 15775 days"
Mon Mar 11 00:00:00 CST 2013~ date -d "1970-01-01 19188 days"
Fri Jul 15 00:00:00 CST 2022

日期转时间戳

~ echo $(($(date --date="2013/03/11" +%s)/86400+1))
15775~ echo $(($(date --date="2022/8/11" +%s)/86400+1))
19215
~ getent shadow user1
user1:$6$GuICMum6$giOwTp2nkXWvf5mxntP6tP/teKHckB1mA491lmX.GokT8ufWRKFN9rVpsYr.wZG31Ww4Xyza6jXMOwIBQJElo1:19215:0:99999:7:::

第四列:两次密码的修改间隔时间(和第3字段相比,不推荐修改)

第五例:密码有效期(和第3字段相比,99999 相当于是永久有效)

  • 密码的三要素:复杂性、记忆性、时效性。

第六列:密码修改到期前的警告天数(和第5字段相比)

第七列:密码过期后的宽限天数(和第5字段相比)

  • 默认值是 -1,代表该用户的密码是永不过期的。
  • 设置为 0 ,代表该用户密码过期后就不会生效。

第八列:密码失效时间

这里同样要写时间戳,也就是用1970年1月1日进行时间换算。如果超过了失效时间,就算密码没有过期,用户也就失效无法使用了。

  • 密码失效后,会在用户的加密密码上添加一个"!" 以达到用户暂时无法登录的效果。需要管理员手动修改。

第九列:保留

5.1.3 /etc/group 组信息文件

root❌0:root

第一列:组名

第二列:组密码位,并不推荐在用户组上设置密码。

第三列:GID,组ID号

第四列:此组中支持的其他用户,附加组是此组的用户

初始组:每个用户初始组只能有一个,初始组只能有一个,一般都是和用户名相同的组作为初始组

附加组:每个用户可以属于多个附加组。要把用户加入组,都是加入附加组

5.1.4 组密码文件 /etc/gshadow

如果我给用户组设定了组管理员,并给该用户组设定了组密码,组密码就保存在这个文件当中。组管理员就可以利用这个密码管理这个用户组了。

5.1.5 用户的家目录

默认普通用户的家目录是在 /home 下创建同名的家目录

5.1.6 用户的邮箱目录

这个邮箱在/var/spool/mail目录当中,例如lamp用户的邮箱就是/var/spool/mail/lamp文件

5.1.7 用户模板目录

/etc/skel 目录是用来存放新用户配置文件的目录,当我们添加新用户的时候,这个目录下的所有文件会自动被复制到新添加的用户的家目录下。
这个目录下的所有文件都是隐藏文件(以.点开头的文件)。
通过修改、添加、删除/etc/skel目录下的文件,我们可为新创建的用户提供统一的、标准的、初始化用户环境。

5.1.8 用户创建的默认值

/etc/default/useradd 定义创建新用户的适合,从哪里 COPY 环境变量文件,默认执行 Shell 的方式等等

# useradd defaults file
GROUP=100                              #用户默认组
HOME=/home                         #用户家目录
INACTIVE=-1                            #密码过期宽限天数(shadow文件 7 字段)
EXPIRE=                                    #密码失效时间(shadow文件 8 字段)
SHELL=/bin/bash                    #默认Shell类型
SKEL=/etc/skel                 #模板目录
CREATE_MAIL_SPOOL=yes      #是否建立邮箱

5.2 用户管理命令

5.2.1 添加用户

5.2.1.1 手工删除用户

手工删除用户实验:手工删除,如果可以正常建立用户,证明用户删除干净

  1. /etc/passwd
  2. /etc/shadow
  3. /etc/group
  4. /etc/gshadow
  5. /home/user1
  6. /var/spool/mail/user1 邮箱
DELUSER="user1"
sed -i.bak -r "/${DELUSER}/d" /etc/passwd
sed -i.bak -r "/${DELUSER}/d" /etc/shadow
sed -i.bak -r "/${DELUSER}/d" /etc/group
sed -i.bak -r "/${DELUSER}/d" /etc/gshadow
rm -rf /home/${DELUSER} ; rm -rf /var/spool/mail/${DELUSER}~ id user1
id: user1: no such user# userdel -r user1

5.2.1.2 useradd 命令

useradd 选项 用户名

选项

  • -u 550 指定UID,不太推荐使用
  • -g 组名 指定初始组,不要手工指定
  • -G 组名 指定附加组,把用户加入组,使用附加组
  • -c 说明 添加说明
  • -d 目录 手工指定家目录,目录不需要事先建立
  • -s shell /bin/bash

例如:

~ groupadd lamp1
#先手工添加lamp1用户组,因为我一会要把lamp1用户的初始组指定过来,如果不事先建立,会报错用户组不存在~ useradd -u 550 -g lamp1 -G root -d /home/lamp1 -c "test user" -s /bin/bash lamp1
#建立用户lamp1的同时指定了UID(550),初始组(lamp1),附加组(root),家目录(/home/lampl),
#用户说明(test user)和用户登录shell (/bin/bash)~ grep "lamp1" /etc/passwd /etc/shadow /etc/group
/etc/passwd:lamp1:x:550:1002:test user:/home/lamp1:/bin/bash
#用户的UID、初始组、用户说明、家目录和登录shell都和命令手工指定的一致
/etc/shadow:lamp1:!!:19215:0:99999:7:::
#lamp1用户还没有设定密码
/etc/group:root:x:0:lamp1
#lamp1用户加入了root组, root组是lamp1用户的附加组
/etc/group:lamp1:x:1002:
#GID502的组是lamp1组~ ls -ld /home/lamp1/
drwx------ 3 lamp1 lamp1 95 Aug 11 11:12 /home/lamp1/
# 家目录也建立了,不需要手工建立家目录

范例:-g 和 -G 的区别

~ groupadd t1 ; groupadd t2
~ useradd -g t1 u1 ; useradd -G t2 u2~ id u1
uid=1001(u1) gid=1003(t1) groups=1003(t1)
~ id u2
uid=1002(u2) gid=1005(u2) groups=1005(u2),1004(t2)
~ grep "u2" /etc/passwd
u2:x:1002:1005::/home/u2:/bin/bash
~ grep "t2" /etc/group
t2:x:1004:u2

5.2.1.3 useradd 默认值

useradd 添加用户时参考的默认值文件主要有两个,分别是 /etc/default/useradd 和 /etc/login. defs。

1)/etc/default/useradd

~ vim /etc/default/useradd
# useradd defaults file
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=yes

挨个解释下:

  • GROUP=100

这个选项是建立用户的默认组,也就是说添加每个用户时,用户的初始组就是GID为100的这个用户组。目前我们采用的机制私有用户组机制。

  • HOME=/home

这个选项是用户的家目录的默认位置,所以所有的新建用户的家目录默认都在/home/下。

  • INACTIVE=-1

这个选项就是密码过期后的宽限天数,也就是 /etc/shadow 文件的第七个字段。如果是天数,比如10代表密码过期后10天后失效;如果是0,代表密码过期后立即失效;如果是-1,则代表密码永远不会失效。这里默认值是-1,所以所有新建立的用户密码都不会失效。

推荐改为 0 ,代表密码过期后立刻失效。

  • EXPIRE=

这个选项是密码失效时间,也就是 /etc/shadow 文件的第八个字段。也就说用户到达这个日期后就会直接失效。当然这里也是使用时间戳来表示日期的。默认值是空,所以所有新建用户没有失效时间,永久有效。

  • SHELL=/bin/bash

这个选项是用户的默认shell的。/bin/bash 是 Linux 的标志 shell,所以所有新建立的用户默认都具备 shell 赋予的权限。

  • SKEL=/etc/skel

这个选项就是定义用户的模板目录的位置,/etc/skel/目录中的文件都会复制到新建用户的家目录当中。

  • CREATE_MAIL_SPOOL=yes

这个选项定义是否给新建用户建立邮箱,默认是创建,也就是说所有的新建用户系统都会新建一个邮箱,放在 /var/spool/mail/ 下和用户名相同。

2)/etc/login.defs

~ grep -Ev "^#" /etc/login.defs
# vim /etc/login.defs
#这个文件有些注释,把注释删除掉,文件内容就变成下面这个样子
MAIL_DIR        /var/spool/mailPASS_MAX_DAYS   99999
PASS_MIN_DAYS   0
PASS_MIN_LEN    5
PASS_WARN_AGE   7UID_MIN                  1000
UID_MAX                 60000
SYS_UID_MIN               201
SYS_UID_MAX               999GID_MIN                  1000
GID_MAX                 60000
SYS_GID_MIN               201
SYS_GID_MAX               999CREATE_HOME     yesUMASK           077USERGROUPS_ENAB yesENCRYPT_METHOD SHA512

我们一行一行解释下文件内容:

  • MAIL_DIR /var/spool/mail

这行指定了新建用户的默认邮箱位置。比如lamp用户的邮箱是就是/var/spool/mail/lamp。

  • PASS_MAX_DAYS 99999

这行指定的是密码的有效期,也就是/etc/shadow文件的第五字段。代表多少天之后必须修改密码,默认值是99999。推荐进行修改该参数的值,尽量设置的小一些。

  • PASS_MIN_DAYS 0

这行指定的是两次密码的修改间隔时间,也就是/etc/shadow文件的第四字段。代表第一次修改密码之后,几天后才能再次修改密码。默认值是0。

  • PASS_MIN_LEN 5

这行代表密码的最小长度,默认不小于5位。但是我们现在用户登录时验证已经被PAM模块取代,所以这个选项并不生效。

  • PASS_WARN_AGE 7

这行代表密码修改到期前的警告天数,也就是/etc/shadow文件的第六字段。代表密码到底有效期前多少天开始讲行警告提醒,默认值是7天。

  • UID_MIN 500
  • UID_MAX 60000

这两行代表创建用户时,最小UID和最大的UID的范围。我们2.6.x内核开始,Linux用户的UID最大可以支持2这么多,但是真正使用时最大范围是60000。还要注意如果我手工指定了一个用户的UID是550,那么下一个创建的用户的UID就会从551开始,哪怕500-549之间的UID没有使用(小于500的UID是给伪用户预留的)。

  • GID_MIN 500
  • GID_MAX 60000

这两行指定了GID的最小值和最大值之间的范围。

  • CREATE_HOME yes

这行指定建立用户时是否自动建立用户的家目录,默认是建立

  • UMASK 077

这行指定的是建立的用户家目录的默认权限,因为umask值是 077,所以新建的用户家目录的权限是700,umask的具体作用和修改方法我们可以参考下一章权限设定章节。

  • USERGROUPS_ENAB yes

这行指定的是使用命令 userdel 删除用户时,是否删除用户的初始组,默认是删除。

  • ENCRYPT_METHOD SHA512

这行指定Linux用户的密码使用 SHA512 散列模式加密,这是新的密码加密模式,原先的Linux只能用 DES 或 MD5 方式加密

5.2.2 设定密码

超级用户可以设置其他普通用户以及自身的密码;普通用户只能设置自身的密码。

~ passwd [选项] 用户名
选项:-l:暂时锁定用户。仅root用户可用-u:解锁用户。仅root用户可用--stdin:可以将通过管道符输出的数据作为用户的密码。主要在批量添加用户时使用~ passwd
#passwd 直接回车代表修改当前用户的密码

也可以使用字符串作为密码:

~ echo "123" | passwd --stdin lamp
# 更改用户 lamp 的密码

可以通过命令,把密码修改日志归零(shadow 第3字段)。这样用户一登陆就要修改密码,例如:

chage -d 0 lamp# 登录强制修改密码
chage -d 0 <user-name>
passwd -e <user-name>

5.2.3 用户信息修改

usermod命令是修改已经添加的用户的信息的,命令如下:

~ usermod [选项] 用户名
选项:
-u UID  :修改用户的UID
-d 家目录:修改用户的家目录。家目录必须写绝对路径
-c 用户说明:修改用户的说明信息,就是/etc/passwd文件的第五个字段
-g 组名   :修改用户的初始组,就是/etc/passwd 文件的第四个字段
-G 组名   :修改用户的附加组,其实就是把用户加入其他用户组(usermod 常用的选项)
-s shell:修改用户的登录Shell。默认是/bin/bash
-e 日期   :修改用户的失效日期,格式为“YYYY-MM-DD”。也就是/etc/shadow文件的第八个字段
-L  :临时锁定用户(Lock)
-U  :解锁用户(Unlock)

Linux 系统中,不建议修改用户名;原因:Windows 更加的智能,修改用户名之后,会自动的将日志中该用户名也进行相关的修改操作,而 Linux 系统中的用户名修改后,初始组以及对应的信息均不会进行修改。

那用户可以修改用户名吗?当然可以:

~ usermod -l 新名 旧名
# 改名

但是真不建议改名,这样及其容易把管理员自己搞晕菜,建议删除旧用户,再建立新用户!

5.2.4 删除用户

~ userdel [-r] 用户名
选项:-r:在删除用户的同时删除用户的家目录-f:强制删除

范例:

userdel -r user2

5.2.5 切换用户身份

su命令可以切换成不同的用户身份,命令格式如下:

~ su [选项] 用户名
选项:-          :选项只使用“-”代表连带用户的环境变量一起切换-c 命令:仅执行一次命令,而不切换用户身份

“_”不能省略,它代表切换用户身份时,用户的环境变量也要切换成新用户的环境变量。

~ su - u1
[u1@zdevops-master ~]$ pwd
/home/u1# 执行一次命令,而不切换用户身份
[u1@zdevops-master ~]$ su - root -c ls /root
Password:
anaconda-ks.cfg  reset.sh

5.3 组管理命令

5.3.1 添加用户组:groupadd

添加用户组的命令是groupadd,命令格式如下:

~ groupadd [选项] 组名
选项:-g GID:指定组ID

添加用户组的命令比较简单,举个例子:

~ groupadd group1
#添加group1组
~ grep "group1" /etc/group
group1:x:1005:

5.3.1 删除用户组:groupdel

groupdel命令用于删除用户组,命令格式如下:

~ groupdel 组名#例子:
~ groupdel testgrp
#删除 testgrp 组

不过大家要注意,要删除的组不能是其他用户的初始组,也就是说这个组中没有初始用户才可以删除。如果组中有附加用户,则删除组时不受影响。

删除用户组时,一定要确保该用户组内不能含有其他用户使用该用户组。删除用户组的时候,必须确保该用户组没有初始用户。否则是无法删除的。

5.4 把用户添加进组或从组中删除:gpasswd

其实 gpasswd命令是用来设定组密码并指定组管理员的,不过我们在前面已经说了,组密码和组管理员功能很少使用,而且完全可以被sudo命令取代,所以 gpasswd命令现在主要用于把用户添加进组或从组中删除。命令格式如下:

~ gpasswd [选项] 组名
选项:-a 用户名:把用户加入组-d 用户名:把用户从组中删除

举个例子:

~ groupadd grouptest
#添加组 grouptest~ gpasswd -a lamp grouptest
Adding user lamp to group grouptest
#把用户lamp加入到 grouptest~ grep "lamp" /etc/group
grouptest:x:1006:lamp
lamp:x:1007:
#查看一下,lamp用户已经作为附加用户加入到grouptest用户组~ gpasswd -d lamp grouptest
Removing user lamp from group grouptest
#把用户lamp从组中删除~ grep "lamp" /etc/group
lamp:x:1007:
#组中没有lamp用户了

大家注意,也可以使用usermod命令把用户加入某个组,不过usermod命令的操作对象是用户,命令是“usermod -G grouptest lamp”,把用户名作为参数放在最后;而 gpasswd 命令的操作对象是组,命令是“gpasswd -a lamp grouptest”,把组名作为参数放在最后。

5.5 改变有效组:newgrp

我们说过,每个用户可以属于一个初始组(用户是这个组的初始用户),也可以属于多个附加组(用户是这个组的附加用户)。既然用户可以属于这么多用户组,那么用户在创建文件后,默认生效的组身份是哪个呢?当然是初始用户组的组身份生效了,因为初始组是用户一旦登录就直接获得的组身份。也就是说,用户在创建文件后,文件的属组是用户的初始组,因为用户的有效组默认是初始组。既然用户属于多个用户组,那么能不能改变用户的有效组呢﹖使用命令newgrp就可以切换用户的有效组。命令格式如下:

~ newgrp 组名
#前提是该用户需要在修改的用户组内(附加组)

举个例子,我们已经有了普通用户user1,默认会建立user1用户组,user1组是user1用户的初始组。我们再把user1用户加入group1组,那么group1组就是user1用户的附加组。当user1 用户创建文件test1时,test1文件的属组是user1组,因为userl组是user1用户的有效组。通过newgrp 命令就可以把user1用户的有效组变成 group1组,当 user1用户创建文件test2 时,就会发现 test2文件的属组就是group1组。命令如下:

➜  ~ useradd -c "Test User1" user1 ; useradd -c "Test User2" user2
#添加测试用户
➜  ~ groupadd group1
#添加组group1
➜  ~ gpasswd -a user1 group1
#把user1用户加入group1组
Adding user user1 to group group1
➜  ~ grep "user1" /etc/group
group1:x:1049:user1
user1:x:1050:
#user1用户即属于user1,也属于group1组
➜  ~ su - user1
#切换成user1身份,超级用户切换成普通用户不用密码
[user1@kubesphere-docker ~]$ touch test1
[user1@kubesphere-docker ~]$ ls -l test1
-rw-rw-r-- 1 user1 user1 0 Aug 11 14:55 test1
#test1文件的默认属组是 user1 组
[user1@kubesphere-docker ~]$ newgrp group1
#切换user1用户的有效组为 group1 组,会新开启一个Bash,用户组为 newgrp 的组
[user1@kubesphere-docker ~]$ touch test2
[user1@kubesphere-docker ~]$ ls -l
total 0
-rw-rw-r-- 1 user1 user1  0 Aug 11 14:55 test1
-rw-r--r-- 1 user1 group1 0 Aug 11 14:56 test2
#test2文件的默认属组是 group1 组

通过这个例子明白有效组的作用了吗?其实就是当用户属于多个组时,在创建文件时哪个组身份生效。使用newgrp命令可以在多个组身份之间切换。

扩展

~ id user2
uid=502(user2) gid=502(user2) groups=502(user2),501(user1)
#用户ID,用户组ID,用户组:初始组,附加组~ su - user2
$ whoami
user2
$ pwd
/home/user2

5.6 组权限实验

#新建测试目录
~ mkdir -pv /www
#创建新增用户
~ useradd -c "Test User" sc
~ echo "123456" | passwd --stdin sc &> /dev/null~ groupadd tg
~ for u in user{1,2} ; do useradd -c "Test User" $u ; echo "123456" | passwd --stdin $u &> /dev/null ; done
~ gpasswd -a user1 tg ; gpasswd -a user2 tg
~ id user1
uid=501(user1) gid=501(user1) groups=501(user1),504(tg)
~ id user2
uid=502(user2) gid=502(user2) groups=502(user2),504(tg)~ chown sc:tg /www/
~ ls -ld /www/
drwxr-xr-x 2 sc tg 6 Aug 11 15:57 /www/
~ chmod 770 /www/
~ ls -ld /www/
drwxrwx--- 2 sc tg 6 Aug 11 15:57 /www/

六 权限管理

Windows 系统中的权限管理也是依旧复杂,结合了域控制之后,权限管理会更加复杂。

传统的所有者,所属组,其他人的三种身份权限显得不够,需要使用ACL权限来解决用户对文件身份不足的问题。

6.1 ACL 权限

6.1.1 ACL 概述

ACL 主要是用于解决用户对文件身份不足的问题。

在普通权限中,用户对文件只有三种身份,就是属主、属组和其他人;每种用户身份拥有读(read)、写(write)和执行(execute)三种权限。但是在实际工作中,这三种身份实在是不够用,我们举个例子来看看。

根目录中有一个 /project 目录,这是班级的项目目录。班级中的每个学员都可以访问和修改这个目录,老师也需要对这个目录拥有访问和修改权限,其他班级的学员当然不能访问这个目录。需要怎么规划这个目录的权限呢?应该这样:老师使用 root 用户,作为这个目录的属主,权限为 rwx;班级所有的学员都加入 tgroup 组,使 tgroup 组作为 /project 目录的属组,权限是 rwx;其他人的权限设定为 0。这样这个目录的权限就可以符合我们的项目开发要求了。

有一天,班里来了一位试听的学员 st,她必须能够访问 /project 目录,所以必须对这个目录拥有 r 和 x 权限;但是她又没有学习过以前的课程,所以不能赋予她 w 权限,怕她改错了目录中的内容,所以学员 st 的权限就是 r-x。可是如何分配她的身份呢?变为属主?当然不行,要不 root 该放哪里?加入 tgroup 组?也不行,因为 tgroup 组的权限是 rwx,而我们要求学员 st 的权限是 r-x。如果把其他人的权限改为 r-x 呢?这样一来,其他班级的所有学员都可以访问 /project 目录了。

当出现这种情况时,普通权限中的三种身份就不够用了。ACL 权限就是为了解决这个问题的。在使用 ACL 权限给用户 st 赋予权限时,st 既不是 /project 目录的属主,也不是属组,仅仅赋予用户 st 针对此目录的 r-x 权限。这有些类似于 Windows 系统中分配权限的方式,单独指定用户并单独分配权限,这样就解决了用户身份不足的问题。

ACL是Access Control List(访问控制列表)的缩写,不过在Linux系统中,ACL用于设定用户针对文件的权限,而不是在交换路由器中用来控制数据访问的功能(类似于防火墙)。

6.1.2 开启ACL

在 CentOS 6.x 系统中 ACL 权限默认是开启的,不需要手工开启。不过,如果你的操作系统不是 CentOS 6.x,那该如何查看 ACL 权限是否开启了呢?可以这样查看:

mount | grep acl
#使用mount命令可以看到系统中已经挂载的分区,但是并没有看到ACL权限的设置#dump2fs 命令是查询指定分区详细文件系统信息的命令
#选项:-h:仅显示超级块中的信息,而不是显示磁盘块组的详细信息
~ dumpe2fs /dev/sda1
...省略部分输出...
Default mount options:    user_xattr acl
...省略部分输出...#ACL权限是绑定在分区上的

如果没有开启,手工开启分区的 ACL 权限:

mount -o remount,acl /
#重新挂载根分区,并挂载加入 ACL 权限

使用 mount 命令重新挂载,并加入 ACL 权限。不过使用此命令是临时生效的。要想永久生效,需要修改 /etc/fstab 文件,命令如下:

~ vim /etc/fstab
UUID=c2ca6f57-b15c-43ea-bca0-f239083d8bd2 /ext4 defaults, acl 1 1
#加入ACL权限[root@localhost ~]# mount -o remount /
#重新挂载文件系统或重启系统,使修改生效

在你需要开启 ACL 权限的分区行上(也就是说 ACL 权限针对的是分区),手工在 defaults 后面加入",acl"即可永久在此分区中开启 ACL 权限。

6.1.3 ACL 基本命令

注意:一旦拥有的ACL权限,那么 ls -l 查看的权限就会有不准确的情况。

ACL 权限,一旦递归之后,不可避免的出现权限溢出。例如:赋予执行之后,对目录来说就是是否可以进入该目录,对文件来说就是可以运行该文件。

尽量使用标准权限,能不使用ACL权限就尽量不要使用。

getfacl 文件名 查询文件的ACL权限

setfacl [选项] 文件名 设定 ACL权限

  • -m :设定ACL权限
  • -b :输出ACL权限
  • -x :用户,删除单个用户的ACL权限

setfacl -m u:用户名:权限 文件名

setfacl -m g:组名:权限 文件名

范例:

setfacl -m u:aa:rwx /test
#给test目录赋予 aa 是读写执行的ACL权限
setfacl -m u:cc:rw -R soft/
#赋予递归ACL权限,只能赋予目录
-R:递归setfacl -m d:u:aa:rwx -R
#ACL默认权限。注意:默认权限只会赋予目录

注意:如果给目录赋予acl权限,两条命令都要输入

递归与默认的区别:

#只对已经存在的文件生效
setfacl -m u:cc:rx -R soft/#只对以后新建的文件生效
setfacl -m d:u:cc:rx -R soft/

范例:

~ setfacl -m d:u:st:r-x /www/
~ getfacl /www/
getfacl: Removing leading '/' from absolute path names
# file: www/
# owner: sc
# group: tg
user::rwx
user:st:r-x
group::rwx
mask::rwx
other::---
default:user::rwx
default:user:st:r-x
default:group::rwx
default:mask::rwx
default:other::---~ touch /www/def
~ getfacl /www/def
# file: def
# owner: root
# group: root
user::rw-
user:st:r-x                     #effective:r--
group::rwx                      #effective:rw-
mask::rw-
other::---

6.1.4 最大有效权限 mask

mask 是用来指定最大有效权限的。mask 的默认权限是 rwx,如果我给 st 用户赋予了 r-x 的 ACL 权限,mj 需要和 mask 的 rwx 权限"相与"才能得到 st 的真正权限,也就是 r-x "相与"rwxtj 出的值是 r-x,所以 st 用户拥有 r-x 权限。

如果把 mask 的权限改为 r–,和 st 用户的权限相与,也就是 r–"相与"r-x 得出的值是 r–,st 用户的权限就会变为只读。大家可以这么理解:用户和用户组所设定的权限必须在 mask 权限设定的范围之内才能生效,mask权限就是最大有效权限。

不过我们一般不更改 mask 权限,只要给予 mask 最大权限 rwx,那么任何权限和 mask 权限相与,得出的值都是权限本身。也就是说,我们通过给用户和用户组直接赋予权限,就可以生效,这样做更直观。

~ setfacl -m m:rx project/
#设定 mask 权限为 r-x,使用"m:权限"格式~ getfacl project/
# file: project/
# owner: sc
# group: tg
user::rwx
user:st:r-x                     #effective:r--
group::rwx                      #effective:rw-
mask::rw-
#mask权限变为了 r-x
other::---###Mask权限默认即可。因为在每一次用户ACL刷新后,Mask权限值都会随之刷新。
###只有等到用户ACL权限设置完毕后,再最后对Mask权限进行设置

6.1.5 删除ACL 权限

~ setfacl -x u:st /project/
#删除指定用户和用户组的ACL权限~ setfacl -b /project/
#会输出文件/目录的所有的ACL权限

6.2 sudo 授权

给普通用户赋予部分管理员权限。Linux sudo命令以系统管理者的身份执行指令,也就是说,经由 sudo 所执行的指令就好像是 root 亲自执行。

使用权限:在 /etc/sudoers 中有出现的使用者。

sudo 赋予的权限越详细,普通用户得到的权限越小

赋予的权限越简单,普通用户得到的权限越大
  • /sbin/ 在此目录下命令只有超级用户才能使用
  • /usr/sbin/

1 root 身份:

visudo 赋予普通用户权限命令,命令执行后和vi一样使用。(类似于 vim /etc/sudoers)

root    ALL=(ALL)       ALL
#用户名    被管理主机的地址=(可使用的身份) 授权命令(绝对路径)
%wheel  ALL=(ALL)       ALL
#%组名    被管理主机的地址=(可使用的身份) 授权命令(绝对路径)
#ALL=(ALL) 第一个ALL代表任意被管理端主机
  • 用户名/组名:代表root给哪个用户或用户组赋予命令,注意组名前加“%”
  • 用户可以用指定的命令管理指定IP地址的服务器。如果写ALL,代表可以管理任何主机,如果写固定IP,代表用户可以管理指定的服务器。(这里真的很奇怪啊,一直认为这里的IP地址管理的是登录者来源的IP地址,查了很多资料也都是这样的。直到有一天查看“man 5 sudoers”帮助,才发现大家原来都理解错误了,这里的IP指定的是用户可以管理哪个IP地址的服务器。那么如果你是一台独立的服务器,这里写ALL和你服务器的IP地址,作用是一样的。而写入网段,只有对NIS服务这样用户和密码集中管理的服务器才有意义)。如果我们这里写本机的IP地址,不代表只允许本机的用户使用指定命令,而代表指定的用户可以从任何IP地址来管理当前服务器。
  • 可使用身份:就是把来源用户切换成什么身份使用,(AL〉代表可以切换成任意身份。这个字段可以省略
  • 授权命令:代表root把什么命令授权给普通用户。默认是ALL,代表任何命令,这个当然不行。如果需要给那个命令授权,写入命令名即可,不过需要注意一定要命令写成绝对路径
~ man 5 sudoers
Host_Alias      CSNETS = 128.138.243.0, 128.138.204.0/24, 128.138.242.0jack CSNETS = ALL用户jack可以在CSNETS别名(网络)中的机器上运行任何命令
128.138.243.0、128.138.204.0 和 128.138.242.0)。这些网络中,只有128.138.204.0
有一个显式的网络掩码 (在CIDR符号中) 表明它是一个 C 类网络。为在CSNETS的其他网络中,本地机器的子网掩码将在匹配时使用。

2 举例

1)举个例子,比如授权用户 user1 可以重启服务器,则由root用户添加如下行:

~ visudo
user1 ALL=/sbin/shutdown -r now~ sudo -l
Matching Defaults entries for root on this host:!visiblepw, always_set_home, env_reset, env_keep="COLORS DISPLAY HOSTNAME HISTSIZE INPUTRCKDEDIR LS_COLORS", env_keep+="MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE",env_keep+="LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES", env_keep+="LC_MONETARYLC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE", env_keep+="LC_TIME LC_ALL LANGUAGE LINGUAS_XKB_CHARSET XAUTHORITY", secure_path=/sbin\:/bin\:/usr/sbin\:/usr/binUser root may run the following commands on this host:(ALL) ALL
#查看可用的授权#use1 用户登录
$sudo -l
User user1 may run the following commands on this host:(root) /sbin/shutdown -r now

2)再举个例子,授权一个用户管理你的Web服务器,不用自己插手是不是很爽,以后修改设置更新网页什么都不用管,一定Happy死了,Look:

首先要分析授权用户管理Apache至少要实现哪些基本授权:

1、可以使用Apache管理脚本

2、可以修改Apache配置文件

3、可以更新网页内容

假设 Apache管理脚本程序为/etc/rc.d/ init.d/httpd 。为满足条件一,用 visudo 进行授权:

~ vim /etc/sudoers
user1 ALL=/etc/rc.d/init.d/httpd reload, /etc/rc.d/init.d/httpd configtest
#user1 192.168.0.156=/etc/rc.d/init.d/httpd reload,/etc/rc.d/init.d/httpd configtest

授权用户user1 可以连接192.168.0.156 上的Apache服务器,通过Apache管理脚本重新读取配置文件让更改的设置生效(reload)和可以检测Apache配置文件语法错误(configtest),但不允许其执行关闭(stop)、重启(restart)等操作。(“\”的意思是一行没有完成,下面的内容和上一行是同一行。)

范例:

$ sudo -l
[sudo] password for user1:User user1 may run the following commands on this host:(root) /etc/rc.d/init.d/httpd reload, (root) /etc/rc.d/init.d/httpd configtest

为满足条件二,同样使用 visudo 授权:

~ vim /etc/sudoers
user1   ALL=/etc/rc.d/init.d/httpd reload, /etc/rc.d/init.d/httpd configtest, \/bin/vi /etc/httpd/conf/httpd.conf
#user1 192.168.0.156=/bin/vi /etc/httpd/conf/httpd.conf
#允许user1 在192.168.0.156上执行/bin/vi /etc/httpd/conf/httpd.conf
$ sudo -l
[sudo] password for user1:User user1 may run the following commands on this host:(root) /etc/rc.d/init.d/httpd reload, (root) /etc/rc.d/init.d/httpd configtest, (root)/bin/vi /etc/httpd/conf/httpd.conf

授权用户user1 可以用root身份使用vi编辑Apache配置文件。

以上两种sudo的设置,要特别注意,很多朋友使用sudo会犯两个错误:第一,授权命令没有细化到选项和参数;第二,认为只能授权管理员执行的命令。

条件三则比较简单,假设网页存放目录为/var/www/html ,则只需要授权userl对此目录具有写权限或者索性更改目录所有者为user1即可。如果需要,还可以设置 user1 可以通过FTP等文件共享服务更新网页。

3)授权aa用户可以添加其他普通用户

aa ALL=/usr/sbin/useradd 赋予aa添加用户权限,命令必须写入绝对路径

aa ALL=/usr/bin/passwd 赋予改密码权限,直接使用该操作会导致用户可以修改root密码

取消对root的密码修改

#! 代表取反的意思

aa ALL=/usr/bin/passwd [A-Za-z0-9]*, !/usr/bin/passwd “”, !/usr/bin/passwd root

aa 身份

sudo /usr/sbin/useradd ee 普通用户使用sudo命令执行超级用户命令

范例:

~ vim /etc/sudoers
user1   ALL=/etc/rc.d/init.d/httpd reload, /etc/rc.d/init.d/httpd configtest, \/bin/vi /etc/httpd/conf/httpd.conf
user1   ALL=/usr/sbin/useradd, /usr/bin/passwd [A-Za-z0-9]*, !/usr/bin/passwd "", \!/usr/bin/passwd root$ sudo -l
User user1 may run the following commands on this host:(root) /etc/rc.d/init.d/httpd reload, (root) /etc/rc.d/init.d/httpd configtest, (root)/bin/vi /etc/httpd/conf/httpd.conf(root) /usr/sbin/useradd, (root) /usr/bin/passwd [A-Za-z0-9]*, (root) !/usr/bin/passwd \"\",(root) !/usr/bin/passwd root

6.3 文件特殊权限SetUID、SetGID、StickyBIT

SetUID、SetGID、StickyBIT,该三个特殊权限也会简称为SUID,SGID,SBIT。是Linux 系统下的三个特殊权限。是Linux 应对特殊情况所准备的特殊权限。主要是用于LInux 的特殊命令,不建议以及不推荐用户手工设置特殊权限。尤其是 SUID。

特殊权限:

  • SUID:只能针对执行程序
  • SGID:既可以针对执行文件,也可以针对目录文件
  • SBIT:只能针对目录文件
  • 针对文件都是拥有风险的,针对目录的风险不是特别严重。

6.3.1 SetUID

1)SetUID 是什么

SetUID的功能可以这样理解:

  • 只有可以执行的二进制程序(执行文件)才能设定 SUID 权限
  • 命令执行者要对该程序拥有x(执行)权限
  • 命令执行者在执行该程序时获得该程序文件属主的身份(在执行程序的过程中灵魂附体为文件的属主)
  • SetUID权限只在该程序执行过程中有效,也就是说身份改变只在程序执行过程中有效
  • SUID 必须要在所有者上拥有执行权限,没有执行权限就会变成S(大写),是不会其作用的。可以得到 s(小写) = S(大写) + x。

SetUID 需要满足本身是可执行文件(在所有者上 x 执行权限),其次是其他用户可以拥有该可执行文件的执行权限(x 执行权限)。这样才会使得 SetUID 生效。

2)举例

~ ls -l /etc/passwd
-rw-r--r-- 1 root root 2773 Aug 11 14:54 /etc/passwd
~ ls -l /etc/shadow
---------- 1 root root 2750 Aug 13 11:17 /etc/shadow

因为

~ ls -l /usr/bin/passwd
-rwsr-xr-x. 1 root root 27856 Apr  1  2020 /usr/bin/passwd#普通用户是无法指定特定的用户修改密码的
~ passwd user1
passwd: Only root can specify a user name.
~ passwd
Changing password for user user1.
Changing password for user1.
New password: Admin@h3c
Retype new password: Admin@h3c
passwd: all authentication tokens updated successfully.
#这样就可以避免普通用户修改root密码以及其他用户的密码

/usr/bin/passwd 命令拥有特殊权限 SetUID,也就是在属主的权限位的执行权限上是s。可以这样来理解它:当一个具有执行权限的文件设置SetUID 权限后,用户执行这个文件时将以文件所有者的身份执行。/usr/bin/passwd命令具有SetUID 权限,所有者为root (Linux 中的命令默认所有者都是root),也就是说当普通用户使用passwd更改自己密码的时候,那一瞬间突然灵魂附体了,实际是在用 passwd 命令所有者root 的身份在执行passwd命令,root当然可以将密码写入/etc/shadow文件(不要忘记root这个家伙是superman 什么事都可以干),所以普通用户也可以修改 /etc/shadow 文件,命令执行完成后该身份也随之消失。

如果取消SetUID权限,则普通用户就不能修改自己的密码了

~ chmod u-s /usr/bin/passwd
~ ls -l /usr/bin/passwd
-rwxr-xr-x. 1 root root 27856 Apr  1  2020 /usr/bin/passwd
~ passwd
Changing password for user user1.
Changing password for user1.
(current) UNIX password:
New password:
Retype new password:
passwd: Authentication token manipulation error
#修改回来之后,就可以正常修改密码

3)危险的 SetUID

~ chmod u+s /usr/bin/vim
~ ls -l /usr/bin/vim
-rwsr-xr-x 1 root root 2337208 Dec 16  2020 /usr/bin/vim

4)有几点建议:

  • 系统分配的SUID权限的可执行权限,都是会有保险机制的,例如 passwd 命令,普通用户执行的时候只能够修改本身的密码,无法指定用户修改密码。
  • 关键目录应严格控制写权限。比如“”、“/usr”等;
  • 用户的密码设置要严格遵守密码三原则;
  • 对系统中默认应该具有SetUID权限的文件作一列表,定时检查有没有这之外的文件被设置了SetUID权限。

5)检测 SetUID 的脚本

~ find / -perm -4000 -o -perm -2000 | grep -E "^/usr/(bin|sbin)" > /root/suid.list
#创建模板文件~ vim suidcheck.sh
#!/bin/bashfind / -perm -4000 -o -perm -2000 | grep -E "^/usr/(bin|sbin)" > /tmp/setuid.check
#搜索系统中所有拥有SUID和SGID的文件,并保存到临时目录中。for i in $(cat /tmp/setuid.check)
#做循环,每次循环取出临时文件中的文件名
dogrep $i /root/suid.list > /dev/null#比对这个文件名是否在模板文件中if [ "$?" != "0" ] ; thenecho "$i isn't in listfile!"echo "$i isn't in listfile!" >> /root/suid_log_$(date +%F)#如果文件名不再模板文件中,则报错。并把报错报错到日志中fi
done
rm -rf /tmp/setuid.check
#删除临时文件~ chmod u+s /usr/bin/vim
#手工给 ls 加入SUID 权限
~ ./suidcheck.sh
#执行检测脚本
~ cat suid_log_2022-08-13
/usr/bin/ls isn't in listfile!
#报错了,ls不再模板文件中。代表 ls 被修改了SUID权限

6.3.2 SetGID

1)针对文件的作用

SGID即可以针对文件生效,也可以针对目录生效,这和SUID明显不同。如果针对文件,SGID的含义如下:

☆ 只有可执行的二进制程序才能设置SGID权限

☆ 命令执行者要对该程序拥有x(执行)权限

☆ 命令执行在执行程序的时候,组身份升级为该程序文件的属组

☆ SetGID权限同样只在该程序执行过程中有效,也就是说组身份改变只在程序执行过程中有效

~ ls -l /var/lib/mlocate/mlocate.db
-rw-r----- 1 root slocate 6469897 Aug 13 03:06 /var/lib/mlocate/mlocate.db

大家发现属主权限是 r、w,属组权限是r,但是其他人权限是 0 :

~ ls -l /usr/bin/locate
-rwx--s--x 1 root slocate 40520 Apr 11  2018 /usr/bin/locate

当普通用户user1执行locate命令时,会发生如下事情:

  • /usr/bin/locate是可执行二进制程序,可以赋予SGID
  • 执行用户user1对/usr/bin/locate命令拥有执行权限
  • 执行/usr/bin/locate命令时,组身份会升级为 slocate 组,而 slocate组对 /var/lib/mlocate/mlocate. db 数据库拥有r 权限,所以普通用户可以使用locate命令查询mlocate.db数据库
  • 命令结束,user1用户的组身份返回为user1组

2)针对目录的作用

如果SGID针对目录设置,含义如下:

  • 普通用户必须对此目录拥有 r 和 x 权限,才能进入此目录(普通用户需要对该目录拥有 rwx 7权限)
  • 普通用户在此目录中的有效组会变成此目录的属组
  • 若普通用户对此目录拥有 w 权限时,新建的文件的默认属组是这个目录的属组

这样写的实在太难看明白了,举个例子:

~ cd /tmp/
#进入临时目录做此实验。因为临时目录才允许普通用户修改
~ mkdir dtest
#建立测试目录
~ chmod g+s dtest
#给测试目录赋予SGID
~ ls -ld dtest/
drwxr-sr-x 2 root root 6 Aug 13 12:26 dtest/
#SGID已经生效
~ chmod 777 dtest/
#给测试目录权限,让普通用户可以写
~ su - user1
#切换成普通用户user1
$ cd /tmp/dtest/
#普通用户进入测试目录
$ touch abc
#普通用户建立 abc 文件
$ ls -l abc
-rw-rw-r-- 1 user1 root 0 Aug 13 12:41 abc
#若不添加SGID权限,那么普通用户创建的文件所属组依旧是普通用户
#abc文件的默认属组不再是user1用户组,而变成了dtest组的属组root

6.3.3 StickyBIT

Sticky BIT粘着位,也简称为SBIT。SBIT目前仅针对目录有效,它的作用如下:

  • 粘着位目前只对目录有效
  • 普通用户对该目录拥有 w 和 x 权限,即普通用户可以在此目录拥有写入权限(普通用户需要对该目录拥有 rwx 7权限)
  • 如果没有粘着位,因为普通用户拥有w权限,所以可以删除此目录下所有文件,包括其他用户建立的文件。一但赋予了粘着位,除了root可以删除所有文件,普通用户就算拥有w权限,也只能删除自己建立的文件,但是不能删除其他用户建立的文件。
~ ls -ld /tmp/
drwxrwxrwt. 8 root root 105 Aug 13 13:04 /tmp/
~ ls -l
total 0
-rw-r--r-- 1 root  root  0 Aug 13 13:05 abc
-rw-rw-r-- 1 user1 user1 0 Aug 13 13:05 user1.txt
-rw-rw-r-- 1 user2 user2 0 Aug 13 13:05 user2.txt#切换到 user1 执行删除 user2 文件
~ su - user1
$ rm -rf /tmp/user2.txt
rm: cannot remove ‘/tmp/user2.txt’: Operation not permitted

6.3.4 设定文件特殊权限

特殊权限这样来表示:

  • 4 代表 SUID
  • 2 代表 SGID
  • 1 代表 SBIT
~ chmod 4755 ftest
#赋予SUID权限
~ chmod 2755 ftest
#赋予SGID权限~ mkdir dtest
~ chmod 1755 dtest
#赋予SBIT权限.
##SBIT只对目录有效,所以建立测试目录,并赋予SBIT

七 文件系统属性 chattr 权限

7.1 chattr 命令格式

chattr命令 用来改变文件属性。这项指令可改变存放在ext2文件系统上的文件或目录属性,这些属性共有以下8种模式:

chattr [+-=] [选项] 文件或者目录名
选项:+:增加权限-:删除权限=:等于某个权限i:如果对文件设置i属性,那么不允许对文件进行删除、改名,也不能添加和修改数据;如果对目录设置i属性,那么只能修改目录下文件的数据,但不允许建立和删除文件。a:如果对文件设置a属性,那么只能在文件中增加数据,但是不能删除也不能修改数据;如果对目录设置a属性,那么只允许在目录中建立和修改文件,但是不允许删除e:Linux中绝大多数的文件都默认拥有e属性。表示该文件是使用ext文件系统进行存储的,而且不能使用“chattr -e”命令取消e属性。

选项:

a:让文件或目录仅供附加用途;

b:不更新文件或目录的最后存取时间;

c:将文件或目录压缩后存放;

d:将文件或目录排除在倾倒操作之外;

i:不得任意更动文件或目录;

s:保密性删除文件或目录;

S:即时更新文件或目录;

u:预防意外删除。


-R:递归处理,将指令目录下的所有文件及子目录一并处理;

-v<版本编号>:设置文件或目录版本;

-V:显示指令执行过程;

+<属性>:开启文件或目录的该项属性;

-<属性>:关闭文件或目录的该项属性;

=<属性>:指定文件或目录的该项属性。

范例:

#进入到测试目录
~ cd /tmp
~ touch abc#添加 -i 权限
~ chattr +i /tmp/abc
~ lsattr -a /tmp/abc
----i----------- /tmp/abc~ echo "Hello root" > /tmp/abc
bash: /tmp/abc: Permission denied
~ rm -rf /tmp/abc
rm: cannot remove ‘/tmp/abc’: Permission denied
#超级用户和普通用户都无法对该文件进行任何的操作~ chattr -i /tmp/abc
~ lsattr /tmp/abc
---------------- /tmp/abc
~ rm -rf /tmp/abc

7.2 查看文件系统属性 lsattr

查看文件的第二扩展文件系统属性

lsattr 选项 文件名
选项:-a:显示所有文件和目录-d:若目标是目录,仅列出目录本身的属性,而不是子文件的-E:可显示设备属性的当前值,但这个当前值是从用户设备数据库中获得的,而不是从设备直接获得的。
-D:显示属性的名称,属性的默认值,描述和用户是否可以修改属性值的标志。
-R:递归的操作方式;
-v(小写):显示文件或者目录版本
-V(大写):显示指令的版本信息;

7.3 举例

#例子1:
#给文件赋予 i 属性
~ touch ftest
#建立测试文件
~ chattr +i ftest
~ rm -rf ftest
rm: cannot remove ‘ftest’: Operation not permitted
#赋予i属性后,root也不能删除
~ echo "test new" >> ftest
bash: ftest: Permission denied
#也不能修改文件的数据#给目录赋予 i 属性
~ mkdir dtest
#建立测试目录
~ touch dtest/abc
#再建立一个测试文件 abc
~ chattr +i dtest
#给目录赋予 i 属性
~ touch dtest/bcd
touch: cannot touch ‘dtest/bcd’: Permission denied
#dtest目录不能新建文件
~ echo "test new" >> dtest/abc
~ cat dtest/abc
test new
#但是可以修改文件内容
~ rm -rf dtest/abc
rm: cannot remove ‘dtest/abc’: Permission denied
#不能删除
#例子:
~ mkdir -pv /back/log
#建立备份目录
~ chattr +a /back/log
#赋予 a 属性
~ lsattr -av /back/log
990274326 -----a---------- /back/log/.
679344668 ---------------- /back/log/..
~ cp -av /var/log/messages /back/log
#可以复制文件和新建文件到指定目录
‘/var/log/messages’ -> ‘/back/log/messages’
~ rm -rf /back/log/messages
rm: cannot remove ‘/back/log/messages’: Operation not permitted
#但是不允许删除
~ touch /tmp/abc.txt
#增加了 a 属性
~ chattr +a /tmp/abc.txt
#不能使用 vim 编辑器修改abc.txt
#只能使用 echo 追加的指令
~ echo "hello root" > /tmp/abc.txt
bash: abc.txt: Operation not permitted
~ echo "hello root" >> /tmp/abc.txt
~ cat abc.txt
hello root

【Linux系统管理】07 软件包管理 08 用户和权限相关推荐

  1. linux根-文件系统-目录管理-文件管理-用户及权限详解-用户组-用户管理-权限管理...

    一 .Linux文件结构 文件结构是文件存放在磁盘等存贮设备上的组织方法.主要体现在对文件和目录的组织上. 目录提供了管理文件的一个方便而有效的途径. Linux使用标准的目录结构,在安装的时候,安装 ...

  2. 大数据与云计算学习计划 (一) 云计算系统管理 6 Linux中RPM软件包管理操作 、 Yum软件包仓库操作(概念与实操)

    大数据与云计算学习计划 (一) 云计算系统管理 6 Linux中RPM软件包管理操作 . Yum软件包仓库操作(概念与实操) 一.RPM软件包管理 1.常见软件包类型 2.RPM包文件名特征 3.RP ...

  3. Linux Command dnf 软件包管理

    Linux Command dnf 软件包管理 tags: 软件包管理 文章目录 Linux Command dnf 软件包管理 1. 简介 2. 语法 3. 安装 4. 示例 4.1 查看DNF版本 ...

  4. Linux基础命令-软件包管理

    Linux基础命令-软件包管理 软件包管理 一.软件包基础 1. 软件运行与编译 2. 静态链接和动态链接 3. 包和包管理器 4. 包命名和工具 5. 程序包的来源 二.rpm安装 1.rpm包管理 ...

  5. Alpine Linux的apk软件包管理器

    Alpine Linux的apk软件包管理器 Alpine Linux简介 apk包管理器常用 刷新源apk update 搜索包apk search 安装软件包apk add 安装指定版本软件包 查 ...

  6. centos linux 包管理,Linux和CentOS软件包管理

    Linux和CentOS软件包管理 (此处以httpd-2.2.15-56.el6.centos.3.x86_64.rpm为例)安装:# rpm-ivhhttpd-2.2.15-56.el6.cent ...

  7. Linux 软件安装 - 软件包管理

    文章目录 一.软件包管理简介 1.1 软件包分类 1.2 源码包 1.3 RPM 包 二.RPM包管理-rpm命令管理 2.1 rpm 命令管理 - 包命名与依赖性 2.2 RPM包依赖性 2.3 包 ...

  8. Linux系统下软件包管理四

    3.其它类型软件:1)基于perl 和python 的程序的安装:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com: ...

  9. Linux中deb软件包管理怎么看,Deb软件包管理

    一.流行的两种软件包管理机制 1.Debian Linux首先提出"软件包"的管理机制--Deb软件包 将应用程序的二进制文件.配置文档.man/info帮助页面等文件合并打包在一 ...

最新文章

  1. MongoDB的NUMA CPU架构问题
  2. jvm:类加载器与双亲委派模型
  3. 我的第一篇blog 【随意】
  4. boost::histogram::make_weighted_histogram用法的测试程序
  5. centos node跟npm 安装
  6. arcgis api for javascript创建webmap
  7. ssh(Spring+Spring mvc+hibernate)——IDeptService.java和IEmpService.java
  8. c语言中图形驱动程序功能_C / C ++中的图形:一些更有趣的功能
  9. varchar和Nvarchar区别
  10. 单片机ad显示程序c语言,pic单片机ad转换c程序分享
  11. fatal: git-write-tree: error building trees
  12. php错误日志框架,错误与日志 - Laravel - 为 WEB 艺术家创造的 PHP 框架。
  13. 阶段3 3.SpringMVC·_07.SSM整合案例_03ssm整合之编写Spring框架
  14. matlab 画的点连成线,matlab怎么把点连成线
  15. python爬取图虫网图库
  16. 集成算法 | 随机森林回归模型
  17. 伪原创工具,AI采集伪原创,内容伪原创工具
  18. c语言编程身高体重测量,身高体重测量系统设计.doc
  19. 关于VS2019调试问题:进程已退出,代码为-1073741819(已解决)
  20. 程序员职业规划和学习规划

热门文章

  1. python打包pyc
  2. 实现微信小程序摇一摇功能
  3. 技术债是什么、怎么还?你想知道的都在这一篇文章里了!
  4. 使用CRT作为sock5代理,本地浏览器直接访问堡垒机
  5. 股票模拟交易日志(八)
  6. 关于临时修改mysql最大连接数与永久修改
  7. 计算机启动蓝屏,电脑一开机就蓝屏,详细教您电脑一开机就蓝屏怎么解决
  8. 30岁生日快乐图片_50岁生日快乐心理
  9. 禁止firefox 缓存input
  10. 中小企业有没有必要使用oa软件?