Linux 环境常用命令

Linux 命令尤其多,没办法一下子全部搞明白,下面来不及看的部分我就用 TODO 标出了。

输出

echo

1
2
$ echo asd
$ echo $SHELL

date

date 使用+开头指定格式来输出系统时间,常见格式如下:

  • | -
    参数 | 作用
    %t | 跳格[TAB键]
    %H | 小时(00-23)
    %I | 小时(01-12)
    %M | 分钟(00-59)
    %S | 秒(00-60)
    %X | 相当于%H:%M:%S
    %Z | 显示时区
    %p | 显示本地 AM 或 PM
    %A | 星期几 (Sunday-Saturday)
    %a | 星期几 (Sun-Sat)
    %B | 完整月份 (January-December)
    %b | 缩写月份 (Jan-Dec)
    %d | 日(01-31)
    %j | 一年中的第几天(001-366)
    %m | 月份(01-12)
    %Y | 完整的年份
1
2
3
4
$ date
$ date "+%Y-%m-%d %H:%M:%S"
$ date "+%j" #查看今天是一年中的第几天
$ date -s "20160901 8:30:00" #设置当前的系统时间

读取

pwd

显示当前所处的工作目录

cd

1
2
3
4
5
6
# 切换工作路径
cd /tmp
# 返回到上一次的目录
cd -
# 快速返回到用户自己的目录
cd ~

ls

显示目录中的文件信息
-a 参数可以看到全部文件
-l 参数可以看到文件的属性、大小等信息

1
$ ls -al

-d 查看目录本身的信息

1
$ ls -ld /etc

cat [选项] [文件]

1
2
# 显示行号
cat -n test.txt

more [选项] 文件

head [选项] [文件]

head 命令用于查看纯文本文档的前 N 行

1
head -n 10 test.txt

tail [选项] [文件]

查看纯文本文档的后 N 行或持续刷新内容

1
2
# 查最后300行,持续监听
tail -300f Xxx.log

wc [参数] 文本

统计指定文本的行数、字数、字节数

参数 作用
-l 只显示行数
-w 只显示单词数
-c 只显示字节数
1
2
# 统计系统中有多少个用户
$ wc -l /etc/passwd

stat 文件

查看文件的具体存储信息和时间等信息

1
stat test.txt

diff

比较多个文本文件的差异

1
2
3
4
# 仅判断两个文件是否一致,不判断哪些地方不一样
diff --brief a.txt b.txt
# 判断不同,且输出不同的行号
diff -c a.txt b.txt

grep [选项] [文件]

对文本内容进行正则匹配
-n:显示搜索到的信息的行号
-v:反选信息(即没有包含关键词的所有信息行)

Linux 系统中的/etc/passwd 文件是保存着所有用户信息的文件,而一旦用户的登陆终端被设置成“/sbin/nologin”则不再允许登陆系统,因此我们可以通过使用 grep 命令来匹配出当前系统中所有不允许登陆系统的用户信息

1
2
3
4
5
6
7
8
9
$ grep /sbin/nologin /etc/passwd

bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
......省略

使用正则表达式匹配

1
cat file | grep 'str1\|str2'

使用 grep 高效地查日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
grep key request.log
# 查找多个文件
grep key request.log catalina.out
# 目录下查找所有符合关键字的文件
grep key /home/UserName -r -n
# 指定文件后缀
grep key /home/UserName -r -n --include *.{vm,java}
# 反匹配
grep key /home/UserName -r -n --exclude *.{vm,java}
# 上匹配
grep key request.log -A 3
# 下匹配
grep key request.log -B 3
# 上下匹配
grep key request.log -C 3

find [查找路径] 寻找条件 操作

查找文件
根据不同的文件特性来做为匹配项(如文件名、大小、修改时间、权限等)

参数 作用
-name 匹配名称
-perm 匹配权限(mode 为完全匹配,-mode 为包含即可)
-user 匹配所有者
-group 匹配所有组
-mtime -n +n 匹配修改内容的时间(-n 指 n 天以内,+n 指 n 天以前)
-atime -n +n 匹配访问文件的时间-n 指 n 天以内,+n 指 n 天以前
-ctime -n +n 匹配修改权限的时间-n 指 n 天以内,+n 指 n 天以前
-nouser 匹配无所有者的文件
-nogroup 匹配无所有组的文件
-newer f1 !f2 匹配比文件 f1 新却比 f2 旧的文件
–type b/d/c/p/l/f 匹配文件类型(块设备、目录、字符设备、管道、链接文件、文件文件)
-size 匹配文件的大小(+50k 查找超过 50k 的文件,而-50k 则代表查找小于 50k 的文件)
-prune 忽略某个目录
-exec {} ; 后面可接对搜索到结果进一步处理的命令(下面会有演示)

