跟运维学 Linux - 02

文件操作和用户

复制移动和删除

在Windows中我们可以通过快捷键 ctrl + c 复制,ctrl + v 粘贴,在 linux 中需要使用命令。

复制移动

cp 就是 copy 的意思。请看示例:

// 将 a.txt 复制一份,重命名为 b.txt
test11@pj-pc:~$ cp a.txt b.txt
test11@pj-pc:~$ ls
模板  桌面  a.txt  b.txt  dir1
// 将 a.txt 复制到 dir1 目录中
test11@pj-pc:~$ cp a.txt dir1
test11@pj-pc:~$ ls dir1
a.txt
// 将 dir1/a.txt 复制到当前目录
test11@pj-pc:~$ cp dir1/a.txt .

如果当前目录有同名的文件,需要询问是否覆盖,可以使用参数 -i

// -i 会询问是否覆盖
test11@pj-pc:~$ cp -i dir1/a.txt .
cp:是否覆盖'./a.txt'? n
test11@pj-pc:~$ rm a.txt
// 没有同名文件,则无需询问
test11@pj-pc:~$ cp -i dir1/a.txt .
test11@pj-pc:~$

文件夹的拷贝需要使用参数 -r,否则会提示错误:

// 报错:缺少 -r
test11@pj-pc:~$ cp dir1 dir2
cp: 未指定 -r;略过目录'dir1'
// 拷贝目录
test11@pj-pc:~$ cp -r dir1 dir2
test11@pj-pc:~$ ls
模板  桌面  dir1  dir2

拷贝文件比较清晰,而拷贝文件夹就没那么好理解,我们分几种情况详细介绍:

// 将 dir1 文件夹拷贝到 dir2目录中
test11@pj-pc:~/dir$ cp -r dir1 dir2
test11@pj-pc:~/dir$ ls dir2
c.txt  dir1
test11@pj-pc:~/dir$
// tree 可通过包管理器安装
test11@pj-pc:~/dir$ tree
.
├── a.txt
├── dir1
│   └── b.txt
└── dir2
    └── c.txt

