Go to start of metadata
Linux/Unix系统的一大特点是包括很多功能各异的小工具。根据Unix的设计理念“Do One Thing and Do It Well”,每个小工具实现了某个单一功能。这一部分介绍各种工具,下一部分介绍怎样将工具融合起来,发挥更大的威力。
对于每一个命令,可以用man <cmd>来看帮助页面. 习惯上, 很多命令也支持使用 <cmd> --help 来获取帮助信息.
# 之后是注释。
Bash基础知识
标注输出/标准错误/标准输入
程序运行时会产生输出。一般程序有两种输出,一种叫做标准输出(stdout),一种叫做标准错误(stderr)。习惯上,前者用来表示程序正常运行的输出,后者用来表示更特殊的输出,如错误和提醒。在terminal中人手动交互的键入命令执行时,stdout和stderr都会输出到terminal中,仅从视觉上效果相同。
标准输入(stdin)是指程序运行时,从terminal中读入人手动键入的文字。
stdout/stderr/stdin都有一些高级用法,下面会做介绍。
echo printf |
echo把参数输出到屏幕:
$ echo
"I don't always test my code."
"But when I do I do it in production."
I don't always test my code. But when I
do
I
do
it in production.
|
printf和c语言里的printf很像,第一个参数是format string,后面的参数是format string里的参数:
$
printf
"Even if you test the code for %d times, it could still fail at the %d-th time.\n"
100 101
Even
if
you test the code
for
100 times, it could still fail at the 101-th
time
.
$
printf
"the usage of cpu is %.2f%%\n"
33.3333
the usage of cpu is 33.33%
|
注意echo默认会输出一个new line,而printf不会。
|
stdout stderr |
程序的输出包括stdout和stderr,默认都会输出到屏幕上。
可以用下面的方法把输出保存到文件里:
# stdout到文件里,stderr到屏幕上。ls是列出当前目录的命令。
$ ls > /tmp/ls.stdout
# stdout到文件ls.stdout,stderr到文件ls.stderr。
$ ls 1> /tmp/ls.stdout 2> /tmp/ls.stderr
# stdout和stderr都到同一个文件里。
$ ls &> /tmp/ls.stdall
|
|
stdin |
$ rev # rev可以把输入左右颠倒
yitutech # 这是人工输入,需要回车
hcetutiy # 这是程序输出
(人工按 ctrl-D,程序结束。ctrl-D 在标准输入中意味着输入终止。
|
|
能把多个命令组合起来是bash很强大的功能。.把不同的命令组合起来,有很多种方法. 这部分很有用但难度稍高, 建议整体Bash教程学完后再回看一遍.
|
|
可以用|(管道、pipe)把多个命令组合起来,前一个命令的输出会成为后一个命令的输入。
$ echo yitutech | rev # 程序从标准输入读入
'yitutech'
,效果和上例基本相同。
hcetutiy
|
|
&& || |
另外一种方法是用逻辑运算符&&。由于每个命令会返回一个返回值,命令a && b的执行方式是:
(1)bash 先执行 a
(2)如果a失败了(返回结果不是0),那么根据short circuiting,第二个命令b就不会被执行。
(3)如果a成功了(返回结果是0),那么第二个命令b就会接着被执行。
例子:
$ mkdir /tmp/good && cd /tmp/good # 只有当mkdir(创建目录)成功,cd才会被执行
|
类似的组合方法包括逻辑运算符||。例子:
$ mkdir /tmp/good || echo
"failed to create folder /tmp/good"
# 如果mkdir不成功, echo就会被执行。
|
|
$() `` |
使用$(this_is_a_command)方式,可以把一个命令的输出嵌入成另一个命令的一部分。
$ seq 1 3 # seq 可以产生一个序列
1
2
3
# 把 seq 1 3 的输入嵌入,实际执行的命令是 touch 1 2 3.
# touch 这个命令用来创建空文件
$ touch $(seq 1 3)
# 另外,$(some_command)也可以用`some_command`来替代。这个字符(反引号)在主键盘'1'键左边。
$ ls # 这里可以看到上一条命令的执行结果
1 2 3
|
|
()多命令group |
()内部有多个命令时, 可以统一操作这些命令的stdout和stderr
$ (echo
'first line'
; echo
'second line'
) > output.txt
$ cat output.txt
first line
second line
|
|
文件系统
在命令行中,任何时候都有一个“当前工作目录”(working directory)。用pwd命令查看工作目录。用cd改变工作目录。用ls查看目录里的文件和目录。
pwd |
查看当前工作目录。
$ pwd
/home/hchen/projects/bash-tutorial
|
|
ls |
查看当前工作目录下的文件和文件夹。
$ ls
books phones readme.txt
|
其中books和phones是目录,readme.txt是文件。
|
cd |
切换目录。
$ cd phones # 换到目录phone中
$ pwd
/home/hchen/projects/bash-tutorial/phones
$ cd .. # 换到工作目录的上一层目录
$ pwd
/home/hchen/projects/bash-tutorial
|
|
basename |
去掉文件路径中的目录, 仅保留文件名.
$ basename
'/a/long/path/filename.ext'
filename.ext
|
|
du |
统计文件夹大小。
$ du -sh * # 统计当年目录所有文件夹占用空间
412K all
592M asr
4.0K Desktop
8.7G Downloads
12K examples.desktop
|
|
df |
统计磁盘分区利用情况。
$ # 统计这两个mount点的磁盘利用情况。可以看到剩余空间大小
$ df -h /mnt/ficuscolombia /mnt/ficusdenmark
Filesystem Size Used Avail Use% Mounted on
10.40.40.83:/mnt/ficuscolombia 22T 18T 4.2T 81% /mnt/ficuscolombia
10.40.40.84:/mnt/ficusdenmark 22T 21T 187G 100% /mnt/ficusdenmark
|
|
ncdu |
是du的升级版。统计文件空间大小后,可以深入下层文件夹。实际中可以用于清理空间时追查到底什么文件占用了大量空间。
$ ncdu ~ # 再统计完成的界面上,可以用上下左右方向键浏览文件系统。可以直接按
'd'
键删除一个文件夹。
ncdu 1.11 ~ Use the arrow keys to navigate, press ?
for
help
--- /home/zzhang ---------------------------------------------------------------
8.7 GiB [##########] /Downloads
856.5 MiB [ ] /.cache
591.2 MiB [ ] /asr
181.8 MiB [ ] /repos
134.6 MiB [ ] /.config
15.3 MiB [ ] /.mozilla
10.2 MiB [ ] /.vim
|
|
在系统中查找文件,可以用下面的命令。
find |
查找文件。
$ find . -name iphone7 # 第一个参数
"."
表示在哪个目录查找;第二个参数iphone7表示查找的文件名
./phones/iphone7
|
文件名也可以带*进行匹配。
$ find . -name
'*book*'
./books
./books/coding-book.txt
./books/history-book.txt
|
|
对文件进行移动、拷贝、创建文件夹等,可以用下面的命令。
cp mv rm chmod mkdir rmdir |
拷贝:cp <file1> <file2> # 把file1拷贝到file2
移动:mv <file1> <file2> # 把file1移动到file2
删除:rm <file> # 把file删除
文件属性:文件一共有9个属性:文件所属用户的读、写、执行;文件所属用户组的读、写、执行;所有用户的读、写、执行。每个属性可以用一个bit来表示。比如:
$ ls -l display_current_user.sh
-rw-rw-r-- 1 hchen hchen 17 Apr 23 18:22 display_current_user.sh
|
可以看到文件属性是:用户可读、写文件,但不能执行(第一组rw-,分别对应读、写、执行);用户组可读、写文件,但不能执行(第二组rw-,分别对应读、写、执行);其他所有用户可读该文件,但不能写或者执行(最后的r--)。
改变文件属性:chmod <mode> <file> # 改变文件属性。一个常见的用法是,写了一个脚本文件my_tool.sh后,默认的文件属性并不能执行文件,可以用下面的命令允许执行该文件:
$ chmod +x display_current_user.sh
$ ls -l display_current_user.sh
-rwxrwxr-x 1 hchen hchen 17 Apr 23 18:22 display_current_user.sh
|
命令里的+x表示允许执行,可以看到,文件所属用户、文件所属组和所有用户都可以执行这个文件了。
创建文件夹:mkdir <folder> # 在当前工作目录下创建文件夹folder。folder也可以是绝对路径。
删除文件夹:rmdir <folder> # 删除文件夹folder。必须是空的文件夹。如果要删除整个文件夹,使用rm -rf <folder>命令。其中-r表示recursive,-f表示force。慎用。
|
⚠️注意: 以上的几个操作会对文件系统进行永久性的修改。为了避免不小心删除、覆盖文件,可以在运行cp,mv,rm的时候加上-i参数,这样如果命令会删除或者覆盖文件,会提示用户confirm。
实际中,一般的做法是对这几个命令设置alias。比如在~/.bashrc文件中,加入下面的命令:
alias cp=
'cp -i'
alias rm=
'rm -i'
alias mv=
'mv -i'
|
文件内容
用下面的命令查看文件内容。
cat
| 查看文件:cat <file> # 查看文件file的内容。
|
head | 看文件的前面若干行:head -n <file> # 查看文件file的前n行。 |
tail | 看文件的最后若干行: tail -n <file> # 查看文件file的最后n行。 如果一个文件(比如日志文件)正在不停地在文件尾部增加内容,可以用这个命令实时地看新加进的内容:tail -f foo.log 这里f表示follow。 |
more less | 有时文件太长,可以使用more或者less命令来分页看文件内容, 一般比用vim打开更快: more [file] # 分页看file内容。按空格翻一页;按回车翻一行。 less [file] # 分页看file内容。less是more的升级版,支持一些类vi的快捷键、翻页、搜索等等,基本可以alias more=‘less’ |
diff |
对比两个文件的内容:diff file1 file2
$ cat file1
1
2
3
4
$ cat file2
2
A
4
5
# diff命令输出中的 < 指仅左边文件的内容, > 指仅右边文件的内容.
$ diff file1 file2
1d0
< 1
# 以上两行输出, 代表 1 仅在左边文件中
3c2
< 3
---
> A
# 以上4行输出, 代表左边文件中的 3 在右边文件中被替换成了 A
4a4
> 5
# 以上两行输出, 代表 5 仅在右边文件中
# 上面介绍了 < > 的含义, 在日常操作中一般够用. 更详细的 '1d0' 是什么含义, 可以参考下面链接.
|
diffh输出详细解释
另外, vimdff file1 file2 提供了一种更加交互更加友好的diff展现方式.请自行在上面例子中用vimdiff比较, 观察vimdiff的效果.
|
如果想了解文件概况,用下面的命令。
wc | wc file # 得到文件有多少行、多少个词、和总共多少个字节。 |
md5sum | md5sum file # 得到文件的md5码。 # md5文件的一个"特征值". 如果两个文件md5相同, 一般可以认为两个文件相同. # 可以用来比较两个应该相同的文件是不是确实相同.(如拷贝数据之后)
|
用下面命令来对文件内容进行操作。
cut
|
$ printf "3\ta\tb\n1\tc\td\n2\te\tf\n" > /tmp/1.tmp # 产生如下的文件
$ cat /tmp/1.tmp
3 a b
1 c d
2 e f
|
只显示文件的第1列和第3列:
$ cut -f1,3 /tmp/1.tmp
3 b
1 d
2 f
|
如果使用-b参数,指定的列是按照字节来计算的:
$ cut -b1 /tmp/1.tmp
3
1
2
|
|
sort |
对文件的所有行按照字典序排序:
$ sort /tmp/1.tmp
1 c d
2 e f
3 a b
|
其他常见用法:
- sort -r 反向,即从大到小
- sort -n 按照整数数字(默认是字典序)
- sort -g 按照小数数字
- sort -t',' 按照逗号做分隔符, 而不是默认的空格
|
uniq |
如果文件的相邻行可能会相同,用uniq命令显示不相同的行。如果相同的行不相邻,都会保留。
$
printf
"a\na\na\nb\nb\na\n"
> /tmp/2.tmp # 产生下面的文件
$ cat /tmp/2.tmp
a
a
a
b
b
a
$ uniq /tmp/2.tmp
a
b
a
$ uniq -c /tmp/2.tmp # 用-c参数,可以统计每个词出现的频率。
3 a
2 b
1 a
|
调用uniq之前,常常会先调用sort,因为uniq只对相邻的行去掉重复。比如:
$ cat /tmp/favorite_languages.txt
java
c++
python
go
c++
java
go
c++
$ sort /tmp/favorite_languages.txt | uniq
c++
go
java
python
$ sort /tmp/favorite_languages.txt | uniq -c
3 c++
2 go
2 java
1 python
|
|
grep |
用grep命令查找文件中的特定字串:
$ cat games.txt
age of empires
starcraft 2
warcraft
hearts of iron iv
final fantasy 15
The Operational Art of War
$ grep craft games.txt # 基本用法. 过滤出匹配的
starcraft 2
warcraft
$ grep -v of games.txt # 仅过滤出不匹配的
starcraft 2
warcraft
final fantasy 15
$ grep -i art games.txt # 大小写无关
hearts of iron iv
The Operational Art of War
$ grep -P
'\d\d'
games.txt # 正则表达式. 要求出现两个连续的数字
final fantasy 15
$ grep
'empires\|fantasy'
games.txt
age of empires
final fantasy 15
|
其他常见用法:
- grep -r 'some_str' some_folder # 文件夹中找文本
|
sed |
sed是一个对文件内容进行逐行修改的工具。
$ echo -e
'abcabc\nrabbit'
| sed
's#ab#TAT#'
#把每行ab换成TAT,每行仅替换第一个
TATcabc
rTATbit
$ echo 乐视网接连任命11名高管|sed
's/连任/**/'
# 用于分割匹配模式的
'#'
可以换成任意字符。习惯上用#和/较多。
乐视网接**命11名高管
$ echo
'abcabc'
| sed
's#ab#TAT#g'
# 当末尾有g时,代表全行所有match都要替换。
TATcTATc
$ echo 东四十四条位于北京市东城区|sed
's|十四条||'
# sed也可以用于删除特定匹配
东四位于北京市东城区
# 下面例子中,把文件里的所有字串“difficult”替换成”awesome”:
$ cat /tmp/7.tmp
C++ is difficult to learn.
It is difficult to pass a code review.
$ sed
's/difficult/awesome/g'
/tmp/7.tmp
C++ is awesome to learn.
It is awesome to pass a code review.
# sed可以基于正则表达式做非常复杂的文本替换
# 在下面的例子中, [0-9][0-9]代表两个连续数字, [a-z]\+表示连续多个小写字母.
# 整体的意思是, 当出现 小写字母词汇, 后面一个空格, 再后面两个数字 这种pattern的时候, 将数字段和单词段互换位置
# 其中 pattern 部分的\(some_regex\)代表如果match这个pattern, 就把这个pattern match的内容记下来, 留作后用
# pattern 部分的两个带括号match, 分别match了 fantasy 和 15, 在 后面的 replace 部分, 可以用 \1 \2 来获取这两段内容的值
$ cat games.txt | sed
's#\([a-z]\+\) \([0-9][0-9]\)$#\2 \1#'
age of empires
starcraft 2
warcraft
hearts of iron iv
final 15 fantasy
The Operational Art of War
|
下面是输出文件内容时把所有包含”C++”的行去掉:
$ sed
'/C++/d'
/tmp/7.tmp
It is difficult to pass a code review.
|
|
awk |
awk包括了一个完整的脚本语言,有强大的文本处理能力。这里举两个简单例子:
$ cat /tmp/1.tmp
3 a b
1 c d
2 e f
# 输出每行的第一列和第三列:
$ awk
'{print $1,$3}'
/tmp/1.tmp
3 b
1 d
2 f
# 输出第1列的和. END后面脚本在处理文件结束之后完成。
$ awk
'{ sum += $1; } END { print sum; }'
/tmp/1.tmp
6
# 求和是一个常见的操作, 另一种更简单的方式如下.
$ cut -f1 /tmp/1.tmp | paste -sd+ | bc
6
# 输出第1列的和. END后面脚本在处理文件结束之后完成。
$ awk
'{ sum += $1; n++ } END { if (n > 0) print sum / n; }'
/tmp/1.tmp
2
|
出第1列的平均:
|
shuf |
文件基于行随机shuffle
# 把整个文件做行shuffle
$ shuf a_file_name
# 从文件中随机抽取10行。注意,到文件比较大时,比 shuf a_file_name | head -n 10 显著快
$ shuf -n 10 a_file_name
|
|
rev |
把文件每行都左右反转
$ echo -e
'abc\ndef'
| rev
cba
fed
$ find . -type f | rev | cut -d
'/'
-f1 | rev # 列出目录树下所有的不包含文件夹路经的文件名。原理是通过两个rev,实际上cut出来了按照
'/'
切分的最后一段。
|
|
tr |
可以做字符替换。
# 这个例子中展示了普通的字符替换
$ echo
'abcabc'
|tr
'a'
'd'
dbcdbc
# 这个例子是1到10的求和。先生成10行依次是1到10,之后把换行变成加号,得到 1+2+3+4+5+6+7+8+9+10+
# 再之后把最后的加号换成回车,喂给计算器bc得到结果
$ seq 1 10|tr
'\n'
'+'
|sed
's#+$#\n#'
|bc
55
# 当然,同样的问题bash会有非常多的解法。随便给几个。不在本教程中解释和做要求。学有余力自行查看文档。
# seq 1 10|paste -sd+|bc # 使用paste命令
# seq 1 10|sed -z 's#\n\([0-9]\)#+\1#g' |bc # 基于正则表达式替换。当一个换行后面有数字时,就换成加号。
# seq -s '+' 1 10|bc # 直接使用+来连接
# (seq 1 10|tr ' \n' '+';echo 0) | bc # 输入后面补零
# echo `seq 1 10|tr ' \n' '+'` 0 | bc # 输入后面补零,第二种做法
|
|
tar |
归档/压缩/解压工具。
$ tar xvf some_file.tar.gz # 解压文件some_file.tar.gz
$ tar zcvf target.tar.gz some_folder # 将some_folder压缩成target.tar.gz
|
|
sed和awk的功能非常强大,上面的例子不能表达万分之一。有兴趣的同学可以参考下面两个页面:
系统相关
htop | 可以看到各个进程的实时CPU占用率、内存使用,进程ID,命令行,启动时间,用户等信息。还有机器整体的CPU占用率和内存使用情况。 最重点需要观察的是: CPU占用率是否符合预期? 内存占用率是否符合预期? 最占CPU/内存的进程是什么, 是否符合预期? 其中 F4 可以筛选想看的进程. F9可以直接杀死想杀死的进程.
|
top | 弱化版的htop。仅在系统没有安装htop的时候才推荐使用。 |
ps |
ps提供当前各个进程状态的snapshot。ps的参数组合比较复杂,这里列举两个:
ps aux # 得到当前所有进程的 用户,ID,CPU,内存,binary等信息。
ps aux | grep gedit | grep -v grep # 得到cmd中带
"gedit"
的进程
ps auxf # 打印进程树形结构
|
|
dstat | 系统资源统计。可以查看每秒的CPU,磁盘读写,网络出入等信息。 |
netstat |
网络详细信息。
$ sudo netstat -tulpn |grep 80 # 可以看到哪个进程占用了80端口
|
|
nvidia-smi |
查看GPU的状态。
$ nvidia-smi # 显示基本信息。包含 GPU的利用率,GPU的显存使用情况等等。
$ nvidia-smi topo -m # 得到GPU连接方式
$ nvidia-smi --format=csv,noheader --query-gpu=utilization.gpu # 按照csv格式输出GPU利用率。更加适合脚本后续自动化处理。
|
|
ssh |
登陆远程机器。之后你可以在远程机器上键入命令执行。
$ ssh zzhang@ficusdenmark # 以zzhang用户身份登陆ficusdenmark这台机器。
$ ssh ficusdenmark # 如果目前用户名和打算用来远程登陆的用户名一致时,用户名可省略
$ ssh zzhang@ficusdenmark
'ls /home/zzhang'
# 在ficusdenmark上运行后面的命令
|
拓展阅读:
如何避免每次登陆都需要输入密码
|
scp |
在机器之间复制文件。
$ scp -r ficusdenmark:/home/zzhang/a_folder ficuscolombia:/tmp # 两台机器之间拷贝文件夹。-r表示文件夹
|
|
rsync |
和scp接近,文件传输工具。特别适用于大量小文件场合,此时速度会明显快于scp。
# 建议拷贝文件时使用的命令。详细的命令解释可以看文档:man rsync
# 注意: 很多人用的命令是 -avzP. 此处多加的 z 代表压缩. 但是在公司内部的数据中心里, 一般来看不使用压缩时的整体传输时间g更短. 因为万兆网中传输, 压缩的计算反而会成为瓶颈. 仅当非常确定压缩能够极大缩小传输开销时(如大量相同格式的文本等), 才使用 z 选项.
$ rsync -avP local_folder ficusdenmark:/tmp/
|
|
ctrl c kill killall pkill
|
我们能够对程序发送不同的signal(信号). 不同的signal程序会做不同的相应.
既可以使用键盘快捷键发送信号, 也可以使用 kill 命令来发送.
ctrl c给程序发 sigint 信号, 一般导致的行为是程序做一些cleanup后"优雅"退出.
ctrl c 等价于 kill -2 <PID> 或者 kill -SIGINT <PID>.
kill <PID> 等价于 kill -TERM <PID>, 是一种比 -SIGINT 更加暴力的信号.用于杀死进程。
信号本身内容较复杂. 新手仅需要记住按照先 ctrl c 不行再 kill 的顺序杀死进程即可.
先使用htop得到希望结束的进程的ID。
$ kill <this_porcess_id>
$ kill -9 <this_process_id> # 更加暴力的结束进程方法。可以结束掉一些kill杀不死的进程,但是更可能造成数据损失。慎用。
$ killall python # 结束本用户的所有python进程。不会影响别人
$ sudo killall python # 结束所有用户的所有python进程。会影响别人
# kill依据进程号发送信号,pkill依据进程名发送信号。
$ pkill _unittest # 杀死名字中带_unittest的所有进程
|
供参考:
kill -9 的解释
不同signal含义的区别
另一个类似解释
|
后台运行相关 |
$ ./a_time_consuming_process &> aaa.
log
# 此后这个进程会在后台运行,并且stdout和stderr输出到 aaa.
log
。此后你还可以在terminal中输入其他命令运行。
$ jobs # 可以看到哪些进程在后台运行
$ fg # 把后台运行的进程调到前台。terminal不能再输入其他命令运行。
ctrl-z # 对于现在正在前台运行的命令,可以手动 ctrl-z 使它暂停
$ bg # 把刚刚暂停的进程,在后台继续运行。因此任务启动后 ctrl-z 加 bg,实际效果等同于直接用
'&'
来后台运行。
|
|
proc文件系统 |
/proc/ 下面, 可以得到很多机器和进程信息.
$ cat /proc/cpuinfo # 输出CPU信息
$ ls /proc/1314/ # 1314是某个正在运行的进程号
|
|
常用工具
date |
显示当前时间.
$ date # 当前时间
2018年 03月 17日 星期六 18:31:18 CST
$ date
'+%Y%m%d_%H%M%S'
# 格式化时间输出
20180317_183219
# 每次运行的时候, train.py 的输出都会到一个按照时间命名的文件中.
# 这样能够方便的留存每次运行的日志.
$ python train.py &>
log
/$(date
'+%Y%m%d_%H%M%S'
).
log
|
|
wget |
|
xargs |
把从标准输入读入的每行或每若干行,都执行特定的命令。用好之后是非常灵活强大的必备工具。下面展示几种样例用法
# 列出all目录下所有文件名带'2018/03'的文件
$ find all -type f |grep
'2018/03'
all/2018/0305 all/2018/0308
# 统计这些文件的行数。实际执行的命令是 " wc -l all/2018/0305 all/2018/0308"
$ find all -type f |grep
'2018/03'
| xargs wc -l
716 all/2018/0305
719 all/2018/0308
1435 total
# 实际执行的命令是 "wc -l all/2018/0305" 和 "wc -l all/2018/0308" 两条。
$ find all -type f |grep
'2018/03'
| xargs -I {} wc -l {}
716 all/2018/0305
719 all/2018/0308
|
|
jq |
可以用来解析json。
# 这个例子中简单的选择了json中的一个键。jq的更多高级用法可以自行查阅文档。
$ echo
'{"key1":"value1","key2":"value2"}'
| jq
'.key2'
"value2"
|
|
parallel |
用于并行执行多个相近的命令。
# 并行下载给定列表中的文件,最大并行度4
$ cat 20urls.list | parallel -j 4 wget -q {}
# 在ficusdenmark,ficusxi,ficuspi三台机器上,分别占用1,2,3的并行度,来并行(不保证顺序)处理10个任务。
# 本例子中的
$ parallel --no-notice --sshlogin 1/ficusdenmark,2/ficusxi,3/ficuspi echo
"Number {}: Running on \`hostname\`"
::: `seq 1 10`
Number 2: Running on ficusdenmark
Number 4: Running on ficusxi
Number 6: Running on ficuspi
Number 1: Running on ficusxi
Number 3: Running on ficuspi
Number 5: Running on ficuspi
Number 7: Running on ficusdenmark
Number 8: Running on ficusxi
Number 10: Running on ficusxi
Number 9: Running on ficuspi
|
|
convert |
非常强大的图片处理工具
$ convert input.jpg output.png # 转化格式
$ convert -flip input.jpg input-flipped.jpg # 左右反转
$ convert -resize 50% input.jpg output.jpg # 按照比例resize
$ convert -resize 200x100 input.jpg output.jpg # 按照像素resize
|
|
time |
统计一个命令运行的时间
# 可以看到, cp -r dir1 dir2 实际运行时间 5.81s
$
time
cp -r dir1 dir2
real 0m5.810s
user 0m0.032s
sys 0m2.184s
|
|
修改 ~/.bashrc | vim ~/.bashrc (注意那个点!) 可以看目前用户的bash配置文件 每个运行中的bash在启动时都会执行一遍这里面的命令. 常见的用途是, 在 ~/.bashrc 里面 用 export 来设置一些环境变量, 如 PATH LD_LIBRARY_PATH, 或者做一些命令的别名. 如 alias grep='grep --color'等 |
history | 显示过去一段时间用户输入过的命令. history | grep mkdir # 显示我过去的带"mkdir"的命令 |