linux 系统中的配置文件根据 FHS 协议会被保存到/etc 目录,以下获得该目录中所有 host 开头的文件(-print 表达式加不加都没事):

1
$ find /etc -name "host*" -print

在整个系统中搜索所以权限中包括 SUID 权限的文件(使用-4000):

1
$ find / -perm -4000 -print

在整个的文件系统中找出所有归属于 tallate 用户的文件并复制到./findresults 目录

1
$ find / -user tallate -exec cp -arf {} findresults/ \;

其中{}代表 find 命令搜索处的逐个文件,并且命令的结尾必须是;

其他的一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
sudo -u admin find /home/admin /tmp /usr -name \*.log(多个目录去找)
find . -iname \*.txt(大小写都匹配)
find . -type d(当前目录下的所有子目录)
find /usr -type l(当前目录下所有的符号链接)
find /usr -type l -name "z*" -ls(符号链接的详细信息 eg:inode,目录)
find /home/admin -size +250000k(超过250000k的文件,当然+改成-就是小于了)
find /home/admin f -perm 777 -exec ls -l {} \; (按照权限查询文件)
find /home/admin -atime -1 1天内访问过的文件
find /home/admin -ctime -1 1天内状态改变过的文件
find /home/admin -mtime -1 1天内修改过的文件
find /home/admin -amin -1 1分钟内访问过的文件
find /home/admin -cmin -1 1分钟内状态改变过的文件
find /home/admin -mmin -1 1分钟内修改过的文件

sort

1
sort -t $'\t' -k 3 -u filename

常用

1
2
3
-t 指定分隔符为‘\t’ 
-k 指定第三列
-u 去重

其他一些选项

1
2
3
4
5
6
7
8
9
10
11
12
13
-r 降序排列 
-o 把排序结果输出到源文件
sort默认是把结果输出到标准输出,所以需要用重定向才能将结果写入文件,形如
sort filename>newfile
如果将结果输出到原文件,用重定向相当于清空
-n 当作数字来比较
你有没有遇到过10比2小的情况。我反正遇到过。出现这种情况是由于排序程序将这些数字按字符来排序了,排序程序会先比较1和2,显然1小,所以就将10放在2前面喽。这也是sort的一贯作风。
我们如果想改变这种现状,就要使用-n选项,来告诉sort,“要以数值来排序”!
-f 会将小写字母都转换为大写字母来进行比较,亦即忽略大小写
-c 会检查文件是否已排好序,如果乱序,则输出第一个乱序的行的相关信息,最后返回1
-C 会检查文件是否已排好序,如果乱序,不输出内容,仅返回1
-M 会以月份来排序,比如JAN小于FEB等等
-b 会忽略每一行前面的所有空白部分,从第一个可见字符开始比较。

修改文件 / 文件夹

mkdir [option] dir

创建空白的文件夹

1
2
3
4
创建单个目录
`mkdir` a
使用-p参数创建嵌套的文件目录
`mkdir` -p a/b/c

tr [原始字符] [目标字符]

替换文本文件中的字符

1
2
# 全部替换为答谢字母
$ cat test.txt | tr [a-z] [A-Z]

touch

创建空白文件,或者设置文件的各种时间(修改、更改、读取)

  • 更改时间(mtime):内容修改时间(不包括权限的)
  • 更改权限(ctime):更改权限与属性的时间
  • 读取时间(atime):读取文件内容的时间

创建空白文件很简单:

1
touch test.log
参数 作用
-a 仅修改“访问时间”(atime)
-m 仅修改“更改时间”(mtime)
-d 同时修改 atime 与 mtime

我们可以在修改一个文件前先查看下文件的修改时间,然后再通过 touch 命令将修改后的文件时间设置伪装成自己没有动过的一样,很多黑客就会这么做呢:

1
2
3
4
5
6
7
8
$ ls -l test.log 
-rwxrwxrwx 1 root root 5 9月 24 13:33 test.log
$ echo "there are sth new" >> test.log
$ ls -l test.log
-rwxrwxrwx 1 root root 23 9月 24 13:34 test.log
$ sudo touch -d "2016-09-24 13:33" test.log
$ ls -l test.log
-rwxrwxrwx 1 root root 23 9月 24 13:33 test.log