2 directories, 3 files
// 将dir1文件夹中的内容拷贝到 dir2 中
test11@pj-pc:~/dir$ cp dir1/* dir2
test11@pj-pc:~/dir$ ls dir2
b.txt  c.txt

dir1/a.txt 拷贝到当前目录,以下两种写法一个有提示,一个没有提示,是什么原因?

test11@pj-pc:~/dir$ tree
.
├── a.txt
├── dir1
│   ├── a.txt
│   └── b.txt
└── dir2
    ├── b.txt
    └── c.txt

2 directories, 5 files
// 没有提示
test11@pj-pc:~/dir$ \cp dir1/a.txt .
// 有提示
test11@pj-pc:~/dir$ cp dir1/a.txt .
cp:是否覆盖'./a.txt'? y

通过 alias 命令我们得知 cp 其实等同于 cp -i,所以有提示,而 \cp 表示不使用别名,表示纯 cp 命令。

test11@pj-pc:~/dir$ alias
alias cp='cp -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias l='ls -CF'
alias la='ls -A'
alias ll='ls -alF'
alias ls='ls --color=auto'

Tip:alias 显示当前定义的别名。创建一个新的别名 alias ll='ls -l',删除一个别名 unalias ll

删除

删除文件和目录需要使用 rm 命令。

文件直接即可删除:

test11@pj-pc:~/dir$ ls
a1.txt  a2.txt  a3.txt  dir1  dir2
// 删除文件
test11@pj-pc:~/dir$ rm a1.txt
// -i 删除前确认
test11@pj-pc:~/dir$ rm -i a2.txt
rm:是否删除普通空文件 'a2.txt'?n
test11@pj-pc:~/dir$

删除文件夹需要使用 -r 参数,否则报错:

// 报错:需要使用 -r
test11@pj-pc:~/dir$ rm dir1
rm: 无法删除'dir1': 是一个目录
// 删除目录
test11@pj-pc:~/dir$ rm -r dir1
test11@pj-pc:~/dir$ ls
a2.txt  a3.txt  dir2
// 删除前确认
test11@pj-pc:~/dir$ rm -ir dir2
rm:是否进入目录'dir2'? y
rm:是否删除普通空文件 'dir2/c.txt'?y
rm:是否删除普通空文件 'dir2/b.txt'?y
rm:是否删除目录 'dir2'?y
test11@pj-pc:~/dir$ ls
a2.txt  a3.txt

Tip: 一名合格的运维工程师在修改文件之前需要对源文件(文件夹)进行备份。否则一旦改错,又改不回去,就很麻烦。

查找文件和隐藏文件

比如知道文件或文件夹的名字,但忘记在哪里,可以使用 find 命令。

// 在当前目录中查找名字是 dir2 的文件或名录
test11@pj-pc:~/dir$ find . -name dir2
./dir1/dir2
./dir2

ls 显示的是非隐藏文件(文件夹),如果需要查看隐藏文件(文件夹),可以增加参数 -a

test11@pj-pc:~/dir$ ls
a3.txt  dir1
// 显示隐藏文件和隐藏目录
test11@pj-pc:~/dir$ ls -a
// . 当前目录
// .. 上一层目录
.  ..  .a2.txt  a3.txt  dir1  .dir2

隐藏文件(文件夹)以点(.)开头,也是一种保护机制。

隐藏文件查看方式和普通文件相同:

test11@pj-pc:~/dir$ cat .a2.txt
apple

如果需要将隐藏文件或隐藏目录转成非隐藏,重命名(删除.)即可。

test11@pj-pc:~/dir$ mv .a2.txt a2.txt
test11@pj-pc:~/dir$ mv .dir2 dir2
// a2.txt 和 dir2 不在隐藏
test11@pj-pc:~/dir$ ls
a2.txt  a3.txt  dir1  dir2

一切皆文件

我们现在一直围绕着文件学习 linux 命令,为什么总是围绕文件?因为 Linux 中一切皆文件。

笔者的 linux 有一块磁盘 /dev/sda 931G。

/dev/sda 是一个文件,用它来表示硬盘。

// fdisk -l 查看本地磁盘信息
pj@pj-pc:/home/test11/dir$ sudo fdisk -l
Disk /dev/sda:931.53 GiB,1000204886016 字节,1953525168 个扇区
Disk model: WDC WD10EZEX-75W
单元:扇区 / 1 * 512 = 512 字节
...

这个文件和其他文件一样,也有自己的属性:

pj@pj-pc:/home/test11/dir$ ls -l /dev/sda
brw-rw---- 1 root disk 8, 0 7月  17 14:52 /dev/sda

最前面的一位 b,b=block,也就是块设备,说白了就是硬盘。

于是我们知道在 linux 中,用文件表示各种东西。

路径

登陆后默认来到用户的家目录,但对于 linux 来说,家目录不是不是最原始的起点。

Linux 下所有目录最开始的起点叫做“根”,也就是/。所有目录都以它为起点,如树杈一样,一层一层向下扩展。

感觉根有点虚,其实是可以看见的:

pj@pj-pc:~$ ls /
backup  bin  boot  cdrom  data  dev  etc  home  lib  lib32  lib64  libx32  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

这里显示的就是一级目录,不同发行版,一级目录都差不多(目录名)

pj@pj-pc:~$ tree -L 1 /
/
├── backup
├── bin -> usr/bin
├── boot
├── cdrom
├── data
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib32 -> usr/lib32
├── lib64 -> usr/lib64
├── libx32 -> usr/libx32
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
└── var

25 directories, 0 files

如果一个路径从 / 开始,例如 "/home/user1/xx" 就是一个绝对路径。

无敌的 root

接下来我们得真正用 linux 干点活了。

主管:来了2个新人,你(运维工程师)给他们在服务器A中给他们创建账号并邮件通知他们(省去许多其他要求...)

在 windows 中,给用户创建账号,最好是管理员角色。在 linux 中不叫管理员,而是 root,也是一个特殊的用户。

root 在 linux 中拥有最高的权限,无所不能。所以公司通常会加以限制,root账户只对少数人开放(其他人不允许用root登录),例如运维工程师,为了服务器和系统的稳定需要随时拥有最高权限。

通过 whoami 查看当前用户:

pj@pj-pc:~$ whoami
user-pj

Tip: 笔者没有测试服务器的 root 账号。

useradd 创建用户(sudo 让普通用户临时拥有root的权限),并通过 id 查看用户是否真的被创建出来:

// 创建一个叫 test18 的用户
pj@pj-pc:~$ sudo useradd test18
// 用户创建成功
pj@pj-pc:~$ id test18
uid=1005(test18) gid=1005(test18) 组=1005(test18)
pj@pj-pc:~$

Tip:adduser 和 useradd 功能类似,但有一些区别。adduser 是一个高级的用户管理工具;而 useradd 更基本,比如 useradd 不会创建家目录;

root 不是角色,而是一个实实在在的用户。虽然 root 用户只有一个,但是通过权限和分组,可以让普通用户拥有root一样高的权限。

// 创建一个叫 root 的用户
pj@pj-pc:~$ sudo useradd root
输入密码
useradd:用户“root”已存在

现在我们创建了 test18 用户,接下来得给他分配密码。通过 passwd 给用户创建密码:

pj@pj-pc:~$ sudo passwd test18
新的密码:
// linux 中密码有一定规范
无效的密码:密码少于 8 个字符
新的密码:
无效的密码:密码包含的字符类型少于 2 种
新的密码:
重新输入新的密码:
passwd:已成功更新密码

Tip: 如果你使用root给新用户创建密码,即使使用一个不符合规则的密码,也能创建成功,因为 root 有最高权限。

如果需要切换用户登录,可以使用 su - 用户名

pj@pj-pc:~$ su - test18
输入密码
$
// 再次确定是否切换成功
$ whoami
test18
$ id
uid=1006(test18) gid=1006(test18) 组=1006(test18)
$

登录后修改自己的密码,直接输入 passwd 即可:

$ passwd
为test18更改密码
当前密码:
新的密码:
无效的密码:与旧密码相同
新的密码:

系统账号

前面我们已经对linux 账号有所了解(root、普通用户),这里我们在认识一下系统账号

系统账号不是给人用的,而是给程序用的。系统账号长什么样子?比如 mail:

pj@pj-pc:~$ id mail
uid=8(mail) gid=8(mail) 组=8(mail)

系统账号安装软件时,程序自动创建的。例如现在没有ntp账号,安装 ntp 只有就有该账号了:

// 没有 ntp 账号
pj@pj-pc:~$ id ntp
id: “ntp”:无此用户
// 安装 ntp
pj@pj-pc:~$ sudo apt install ntp
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
...
// 有 ntp 账号
pj@pj-pc:~$ id ntp
uid=124(ntp) gid=132(ntp) 组=132(ntp)

系统账号不能拿来直接使用,而是软件运行时,由它们自己来使用。

Tip:约定Uid小于1000的是系统账号。

第一个配置文件

只是学会用命令创建账号、修改密码,这是最基本的入门。

我们要深入探索 Linux 用户账号,先学习用户账号的管理。

要掌握 linux 用户管理,首先得知道全部用户都定义在哪里。如下操作:

pj@pj-pc:~$ head /etc/passwd
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin

/etc 目录放置的都是配置文件,全部用户就定义在 /etc/passwd 配置文件中。

这些都是用户:root、daemo、bin...

pj@pj-pc:~$ id root
uid=0(root) gid=0(root) 组=0(root)

pj@pj-pc:~$ id daemon
uid=1(daemon) gid=1(daemon) 组=1(daemon)

pj@pj-pc:~$ id bin
uid=2(bin) gid=2(bin) 组=2(bin)

先来认识一下什么是配置文件

我们的 linux 上面运行着各种各样的软件,软件到了底层,就是程序在运行。

如果想改变程序的运行方式,直接跟程序说没用,因为程序不接受你的直接调遣。如果你通过配置文件让其改变,程序就会乖乖就范。

上文我们学习的用户管理,背后也是有对应的程序在运行。

我们直接通过命令 useradd 创建用户,根本没有接触配置文件,其实这是表象。做一个试验就知道了。我们直接修改 /etc/passwd 模仿 test18 增加一条数据:

pj@pj-pc:~$ id test19
id: “test19”:无此用户
pj@pj-pc:~$ tail -n 2 /etc/passwd
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:1007::/home/test19:/bin/sh

用户(test19)创建成功:

// 不一样
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007 组=1007
pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 组=1006(test18)

这样编辑一下 /etc/passwd 创建创建出来的用户,是不完整的,缺少一些东西,接下来将围绕这个遗留问题,继续操作和讲解。

用户组

用户 test18 使用useradd 命令创建,而 test19 是直接编辑配置文件创建的。通过 id 就会发现有所不同:

pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 组=1006(test18)
// gid=1007(缺少) 组=1007(缺少)
pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007 组=1007

为了讲清楚这部分差异,我们下面分几个步骤。

在linux中,每个用户必须属于一个组织,这个组织就是主组(gid)和附属组(groups,笔者这里就是)。

以 test18 为例,gid=1006(test18) 其主组是 test18,组=1006(test18) 附属组也是 test18。

当执行 useradd,系统会给 test18 创建一个同名的组 test18,并让该用户的主组是它。

主组只有一个,附属组可以没有或者有多个。下面我们给 test18 增加一个附属组(usermod -aG):

// 通过 usermod 给 test18 增加一个附属组
pj@pj-pc:~$ sudo usermod -aG mail test18
输入密码
pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 组=1006(test18),8(mail)
pj@pj-pc:~$

组在哪里定义的,我们可以自己创建吗?

pj@pj-pc:~$ cat /etc/group |grep 'test18'
mail:x:8:test18
test18:x:1006:

/etc/group 配置文件中定义了所有的组,其中用户test18的主组gid=1006(test18)就在其中:

pj@pj-pc:~$ id test18
uid=1006(test18) gid=1006(test18) 组=1006(test18),8(mail)

而 test19 对应的组 1007 根本不存在

pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007 组=1007

给配置文件增加一行(test19:x:1007:):

pj@pj-pc:~$ cat /etc/group |egrep "test18|test19"
mail:x:8:test18
test18:x:1006:
// 增加这一行(shift+g定位到最后一行)
test19:x:1007:

这样就显示正常了:

pj@pj-pc:~$ id test19
uid=1007(test19) gid=1007(test19) 组=1007(test19)
pj@pj-pc:~$

我们在看下面段代码,1007:1007 是什么?

pj@pj-pc:~$ cat /etc/passwd |egrep "test18|test19"
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:1007::/home/test19:/bin/sh

前一个1007表示系统分配给用户 test19 的 ID,不可以随便改变,后一个1007是主组ID

Tip:在Linux用户管理系统中,每个用户和组都有一个唯一的数字标识符(UID和GID)。虽然用户名和组名更加易于人类理解,但实际上,系统在内部使用对应的数字来识别用户和组。

做一个小实验,看主组能否改变。

将 test19 的主组id改成test18的主组id:

pj@pj-pc:~$ tail -n 2 /etc/passwd
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:1006::/home/test19:/bin/sh

真的改成功了,现在 test19 的用户组是 test18:。

pj@pj-pc:~$ id test19
uid=1007(test19) gid=1006(test18) 组=1006(test18)

我们再做一个实验,如果一个用户,一个组都不属于会怎么样?

pj@pj-pc:~$  tail -n 2 /etc/passwd
test18:x:1006:1006::/home/test18:/bin/sh
test19:x:1007:::/home/test19:/bin/sh

用户信息报错:

pj@pj-pc:~$ id test19
id: “test19”:无此用户

用户家目录

我们编辑配置文件创建了 test19,前文已经知道 1007:1007 的含义:

test19:x:1007:1007::/home/test19:/bin/sh

现在再来看一下 /home/test19,表示test19的家目录。

pj@pj-pc:~$ ls /home/test19
ls: 无法访问'/home/test19': 没有那个文件或目录

既然没有这个目录,我们自己创建:

// 创建目录
pj@pj-pc:~$ sudo mkdir /home/test19
pj@pj-pc:~$ ls -l /home
drwxr-xr-x  2 root    root    4096 7月  18 15:08 test19
// 将 /home/test19 目录及其所有子目录和文件的所有者和所属群组都修改为 test19
pj@pj-pc:~$ sudo chown -R test19:test19 /home/test19
pj@pj-pc:~$ ls -l /home
drwxr-xr-x  2 test19  test19  4096 7月  18 15:08 test19

Tip:chown 用于修改权限,后面会讲到。

现在路径是/home/demo,切换 test19 登录后,自动进入对应的家目录:

pj@pj-pc:~$ pwd
/home/demo
pj@pj-pc:~$ su - test19
输入密码
$ pwd
/home/test19
$

Tip: 这里如果使用 su test19,则不会进入该用户的家目录。su -su 是两个命令,su -会同时加载该用户的所有环境变量和配置文件。

用户登录的角度认识bash

所谓登录,到底是登录什么?

有同学说是 linux。对也不对!linux前文我们说是 linux 内核,是深不见底的东西。是有什么东西在协助我们?

是 Shell。表示 linux 内核外的一层壳。而 bash 是最知名的一种 shell。

现在 test19 最后一个字段是 /bin/bash,表示该用户登录后,给他 bash。

test19@pj-pc:~$ tail -3 /etc/passwd
test19:x:1007:1007::/home/test19:/bin/bash
// 当前所使用的 shell 的路径
test19@pj-pc:~$ echo $SHELL
/bin/bash

// 输出当前 shell 的名称
test19@pj-pc:~$ echo $0
-bash

Tip/bin 目录下还有许多常用命令,比如vi,所有用户都可以使用。

如果你将 test19 的 /bin/bash 改成 /bin/vi,登录后就不会给bash,而是vi,感兴趣的同学可以试一下。

我们还看到:

ntp:x:124:132::/nonexistent:/usr/sbin/nologin

nologin 就是禁止登录,我们将其分配给 test19 看看会怎么样?

// sbin 就是 usr/sbin(sbin -> usr/sbin)
test19:x:1007:1007::/home/test19:/sbin/nologin

用户无法登录

pj@pj-pc:~$ su - test19
输入密码
// 这个帐号当前不可用
This account is currently not available.

Tip:不建议将 root 设置成这种登录方式,对于初学者比较麻烦。

使用 sudo 切换用户

前面我们用 su 切换用户,相等于注销当前用户,换一个用户来使用。

在日常中,较少使用 su,更多是使用 sudo

普通用户直接查看 /root 不允许:

$ ls /root
ls: 无法打开目录'/root': 权限不够

临时使用 root 的用户运行 ls /root

test19@pj-pc:~$ sudo -u root ls /root
模板  桌面
test19@pj-pc:~$ whoami
test19

Tip:直接使用 sudo 可能提示不在 sudoers 文件中,需要通过 visudo 命令修改 sudo 配置文件

test19@pj-pc:~$ sudo ls /root
输入密码
test19 不在 sudoers 文件中。此事将被报告。
pj@pj-pc:~$ sudo visudo

root ALL=(ALL:ALL) ALL
// 增加一行
// <用户名> <主机名>=(<身份>:<终端>) <命令>
test19 ALL=(ALL:ALL) ALL

指定了 test19 用户在任何主机、以任何用户身份、在任何终端上都可以使用 sudo 命令

密码管理

前面我们通过编辑配置文件 /etc/passwd 创建用户,我们也知道用 passwd 给用户创建密码。

密码没有存在 /etc/passwd,而是在 /etc/shadow 中,加密之后保存的。例如搜索用户 test19 的密码:

pj@pj-pc:~$ sudo cat /etc/shadow |grep 'test19'
test19:$6$7ZkiOkEth7bdStHU$GWt/YVaD/KlJ5b21afWhqXPECRDj5tDmNBx.TDKW                                                                                                                                     6M2jd1jvtMlYFcrGVoWsmSkJ5hnIaEQyI8nLs4PDNJOm4.:19556::::::

虽然密码并不是使用 md5sum 加密,但我们可以使用其模拟一下:

// 输入不变,输出也不变
pj@pj-pc:~$ echo -n '123456' | md5sum
e10adc3949ba59abbe56e057f20f883e  -
pj@pj-pc:~$ echo -n '123456' | md5sum
e10adc3949ba59abbe56e057f20f883e  -
pj@pj-pc:~$

本地用户和远程用户

机器就在身边是本地登录,更多的是远程登录。

无论是本地登录还是远程登录,都是 linux 本地账号密码

在一个系统中,如果两个用户都使用 root 身份进行登录,一个是本地登录,另一个是远程登录,那么它们之间可能会互相不知道对方的存在。这种情况下可以被看作是一种多用户管理模式,其中每个用户都以独立的身份登录并运行各自的操作。

posted @ 2023-07-18 17:32  彭加李  阅读(469)  评论(0编辑  收藏  举报