本节课讲解的是管道,环境变量,以及常用命令
管道
概念
管道类似文件重定向,可以将前一个命令的stdout重定向到下一个命令的stdin
要点
管道命令仅处理stdout,会忽略stderr
管道右边的命令必须能接受stdin
多个管道命令可以串联
与文件重定向的区别
文件重定向,左边是命令,右边是文件
管道左右两边都是命令,左边的命令要有stdout,右边的命令要有stdin
举例
find . -name '*.py' | xargs cat | wc -l
统计当前目录所有python文件的总行数
对上面的命令进行解释:
首先,我们单独运行find . -name '*.py' ,会查找出当前目录下,所有以py结尾的文件,如下
而我们的cat命令,其作用是,给定一堆文件,将文件的内容,输出到stdout中(Concatenate FILE(s) to standard output),所以,cat命令,它接收参数,参数指定了文件名,比如cat console.log,表示将console.log这个文件中的内容,输出到stdout。
而xargs的作用,就是将前一个命令的stdout,转变为行参数(用空格隔开),传递给下一个命令。
假设find . -name '*.py' 的结果是
./client.py
./server.py
则find . -name '*.py' | xargs cat
就相当于cat ./client.py ./server.py
而cat会将多个文件的内容输出到stdout,此时再通过管道命令,将stdout传递给下一个命令wc -l,(-l for lines)就会从stdout中统计出行数。所以
find . -name '*.py' | xargs cat | wc -l
这个命令,实现的效果就是,统计当前目录下所有python文件的代码总行数。结果如下
如果上面的命令,不加xargs,会是什么效果呢
find . -name '*.py' | cat | wc -l
此时,实际统计的,就是当前目录下python文件的个数。(cat命令也接受stdin的数据,接收stdin时,就仅仅是将stdin输出到stdout)
查看某个命令的用法,可以通过cmd --help,或者man cmd进行。比如查看wc命令的用法,执行wc --help
Usage: wc [OPTION]... [FILE]...
? or:? wc [OPTION]... --files0-from=F
Print newline, word, and byte counts for each FILE, and a total line if
more than one FILE is specified.? A word is a non-zero-length sequence of
characters delimited by white space.
With no FILE, or when FILE is -, read standard input.
The options below may be used to select which counts are printed, always in
the following order: newline, word, character, byte, maximum line length.
? -c, --bytes??????????? print the byte counts
? -m, --chars??????????? print the character counts
? -l, --lines??????????? print the newline counts
????? --files0-from=F??? read input from the files specified by
?????????????????????????? NUL-terminated names in file F;
?????????????????????????? If F is - then read names from standard input
? -L, --max-line-length? print the maximum display width
? -w, --words??????????? print the word counts
????? --help???? display this help and exit
????? --version? output version information and exit
环境变量
Linux系统中有很多配置信息。其中,有一些配置信息,是记录在文件中的,比如系统的cpu信息,记录在/proc/cpuinfo这个文件中
cat /proc/cpuinfo
但是Linux也有一些配置信息,是放在环境变量里的。环境变量,是一种全局变量,可以被各个进程访问到,我们可以通过修改环境变量来修改系统的一些配置,很方便。
查看
查看当前环境下的全部环境变量
env # 显示当前用户的变量
set # 显示当前shell的变量,包括当前用户的变量
export # 显示当前导出为用户变量的shell变量
查看某个环境变量,比如查看PATH这个环境变量
echo $PATH
修改
可以参考shell语法章节 - 变量 小节。
比如修改HOME变量
export HOME=/
随后我们执行cd命令,当cd命令没有参数时,会回到用户的家目录(也就是回到环境变量HOME指定的目录),此时我们可以看到回到了根目录/
但是export命令修改的环境变量,只对当前这个bash生效,当我们关闭bash并重新打开一个,会发现之前的修改已失效。
那么,如何将环境变量的修改进行持久化呢?(也就是说,修改完后,我们希望之后打开的所有bash,都能够应用到此修改)
可以将修改命令放到~/.bashrc(放到这个文件的末尾,因为如果存在相同命令,后面的会覆盖前面的),修改完~/.bashrc后,记得source ~/.bashrc,来将修改应用到当前的bash环境
为何将修改命令放到~/.bashrc后,就可以确保修改会影响未来的所有bash环境呢?因为
每次启动bash,都会先执行~/.bashrc
每次ssh登录远程服务器,都会启动一个bash命令行给我们
每次tmux新开一个pane,都会启动一个bash命令行给我们
由于每次启动bash,都会加载一遍~\.bashrc,所以未来所有新开的bash环境,都会加载我们修改的内容。
(其实Linux下执行的命令,都是单独开一个进程去执行的,比如执行一个不会立即结束的命令top,可以看到最下面的那个进程就是执行top命令的进程。)
常用环境变量
HOME:用户的家目录
PATH:可执行文件(命令)的存储路径。路径之间用:分隔。在bash命令行中执行一个命令,Linux系统是怎么找到这个命令的呢?是通过遍历PATH变量下的目录,从这些目录中找到(第一个)匹配的命令或可执行文件。当某个可执行文件同时出现在多个路径中时,会选择从左到右数第一个路径中的执行。下列所有存储路径的环境变量,均采用从左到右的优先顺序。
LD_LIBRARY_PATH:用于指定动态链接库(.so文件)的路径,其内容是以冒号分隔的路径列表。
C_INCLUDE_PATH:C语言的头文件路径,内容是以冒号分隔的路径列表。
CPLUS_INCLUDE_PATH:CPP的头文件路径,内容是以冒号分隔的路径列表。
PYTHONPATH:Python导入包的路径,内容是以冒号分隔的路径列表。
JAVA_HOME:jdk的安装目录。
CLASSPATH:存放Java导入类的路径,内容是以冒号分隔
常用命令
系统状况
top:查看所有进程的信息(Linux的任务管理器)
打开后,输入M:按使用内存排序
打开后,输入P:按使用CPU排序
打开后,输入q:退出
df -h:查看硬盘使用情况
free -h:查看内存使用情况
du -sh:查看当前目录占用的硬盘空间
du -h --max-depth=1
ps aux:查看所有进程
kill -9 pid:杀死编号为pid的进程
传递某个具体的信号:kill -s SIGTERM pid
netstat -nt:查看所有网络连接
w:列出当前登陆的用户
ping www.baidu.com:检查是否连网
文件权限
chmod:修改文件权限
chmod +x xxx:给xxx文件添加可执行权限
chmod -x xxx:给xxx文件去掉可执行权限
chmod 777 xxx:将xxx的权限改成777
chmod 777 xxx -R:递归修改整个文件夹的权限
其余关于Linux的权限:见附录
文件检索
find /path/to/directory/ -name '*.py':搜索某个文件路径下的所有*.py文件
grep xxx:从stdin中读入若干行数据,如果某行中包含xxx,则输出该行。(也可以添加文件名作为参数,则就是查找某个文件中的某一行是否出现xxx,若出现,则将那一行输出到stdout)
wc:统计行数,单词数,字节数
既可以从stdin中直接读取内容,也可以传入文件名作为参数
wc -l:统计行数
wc -w:统计单词数
wc -c:统计字节数
wc --help:查看帮助文档
tree:展示当前目录的文件结构
tree /path/to/directory/:展示某个目录的文件结构
tree -a:展示所有文件(包括隐藏文件)
ag xxx:搜索当前目录下的所有文件,检索xxx字符串(会列出xxx在哪个文件中的哪一行)
cut:分割一行内容
从stdin中读入多行数据
echo $PATH | cut -d ':' -f 3,5:输出PATH用:分割后第3,5列的数据
echo $PATH | cut -d ':' -f 3-5:输出PATH用:分割后第3-5列的数据
echo $PATH | cut -c 3,5:输出PATH的第3,5个字符
echo $PATH | cut -c 3-5:输出PATH的第3-5个字符
sort:将每行内容按照字典序排序
可以从stdin中读取多行数据
也可以从将文件名作为命令行参数
xargs:将stdin中的数据用空格或回车分割成命令行参数
例:find . -name '*.py' | xargs cat | wc -l:统计当前目录下所有python文件的总行数
查看文件内容
more:浏览文件内容
回车:下一行
空格:下一页
b:上一页
q:退出
less:与more类似,功能更全
回车:下一行
y:上一行
Page Down:下一页
Page Up:上一页
q:退出
head -3 xxx:展示xxx的前三行
tail -3 xxx:展示xxx的末尾三行
用户相关
history:展示当前用户的历史操作。内容会持久化到~/.bash_history
其他工具
md5sum:计算md5值
可以从stdin读取数据(stdin输入数据后,敲回车,再按Ctrl + D结束输入)
也可以将文件名作为参数传入
time cmd:统计cmd命令的执行时间
ipython3:交互式python3环境。可以做计算器,或批量管理文件
tar:压缩文件
tar -zcvf xxx.tar.gz /path/to/file/*:压缩指定目录下所有文件
tar -zxvf xxx.tar.gz:解压缩
diff xxx yyy:查找文件xxx与yyy的不同点
sz file:在Xshell等工具中,发送服务器的文件到本地(s for send)
rz:在Xshell等工具中,发送本地的文件到服务器(r for read)
需要运行apt-get install lrzsz,先进行安装
安装软件
sudo cmd:以root身份执行cmd命令udo cmd:
apt-get install xxx:安装某个软件(ubuntu)
pip install xxx --user --upgrade:安装python包
附录
Linux权限
用ls -l 查看当前目录的文件
最左一列的是文件的权限相关信息,一共有10位,最左侧的第1位表示文件类型,如上图
d:表示文件夹,directory
l:表示链接,link
f:表示普通文件,file
后面的9位代表权限,前3位表示文件所有者的权限,中间3位表示文件所属用户组的权限,后3位表示其他用户的权限。
左边第二列的数字表示这个文件的连接数
左边第三列表示这个文件的拥有者(owner)
左边第四列表示这个文件所属的用户组
左边第五列表示这个文件的大小
左边第六列表示这个文件的修改时间
比如,
dr-xr-x---. 22 root root 4096 10月 20 15:01 root
这个root,是个文件夹,并且其owner是root用户,其属于root用户组,大小位4096字节。
左边第一列,后9位是文件权限,前3位是owner权限,r-x,表示这个root文件夹,对于root用户,是可读,可执行的,中间3位是用户组权限,r-x表示这个root文件夹,对于root用户组里的用户,是可读,可执行的,最后3位是其他用户的权限,---表示其他用户对这个文件夹不可读,不可写,不可执行。
可以为某个文件修改权限,使用chmod
chmod u+x run.sh 给run.sh这个文件的owner添加执行权限
chmod g+r run.sh 给run.sh这个文件所属的用户组添加读权限
chmod o-w run.sh 给run.sh这个文件的其他用户删除写权限
chmod a+x run.sh 给run.sh这个文件的所有用户添加执行权限
权限就3种,rwx,读,写,执行,也用3个二进制位来表示,比如111表示三个权限都有,十进制就是7,110表示只有读写权限,十进制就是6,一般我们会用chmod 777 run.sh 给全部用户添加全部权限
chmod 751 run.sh 给run.sh的owner添加全部全写,给其所属的用户组添加读,执行权限(101),给其他用户添加执行权限001
chmod u=rwx,g=rx,o=x run.sh 效果跟上面的命令一样
chmod =r run.sh 给所有用户分配读权限(augo不写的话默认是a)
chmod 444 run.sh 效果同上
chmod -R u+r dir 递归地给 dir这个目录下所有文件及其子目录的owner分配读权限
若想要改变某个文件的owner,可以用chown命令(有时某个目录或文件没有执行权限,可以通过修改文件或目录的owner来解决)
如,递归的给dir目录下的所有文件及子目录修改其owner为yogurt
chown -R yogurt:yogurt dir/
第一个yogurt是用户,第二个yogurt是所属用户组
如何查看系统都有哪些用户?
cat /etc/passwd
只看用户名称
cat /etc/passwd | cut -f1 -d :
查看某个用户的所属组
groups 查看当前用户所属的用户组
groups yogurt 查看用户yogurt所属的用户组
切换用户:su root 切换到root用户 ,su yogurt 切换到yogurt用户(su for switch user,or shift user)
不带参数的su 表示切换到root用户
注意,su 只是切换了用户,而没有切换用户所使用的shell,即,如果当前用户是yogurt
然后我使用su root切换到root用户,则只是换了用户身份,但是shell环境仍然是yogurt的shell,所以在root的PATH变量中的一些命令,是调用不到的
可以看到,只是切换用户的话,当前工作目录都没有发生变化。用su -,会同时切换shell环境。用su只切换用户身份
sudo表示以root权限来运行某个命令。默认情况下,只有root用户才能执行sudo命令,但可以让普通用户以root权限执行某条命令,只要将该用户配置在/etc/sudoers里面即可,
比如sudo su表示以root权限来运行su命令,这样可以不用输入密码root的密码(前提是,在/etc/sudoers配置文件中配置当前用户)
比如当前用户是yogurt,若没进行配置
则会要求输入yogurt的密码
用root用户,修改/etc/sudoers配置文件
然后再在yogurt用户下,用sudo su 就能直接切换到root
当然,用su来切换到root,仍然需要输入root密码