cp [option] source target

复制文件或目录

  1. 如果目标文件是个目录,则会将源文件复制到 该目录中;
  2. 如果目标文件也是个普通文件,则会提示是否要覆盖它;
  3. 最后是第三种的情况了,如果目标文件是不存在的,则会将源文件修改成目标文件 的名称,类似于是重命名的操作。
参数 作用
-p 保留原始文件的属性
-d 若对象为”链接文件”,则保留该”链接文件”的属性
-r 递归持续复制(用于目录)
-i 若目标文件存在则询问是否覆盖
-a 相当于-pdr(p,d,r 为上述的参数)

首先创建一个名为 install.log 的文件,然后将其复制出来一份名为 x.log 的备份文件:

1
2
3
4
$ touch install.log
$ cp install.log x.log
$ ls
install.log x.log

mv [option] source [dir|file]

移动文件(剪切)或改名

1
$ mv x.log linux.log

rm [option] file

删除文件或目录

参数 作用
-f 强制删除,忽略询问是否要执行删除
-r 删除目录并递归删除其内容
1
2
3
4
5
6
7
[root@linuxprobe ~]# ls
install.log linux.log
[root@linuxprobe ~]# rm install.log
rm: remove regular empty file ‘install.log’? y
[root@linuxprobe ~]# rm -rf linux.log
[root@linuxprobe ~]# ls
[root@linuxprobe ~]#

dd [operand]

指定大小的拷贝的文件或指定转换文件。
它能够让用户指定数据块的大小和个数来复制一个文件的内容,当然如果您愿意的话还可以在复制过程中转换其中的数据。

参数 作用
if 输入的文件名称。
of 输出的文件名称。
bs 设置每个“块”的大小。
count 设置要拷贝“块”的个数。

Linux 系统中有一个叫做/dev/zero的设备文件,它不会占用您的系统存储空间,但里面却可以保存有无穷无尽的数据,一般用来搭配 dd 命令来生成出来一个指定大小的文件是再好不过的了。

1
2
3
4
$ dd if=/dev/zero of=560_file count=1 bs=560M
记录了1+0 的读入
记录了1+0 的写出
587202560 bytes (587 MB, 560 MiB) copied, 1.68985 s, 347 MB/s

dd 命令也绝对不仅限于复制文件这么简单,如果您想把一个光盘设备只做成 iso 格式的镜像文件,在 Windows 系统中一定免不了要用到第三方的很多软件才可以,但我们可以直接使用这个 dd 命令来复制并压制光盘设备变成一个可立即使用的 iso 镜像哦:

1
2
3
4
$ dd if=/dev/cdrom of=RHEL-server-7.0-x86_64-LinuxProbe.Com.iso
7311360+0 records in
7311360+0 records out
3743416320 bytes (3.7 GB) copied, 370.758 s, 10.1 MB/s

打包压缩

tar

对文件打包压缩或解压
linux 下常用压缩包格式为.tar 或.tar.gz 或.tar.bz2,tar 命令的参数很多:

参数 作用
-c 创建压缩文件
-x 解压文件
-z 指定使用 Gzip 格式来压缩解压文件
-j 指定使用 bzip2 参数来压缩解压文件
-v 不断显示压缩解压的过程
-C 指定要解压到哪个指定的目录
-f 该参数必须放到参数的最后一位,代表要压缩或解压的软件包名称

比如可以使用“tar -czvf 目标压缩包名.tar.gz 要打包目录”将指定文件打包,同样解压使用“tar -xzvf 压缩包名.tar.gz”

对/etc 目录内文件通过 gzip 格式进行打包压缩,并命名为 etc.tar.gz:

1
2
3

$ tar czvf etc.tar.gz /etc

将刚打包的压缩包文件指定解压到/home/tallate 目录中:

1
2
3

$ tar xzvf etc.tar.gz -C /home/tallate

文件编码

locale

  • 查看系统默认编码
    1
    locale
  • 查看系统支持的所有语言
    1
    locale -a

enca

TODO

iconv

TODO

用户和组

CMOS

为 bios 设置的密码会被保存在 CMOS 芯片中,对 CMOS 放电相当于对 BIOS 进行了出厂设置。

useradd、adduser 和 passwd

adduser 是交互式的,useradd 更适合在已经确定用户属性的情况下使用,或者是批量创建

