- A+
文件操作和用户
复制移动和删除
在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 身份进行登录,一个是本地登录,另一个是远程登录,那么它们之间可能会互相不知道对方的存在。这种情况下可以被看作是一种多用户管理模式,其中每个用户都以独立的身份登录并运行各自的操作。