1
2
3
adduser username # 终端会提示输入密码等信息
useradd -u 544 -d /home/username -g users -m username # 创建一个用户username,属于组users,主目录为/home/username且如果不存在就自动创建,用户ID=544
passwd username # 修改用户密码

addgroup 和 groupadd

TODO

w、who 和 whoami

w命令用于显示已经登录系统的用户的名称,以及他们正在做的事。该命令所使用的信息来源于/var/run/utmp 文件。
用户名称
用户的机器名称或 tty 号
远程主机地址
用户登录系统的时间
空闲时间(作用不大)
附加到 tty(终端)的进程所用的时间(JCPU 时间)
当前进程所用时间(PCPU 时间)
用户当前正在使用的命令

who命令查看当前登入主机的用户终端信息
用户名 tty 号 时间日期 主机地址

1
2
3
4
$ who
tallate :0 2016-09-23 05:27 (:0)
tallate pts/0 2016-09-23 05:28 (:0)
tallate pts/1 2016-09-23 05:45 (:0)

whoami命令用于显示登入的用户名。

id

1
id <用户名> # 查看指定用户信息

last

下面使用 last 命令看到的本机登陆信息,其实仅仅是调取了过往保存到系统中的日志文件罢了,篡改里面的文字其实也很简单,因此对于做“黑客”入侵行为审计时其实并不牢靠,只能仅供我们参考而已

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
last # 查看用户登录日志
tallate pts/1 :0 Fri Sep 23 05:45 still logged in
tallate pts/0 :0 Fri Sep 23 05:28 still logged in
tallate :0 :0 Fri Sep 23 05:27 still logged in
(unknown :0 :0 Fri Sep 23 05:27 - 05:27 (00:00)
reboot system boot 3.10.0-123.el7.x Fri Sep 23 05:27 - 05:51 (00:24)
tallate pts/0 :0 Fri Aug 26 05:33 - 06:48 (01:14)
tallate :0 :0 Fri Aug 26 05:30 - 06:48 (01:18)
(unknown :0 :0 Fri Aug 26 05:28 - 05:30 (00:01)
reboot system boot 3.10.0-123.el7.x Fri Aug 26 05:28 - 06:48 (01:19)
tallate pts/0 :0 Thu Aug 25 07:30 - 07:50 (00:19)
tallate :0 :0 Thu Aug 25 06:52 - 07:50 (00:58)
(unknown :0 :0 Thu Aug 25 06:46 - 06:52 (00:06)
reboot system boot 3.10.0-123.el7.x Thu Aug 25 06:39 - 07:50 (01:11)
wtmp begins Thu Aug 25 06:39:08 2016

history

显示历史执行过的命令
history 命令默认会保存 1000 条执行过的命令,若要修改可直接编辑/etc/profile 文件的 HISTSIZE 值。它能显示出当前用户在本地计算机中执行过的所有命令记录,您可以使用-c 参数来清空里面的历史数据,还可以使用“!编码数字”的方式来重复执行某一次的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$ history
1 cd /etc/
2 cd yum.repos.d/
3 la
4 ls
5 yum
6 rpm
7 yum repolist all
8 yum update
9 sudo yum repolist all
10 sudo yum update
11 cat /etc/systemd/system/nfs.target.wants/nfs-lock.service
12 cd /etc/
13 cd /lib
14 cd systemd/
15 cd system
16 ls
17 vim
18 sudo vim multi-user.target
19 man ln
20 free
21 free -h
22 who
23 last
24 history

可以使用!<命令序号>的格式来选择命令执行:

1
2
3
4
5
$ !22
who
tallate :0 2016-09-23 05:27 (:0)
tallate pts/0 2016-09-23 05:28 (:0)
tallate pts/1 2016-09-23 05:45 (:0)

历史命令将保存到用户目录中的**.bash_history**文件中,可以使用下面命令清空历史命令:

1
history -c

修改权限

1
2
3
4
5
sudo passwd # 修改密码
su - # 转换当前登录用户(接用户名,-代表root)
ls -al # 查看文件权限
chown -R mysql:mysql mysql # 修改文件拥有者,使得mysql群组的mysql用户能够存取mysql文件
chmod mode file # 修改访问权限

su 和 sudo

在 GNU/Linux 中,有两种方式可以用提升的权限来运行命令:

  • 使用 su 命令
  • 使用 sudo 命令

su 和 sudo 区别

suswitch user)是切换用户身份的命令,第一次切换时需要设置系统的密码:

1
2
3
su # 只是切换了root身份,但Shell环境仍然是普通用户的Shell,环境变量仍是原来的
su - # 连用户和Shell环境一起切换成root身份
su - user_name # 以此类推,切换到其他用户也应该使用 su - 命令而不是 su

使用 su 命令我们可以切换到 root 用户并且执行命令,但是这种方法存在一些缺点:

  • 我们需要与他人共享 root 的密码。
  • 因为 root 用户为超级用户,我们不能授予受控的访问权限。
  • 我们无法审查用户在做什么。

sudo 表示 “superuser do”。 它允许已验证的用户以其他用户的身份来运行命令。其他用户可以是普通用户或者超级用户。然而,大部分时候我们用它来以提升的权限来运行命令。
sudo 命令与安全策略配合使用,默认安全策略是 sudoers,可以通过文件 /etc/sudoers 来配置。其安全策略具有高度可拓展性。人们可以开发和分发他们自己的安全策略作为插件。
可见,sudo 相对 su 来说有以下优点:

  • 我们不需要妥协来分享 root 用户的密码。普通用户使用他们自己的密码就可以用提升的权限来执行命令。
  • 我们可以控制 sudo 用户的访问,这意味着我们可以限制用户只执行某些命令。
  • 除此之外,sudo 用户的所有活动都会被记录下来,因此我们可以随时审查进行了哪些操作。在基于 Debian 的 GNU/Linux 中,所有活动都记录在 /var/log/auth.log 文件中。

sudo 实现原理

sudo 是一个特殊的用户组,在这个组内的用户可以一定程度上地使用 root 权限,但为用户分配 sudo 权限的过程比较特殊,需要使用visudo命令,在打开的 sudoers 文件末尾加上:

1
2
3
4
username ALL=(ALL) ALL
username ALL = NOPASSWD: ALL
# 限制用户只执行某些命令
username ALL=(ALL) NOPASSWD: /bin/echo /bin/ls

上述命令中:

  • username 表示用户名
  • 第一个 ALL 指示允许从任何终端、机器访问 sudo
  • 第二个 (ALL) 指示 sudo 命令被允许以任何用户身份执行
  • 第三个 ALL 表示所有命令都可以作为 root 执行

以其他用户身份执行命令

要用提升的权限执行命令,只需要在命令前加上 sudo,除此之外,我们可以使用 sudo 以另一个用户身份执行命令。例如,在下面的命令中,用户 username 以用户 devesh 的身份执行命令:

1
sudo -u devesh whoami

使用内置命令行为

sudo 的一个限制是 —— 它无法使用 Shell 的内置命令。例如, history 记录是内置命令,如果你试图用 sudo 执行这个命令,那么会提示如下的未找到命令的错误:

1
2
$ sudo history
sudo: history: command not found

为了克服上述问题,我们可以访问 root shell,并在那里执行任何命令,包括 Shell 的内置命令。
要访问 root shell, 执行下面的命令:

1
$ sudo bash

执行完这个命令后——您将观察到提示符变为井号(#)。

以 sudo 用户执行历史命令

1
$ sudo !4

在 vim 里使用 sudo 命令

很多时候,我们编辑系统的配置文件时,在保存时才意识到我们需要 root 访问权限来执行此操作。因为这个可能让我们丢失我们对文件的改动。没有必要惊慌,我们可以在 Vim 中使用下面的命令来解决这种情况:

1
:w !sudo tee %

上述命令中:

  • 冒号 (:) 表明我们处于 Vim 的退出模式
  • 感叹号 (!) 表明我们正在运行 shell 命令
  • sudo 和 tee 都是 shell 命令
  • 百分号 (%) 表明从当前行开始的所有行

使用 sudo 执行多个命令

至今我们用 sudo 只执行了单个命令,但我们可以用它执行多个命令。只需要用分号 (;) 隔开命令,如下所示:

1
$ sudo -- bash -c 'pwd; hostname; whoami'

上述命令中
双连字符 (–) 停止命令行切换
bash 表示要用于执行命令的 shell 名称
-c 选项后面跟着要执行的命令

无密码运行 sudo 命令

当第一次执行 sudo 命令时,它会提示输入密码,默认情形下密码被缓存 15 分钟。但是,我们可以避免这个操作,并使用 NOPASSWD 关键字禁用密码认证,同样适用 visudo 命令来设置,如下所示:

1
username ALL=(ALL) NOPASSWD: ALL

参考

  1. Linux 的 capabilities 机制