linux学习记录
资料:
Linux的基本操作(一) - 星辰大海6 - 博客园 (cnblogs.com)
(5条消息) Linux中的Git(过程 + 总结)_VVPU的博客-CSDN博客_git linux
还有一些零零散散的…
(实训内容与其他知识点有重复)
文章目录
一、
1.操作系统概述
计算机是由硬件和软件组成。
硬件:计算机系统中由电子,机械和光电元件等组成的各种物理装置的总称。(看得见的,cpu,内存,鼠标,键盘)
操作系统是计算机软件的一种,它主要负责:作为用户和计算机硬件之间的的桥梁,调度和管理计算机硬件进行工作。
没有操作系统的计算机就只是一堆无法使用的塑料而已。
操作系统可以:
- 调度cpu进行工作
- 调度内存进行工作
- 调度硬盘进行数据存储
- 调度网卡进行网络通讯
- 调度音响发出声音
- 调度打印机打印内容
- ……
常见的操作系统:
pc端:window,linux,macOS
移动设备:Android,ios,HarmonyOS
2.初识linux
linux的诞生
创始人:林纳斯·托瓦兹
1991年,创始人上大学期间写了linux的原型。
经过全世界网友的支持,目前能兼容多种硬件,成为最流行的服务器操作系统之一。
linux内核
linux系统的组成如下:
- linux系统内核
- 系统级应用程序
其中:
-
内核提供最核心的功能,如:调度cpu、调度内存、调度文件系统、调度网络通讯、调度IO等。
-
系统级应用程序,可以理解为出厂自带程序,可供用户快速上手操作系统,如:文件管理器、任务管理器、图片查看、音乐播放等。
如播放音乐,无论用户使用自带音乐播放器还是第三方播放器均是由播放器程序,调用内核提供相关的功能,由内核去调度硬件cpu进行解码,调度外设音响进行发声等。
内核无法被用户直接使用,需要配合应用程序才能被用户使用。
linux发行版
内核是免费、开源的:
- 任何人都可以获得并修改内核,并且自行集成系统级程序
- 提供了内核+系统级程序的完整封装,称之为linux发行版
Ubuntu,centOS,deepin……
不同发行版:
- 基础命令100%相同
- 部分操作不同(如软件安装)
3.虚拟机介绍
学习Linux系统,需要有一个可用的linux系统。
需要借助虚拟机来获得可用的linux系统环境进行学习。
虚拟机
虚拟硬件+操作系统
借助虚拟化技术,可以在系统中,通过软件:模拟计算机硬件,并给虚拟硬件安装真实的操作系统。
3.安装
4.远程连接linux系统
图形化(linux使用)、命令行
- 图形化:使用操作系统提供的图形化页面,以获得图形化反馈的形式去使用操作系统。
- 命令行:使用操作系统提供的各类命令,以获得字符反馈的形式去使用操作系统。
对操作系统的使用,有2种使用形式:
- 图形化页面使用操作系统
- 以命令的形式使用操作系统
FinalShell
通过第三方软件FinalShell,远程连接到linux操作系统之上。
并通过FinalShell去操作linux系统。
《问题1:连不上》
方法尝试了很多…
5.WSL(Windows Subsystem for Linux)
(使用WSL获得Ubuntu系统环境)
基于Windows系统之上的linux子系统。
作用:在Windows系统中获得linux系统环境,并完全直连计算机硬件,无需通过虚拟机虚拟硬件。
《问题2:电脑打不开子系统》
6.虚拟机快照
VMware虚拟机支持为虚拟机制作快照。
通过快照将当前虚拟机的状态保存下来,在以后可以通过快照恢复虚拟机到保存的状态。
最好关机了制作
二、
1.linux目录结构
(1)Linux的目录结构
Linux的目录结构是一个树型结构
Windows系统可以拥有多个盘符,如C盘、D盘,而Linux没有盘的概念,只有一个根目录/,所有文件都在它下面
(2)linux路径的描述方式
-
Linux系统中,路径之间的层级关系,使用:**/**来表示(/usr/local/hello.txt)
-
在windows系统中,路径之间的层级关系用:\来表示(D:\data\workhello.txt)
2.Linux命令入门
(1)Linux命令基础
什么是命令行、命令
学习Linux,本质上是学习在命令行下熟练使用linux的各类命令
-
命令行:即Linux终端,是一种命令提示符页面。以纯“字符”的形式操作系统,可以使用各种字符化命令对系统发出操作指令。
-
命令:即Linux程序。一个命令就是一个Linux的程序。命令没有图形化页面,可以在命令行(终端中)提供字符化的反馈。
Linux命令基础格式
command [-options] [parameter]//[]表示可选
- command:命令本身
- -optons:[可选,非必填]命令的一些选项,可以通过选项控制命令的行为细节
- parameter:[可选,非必填]命令的参数,多数用于命令的指向目标等
ls -l /home/itheima
- 意思是以列表的形式,显示/home/itheima目录内的内容
cp -r test1 test2
- 意思是复制文件夹test1成为test2
(2)ls命令入门
ls命令
作用是列出目录下的内容,语法细节如下:
ls [-a -l -h] [linux路径]
- -a -l -h是可选的选项
- Linux路径是此命令可选的参数
当不使用选项和参数,直接使用ls命令本体,表示:以平铺形式,列出当前工作目录下的内容
默认列出HOME目录的内容(?实际操作并不是啊,列出的是桌面的)
HOME目录:每个Linux操作用户在Linux系统的个人账户目录,路径在/home/用户名
(3)ls命令的参数和选项
ls命令的参数
ls [-a -l -h] [linux路径]
ls命令的-a选项
-
-a选项表示:all的意思,即列出全部文件(包含隐藏的文件/文件夹)
-
以.开头的,表示是Linux系统的隐藏文件/文件夹(只要以.开头就能自动隐藏)
-
只有通过-a选项,才能看到这些隐藏的文件/文件夹
-
ls命令的-l选项
- -l选项表示:以列表(竖向排列)的形式展示内容,并展示更多信息
- -l和图形化中,文件夹以列表形式排列是一个意思
ls命令的组合使用
如:
- ls -l -a
- ls -la
- ls -al
ls命令的-h选项
- -h表示以易于阅读的形式,列出文件大小,如K、M、G
- -h选项必须要搭配-l一起使用
3.目录切换相关命令(cd/pwd)
cd 切换工作目录
(change directory)
语法:cd [Linux路径]
- cd命令无需选项,只有参数,表示要切换到哪个目录下
- cd命令直接执行,不写参数,表示回到用户的HOME目录
pwd查看当前工作目录
(Print Work Directory)
语法:pwd
- pwd命令,无选项,无参数,直接输入pwd即可
4.相对路径绝对路径和特殊路径符
相对路径和绝对路径
- cd /home/用户名/Desktop 绝对路径以根目录为起点,以/开头
- cd Desktop 相对路径:以当前目录为起点,无需以/开头
都可以切换
特殊路径符
- “.”表示当前目录,比如cd ./Desktop 表示切换到当前目录下的Desktop目录内,和cd Desktop效果一样
- “…”表示上一级目录,比如cd … 即可切换到上一级目录,cd …/…切换到上二级目录
- “~”表示HOME目录,比如cd ~ 即可切换到HOME目录,cd ~/Desktop
5.创建目录命令(mkdir命令)
mkdir命令
通过mkdir命令可以创建新的目录(文件夹)
mkdir来自英文:Make Directory
语法:mkdir [-p] Linux路径
- 参数必填,表示Linux路径,即要创建的文件夹的路径,相对路径和绝对路径都可以(特殊路径符也可以)
- -p选项可选,表示自动创建不存在的父目录,适用于创建连续多层级的目录
mkdir -p选项
自动创建不存在的父目录,适用于创建连续多层级的目录
!:确保创建文件夹操作均在home目录内,不要在home外操作(涉及到权限问题)
补:一些快捷键
ctrl+c:取消命令,并且换行
ctrl+u:清空本行命令
tab键:可以补全命令和文件名,如果补全不了,快速按两下tab键,可以显示备选选项
1. 在终端下:复制命令:Ctrl + Shift + C 组合键. 粘贴命令:Ctrl + Shift + V 组合键.
2. 在控制台下: 复制命令:Ctrl + Insert 组合键或用鼠标选中即是复制.粘贴命令:Shift + Insert 组合键或单击鼠标滚轮即为粘贴.
ctrl+l:清屏
6.文件操作命令1(touch-cat-more)
touch 创建文件
语法:touch Linux路径
- touch命令无选项,参数必填,表示要创建的文件路径,相对、绝对、特殊路径符均可以使用
(文件夹与文件的颜色不一样,ls -l中标识为d的是文件夹,标识为-的是文件)
cat 查看文件内容
-n 或 --number:由 1 开始对所有输出的行数编号。
-b 或 --number-nonblank:和 -n 相似,只不过对于空白行不编号。
-s 或 --squeeze-blank:当遇到有连续两行以上的空白行,就代换为一行的空白行。
-v 或 --show-nonprinting:使用 ^ 和 M- 符号,除了 LFD 和 TAB 之外。
-E 或 --show-ends : 在每行结束处显示 $。
-T 或 --show-tabs: 将 TAB 字符显示为 ^I。
-A, --show-all:等价于 -vET。
-e:等价于"-vE"选项;
-t:等价于"-vT"选项;
(学习了vi编辑器后,可以向文件内编辑内容)
more命令查看文件内容
- cat是直接将内容全部展示出来
- more支持翻页,如果文件内容过多,可以一页页的展示
语法:more Linux路径
-
同样没有选项,只有必填参数,参数表示:被查看文件路径,相对、绝对、特殊路径符都可以使用
-
查看过程中,通过空格翻页
-
通过q退出查看
7.文件操作命令2(cp-mv-rm)
cp 复制文件/文件夹
语法: cp [-r] 参数1 参数2
- -r选项,可选,用于复制文件夹使用,表示递归
- 参数1,Linux路径,表示被复制的文件或文件夹
- 参数2,Linux路径,表示要复制去的地方
mv 移动文件/文件夹
语法: mv 参数1 参数2
- 参数1,Linux路径,表示被移动的文件/文件夹
- 参数2,Linux路径,表示要移动去的地方,如果目标不存在,则进行改名,确保目标存在
yang@yang-virtual-machine:~$ ls
公共的 文档 hanshushuru.sh input snap test4.sh test8.sh
模板 下载 hhhhh.txt input.txt test test5.sh test9.sh
视频 音乐 huiwenzhishu noname2.txt test2.sh test6.sh test.sh
图片 桌面 huiwenzhishu.cpp output.txt test3.sh test7.sh yang
yang@yang-virtual-machine:~$ mv test.sh ./test
yang@yang-virtual-machine:~$ ls
公共的 文档 hanshushuru.sh input snap test4.sh test8.sh
模板 下载 hhhhh.txt input.txt test test5.sh test9.sh
视频 音乐 huiwenzhishu noname2.txt test2.sh test6.sh yang
图片 桌面 huiwenzhishu.cpp output.txt test3.sh test7.sh
yang@yang-virtual-machine:~$ mv test2.sh ./test
yang@yang-virtual-machine:~$ mv test3.sh ./test
yang@yang-virtual-machine:~$ mv test4.sh ./test
yang@yang-virtual-machine:~$ ls ./test
test1.sh test2.sh test3.sh test4.sh test.sh
rm 删除文件/文件夹
语法:rm [-r -f] 参数1 参数2 ...... 参数N
- 同cp命令一样,-r选项用于删除文件夹
- -f表示force,强制删除(不会弹出提示确认信息)
- 普通用户删除内容不会弹出提示,只有root管理员用户删除内容才会有提示
- 所以一般普通用户用不到-f
- 参数1、参数2、…、参数N 表示要删除的文件或文件夹路径,用空格隔开
通配符
rm命令支持通配符*,用来做模糊匹配
- 符号*表示通配符,即匹配任意内容(包含空),实例:
- test*,表示匹配任何以test开头的内容
- *test,表示匹配任何以test结尾的内容
- *test *(没有空格),表示匹配任何包含test的内容
- 可以通过 su - root,并输入密码,临时切换到root用户体验;
- 通过输入exit命令,退回普通用户。
8.grep、wc、管道符
grep命令:从文件中通过关键字过滤文件行
语法:grep [-n] 关键字 文件路径
- 选项-n,可选,表示在结果中显示匹配的行的行号
- 参数,关键字,必填,表示过滤的关键字,带有空格或其他特殊符号,建议使用“ ”将关键字包围起来
- 参数,文件路径,必填,表示要过滤内容的文件路径,可作为内容输入端口(可以作为管道符的输入)
wc命令做数量统计
可以通过wc命令统计文件的行数、单词数量等
语法:wc [-c -m -l -w] 文件路径
- -c,统计bytes数量
- -m,统计字符数量
- -l,统计行数
- -w,统计单词数量
- 文件路径,被统计的文件,可作为内容输入端口(可以作为管道符的输入)
管道符:|
管道符含义:将管道符左边命令的结果,作为右边命令的输入
9.which、find命令
which
前面学习的Linux命令,其实它们的本体就是一个个的二进制可执行程序(类似Windows的.exe)
(补充:命令可以是下面四种形式之一:
-
是一个可执行程序,就像我们所看到的位于目录/usr/bin 中的文件一样。 属于这一类的程序,可以编译成二进制文件,诸如用 C 和 C++语言写成的程序, 也可以是由脚本语言写成的程序,比如说 shell,perl,python,ruby,等等。
-
是一个内建于 shell 自身的命令。bash 支持若干命令,内部叫做 shell 内部命令 (builtins)。例如,本地环境中的 cd 命令,就是一个 shell 内部命令。which cd没有结果
-
是一个 shell 函数。这些是小规模的 shell 脚本,它们混合到环境变量中。 比如上面讲到的 cd 命令,在实验楼环境中就是一个 shell 函数。
-
是一个命令别名。我们可以定义自己的命令,建立在其它命令之上。
)
which命令,可以查看所使用的一系列命令的程序文件放在哪里(在PATH变量指定的路径中搜索可执行文件的所在位置。)
只针对于命令的程序文件查找
语法:which 要查找的命令
补充:
- -n<文件名长度> 指定文件名长度,指定的长度必须大于或等于所有文件中最长的文件名。
- -p<文件名长度> 与-n参数相同,但此处的<文件名长度>包括了文件的路径。
- -w 指定输出时栏位的宽度。
- -V 显示版本信息。
find-按文件名查找文件
语法: find 起始路径 -name "被查找文件名"
find-通配符
模糊查询
- test*
- *test
- *test *(没有空格)
find命令-按文件大小查找文件
语法:find 起始路径 -size +|-n[KMG]
- +、-表示大于和小于
- n表示大小数字
- KMG表示大小单位,k(小写字母)表示kb,M表示MB,G表示GB
例子:
- 查找小于10KB的文件:find / -size -10k
- find / -size +100M查找大于100MB的文件
- find / -size +1G查找大于1GB的文件
10.echo、tail、重定向符
echo命令
使用echo命令可以在命令行内输出指定内容
语法:echo 输出的内容
- 无需选项,只有一个参数,表示要输出的内容,复杂内容可以用“ ”包围
- 带有空格或者\等特殊符号,建议使用双引号包围(不包围的话,空格后很容易被识别为参数2,尽管echo不受影响)
反引号``
被`包围的内容,会被作为命令执行,而非普通字符
echo `pwd`//输出当前工作目录
重定向符
- “>”,将左侧命令的结果,覆盖写入到符号右侧指定的文件中
- “>>”,将左侧命令的结果,追加写入到符号右侧指定的文件夹中
tail命令
查看文件尾部内容,跟踪文件的最新更改,语法:
tail [-f -num] linux路径
- 参数,Linux路径,表示被跟踪的文件路径
- 选项,-f,表示持续跟踪(ctrl+c强制停止命令运行)
- 选项,-num(如-1,-5,-6,-9),表示,查看尾部多少行,不填默认10行
三、vi/vim和tmux
1.vi/vim
1.1vim学习
vi/vim编辑器介绍
vi/vim是visual interface的简称,是Linux中最经典的文本编辑器。
同图形化界面中的文本编辑器一样,vi是命令行下对文本文件进行编辑的绝佳选择。
vim是vi的加强版本,兼容vi的所有指令,不仅能编辑文本,而且还具有shell程序编辑的功能,可以不同颜色的字体来辨别语法的正确性,极大地方便了程序的设计和编辑性。
vi/vim的三种工作模式
命令模式(command mode):
- 该模式下,所敲的按键编辑器都理解为命令,以命令驱动执行不同的功能。
- 此模式下,不能自由进行编辑。
输入模式(Insert mode):
- 也就是所谓的编辑模式、插入模式
- 此模式下,可以对文件内容进行自由编辑
- 输入iao进入,esc键回到命令模式
底线命令模式(Last line mode):
- 以:开始,通常用于文件的保存、退出。
- 命令以回车结束运行。
- 输入wq,保存文件并退出(w保存,q退出)
命令模式
进入:vi 文件路径
或vim 文件路径
- 如果文件路径表示的文件存在,那么命令用于编辑已有文件
- 如果文件路径表示的文件不存在,那么命令用于编辑已有文件
y+y+p 复制
d+d删除一行
按u撤销
模式 | 命令 | 描述 |
---|---|---|
命令模式 | i | 在当前光标位置进入输入模式 |
命令模式 | a | 在当前光标位置之后进入输入模式 |
命令模式 | I | 在当前行的开头,进入输入模式 |
命令模式 | A | 在当前行的结尾,进入输入模式 |
命令模式 | o | 在当前光标下一行进入输入模式(开新行) |
命令模式 | O | 在当前光标上一行进入输入模式(开新行) |
输入模式 | esc | 任何情况下按esc 键都能回到命令模式 |
功能:
(1) 命令行模式下的文本编辑器。
(2) 根据文件扩展名自动判别编程语言。支持代码缩进、代码高亮等功能。
(3) 使用方式:vim filename
如果已有该文件,则打开它。
如果没有该文件,则打开个一个新的文件,并命名为filename
模式:
(1) 一般命令模式
默认模式。命令输入方式:类似于打游戏放技能,按不同字符,即可进行不同操作。可以复制、粘贴、删除文本等。
(2) 编辑模式
在一般命令模式里按下i,会进入编辑模式。
按下ESC会退出编辑模式,返回到一般命令模式。
(3) 命令行模式
在一般命令模式里按下:/?三个字母中的任意一个,会进入命令行模式。命令行在最下面。
可以查找、替换、保存、退出、配置编辑器等。
操作:(大部分命令模式下)
(1) i:进入编辑模式
(2) ESC:进入一般命令模式
(3) h 或 左箭头键:光标向左移动一个字符
(4) j 或 向下箭头:光标向下移动一个字符
(5) k 或 向上箭头:光标向上移动一个字符
(6) l 或 向右箭头:光标向右移动一个字符
(7) n:n表示数字,按下数字后再按空格,光标会向右移动这一行的n个字符
(8) 0 或 功能键[Home]:光标移动到本行开头
(9) $ 或 功能键[End]:光标移动到本行末尾
(10) G:光标移动到最后一行
(11) :n 或 nG:n为数字,光标移动到第n行
(12) gg:光标移动到第一行,相当于1G
(13) n:n为数字,光标向下移动n行
(14) /word:向光标之下寻找第一个值为word的字符串。(/进入搜索模式)
(15) ?word:向光标之上寻找第一个值为word的字符串。
(16) n:重复前一个查找操作(向下继续搜索)
(17) N:反向重复前一个查找操作(向上继续搜索)
(18) :n1,n2s/word1/word2/g:n1与n2为数字,在第n1行与n2行之间寻找word1这个字符串,并将该字符串替换为word2
(19) :1, s / w o r d 1 / w o r d 2 / g :将全文的 w o r d 1 替换为 w o r d 2 ( 20 ) : 1 , s/word1/word2/g:将全文的word1替换为word2 (20) :1, s/word1/word2/g:将全文的word1替换为word2(20):1,s/word1/word2/gc:将全文的word1替换为word2,且在替换前要求用户确认。
(21) v:选中文本
(22) d:删除选中的文本(dgg从当前行开始,向上全部删除)(d$从当前的光标开始删除到本行的结尾)(d0从当前光标开始,删除到本行的开头)
(23) dd: 删除当前行(ndd删除当前光标向下n行)(dG从当前行开始向下全部删除)
(24) y:复制选中的文本
(25) yy: 复制当前行(nyy复制当前行和下面的n行)
(26) p: 将复制的数据在光标的下一行/下一个位置粘贴
(27) u:撤销
(28) Ctrl + r:取消撤销
(29) 大于号 >:将选中的文本整体向右缩进一次
(30) 小于号 <:将选中的文本整体向左缩进一次
(31) :w 保存
(32) :w! 强制保存
(33) :q 退出
(34) :q! 强制退出
(35) :wq 保存并退出
(36) :set paste 设置成粘贴模式,取消代码自动缩进(用于从外部复制内容)
(37) :set nopaste 取消粘贴模式,开启代码自动缩进
(38) :set nu 显示行号
(39) :set nonu 隐藏行号
(40) gg=G:将全文代码格式化
(41) :noh 关闭查找关键词高亮
(42) Ctrl + q:当vim卡死时,可以取消当前正在执行的命令31-39、41底线命令模式
shift+pageup(PgUp)向上翻页
shift+pangdown(PgDn)向下翻页
异常处理:
每次用vim编辑文件时,会自动创建一个.filename.swp的临时文件。
如果打开某个文件时,该文件的swp文件已存在,则会报错。此时解决办法有两种:
(1) 找到正在打开该文件的程序,并退出
(2) 直接删掉该swp文件即可
1.2 超算习堂实训
1.2.1基本模式
普通模式
在普通模式中,用的编辑器命令,比如移动光标,删除文本等等。这也是Vim启动后的默认模式。这正好和许多新用户期待的操作方式相反(大多数编辑器默认模式为插入模式)。
在普通模式中,有很多方法可以进入插入模式。比较普通的方式是按a
(append/追加)键或者i
(insert/插入)键。
直接使用vim命令后进入vim的普通模式,在其他模式下,按下ESC
即可返回普通模式。
插入模式
在这个模式中,大多数按键都会向文本缓冲区中插入文本。大多数新用户希望文本编辑器编辑过程中一直保持这个模式。
在插入模式中,可以按ESC
键回到普通模式。
在普通模式下i, I, a, A
等键即可进入插入模式,插入模式下,按键则会输入。
可视模式
这个模式与普通模式比较相似。但是移动命令会扩大高亮的文本区域。高亮区域可以是字符、行或者是一块文本。当执行一个非移动命令时,命令会被执行到这块高亮的区域上。Vim的"文本对象"也能和移动命令一样用在这个模式中。
在普通模式下,按下v, V, <Ctrl>+v
即可进入
选择模式
这个模式和无模式编辑器的行为比较相似(Windows标准文本控件的方式)。这个模式中,可以用鼠标或者光标键高亮选择文本,不过输入任何字符的话,Vim会用这个字符替换选择的高亮文本块,并且自动进入插入模式。
命令行模式
在命令行模式中可以输入会被解释成并执行的文本。例如执行命令(:
键),搜索(/
和?
键)或者过滤命令(!
键)。在命令执行之后,Vim返回到命令行模式之前的模式,通常是普通模式。
在普通模式下,按下:
即可进入
Ex模式
这和命令行模式比较相似,在使用:visual
命令离开Ex模式前,可以一次执行多条命令。
在进入Vim时,加上-e
参数即可进入,例如:vim -e
1.2.2 普通模式–游标移动
字符级移动
在普通模式下,可以使用方向键或者h,j,k,l
进行移动,如下表:
按键 | 方向 |
---|---|
h,← | 左 |
l,→ | 有 |
j,↓ | 下 |
k,↑ | 上 |
行内移动
在行内以移动游标时,可以使用下面的命令来实现:
按键 | 说明 |
---|---|
w | 右移到下一个单词的开头 |
e | 右移到下一个单词的末尾 |
b | 左移到前一个单词的开头 |
0 | 右移到本行的开始 |
$ | 右移到本行的末尾 |
^ | 左移到本行的第一个非空字符 |
页级移动
可以在相邻页之间移动:
按键 | 说明 |
---|---|
crtl +f | 前移一页 |
crtl +b | 后移一页 |
页内移动
当我们到达指定页时,可以在页内快速移动:
按键 | 说明 |
---|---|
H | 将光标移到该页的起始行 |
M | 将光标移到该页的中间行 |
L | 将光标移到该页的末尾行 |
其他移动
Vim提供了很多的移动方式,这里再列举一些大范围移动:
按键 | 说明 |
---|---|
* | 将光标移到该单词的下一个位置 |
# | 将光标移到该单词的上一个位置 |
g | 将光标移到文件的第一行(双击) |
G | 将光标移到文件的末尾行 |
1.2.3普通模式–文档编辑
搜索
Vim的搜索方法非常简单,只需要输入/
+内容
就可以进行搜索,其命令具体如下:
指令 | 说明 |
---|---|
/ +str | 向下搜索字符串str |
n | 继续搜索 |
N | 反向搜索 |
? +str | 反向搜索字符串str |
尝试使用命令搜索ephc
,vmi
替换
Vim的常规替换命令主要由s
和c
完成,但替换命令之后,会进入插入模式,按下ESC
即可返回普通模式,替换命令部分如下:(感觉就是命令模式下按s键会删除光标所在位置的字符,ns删除光标所在开始的n个字符,c$删除从光标开始到行尾的所有字符,c0删除从本行开头到光标的所有字符)
指令 | 说明 |
---|---|
s | 用输入的正文替换游标所在的字符 |
ns | 用输入的正文替换游标右侧n 个字符 |
c$ | 用输入的正文替换从游标开始到行尾的所有字符 |
c0 | 用输入的正文替换从本行开始到游标的所有字符 |
删除
Vim的删除命令主要由d
和x
完成,如下:
指令 | 说明 |
---|---|
x | 删除游标所在的字符 |
X | 删除游标所在前一个字符 |
dw | 删除游标右的单词 |
dd | 删除游标所在行 |
d0 | 删除光标到行的开始 |
d$ | 删除光标到行的末尾 |
复制
Vim中删除操作其实与剪切操作类似,会将内容复制到内存缓冲区,当然,也可以通过命令自行复制而不删除内容:
指令 | 说明 |
---|---|
yy | 复制游标所在行到缓冲区 |
nyy | 复制n 行到缓冲区 |
粘贴
将内容复制到缓冲区后,可以使用命令将内容粘贴:
指令 | 说明 |
---|---|
p | 粘贴到游标后 |
P | 粘贴到游标前 |
撤销
通过指令,可以撤销上一次的操作:
指令 | 说明 |
---|---|
u | 撤销上次操作 |
重复
通过指令,可以重复上一次的操作:?查到说“.”有这个用途
指令 | 说明 |
---|---|
u | 重复上次操作 |
1.2.4插入模式
进入插入模式
我们知道使用Vim命令后首先进入的是普通模式,要编写内容还是要进入插入模式,除了前面已经提及的一些进入插入模式的方法之外,进入插入模式还可以通过命令:
指令 | 说明 |
---|---|
i | 在游标处插入 |
I | 在行首插入(第一个字符) |
a | 在游标右侧插入 |
A | 在行末插入 |
o | 在当前行后添加一行插入 |
O | 在当前行前添加一行插入 |
游标移动
当然,也可以尝试在插入模式时移动,但此时h,j,k,l
已不能移动,只能使用方向键进行小幅移动:
按键 | 方向 |
---|---|
← | 左 |
→ | 有 |
↓ | 下 |
↑ | 上 |
退出插入模式
进入插入模式后,在编辑内容时,往往需要应用其他命令,这时就需要退出插入模式,进入普通模式,使用命令进行操作:
指令 | 说明 |
---|---|
ESC | 退出插入模式 |
Crtl +[ | 退出插入模式 |
1.2.5 命令模式
打开文件
在进入Vim之后,如需打开其他文件,命令未e
+文件名
,例如:
:e ehpc.txt
则可打开ehpc.txt文件
保存文件
编辑之后,我们可以使用命令w
保存文件,也可以另存为其他文件:
:w other-ehpc.txt
退出Vim
退出Vim时,如果未作修改,需要使用q
进行退出,如果有修改内容,但不保存,则可以使用q!
强制退出,如果想要保存内容,并退出,可以使用命令wq
。
行号操作
命令模式下,我们可以直接输入行号进行跳转:
: n
:跳转到第n
行
通过对行号的使用,我们可以结合其他命令做到:
:nw 文件名
将n
行写入文件:m,nw 文件名
将m
到n
行写入文件:m,.w 文件名
将m
到当前行写入文件:.,$w 文件名
将当前行到最后一行写入文件
文件操作
前面指出了可以使用e
打开文件,w
写文件,Vim还有更多的文件操作:
:r 文件名
读取文件并插入到游标之后:f 文件名
重命名文件:f
输出当前文件名称和状态
内容替换
Vim除了在普通模式下能够进行替换操作,命令模式下也可以进行替换操作:
:%s/str1/str2/
用str2
替换(每一)行中首次出现的str1
:s/str1/str2/
用str2
替换光标所在行的第一个str1
- 通过
g
参数可以达到替换所有的操作:
:s/str1/str2/g
用str2
替换行中出现的所有str1
- 还可以指定行数,例如:
:1,$ s/str1/str2/g
用字符串str2
替换正文中所有出现的字符串str1
上述操作也可以通过:g/str1/s//str2/g
实现
1.2.6进阶命令
文件恢复
通过:recover
可以恢复意外退出而没有保存的文件
选项设置
通过:set
命令可以设置选项,比如:
选项 | 说明 |
---|---|
autoindent | 自动缩进 |
number | 显示行号 |
ignorecase | 忽略正则表达式的大小写 |
ruler | 显示游标位置 |
:set autoindent 在此之后,如果在一行的开头输入空格或制表符,那么后续的新行将会缩进到相同的位置。在命令模式下,输入 :set autoindent,然后按回车打开自动缩进。通过设置 shiftwidth 确定缩进级别。例如,:set shiftwidth=4 把每级缩进设置为四个空格
分屏
Vim中可以使用命令进行分屏操作:
命令 | 说明 |
---|---|
:split 或者:sp | 水平分屏 |
:vsplit 或者:vsp | 垂直分屏 |
也可以在启动Vim时分屏,在启动时加入参数:
vim -On file1 file2...
打开 file1 和 file2 ,垂直分屏
vim -on file1 file2...
打开 file1 和 file2 ,水平分屏
各屏幕间移动需要使用快捷键:
命令 | 说明 |
---|---|
Ctrl +w +h | 当前屏的左分屏 |
Ctrl +w +l | 当前屏的右分屏 |
Ctrl +w +j | 当前屏的下分屏 |
Ctrl +w +k | 当前屏的上分屏 |
Ctrl +w +w | 下一个屏 |
diff
可以通过Vim进行不同文件之间的比较,在命令行中,可以直接输入vimdiff file1 file2
即可在Vim里分屏显示两个文件的差异。
在Vim内,也可以通过命令diffsplit file
与其他文件进行比较
Vim插件
Vim本身已经具有丰富的功能,但是通过插件的安装,甚至可以自定义得到IDE。
2.tmux
Tmux 是一个终端复用器(Terminal Multiplexer),非常有用,属于常用的开发、运维工具。
2.1 什么是Tmux
2.1.1 会话与进程
命令行的典型使用方式是,打开一个终端窗口(terminal window,以下简称 “窗口”),在里面输入命令。用户与计算机的这种临时的交互,称为一次 “会话”(session) 。
会话的一个重要特点是,窗口与其中启动的进程是连在一起的。打开窗口,会话开始;关闭窗口,会话结束,会话内部的进程也会随之终止,不管有没有运行完。
为了解决这个问题,会话与窗口可以 “解绑”:窗口关闭时,会话并不终止,而是继续运行,等到以后需要的时候,再让会话 “绑定” 其他窗口。
2.1.2 Tmux 的作用
- Tmux 就是会话与窗口的 “解绑” 工具,将它们彻底分离。
(1)它允许在单个窗口中,同时访问多个会话。这对于同时运行多个命令行程序很有用。
(2)它可以让新窗口 “接入” 已经存在的会话。
(3)它允许每个会话有多个连接窗口,因此可以多人实时共享会话。
(4)它还支持窗口任意的垂直和水平拆分。
一个tmux可以包含多个会话session,一个会话可以包含多个窗口window,一个窗口可以包含多个窗格pane。
2.2 基本用法
2.2.1 安装:输入tmux,按照指令输入
2.2.2 启动与退出
输入tmux进入,输入exit或者按ctrl+d退出
2.2.3 前缀键
tmux的所有快捷键都要通过前缀键唤起。默认是ctrl+b
。
例如:按
ctrl+b ?
,会显示帮助信息(快捷键大全)。按esc或者q可以退出帮助
2.3 会话管理
2.3.1 新建会话
窗口编号从0开始,窗口所对应的会话,就是0号会话、1号会话等。
编号区分不直观,可以命名
$ tmux new -s <session-name>
新建一个指定名称的会话。
(如: tmux new -s huihua1)
2.3.2 分离会话
在tmux窗口中,按下ctrl+b d
或者输入tmux detach
命令,就会将当前会话与窗口分离。
上面的命令执行后,就会退出当前 Tmux 窗口,但是会话和里面的进程仍然在后台运行。
tmux ls
命令(或者tmux list-session
)可以查看当前所有的 Tmux 会话。
2.3.3 接入会话
tmux attach
命令用于重新接入某个已存在的会话。
tmux attach -t 0
//使用会话编号
tmux attach -t <session-name>
//使用会话名称
3.3.4 杀死会话
tmux kill-session
命令用于杀死某个会话。
tmux kill-session -t 0
//使用会话编号
tmux kill-session -t <session-name>
//使用会话名称
3.3.5 切换会话
tmux swich
命令用于切换会话。
tmux switch -t 0
//使用会话编号
tmux switch -t <session-name>
//使用会话名称
3.3.6 重命名会话
tmux rename-session
命令用于重命名会话。
tmux rename-session -t 0 <new-name>
3.3.7 会话快捷键
ctrl+b d
:分离当前对话。ctrl+b s
:列出所有对话。ctrl+b $
:重命名当前对话。
2.4 最简操作流程
综上所述,以下是 Tmux 的最简操作流程。
- 新建会话
tmux new -s my_session
。 - 在 Tmux 窗口运行所需的程序。
- 按下快捷键
Ctrl+b d
将会话分离。 - 下次使用时,重新连接到会话
tmux attach-session -t my_session
。
2.5 窗格操作
tmux可以将窗口分为多个窗格pane,每个窗格运行不同的命令。
2.5.1 划分窗格
tmux split-window
命令用来划分窗格。
# 划分上下两个窗格
$ tmux split-window
# 划分左右两个窗格
$ tmux split-window -h
2.5.2 移动光标
tmux select-pane
命令用来移动光标位置。
# 光标切换到上方窗格
$ tmux select-pane -U
# 光标切换到下方窗格
$ tmux select-pane -D
# 光标切换到左边窗格
$ tmux select-pane -L
# 光标切换到右边窗格
$ tmux select-pane -R
2.5.3 交换窗格位置
tmux swap-pane
命令用来交换窗格位置。
# 当前窗格上移
$ tmux swap-pane -U
# 当前窗格下移
$ tmux swap-pane -D
# 当前窗格左移
$ tmux swap-pane -L
# 当前窗格左移
$ tmux swap-pane -R
2.5.4 窗格快捷键
Ctrl+b %
:划分左右两个窗格。Ctrl+b "
:划分上下两个窗格。Ctrl+b <arrow key>
:光标切换到其他窗格。是指向要切换到的窗格的方向键,比如切换到下方窗格,就按方向键↓。Ctrl+b ;
:光标切换到上一个窗格。Ctrl+b o
:光标切换到下一个窗格。Ctrl+b {
:当前窗格左移。Ctrl+b }
:当前窗格右移。Ctrl+b Ctrl+o
:当前窗格上移。Ctrl+b Alt+o
:当前窗格下移。Ctrl+b x
:关闭当前窗格。Ctrl+b !
:将当前窗格拆分为一个独立窗口。Ctrl+b z
:当前窗格全屏显示,再使用一次会变回原来大小。Ctrl+b Ctrl+<arrow key>
:按箭头方向调整窗格大小。Ctrl+b q
:显示窗格编号。
2.6 窗口管理
2.6.1 新建窗口
tmux new-window
命令用来创建新窗口。
$ tmux new-window
# 新建一个指定名称的窗口
$ tmux new-window -n <window-name>
复制
2.6.2 切换窗口
tmux select-window
命令用来切换窗口。
# 切换到指定编号的窗口
$ tmux select-window -t <window-number>
# 切换到指定名称的窗口
$ tmux select-window -t <window-name>
复制
2.6.3 重命名窗口
tmux rename-window
命令用于为当前窗口起名(或重命名)。
$ tmux rename-window <new-name>
复制
2.6.4 窗口快捷键
下面是一些窗口操作的快捷键。
Ctrl+b c
:创建一个新窗口,状态栏会显示多个窗口的信息。Ctrl+b p
:切换到上一个窗口(按照状态栏上的顺序)。Ctrl+b n
:切换到下一个窗口。Ctrl+b <number>
:切换到指定编号的窗口,其中的是状态栏上的窗口编号。Ctrl+b w
:从列表中选择窗口。Ctrl+b ,
:窗口重命名。
2.7 其他命令
# 列出所有快捷键,及其对应的 Tmux 命令
$ tmux list-keys
# 列出所有 Tmux 命令及其参数
$ tmux list-commands
# 列出当前所有 Tmux 会话的信息
$ tmux info
# 重新加载当前的 Tmux 配置
$ tmux source-file ~/.tmux.conf
四、shell
1. 概述
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言。(用户和内核之间的”翻译官“)(用户登录Linux系统时,自动加载一个shell程序)
Shell 是指一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。
Shell 脚本
Shell 脚本(shell script),是一种为 shell 编写的脚本程序。
业界所说的 shell 通常都是指 shell 脚本。(下面"shell编程" 都是指 shell 脚本编程,不是指开发 shell 自身。)
shell脚本可以直接在命令行中执行,也可以将一套逻辑组织成一个文件,方便复用。
AC Terminal中的命令行可以看成是一个shell脚本在逐行执行。
Linux中常见的shell脚本有很多种,常见的有:
- Bourne Shell(/usr/bin/sh或/bin/sh)
- Bourne Again Shell(/bin/bash)
- C Shell(/usr/bin/csh)
- K Shell(/usr/bin/ksh)
- zsh
- …
Linux系统中一般默认使用bash,所以接下来讲解bash中的语法。文件开头需要写#! /bin/bash
,指明bash为脚本解释器。
#!
告诉系统其后路径所指定的程序即是解释此脚本文件的 Shell 程序。(是一个约定的标记,它告诉系统这个脚本需要什么解释器来执行,即使用哪一种 Shell。)
脚本实例
打开文本编辑器(可以使用 vi/vim 命令来创建文件),新建一个文件 test.sh,扩展名为 sh(sh代表shell),扩展名并不影响脚本执行,如果你用 php 写 shell 脚本,扩展名就用 php 好了。
#! /bin/bash
echo "Hello world!"
运行 Shell 脚本有两种方法:
- 1、作为可执行程序
将上面的代码保存为 test.sh,并 cd 到相应目录:
chmod +x ./test.sh #使脚本具有执行权限
chmod 755 ./test.sh #使脚本具有执行权限 成功
./test.sh #执行脚本
注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去 PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。
- 2、作为解释器参数
这种运行方式是,直接运行解释器,其参数就是 shell 脚本的文件名,如:
/bin/sh test.sh
/bin/php test.php #不存在该文件或目录
bash test.sh
这种方式运行的脚本,不需要在第一行指定解释器信息,写了也没用。
尝试结果
yang@yang-virtual-machine:~/桌面$ vim test.sh
yang@yang-virtual-machine:~/桌面$ chmod -x test.sh
yang@yang-virtual-machine:~/桌面$ ./test.sh
bash: ./test.sh: 权限不够
yang@yang-virtual-machine:~/桌面$ /home/yang/桌面/test.sh
bash: /home/yang/桌面/test.sh: 权限不够
yang@yang-virtual-machine:~/桌面$ bash test.sh
hello world!
yang@yang-virtual-machine:~/桌面$ chmod -x ./test.sh #使脚本具有执行权限 失败 应该是+号,所以失败了
yang@yang-virtual-machine:~/桌面$ ./test.sh
bash: ./test.sh: 权限不够
yang@yang-virtual-machine:~/桌面$ chmod 755 test.sh ##使脚本具有执行权限 成功
yang@yang-virtual-machine:~/桌面$ ./test.sh
hello world!
2. 注释
单行注释
每行中#后面的内容
# 这是一条注释
echo 'hello world' #这也是
多行注释
:<<EOF
第一行注释
第二行注释
EOF
:<<abc
line 1
line 2
abc
:<<!
line 1
line2
!
3.变量
定义变量
定义变量时,变量名不加美元符号($,PHP语言中变量需要),如:
your_name="yange'ch'p"
注意:变量名和等号之间不能有空格。
命名规则:
- 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头。
- 中间不能有空格,可以使用下划线 _。
- 不能使用标点符号。
- 不能使用bash里的关键字(可用help命令查看保留关键字)。
除了显式地直接赋值,还可以用语句给变量赋值,如:
for file in 'ls /etc'
或
for file in $(ls /etc)
以上语句将 /etc 下目录的文件名循环出来。file 是变量, for 读取文件夹etc里的文件名 赋值给file
使用变量
使用一个定义过的变量,只要在变量名前面加美元符号即可,如:
your_name="yang"
echo $your_name
echo ${your_name}mmm #yangmmm
变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界.
已定义的变量,可以被重新定义:
your_name="tom"
echo $your_name
your_name="alibaba"
echo $your_name
第二次赋值的时候不能写$ your_name=“alibaba”,使用变量的时候才加美元符($
)。
只读变量
使用readonly
或者declare
可以将变量变为只读。
name=yang
readonly name
declare -r name # 两种写法均可
name=abc # 会报错,因为此时name只读
删除变量
unset
可以删除变量。
name=yxc
unset name
echo $name # 输出空行
unset 命令不能删除只读变量。
变量类型
运行shell时,会同时存在三种变量:
- 1) 局部变量 局部变量在脚本或命令中定义,仅在当前shell实例中有效,其他shell启动的程序不能访问局部变量。
- 2) 环境变量 所有的程序,包括shell启动的程序,都能访问环境变量,有些程序需要环境变量来保证其正常运行。必要的时候shell脚本也可以定义环境变量。
- 3) shell变量 shell变量是由shell程序设置的特殊变量。shell变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了shell的正常运行
字符串
字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号。
单引号与双引号的区别:
- 单引号中的内容会原样输出,不会执行、不会取变量;
- 单引号字串中不能出现单独一个的单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用;
- 双引号中的内容可以执行、可以取变量;
- 双引号里可以出现转义字符。
name=yang # 不用引号
echo 'hello, $name \"hh\"' # 单引号字符串,输出 hello, $name \"hh\"
echo "hello, $name \"hh\"" # 双引号字符串,输出 hello, yang "hh"
拼接字符串
your_name="yang"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
# 输出结果:
hello, yang ! hello, yang !
hello, yang ! hello, ${your_name} !
获取字符串长度
string="abcd"
echo ${#string} # 输出 4
变量为数组时,${#string}
等价于 ${#string[0]}
string="abcd"
echo ${#string[0]} # 输出 4?
提取字符串
name="hello,yang"
echo ${name:0:5} # 提取从0开始的5个字符
查找子字符串
查找字符 i 或 o 的位置(哪个字母先出现就计算哪个):
string="runoob is a great site"
echo `expr index "$string" io` # 输出 4
注意: 以上脚本中 **`**是反引号,而不是单引号 '。
4.默认变量
文件参数变量
在执行shell脚本时,可以向脚本传递参数。$1
是第一个参数,$2
是第二个参数,以此类推。特殊的,$0
是文件名(包含路径)。
创建文件test.sh
#! /bin/bash
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
然后执行该脚本:
yang@yang-virtual-machine:~$ chmod +x test.sh
yang@yang-virtual-machine:~$ ./test.sh 2 3 4 5
文件名:./test.sh
第一个参数:2
第二个参数:3
第三个参数:4
第四个参数:5
其它参数相关变量
参数 | 说明 |
---|---|
$# | 代表文件传入的参数个数,如上例中值为4 |
$* | 由所有参数构成的用空格隔开的字符串,如上例中值为$1 $2 $3 $4 |
$@ | 每个参数分别用双引号括起来的字符串,如上例中值为"$1" “$2” “$3” “$4” ??? |
$$ | 脚本当前运行的进程ID |
$? | 上一条命令的退出状态(注意不是stdout,而是exit code)。0表示正常退出,其他值表示错误(stdout标准输出,exit code退出代码) |
$(commamd) | 返回command这条命令的stdout(可嵌套)【不理解】 |
command | 返回command这条命令的stdout(不可嵌套)* |
#! /bin/bash
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
echo hhhh $#
echo $*
echo $@
echo $$
echo $?
echo $(command)
yang@yang-virtual-machine:~$ ./test.sh 1 5 6 9
文件名:./test.sh
第一个参数:1
第二个参数:5
第三个参数:6
第四个参数:9
hhhh 4
1 5 6 9
1 5 6 9 #没有双引号?
2652
0
#该行为空
Shell ∗ 和 *和 ∗和@的区别 (biancheng.net)
当 $* 和 $@ 不被双引号" "
包围时,它们之间没有任何区别,都是将接收到的每个参数看做一份数据,彼此之间以空格来分隔。但是当它们被双引号
" "
包含时,就会有区别了:
"$*"
会将所有的参数从整体上看做一份数据,而不是把每个参数都看做一份数据。"$@"
仍然将每个参数都看作一份数据,彼此之间是独立的。比如传递了 5 个参数,那么对于
"$*"
来说,这 5 个参数会合并到一起形成一份数据,它们之间是无法分割的;而对于"$@"
来说,这 5 个参数是相互独立的,它们是 5 份数据。如果使用 echo 直接输出
"$*"
和"$@"
做对比,是看不出区别的;但如果使用 for 循环来逐个输出数据,立即就能看出区别来。
echo "$*" #1 5 6 9
echo "$@" #1 5 6 9
#! /bin/bash
echo "文件名:"$0
echo "第一个参数:"$1
echo "第二个参数:"$2
echo "第三个参数:"$3
echo "第四个参数:"$4
echo hhhh $#
echo $*
echo $@
echo $$
echo $?
echo $(command)
echo "$*"
echo "$@"
echo command #如果加上``,输出空行
echo $(command)
:<<abc
yang@yang-virtual-machine:~$ ./test.sh 1 2 3 4
文件名:./test.sh
第一个参数:1
第二个参数:2
第三个参数:3
第四个参数:4
hhhh 4
1 2 3 4
1 2 3 4
2939
0
1 2 3 4
1 2 3 4
command
abc
5.数组
数组中可以存放多个不同类型的值,只支持一维数组,初始化时不需要指明数组大小。数组下标从0开始。
定义
数组用小括号表示,元素之间用空格隔开。例如:
array=(1 abc "def" y)
也可以直接定义数组中某个元素的值:
array[0]=1
array[1]=abc
array[2]="def"
array[3]=y
读取数组中某个元素的值
格式:
${array[index]} # $array[2] 输出1[2]
例如:
array=(1 abc "def" yxc)
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
echo ${array[3]}
读取整个数组
格式:
${array[@]} #第一种写法
${array[*]} #第二种写法
数组长度
${#array[@]} #1
${#array[*]} #2
${#array[0]} #第0个元素的字符长度
关联数组
Bash 支持关联数组,可以使用任意的字符串、或者整数作为下标来访问数组元素。
关联数组使用 declare 命令来声明,语法格式如下:
declare -A array_name
-A 选项就是用于声明一个关联数组。
关联数组的键是唯一的。
以下实例我们创建一个关联数组 site,并创建不同的键值
declare -A site=(["google"]="www.google.com" ["runoob"]="www.runoob.com" ["taobao"]="www.taobao.com")
我们也可以先声明一个关联数组,然后再设置键和值:
declare -A site site["google"]="www.google.com" site["runoob"]="www.runoob.com" site["taobao"]="www.taobao.com"
也可以在定义的同时赋值:
访问关联数组元素可以使用指定的键,格式如下:
array_name["index"]
通过键来访问关联数组的元素:
declare -A site site["google"]="www.google.com" site["runoob"]="www.runoob.com" site["taobao"]="www.taobao.com" echo ${site["runoob"]}
执行脚本,输出结果如下所示:
www.runoob.com
在数组前加一个感叹号 ! 可以获取数组的所有键,例如:
declare -A site site["google"]="www.google.com" site["runoob"]="www.runoob.com" site["taobao"]="www.taobao.com" echo "数组的键为: ${!site[*]}" echo "数组的键为: ${!site[@]}"
执行脚本,输出结果如下所示:
数组的键为: google runoob taobao 数组的键为: google runoob taobao
yang@yang-virtual-machine:~$ declare -A site yang@yang-virtual-machine:~$ site["google"]="www.google.com" yang@yang-virtual-machine:~$ site["taobao"]="www.taobao.com" yang@yang-virtual-machine:~$ echo ${site["taobao"]} www.taobao.com yang@yang-virtual-machine:~$ echo ${!site[*]} google taobao yang@yang-virtual-machine:~$ echo ${site[*]} www.google.com www.taobao.com
6.expr命令
expr命令用于求表达式的值,格式为:
expr 表达式
表达式说明:
-
用空格隔开每一项,完整表达式要被反引号包围
-
用反斜杠放在shell特定的字符前面(发现表达式运行错误时,可以试试转义)
-
对包含空格和其他特殊字符的字符串要用引号括起来
-
expr会在stdout中输出结果。如果为逻辑关系表达式,则结果为真,stdout为1,否则为0。
-
expr的exit code:如果为逻辑关系表达式,则结果为真,exit code为0,否则为1。
字符串表达式
-
length STRING
返回
STRING
的长度 -
index STRING CHARSET
CHARSET
中任意单个字符在STRING
中最前面的字符位置,下标从1开始。如果在STRING
中完全不存在CHARSET
中的字符,则返回0。 -
substr STRING POSITION LENGTH
返回STRING
字符串中从POSITION
开始,长度最大为LENGTH
的子串。如果POSITION
或LENGTH
为负数,0或非数值,则返回空字符串。
#! /bin/bash
str="Hello world!"
echo `expr length "$str"`
echo `expr index "$str" abw`
echo `expr substr "$str" 2 6`
yang@yang-virtual-machine:~$ chmod -x ./test1.sh #应该是+x,而不是-x
yang@yang-virtual-machine:~$ ./test1.sh
bash: ./test1.sh: 权限不够
yang@yang-virtual-machine:~$ chmod 755 ./test1.sh
yang@yang-virtual-machine:~$ ./test1.sh
12
7
ello w
整数表达式
expr
支持普通的算术操作,算术表达式优先级低于字符串表达式,高于逻辑关系表达式。
+ -
加减运算。两端参数会转换为整数,如果转换失败则报错。* / %
乘,除,取模运算。两端参数会转换为整数,如果转换失败则报错。()
可以改变优先级,但需要用反斜杠转义
#! /bin/bash
a=3
b=4
echo `expr $a + $b`
echo `expr $a - $b`
echo `expr $a \* $b` #*需要转义
echo `expr $a / $b`
echo `expr $a % $b`
echo `expr \( $a - 1 \) \* \( $b + 6 \)`
yang@yang-virtual-machine:~$ chmod +x test2.sh
yang@yang-virtual-machine:~$ ./test2.sh
7
-1
12
0
3
20 #(a-1)*(b+6) 2*10
逻辑关系表达式
|
如果第一个参数非空且非0,则返回第一个参数的值,否则返回第二个参数的值,但要求第二个参数的值也是非空或非0,否则返回0。如果第一个参数是非空或非0时,不会计算第二个参数。&
如果两个参数都非空且非0,则返回第一个参数,否则返回0。如果第一个参为0或为空,则不会计算第二个参数。< <= = == != >= >
比较两端的参数,如果为true,则返回1,否则返回0。”==”是”=”的同义词。”expr”首先尝试将两端参数转换为整数,并做算术比较,如果转换失败,则按字符集排序规则做字符比较。()
可以改变优先级,但需要用反斜杠转义
a=3
b=4
echo `expr $a \> $b` # 输出0,>需要转义
echo `expr $a '<' $b` # 输出1,也可以将特殊字符用引号引起来 单引号,双引号都可以
echo `expr $a '>=' $b` # 输出0
echo `expr $a \<\= $b` # 输出1
c=0
d=5
echo `expr $c \& $d` # 输出0
echo `expr $a \& $b` # 输出3
echo `expr $c \| $d` # 输出5
echo `expr $a \| $b` # 输出3
7.read命令
read
命令用于从标准输入中读取单行数据。当读到文件结束符时,exit code
为1,否则为0。
参数说明
- -p: 后面可以接提示信息
- -t:后面跟秒数,定义输入字符的等待时间,超过等待时间后会自动忽略此命令
yang@yang-virtual-machine:~$ read name #读入name的值
yang #标准输入
yang@yang-virtual-machine:~$ echo $name #输出name的值
yang #标准输出
yang@yang-virtual-machine:~$ read -p "please input your name:" -t 30 name #读入name的值,等待时间30秒
please input your name:yqq #标准输入
yang@yang-virtual-machine:~$ echo $name #输出name的值
yqq #标准输出
8.echo命令
echo
用于输出字符串。
echo STRING
显示普通字符
echo "hello world"
echo hello world #引号可以省略
显示转义字符
echo "\"hello world\"" #注意只能使用双引号,如果使用单引号,则不转义
echo \"hello world\" #也可以省略双引号
显示变量
name=yang
echo "My name is $name"
显示换行
echo -e "Hi\n" #-e开启转义
echo ”Linux“
尝试:
echo -e "hi\n"
echo nihao
echo "hi\n"
#结果
hi
nihao
hi\n
显示不换行
echo -e "Hi \c" # \c 不换行
echo "linux!"
#输出:Hi linux!
显示结果定向至文件
echo "Hello World" > output.txt #将内容以覆盖的方式输出到output.txt中
原样输出字符串,不进行转义或取变量
使用单引号**”**
name=yang
echo '$name\"' #输出$name\"
显示命令的执行结果
用反引号
echo `date`
输出当天日期
9.printf命令
printf
命令用于格式化输出,类似于C/C++
中的printf
函数。
默认不会在字符串末尾添加换行符。
命令格式:
printf format-string [arguments...]
用法示例:
脚本内容:
printf "%10d.\n" 123 # 占10位,右对齐(d后的.必须加)
printf "%-10.2f.\n" 123.123321 # 占10位,保留2位小数,左对齐(f后的.必须加)
printf "My name is %s\n" "yang" # 格式化输出字符串
printf "%d * %d = %d\n" 2 3 `expr 2 \* 3` # 表达式的值作为参数
结果:
123.
123.12 .
My name is yang
2 * 3 = 6
yang@yang-virtual-machine:~$ printf "My name is %s\n" "yang"
My name is yang
yang@yang-virtual-machine:~$ printf "My name is %s" "yang"
My name is yangyang@yang-virtual-machine:~$
10.test命令与判断符号[]
逻辑运算符&&和||
-
&&
表示与,||
表示或 -
二者具有短路原则:
expr1 && expr2
:当expr1
为假时,直接忽略expr2
expr1 || expr2
:当expr1
为真时,直接忽略expr2
-
表达式的
exit code
为0,表示真;为非0,表示假。(与C/C++
中的定义相反)
test命令
在命令行中输入man test
,可以查看test
命令的用法。
test
命令用于判断文件类型,以及对变量做比较。
test
命令用**exit code
**返回结果,而不是使用stdout
。0表示真,非0表示假。
yang@yang-virtual-machine:~$ test -e test.sh && echo "exist" || echo "not exist"
exist
yang@yang-virtual-machine:~$ test -e test4.sh && echo "exist" ||echo "not exist"
not exist
yang@yang-virtual-machine:~$ test 2 -lt 3
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ ls
123 模板 图片 下载 桌面 test1 test2.sh test3.txt test.sh
公共的 视频 文档 音乐 snap test1.sh test3.sh test5 test.txt
文件类型判断
命令格式:
test -e filename # 判断文件是否存在
测试参数 | 代表意义 |
---|---|
-e | 文件是否存在 |
-f | 是否为文件 |
-d | 是否为目录 |
yang@yang-virtual-machine:~$ test -e test3.sh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test -f test3.sh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test -d test3.sh
yang@yang-virtual-machine:~$ echo $?
1
文件权限判断
命令格式:
test -r filename # 判断文件是否可读
测试参数 | 代表意义 |
---|---|
-r | 文件是否可读 |
-w | 文件是否可写 |
-x | 文件是否可执行 |
-s | 是否为非空文件 |
yang@yang-virtual-machine:~$ test -r test3.sh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test -w test3.sh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test -x test3.sh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test -s test3.sh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ touch test4.sh
yang@yang-virtual-machine:~$ test -s test4.sh
yang@yang-virtual-machine:~$ echo $?
1
整数间的比较
命令格式:
test $a -eq $b # a是否等于b
测试参数 | 代表意义 |
---|---|
-eq | a是否等于b |
-ne | a是否不等于b |
-gt | a是否大于b |
-lt | a是否小于b |
-ge | a是否大于等于b |
-le | a是否小于等于b |
yang@yang-virtual-machine:~$ a=5
yang@yang-virtual-machine:~$ b=10
yang@yang-virtual-machine:~$ test $a -eq $b #否
yang@yang-virtual-machine:~$ echo $?
1
yang@yang-virtual-machine:~$ test $a -ne $b #是
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test $a -gt $b #否
yang@yang-virtual-machine:~$ echo $?
1
yang@yang-virtual-machine:~$ test $a -lt $b #是
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test $a -ge $b #否
yang@yang-virtual-machine:~$ echo $?
1
yang@yang-virtual-machine:~$ test $a -le $b #是
yang@yang-virtual-machine:~$ echo $?
0
字符串比较
测试参数 | 代表意义 |
---|---|
test -z STRING | 判断STRING是否为空,如果为空,则返回true |
test -n STRING | 判断STRING是否非空,如果非空,则返回true(-n可以省略) |
test str1 == str2 | 判断str1是否等于str2 |
test str1 != str2 | 判断str1是否不等于str2 |
yang@yang-virtual-machine:~$ ll=""
yang@yang-virtual-machine:~$ test -z ll
yang@yang-virtual-machine:~$ echo $?
1
yang@yang-virtual-machine:~$ test ll
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ ll="yes"
yang@yang-virtual-machine:~$ kk="no"
yang@yang-virtual-machine:~$ hh="yes"
yang@yang-virtual-machine:~$ test $ll == $hh
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ test $ll != $hh
yang@yang-virtual-machine:~$ echo $?
1
yang@yang-virtual-machine:~$ test $ll == $kk #不相等
yang@yang-virtual-machine:~$ echo $?
1
多重条件判定
命令格式:
test -r filename -a -x filename
测试参数 | 代表意义 |
---|---|
-a | 两条件是否同时成立(与) |
-o | 两条件是否至少一个成立(或) |
! | 取反。如 test ! -x file,当file不可执行时,返回true(非) |
判断符号[]
[]
与test
用法几乎一模一样,更常用于if
语句中。另外[[]]
是[]
的加强版,支持的特性更多。
例如:
[ 2 -lt 3 ] # 为真,返回值为0
echo $? # 输出上个命令的返回值,输出0
acs@9e0ebfcd82d7:~$ ls # 列出当前目录下的所有文件
homework output.txt test.sh tmp
acs@9e0ebfcd82d7:~$ [ -e test.sh ] && echo "exist" || echo "Not exist"
exist # test.sh 文件存在
acs@9e0ebfcd82d7:~$ [ -e test2.sh ] && echo "exist" || echo "Not exist"
Not exist # testh2.sh 文件不存在
注意:
[]
内的每一项都要用空格隔开- 中括号内的变量,最好用双引号括起来
- 中括号内的常数,最好用单或双引号括起来
例如:
name="acwing yxc"
[ $name == "acwing yxc" ] # 错误,等价于 [ acwing yxc == "acwing yxc" ],参数太多
[ "$name" == "acwing yxc" ] # 正确
11.判断语句
if…then形式
类似于C/C++
中的if-else
语句。
单层if
命令格式:
if condition
then
语句1
语句2
...
fi
尝试:
a=3
b=4
if [ "$a" -lt "$b" ] && [ "$a" -gt 2 ]
then
echo ${a} is in the range.
fi
结果:
3 is in the range.
单层if-else
命令格式
if condition
then
语句1
语句2
...
else
语句1
语句2
...
fi
尝试:
a=3
b=4
if ! [ "$a" -lt "$b" ]
then
echo ${a} ">=" ${b}
else
echo ${a} "<" ${b}
fi
结果:
3 < 4
多层if-elif-elif-else
命令格式
if condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
...
elif condition
then
语句1
语句2
else
语句1
语句2
...
fi
尝试:
a=4
if [ $a -eq 1 ]
then
echo ${a}等于1
elif [ $a -eq 2 ]
then
echo ${a}等于2
elif [ $a -eq 3 ]
then
echo ${a}等于3
else
echo 其他
fi
结果:
其他
case…esac形式
类似于C/C++
中的switch
语句。
命令格式:
case $变量名称 in
值1)
语句1
语句2
...
;; # 类似于C/C++中的break
值2)
语句1
语句2
...
;;
*) # 类似于C/C++中的default
语句1
语句2
...
;;
esac
尝试:
a=4
case $a in
1)
echo ${a}等于1
;;
2)
echo ${a}等于2
;;
3)
echo ${a}等于3
;;
*)
echo 其他
;;
esac
结果:
其他
12.循环语句
for…in…do…done(会自动换行)
命令格式:
for var in al1 val2 val3
do
语句1
语句2
...
done
尝试:
for i in a 2 cc
do
echo $i
done
for file in `ls`
do
echo $file
done
for i in $(seq 2 11)
do
echo $i
done
for i in {a..z}
do
echo $i
done
for i in {a...z} #应该两个点
do
echo $i
done
for i in {1...10} #应该两个点
do
echo $i
done
输出:
a #1
2
cc
123 #2
公共的
模板
视频
图片
文档
下载
音乐
桌面
snap
test1
test1.sh
test2.sh
test3.sh
test3.txt
test4.sh
test5
test5.sh
test6.sh
test7.sh
test8.sh
test.sh
test.txt
2 #3
3
4
5
6
7
8
9
10
11
a #4
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
{a...z} #5
{1...10} #6
for ((…;…;…)) do…done
命令格式:
for ((expression; condition; expression))
do
语句1
语句2
done
尝试:
for ((i=1; i<=10; i++))
do
echo $i
done
结果:输出1-10,每个数占一行
while…do…done循环
命令格式:
while condition
do
语句1
语句2
...
done
尝试:
while read name #文件结束符为Ctrl+d,输入文件结束符后read指令返回false。
do
echo $name
done
until…do…done循环
- 当条件为真时结束。
命令格式:
until condition
do
语句1
语句2
...
done
尝试:
#当用户输入yes或者YES时结束,否则一直等待读入。
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
do
read -p "Please input yes/YES to stop this program: " word
done
break命令
- 跳出当前一层循环,注意与
C/C++
不同的是:break
不能跳出case
语句。
示例:
while read name
do
for ((i=1;i<=10;i++))
do
case $i in
8)
break # 跳出for循环
;;
*)
echo $i
;;
esac
done
done
该示例每读入非EOF
的字符串,会输出一遍1-7
。
该程序可以输入Ctrl+d
文件结束符来结束,也可以直接用Ctrl+c
杀掉该进程。
continue命令
- 跳出当前循环。
for ((i=1;i<=10;i++))
do
if [ `expr $i % 2` -eq 0 ]
then
continue
fi
echo $i
done
该程序输出1-10中的所有奇数。1 3 5 7 9
死循环的处理方式
如果AC Terminal
可以打开该程序,则输入Ctrl+c
即可。
否则可以直接关闭进程:
- 使用
top
命令找到进程的PID
- 输入
kill -9 PID
即可关掉此进程
PID是程序被操作系统加载到内存成为进程后动态分配的资源,每次程序执行时,操作系统都会重新加载,PID在每次加载的时候都是不同的。
13.函数
bash
中的函数类似于C/C++
中的函数,但return
的返回值与C/C++
不同,返回的是exit code
,取值为0-255
,0表示正常结束。- 如果想获取函数的输出结果,可以通过
echo
输出到stdout
中,然后通过$(function_name)
来获取stdout
中的结果。 - 函数的return值可以通过
$?
来获取。
命令格式:
[function] func_name() { # function关键字可以省略
语句1
语句2
...
}
不获取 return值和stdout值
尝试:
func() {
name=yang
echo "Hello $name"
}
func #Hello yang
获取 return
值和stdout
值
- 不写
return
时,默认return 0
。
尝试:
func() {
name=yang
echo "hello $name"
return 100
}
output=$(func)
ret=$?
echo "output = $output"
echo "return = $ret"
结果:
output = hello yang
return = 100
函数的输入参数
-
在函数内,
$1
表示第一个输入参数,$2
表示第二个输入参数,依此类推。 -
注意:函数内的
$0
仍然是文件名,而不是函数名。
示例:
func() { # 递归计算 $1 + ($1 - 1) + ($1 - 2) + ... + 0
word=""
while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
do
read -p "要进入func($1)函数吗?请输入y/n:" word
done
if [ "$word" == 'n' ]
then
echo 0
return 0
fi
if [ $1 -le 0 ]
then
echo 0
return 0
fi
sum=$(func $(expr $1 - 1))
echo $(expr $sum + $1)
}
echo $(func 10)
结果:
要进入func(10)函数吗?请输入y/n:y
要进入func(9)函数吗?请输入y/n:y
要进入func(8)函数吗?请输入y/n:y
要进入func(7)函数吗?请输入y/n:y
要进入func(6)函数吗?请输入y/n:y
要进入func(5)函数吗?请输入y/n:y
要进入func(4)函数吗?请输入y/n:y
要进入func(3)函数吗?请输入y/n:y
要进入func(2)函数吗?请输入y/n:y
要进入func(1)函数吗?请输入y/n:y
要进入func(0)函数吗?请输入y/n:y
55
函数内的局部变量
-
可以在函数内定义局部变量,作用范围仅在当前函数内。
-
可以在递归函数中定义局部变量。
命令格式:
local 变量名=变量值
例:
#! /bin/bash
func() {
local name=yang
echo $name
}
func
echo $name
结果:
yang
#空行
第一行为函数内的name变量,第二行为函数外调用name变量,会发现此时该变量不存在。
14.exit命令
exit
命令用来退出当前shell
进程,并返回一个退出状态;使用$?
可以接收这个退出状态。exit
命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。exit
退出状态只能是一个介于0~255
之间的整数,其中只有 0 表示成功,其它值都表示失败。
创建脚本test7.sh
,内容如下:
#! /bin/bash
if [ $# -ne 1 ] # 如果传入参数个数等于1,则正常退出;否则非正常退出。
then
echo "arguments not valid"
exit 1
else
echo "arguments valid"
exit 0
fi
执行:
yang@yang-virtual-machine:~$ chmod +x test7.sh
yang@yang-virtual-machine:~$ ./test7.sh hellohello
arguments valid
yang@yang-virtual-machine:~$ echo $?
0
yang@yang-virtual-machine:~$ ./test7.sh
arguments not valid
yang@yang-virtual-machine:~$ echo $?
1
15.文件重定向
每个进程默认打开3个文件描述符:
stdin
标准输入,从命令行读取数据,文件描述符为0
stdout
标准输出,向命令行输出数据,文件描述符为1
stderr
标准错误输出,向命令行输出数据,文件描述符为2
可以用文件重定向将这三个文件重定向到其他文件中。
重定向命令列表
命令 | 说明 |
---|---|
command > file | 将stdout 重定向到file 中(以覆盖的方式写入file中) |
command < file | 将stdin 重定向到file 中 |
command >> file | 将stdout 以追加方式重定向到file 中 |
command n> file | 将文件描述符n 重定向到file 中 |
command n>> file | 将文件描述符n 以追加方式重定向到file 中 |
输入和输出重定向
yang@yang-virtual-machine:~$ echo -e "hello \c" > output.txt
yang@yang-virtual-machine:~$ echo "world" >> output.txt
yang@yang-virtual-machine:~$ read str < output.txt
yang@yang-virtual-machine:~$ echo $str
hello world
同时重定向stdin和stdout
创建bash脚本:
#! /bin/bash
read a
read b
echo $(expr "$a" + "$b")
创建input.txt
,里面的内容为:
3
4
执行命令:
yang@yang-virtual-machine:~$ chmod +x test.sh
yang@yang-virtual-machine:~$ ./test.sh < input.txt > output.txt
yang@yang-virtual-machine:~$ cat output.txt
7
16.引入外部脚本
- 类似于
C/C++
中的include
操作,bash
也可以引入其他文件中的代码。
语法格式:
. filename # 注意点和文件名之间有一个空格
或
source filename
创建test8.sh
,内容为:
#! /bin/bash
name=yang
然后创建test9.sh
,内容为:
#! /bin/bash
. test8.sh
echo My name is: $name
执行命令:
yang@yang-virtual-machine:~$ chmod 755 test9.sh
yang@yang-virtual-machine:~$ ./test9.sh
My name is: yang
五、ssh
ssh登录
基本用法
远程登录服务器:
ssh user@hostname
user
: 用户名hostname
: IP地址或域名
第一次登录时会提示:
The authenticity of host '123.57.47.211 (123.57.47.211)' can't be established.
ECDSA key fingerprint is SHA256:iy237yysfCe013/l+kpDGfEG9xxHxm0dnxnAbJTPpG8.
Are you sure you want to continue connecting (yes/no/[fingerprint])? #差不多,忘记复制了
输入yes
,然后回车即可。
这样会将该服务器的信息记录在~/.ssh/known_hosts
文件中。
然后输入密码即可登录到远程服务器中。
默认登录端口号为22
。如果想登录某一特定端口:
ssh user@hostname -p 22
配置文件
创建文件 ~/.ssh/config
。
输入:
Host yqq
HostName 192.168.232.168
User yang
Host myserver2
Hostname 192.168.232.28
User yang
之后再使用服务器时,可以直接使用别名yqq
、myserver2
。
密钥登录
创建密钥:
ssh-keygen
然后一直回车即可。
(第一个按了yes,多了yes yes.pub)
之后想免密码登录哪个服务器,就将公钥传给哪个服务器即可。
例如,想免密登录myserver
服务器。则将公钥中的内容,复制到myserver
中的~/.ssh/authorized_keys
文件里即可。
也可以使用如下命令一键添加公钥:
ssh-copy-id myserver
执行命令
命令格式:
ssh user@hostname command
例如:
ssh user@hostname ls -a
或者
# 单引号中的$i可以求值
ssh myserver 'for ((i = 0; i < 10; i ++ )) do echo $i; done'
或者
# 双引号中的$i不可以求值
ssh myserver "for ((i = 0; i < 10; i ++ )) do echo $i; done"
yang@yang-virtual-machine:~/.ssh$ ssh yang@192.168.232.128
Welcome to Ubuntu 22.04.1 LTS (GNU/Linux 5.15.0-56-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
1 更新可以立即应用。
这些更新中有 1 个是标准安全更新。
要查看这些附加更新,请运行:apt list --upgradable
Last login: Mon Dec 5 20:20:28 2022 from 192.168.232.128
yang@yang-virtual-machine:~$ ssh yang@192.168.232.128 ls -a
.
..
123
公共的
模板
视频
图片
文档
下载
音乐
桌面
.bash_history
.bash_logout
.bashrc
.cache
.config
hanshushuru.sh
huiwenzhishu.cpp
input
input.txt
.lesshst
.local
.mozilla
output.txt
.profile
snap
.ssh
.sudo_as_admin_successful
test1
test1.sh
test2.sh
test3.sh
test4.sh
test5.sh
test6.sh
test7.sh
test8.sh
test9.sh
test.sh
.thunderbird
.vim
.viminfo
yang@yang-virtual-machine:~$ ssh yang@192.168.232.128 'for ((i = 0; i < 10; i++ )) do echo $i; done'
0
1
2
3
4
5
6
7
8
9
yang@yang-virtual-machine:~$ ssh yang@192.168.232.128 "for ((i = 0; i < 10; i++ )) do echo $i; done"
#空行
scp传文件
基本用法
命令格式:
scp source destination
将source
路径下的文件复制到destination
中
一次复制多个文件:
scp source1 source2 destination
复制文件夹:
scp -r ~/tmp myserver:/home/acs/
将本地家目录中的tmp
文件夹复制到myserver
服务器中的/home/acs/
目录下。(执行不了)
scp -r ~/tmp myserver:homework/
将本地家目录中的tmp
文件夹复制到myserver
服务器中的~/homework/
目录下。
scp -r myserver:homework .
将myserver
服务器中的~/homework/
文件夹复制到本地的当前路径下。
指定服务器的端口号:
scp -P 22 source1 source2 destination
注意: scp
的-r -P
等参数尽量加在source
和destination
之前。
使用scp配置其他服务器的vim
和tmux
scp ~/.vimrc ~/.tmux.conf myserver:
yang@yang-virtual-machine:~$ scp ~/.vimrc ~/.tmux.conf yang@192.168.232.128:
/home/yang/.vimrc: No such file or directory
/home/yang/.tmux.conf: No such file or directory
yang@yang-virtual-machine:~$ scp -r ~/tmp yang:/home/acs/
ssh: Could not resolve hostname yang: Temporary failure in name resolution
lost connection
yang@yang-virtual-machine:~$ scp -r ~/tmp yqq:/home/acs/
ssh: connect to host 192.168.232.168 port 22: No route to host
lost connection
#不知道为什么不可以 !scp -r ~/tmp yqq@192.168.232.128:/home/yang/ 要修改服务器中/home/yang的权限
Permission denied要修改服务器中/home/yang的权限
六、git
git基本概念
- 工作区:仓库的目录。工作区是独立于各个分支的。
- 暂存区:数据暂时存放的区域,类似于工作区写入版本库前的缓存区。暂存区是独立于各个分支的。
- 版本库:存放所有已经提交到本地仓库的代码版本
- 版本结构:树结构,树中每个节点代表一个代码版本。
git常用命令
1.git config --global user.name xxx
:设置全局用户名,信息记录在~/.gitconfig
文件中
2.git config --global user.email xxx@xxx.com
:设置全局邮箱地址,信息记录在~/.gitconfig
文件中
3.git init
:将当前目录配置成git
仓库,信息记录在隐藏的.git
文件夹中
git add XX
:将XX
文件添加到暂存区
4.git add .
:将所有待加入暂存区的文件加入暂存区
5.git rm --cached XX
:将文件从仓库索引目录中删掉
6.git commit -m "给自己看的备注信息"
:将暂存区的内容提交到当前分支
7.git status
:查看仓库状态
8.git diff XX
:查看XX
文件相对于暂存区修改了哪些内容
9.git log
:查看当前分支的所有版本
10.git reflog
:查看HEAD
指针的移动历史(包括被回滚的版本)
11.git reset --hard HEAD^ 或 git reset --hard HEAD~
:将代码库回滚到上一个版本
git reset --hard HEAD^^
:往上回滚两次,以此类推git reset --hard HEAD~100
:往上回滚100
个版本git reset --hard 版本号
:回滚到某一特定版本
12.git checkout — XX或git restore XX
:将XX
文件尚未加入暂存区的修改全部撤销
13.git remote add origin git@git.acwing.com:xxx/XXX.git
:将本地仓库关联到远程仓库
14.git push -u (第一次需要-u以后不需要)
:将当前分支推送到远程仓库
git push origin branch_name
:将本地的某个分支推送到远程仓库
15.git clone git@git.acwing.com:xxx/XXX.git
:将远程仓库XXX
下载到当前目录下
16.git checkout -b branch_name
:创建并切换到branch_name
这个分支
17.git branch
:查看所有分支和当前所处分支
18.git checkout branch_name
:切换到branch_name
这个分支
19.git merge branch_name
:将分支branch_name
合并到当前分支上
20.git branch -d branch_name
:删除本地仓库的branch_name
分支
21.git branch branch_name
:创建新分支
22.git push --set-upstream origin branch_name
:设置本地的branch_name
分支对应远程仓库的branch_name
分支
23.git push -d origin branch_name
:删除远程仓库的branch_name
分支
24.git pull
:将远程仓库的当前分支与本地仓库的当前分支合并
git pull origin branch_name
:将远程仓库的branch_name
分支与本地仓库的当前分支合并
25.git branch --set-upstream-to=origin/branch_name1 branch_name2
:将远程的branch_name1
分支与本地的branch_name2
分支对应
26.git checkout -t origin/branch_name
将远程的branch_name
分支拉取到本地
27.git stash
:将工作区和暂存区中尚未提交的修改存入栈中
28.git stash apply
:将栈顶存储的修改恢复到当前分支,但不删除栈顶元素
29.git stash drop
:删除栈顶存储的修改
30.git stash pop
:将栈顶存储的修改恢复到当前分支,同时删除栈顶元素
31.git stash list
:查看栈中所有元素
以下是跟着 Linux中的Git(过程 + 总结)操作
git版本库创建
yang@yang-virtual-machine:~$ mkdir gitrepository
yang@yang-virtual-machine:~$ cd gitrepository
yang@yang-virtual-machine:~/gitrepository$ git init
提示:使用 'master' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中
提示:配置使用初始分支名,并消除这条警告,请执行:
提示:
提示: git config --global init.defaultBranch <名称>
提示:
提示:除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。
提示:可以通过以下命令重命名刚创建的分支:
提示:
提示: git branch -m <name>
已初始化空的 Git 仓库于 /home/yang/gitrepository/.git/
yang@yang-virtual-machine:~/gitrepository$ ls -al
总用量 12
drwxrwxr-x 3 yang yang 4096 12月 7 20:11 .
drwxrwxrwx 22 yang yang 4096 12月 7 20:09 ..
drwxrwxr-x 7 yang yang 4096 12月 7 20:11 .git
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a version control system.
Git is free software.
yang@yang-virtual-machine:~/gitrepository$ git add readme.txt
yang@yang-virtual-machine:~/gitrepository$ git commit -m "add a file"
[master (根提交) a84c814] add a file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
工作区:就是你在电脑里能看到的目录。如上面的gitrepository目录。
暂存区:英文叫 stage 或 index。一般存放在 .git 目录下的 index 文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。
版本库:工作区有一个隐藏目录 .git,这个不算工作区,而是 Git 的版本库。
文件的四种状态
版本控制就是对文件的版本控制,要对文件进行修改、提交等操作,首先要知道文件当前在什么状态,不然可能会提交了现在还不想提交的文件,或者要提交的文件没提交上。
-
Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.
-
Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件
-
Modified: 文件已修改, 仅仅是修改, 并没有进行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改 !
-
Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified
版本追溯–查看仓库状态的两个常用命令git status和git diff
#首先,对readme.txt文件进行修改,然后不对其进行git add和commit的操作。
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
#git status 查看仓库当前的状态,显示有变更的文件。并且说明了修改的文件,以及改文件所在分支和改文件还没有上传到暂存区以备提交。
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
#git diff 比较文件的不同,即暂存区和工作区的差异
yang@yang-virtual-machine:~/gitrepository$ git diff
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
#下面,我们对修改的文件提交,在git add和gitcommit之后都是用上面两个命令查看状态。
yang@yang-virtual-machine:~/gitrepository$ git add readme.txt
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: readme.txt
yang@yang-virtual-machine:~/gitrepository$ git diff
yang@yang-virtual-machine:~/gitrepository$ git commit readme.txt -m "add a word distributed"
[master f2e8319] add a word distributed
1 file changed, 1 insertion(+), 1 deletion(-)
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
无文件要提交,干净的工作区
yang@yang-virtual-machine:~/gitrepository$ git diff
yang@yang-virtual-machine:~/gitrepository$
版本回退
#这里的版本回退会作用于仓库中的所有文件,这里只有一个文件,所以只回退了一个。
#先对文件进行一次修改并且提交到版本库中。
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
add a new line
yang@yang-virtual-machine:~/gitrepository$ git add readme.txt
yang@yang-virtual-machine:~/gitrepository$ git commit -m "add a new line"
[master 0863c41] add a new line
1 file changed, 1 insertion(+)
#git log命令显示从最近到最远的提交日志。
yang@yang-virtual-machine:~/gitrepository$ git log
commit 0863c41b4a07b8a59fe05c80cb38c4d8665ace71 (HEAD -> master)
Author: yang <1473641801@qq.com>
Date: Fri Dec 16 22:23:54 2022 +0800
add a new line
commit f2e8319b208df2a09c3a65b3a64490f2c6b616a8
Author: yang <1473641801@qq.com>
Date: Wed Dec 7 20:24:30 2022 +0800
add a word distributed
commit a84c814296045ab8b17e14d74cbcd32ad5606326
Author: yang <1473641801@qq.com>
Date: Wed Dec 7 20:14:13 2022 +0800
add a file
#git log --pretty=oneline
#显示简洁版本的日志信息
yang@yang-virtual-machine:~/gitrepository$ git log --pretty=oneline
0863c41b4a07b8a59fe05c80cb38c4d8665ace71 (HEAD -> master) add a new line
f2e8319b208df2a09c3a65b3a64490f2c6b616a8 add a word distributed
a84c814296045ab8b17e14d74cbcd32ad5606326 add a file
#开始回退版本 git reset
#首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交3ac9…(版本号),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100。
#现在回退到上一个版本
yang@yang-virtual-machine:~/gitrepository$ git reset --hard HEAD^
HEAD 现在位于 f2e8319 add a word distributed
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
#查看日志情况
yang@yang-virtual-machine:~/gitrepository$ git log
commit f2e8319b208df2a09c3a65b3a64490f2c6b616a8 (HEAD -> master)
Author: yang <1473641801@qq.com>
Date: Wed Dec 7 20:24:30 2022 +0800
add a word distributed
commit a84c814296045ab8b17e14d74cbcd32ad5606326
Author: yang <1473641801@qq.com>
Date: Wed Dec 7 20:14:13 2022 +0800
add a file
#之前的提交在日志中没有了,也就是说当你回到过去,你将来的东西还没有发生
#恢复回退之前的版本。
yang@yang-virtual-machine:~/gitrepository$ git reset --hard 0863c41
HEAD 现在位于 0863c41 add a new line
#如果已经没有了上次的shell,那么可以通过命令来查找这个版本号。即git reflog找到版本号之后,就可以使用上面的方式回退(过去/未来)某一个版本。
#git reflog命令记录了每一次操作的情况。
yang@yang-virtual-machine:~/gitrepository$ git reflog
0863c41 (HEAD -> master) HEAD@{0}: reset: moving to 0863c41
f2e8319 HEAD@{1}: reset: moving to HEAD^
0863c41 (HEAD -> master) HEAD@{2}: commit: add a new line
f2e8319 HEAD@{3}: commit: add a word distributed
a84c814 HEAD@{4}: commit (initial): add a file
撤销修改
#首先对文件回退到第二个版本
yang@yang-virtual-machine:~/gitrepository$ git reset --hard HEAD^
HEAD 现在位于 f2e8319 add a word distributed
#然后对文件内容进行了修改
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
#通过git status的提示可以看到git restore <文件>可以丢弃工作区的内容。
#命令功能:丢弃工作区的修改(不包括对文件自身的操作,如添加文件、删除文件)
#git restore --staged <file_name> 将暂存区的修改重新放回工作区(包括对文件自身的操作,如添加文件、删除文件)
yang@yang-virtual-machine:~/gitrepository$ git restore readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
#命令git checkout -- file意思就是,把文件在工作区的修改全部撤销(对文件中内容的操作,无法对添加文件、删除文件起作用),有两种情况
#总之,就是让这个文件回到最近一次git commit或git add时的状态。
#一种是,readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
append a line
yang@yang-virtual-machine:~/gitrepository$ git checkout -- readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
#另一种是,readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
appen a line
yang@yang-virtual-machine:~/gitrepository$ git add readme.txt
yang@yang-virtual-machine:~/gitrepository$ vim readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
appen a line
new line
yang@yang-virtual-machine:~/gitrepository$ git checkout -- readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
appen a line
#最后,暂存区的修改撤销
#上面的文件修改中,将修改的文件提交到暂存区,现在可以将暂存区的修改也撤销掉。
#git reset HEAD <file_name> 丢弃暂存区的修改,重新放回工作区,会将暂存区的内容和本地已提交的内容全部恢复到未暂存的状态,不影响原来本地文件(相当于撤销git add 操作,不影响上一次commit后对本地文件的修改) (包括对文件的操作,如添加文件、删除文件)
#git reset命令既可以回退版本,也可以把暂存区的修改回退到工作区。
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
修改: readme.txt
yang@yang-virtual-machine:~/gitrepository$ cat readme.txt
Git is a distributed version control system.
Git is free software.
appen a line
yang@yang-virtual-machine:~/gitrepository$ git reset HEAD readme.txt
重置后取消暂存的变更:
M readme.txt
#经过上面的回退,当前工作区的内容就是相当于没有git add操作的修改的内容。然后把工作区的内容也修改了那么久版本统一了。
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
尚未暂存以备提交的变更:
(使用 "git add <文件>..." 更新要提交的内容)
(使用 "git restore <文件>..." 丢弃工作区的改动)
修改: readme.txt
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
yang@yang-virtual-machine:~/gitrepository$ git restore readme.txt
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
无文件要提交,干净的工作区
文件删除
#git rm 文件名删除改文件,且提交到了暂存区,之后需要git commit生效。
yang@yang-virtual-machine:~/gitrepository$ git rm readme.txt
rm 'readme.txt'
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
删除: readme.txt
yang@yang-virtual-machine:~/gitrepository$ git commit readme.txt -m "delete readme.txt"
[master eda9b0f] delete readme.txt
1 file changed, 2 deletions(-)
delete mode 100644 readme.txt
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
无文件要提交,干净的工作区
#如果执行了git rm v.txt,还没有提交,此时想要撤销删除操作。(结果跟预计的不一样)
yang@yang-virtual-machine:~/gitrepository$ git rm v.txt
error: 下列文件索引中有变更
v.txt
(使用 --cached 保留本地文件,或用 -f 强制删除)
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
要提交的变更:
(使用 "git restore --staged <文件>..." 以取消暂存)
新文件: v.txt
yang@yang-virtual-machine:~/gitrepository$ git restore --staged v.txt
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
v.txt
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
yang@yang-virtual-machine:~/gitrepository$ git restore v.txt
error: 路径规格 'v.txt' 未匹配任何 git 已知文件
yang@yang-virtual-machine:~/gitrepository$ git status
位于分支 master
未跟踪的文件:
(使用 "git add <文件>..." 以包含要提交的内容)
v.txt
提交为空,但是存在尚未跟踪的文件(使用 "git add" 建立跟踪)
yang@yang-virtual-machine:~/gitrepository$ ls -al
总用量 16
drwxrwxr-x 3 yang yang 4096 12月 16 23:03 .
drwxrwxrwx 22 yang yang 4096 12月 16 23:03 ..
drwxrwxr-x 8 yang yang 4096 12月 16 23:05 .git
-rw-rw-r-- 1 yang yang 7 12月 16 23:03 v.txt
yang@yang-virtual-machine:~/gitrepository$ git add v.txt
上述命令总结
-
仓库初始化: git init --> 将当前目录设置为git的工作目录,可以被git所管理 设置用户和邮箱(全局,在git中的所有操作都是该用户的操作) git config --global user.name "vv" git config --global user.email "553354863@qq.com"
-
添加和提交 git add <directory> / <file> # 将指定⽬录的所有修改加⼊到下⼀次commit中(暂存区)。把<directory>替换成<file>将添加指定⽂件的修改 git commit -m "message" #提交暂存区的修改,使⽤指定的<message>作为提交信息
-
状态信息 git status # 显示哪些⽂件已被staged(暂存状态)、未被staged以及未跟踪(untracked)。 git diff # ⽐较⼯作区和暂存区的修改。 git diff HEAD # ⽐较⼯作区和上⼀次commit后的修改。 git diff --cached # ⽐较暂存区和上⼀次commit后的修改。 ## 可以在命令后面添加 -- read.txt表示只判断该文件 git diff HEAD -- readme.txt ## 比较工作区和版本库中的readme.txt文件
-
日志 git log # 显示详细的日志信息,全部显示。 git log -<limit> # 显示log,限制log的显示数量。例如:”git log -5”仅显示最新5条commit git log --oneline # 每⾏显示⼀条commit。简洁版本 git reflog # 显示本地仓库的所有commit⽇志
-
版本回退(针对所有修改的文件) git reset --hard # 移除所有暂存区的修改,并强制删除所有工作区的修改。此时工作区、暂存区和版本库中的版本会一致。(回退到最近的一次提交) git reset # 移除所有暂存区的修改,但不会修改⼯作区。此时的暂存区和版本库一致。(回退到最近的一次提交) git reset --hard <commit id># 移除所有暂存区的修改,并强制删除所有工作区的修改。此时工作区、暂存区和版本库中的版本会一致。(回退到指定的一次提交) git reset <commit id> # 移除所有暂存区的修改,但不会修改⼯作区。此时的暂存区和版本库一致。(回退到指定的一次提交) git reset HEAD <file_name> # 丢弃暂存区的修改,重新放回工作区,会将暂存区的内容和本地已提交的内容全部恢复到未暂存的状态,不影响原来本地文件(相当于撤销git add 操作,不影响上一次commit后对本地文件的修改。此时暂存区和版本库统一,工作区还有修改后的内容) (包括对文件的操作,如添加文件、删除文件) git reset --hard HEAD # 清空暂存区,将已提交的内容的版本恢复到本地,本地的文件也将被恢复的版本替换(恢复到上一次commit后的状态,上一次commit后的修改也丢弃,此时三方版本统一)
-
撤销修改(文件内容 / 文件本身)--> 针对某一个文件 git restore --staged <file_name> # 将暂存区的修改重新放回工作区(包括对文件自身的操作,如添加文件、删除文件) git restore <file_name> # 丢弃工作区的修改(不包括对文件自身的操作,如添加文件、删除文件) git checkout -- <file_name> # 丢弃工作区的修改,并用最近一次的git add 或者 git commit状态时的状态,还原到当前工作区(对文件中内容的操作,无法对添加文件、删除文件起作用) git checkout HEAD^ -- <file_name> # 将指定commit提交的内容(HEAD^表示上一个版本)还原到当前工作区
-
删除文件 git rm file # 删除指定文件,且提交到了暂存区。
七、thrift
thrift教程
(不懂啊,是要干嘛)
1.什么是thrift
thrift是一个编译器,它的作用是让我们在开发项目时,让不同服务器之间的函数能相互调用,并且它能调用不同语言之间的函数。比如我们在客户端用的是python,但我们可以利用thrift调用服务端写的c++函数。
2.使用步骤
2.1 定义接口
首先我们需要定义一个.thrift文件,里面写着服务器交互用到内容。
比如我们实现一个匹配系统,当我们客户端有个用户需要加入匹配时,
我们就需要向服务端请求一个函数,add_user,当我们要取消匹配时,就调用一个remove_user函数。
所以我们就需要定义一些和add_user函数和remove_user函数的一些内容。详细要求看官方文档要求。
namespace cpp match_service
struct User{
1: i32 id,
2: string name,
3: i32 score
}
service Match {
i32 add_user(1: User user, 2: string info),
i32 remove_user(1: User user, 2: string info),
}
接下来就是我们去生成我们服务端和客户端的代码了。
2.2 server服务端
thrift -r --gen <language> <Thrift filename>
调用这个命令,比如我们要生成的是cpp的代码,就thrift -r --gen cpp <Thrift filename>
后面接着是刚刚定义接口的文件。
命令执行完就会生成一个文件,这个就是调用接口的内容了。查看文件看到有命名为file_server的就是thrift自动为我们生成的接口,像这样,然后我们只需要在接口里面写业务就可以了。
2.3 client请求端
客户端和上面的一样,调用thrift -r --gen <language> <Thrift filename>
。
但是客户端接口不会直接生成,不过我们直接去官方狂抄就可以了。
八、管道、环境变量与常用命令
管道
概念
管道类似于文件重定向,可以将前一个命令的stdout
重定向到下一个命令的stdin
。
要点
管道命令仅处理stdout
,会忽略stderr
。
管道右边的命令必须能接受stdin
。
多个管道命令可以串联。
stdout – 标准输出设备 (printf(“…”)) 同 stdout。
stderr – 标准错误输出设备
两者默认向屏幕输出。
与文件重定向的区别
- 文件重定向左边为命令,右边为文件。
- 管道左右两边均为命令,左边有
stdout
,右边有stdin
。
举例
统计当前目录下所有python
文件的总行数,其中find
、xargs
、wc
等命令可以参考常用命令这一节内容。
xargs(英文全拼: eXtended ARGuments)是给命令传递参数的一个过滤器,也是组合多个命令的一个工具。
xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。
xargs 也可以将单行或多行文本输入转换为其他格式,例如多行变单行,单行变多行。
xargs 默认的命令是 echo,这意味着通过管道传递给 xargs 的输入将会包含换行和空白,不过通过 xargs 的处理,换行和空白将被空格取代。
xargs 是一个强有力的命令,它能够捕获一个命令的输出,然后传递给另外一个命令。
之所以能用到这个命令,关键是由于很多命令不支持|管道来传递参数,而日常工作中有有这个必要,所以就有了 xargs 命令
命令格式:
somecommand |xargs -item command
参数:
- -a file 从文件中读入作为 stdin
- -e flag ,注意有的时候可能会是-E,flag必须是一个以空格分隔的标志,当xargs分析到含有flag这个标志的时候就停止。
- -p 当每次执行一个argument的时候询问一次用户。
- -n num 后面加次数,表示命令在执行的时候一次用的argument的个数,默认是用所有的。
- -t 表示先打印命令,然后再执行。
- -i 或者是-I,这得看linux支持了,将xargs的每项名称,一般是一行一行赋值给 {},可以用 {} 代替。
- -r no-run-if-empty 当xargs的输入为空的时候则停止xargs,不用再去执行了。
- -s num 命令行的最大字符数,指的是 xargs 后面那个命令的最大命令行字符数。
- -L num 从标准输入一次读取 num 行送给 command 命令。
- -l 同 -L。
- -d delim 分隔符,默认的xargs分隔符是回车,argument的分隔符是空格,这里修改的是xargs的分隔符。
- -x exit的意思,主要是配合-s使用。。
- -P 修改最大的进程数,默认是1,为0时候为as many as it can ,这个例子我没有想到,应该平时都用不到的吧。
find . -name '*.py' | xargs cat | wc -l
yang@yang-virtual-machine:~/桌面$ find . -name '*.cpp' | xargs cat | wc -l
0
yang@yang-virtual-machine:~/桌面$ cd
yang@yang-virtual-machine:~$ find . -name '*.cpp' | xargs cat | wc -l
147
环境变量
概念
Linux
系统中会用很多环境变量来记录配置信息。
环境变量类似于全局变量,可以被各个进程访问到。我们可以通过修改环境变量来方便地修改系统配置。
查看
列出当前环境下的所有环境变量:
env # 显示当前用户的变量
set # 显示当前shell的变量,包括当前用户的变量;
export # 显示当前导出成用户变量的shell变量
输出某个环境变量的值:
echo $PATH
yang@yang-virtual-machine:~$ env
SHELL=/bin/bash
SESSION_MANAGER=local/yang-virtual-machine:@/tmp/.ICE-unix/1223,unix/yang-virtual-machine:/tmp/.ICE-unix/1223
QT_ACCESSIBILITY=1
COLORTERM=truecolor
XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
SSH_AGENT_LAUNCHER=gnome-keyring
XDG_MENU_PREFIX=gnome-
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
LANGUAGE=zh_CN:zh
GNOME_SHELL_SESSION_MODE=ubuntu
SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
XMODIFIERS=@im=ibus
DESKTOP_SESSION=ubuntu
GTK_MODULES=gail:atk-bridge
PWD=/home/yang
LOGNAME=yang
XDG_SESSION_DESKTOP=ubuntu
XDG_SESSION_TYPE=wayland
SYSTEMD_EXEC_PID=1245
XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.8YAFW1
HOME=/home/yang
USERNAME=yang
IM_CONFIG_PHASE=1
LANG=zh_CN.UTF-8
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:
XDG_CURRENT_DESKTOP=ubuntu:GNOME
VTE_VERSION=6800
WAYLAND_DISPLAY=wayland-0
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/40630108_222f_4e70_95c9_cfbd64160762
GNOME_SETUP_DISPLAY=:1
LESSCLOSE=/usr/bin/lesspipe %s %s
XDG_SESSION_CLASS=user
TERM=xterm-256color
LESSOPEN=| /usr/bin/lesspipe %s
USER=yang
GNOME_TERMINAL_SERVICE=:1.125
DISPLAY=:0
SHLVL=1
QT_IM_MODULE=ibus
XDG_RUNTIME_DIR=/run/user/1000
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
GDMSESSION=ubuntu
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
_=/usr/bin/env
OLDPWD=/home/yang/桌面
yang@yang-virtual-machine:~$ set
BASH=/usr/bin/bash
BASHOPTS=checkwinsize:cmdhist:complete_fullquote:expand_aliases:extglob:extquote:force_fignore:globasciiranges:histappend:interactive_comments:progcomp:promptvars:sourcepath
BASH_ALIASES=()
BASH_ARGC=([0]="0")
BASH_ARGV=()
BASH_CMDS=()
BASH_COMPLETION_VERSINFO=([0]="2" [1]="11")
BASH_LINENO=()
BASH_SOURCE=()
BASH_VERSINFO=([0]="5" [1]="1" [2]="16" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu")
BASH_VERSION='5.1.16(1)-release'
COLORTERM=truecolor
COLUMNS=79
DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus
DESKTOP_SESSION=ubuntu
DIRSTACK=()
DISPLAY=:0
EUID=1000
GDMSESSION=ubuntu
GNOME_DESKTOP_SESSION_ID=this-is-deprecated
GNOME_SETUP_DISPLAY=:1
GNOME_SHELL_SESSION_MODE=ubuntu
GNOME_TERMINAL_SCREEN=/org/gnome/Terminal/screen/40630108_222f_4e70_95c9_cfbd64160762
GNOME_TERMINAL_SERVICE=:1.125
GROUPS=()
GTK_MODULES=gail:atk-bridge
HISTCONTROL=ignoreboth
HISTFILE=/home/yang/.bash_history
HISTFILESIZE=2000
HISTSIZE=1000
HOME=/home/yang
HOSTNAME=yang-virtual-machine
HOSTTYPE=x86_64
IFS=$' \t\n'
IM_CONFIG_PHASE=1
LANG=zh_CN.UTF-8
LANGUAGE=zh_CN:zh
LESSCLOSE='/usr/bin/lesspipe %s %s'
LESSOPEN='| /usr/bin/lesspipe %s'
LINES=20
LOGNAME=yang
LS_COLORS='rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:'
MACHTYPE=x86_64-pc-linux-gnu
MAILCHECK=60
OLDPWD=/home/yang/桌面
OPTERR=1
OPTIND=1
OSTYPE=linux-gnu
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
PIPESTATUS=([0]="0")
PPID=2878
PS1='\[\e]0;\u@\h: \w\a\]${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
PS2='> '
PS4='+ '
PWD=/home/yang
QT_ACCESSIBILITY=1
QT_IM_MODULE=ibus
SESSION_MANAGER=local/yang-virtual-machine:@/tmp/.ICE-unix/1223,unix/yang-virtual-machine:/tmp/.ICE-unix/1223
SHELL=/bin/bash
SHELLOPTS=braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor
SHLVL=1
SSH_AGENT_LAUNCHER=gnome-keyring
SSH_AUTH_SOCK=/run/user/1000/keyring/ssh
SYSTEMD_EXEC_PID=1245
TERM=xterm-256color
UID=1000
USER=yang
USERNAME=yang
VTE_VERSION=6800
WAYLAND_DISPLAY=wayland-0
XAUTHORITY=/run/user/1000/.mutter-Xwaylandauth.8YAFW1
XDG_CONFIG_DIRS=/etc/xdg/xdg-ubuntu:/etc/xdg
XDG_CURRENT_DESKTOP=ubuntu:GNOME
XDG_DATA_DIRS=/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop
XDG_MENU_PREFIX=gnome-
XDG_RUNTIME_DIR=/run/user/1000
XDG_SESSION_CLASS=user
XDG_SESSION_DESKTOP=ubuntu
XDG_SESSION_TYPE=wayland
XMODIFIERS=@im=ibus
_=env
_backup_glob='@(#*#|*@(~|.@(bak|orig|rej|swp|dpkg*|rpm@(orig|new|save))))'
_xspecs=([tex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [freeamp]="!*.@(mp3|og[ag]|pls|m3u)" [gqmpeg]="!*.@(mp3|og[ag]|pls|m3u)" [texi2html]="!*.texi*" [hbpp]="!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])" [lowriter]="!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm|pdf)" [rpm2cpio]="!*.[rs]pm" [localc]="!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)" [hbrun]="!*.[Hh][Rr][Bb]" [vi]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [latex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [view]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [madplay]="!*.mp3" [compress]="*.Z" [pdfjadetex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [pbunzip2]="!*.?(t)bz?(2)" [lrunzip]="!*.lrz" [gunzip]="!*.@(Z|[gGd]z|t[ag]z)" [oowriter]="!*.@(sxw|stw|sxg|sgl|doc?([mx])|dot?([mx])|rtf|txt|htm|html|?(f)odt|ott|odm|pdf)" [epiphany]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [acroread]="!*.[pf]df" [znew]="*.Z" [kwrite]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [xemacs]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [gview]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [lzfgrep]="!*.@(tlz|lzma)" [lzless]="!*.@(tlz|lzma)" [cdiff]="!*.@(dif?(f)|?(d)patch)?(.@([gx]z|bz2|lzma))" [zipinfo]="!*.@(zip|[aegjswx]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|aab|ipa|do[ct][xm]|p[op]t[mx]|xl[st][xm]|pyz|whl)" [pdflatex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [portecle]="!@(*.@(ks|jks|jceks|p12|pfx|bks|ubr|gkr|cer|crt|cert|p7b|pkipath|pem|p10|csr|crl)|cacerts)" [modplugplay]="!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|oct|okt?(a)|p[st]m|s[3t]m|ult|umx|wav|xm)" [lokalize]="!*.po" [lbzcat]="!*.?(t)bz?(2)" [qiv]="!*.@(gif|jp?(e)g|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|svg)" [totem]="!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))" [ps2pdfwr]="!*.@(?(e)ps|pdf)" [dvitype]="!*.dvi" [unpigz]="!*.@(Z|[gGdz]z|t[ag]z)" [mozilla]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [pdfunite]="!*.pdf" [gpdf]="!*.[pf]df" [texi2dvi]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [bunzip2]="!*.?(t)bz?(2)" [zathura]="!*.@(cb[rz7t]|djv?(u)|?(e)ps|pdf)" [kaffeine]="!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))" [mpg123]="!*.mp3" [lzegrep]="!*.@(tlz|lzma)" [xv]="!*.@(gif|jp?(e)g?(2)|j2[ck]|jp[2f]|tif?(f)|png|p[bgp]m|bmp|x[bp]m|rle|rgb|pcx|fits|pm|?(e)ps)" [xdvi]="!*.@(dvi|DVI)?(.@(gz|Z|bz2))" [xfig]="!*.fig" [xpdf]="!*.@(pdf|fdf)?(.@(gz|GZ|bz2|BZ2|Z))" [oobase]="!*.odb" [xelatex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [gharbour]="!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])" [bzcat]="!*.?(t)bz?(2)" [dragon]="!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM|iso|ISO)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))" [xanim]="!*.@(mpg|mpeg|avi|mov|qt)" [lualatex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [rgview]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [rvim]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [xetex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [lomath]="!*.@(sxm|smf|mml|odf)" [zcat]="!*.@(Z|[gGd]z|t[ag]z)" [lynx]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [uncompress]="!*.Z" [xzcat]="!*.@(?(t)xz|tlz|lzma)" [vim]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [loimpress]="!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)" [dvipdf]="!*.dvi" [mpg321]="!*.mp3" [jadetex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [lobase]="!*.odb" [epdfview]="!*.pdf" [ps2pdf14]="!*.@(?(e)ps|pdf)" [ps2pdf13]="!*.@(?(e)ps|pdf)" [ps2pdf12]="!*.@(?(e)ps|pdf)" [poedit]="!*.po" [luatex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [kbabel]="!*.po" [bzme]="!*.@(zip|z|gz|tgz)" [dviselect]="!*.dvi" [realplay]="!*.@(rm?(j)|ra?(m)|smi?(l))" [kdvi]="!*.@(dvi|DVI)?(.@(gz|Z|bz2))" [elinks]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [kghostview]="!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))" [gtranslator]="!*.po" [unzip]="!*.@(zip|[aegjswx]ar|exe|pk3|wsz|zargo|xpi|s[tx][cdiw]|sx[gm]|o[dt][tspgfc]|od[bm]|oxt|epub|apk|aab|ipa|do[ct][xm]|p[op]t[mx]|xl[st][xm]|pyz|whl)" [ggv]="!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))" [oomath]="!*.@(sxm|smf|mml|odf)" [dvipdfmx]="!*.dvi" [makeinfo]="!*.texi*" [okular]="!*.@(okular|@(?(e|x)ps|?(E|X)PS|[pf]df|[PF]DF|dvi|DVI|cb[rz]|CB[RZ]|djv?(u)|DJV?(U)|dvi|DVI|gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx|GIF|JP?(E)G|MIFF|TIF?(F)|PN[GM]|P[BGP]M|BMP|XPM|ICO|XWD|TGA|PCX|epub|EPUB|odt|ODT|fb?(2)|FB?(2)|mobi|MOBI|g3|G3|chm|CHM)?(.?(gz|GZ|bz2|BZ2|xz|XZ)))" [sxemacs]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [aviplay]="!*.@(avi|asf|wmv)" [rgvim]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [dvipdfm]="!*.dvi" [ly2dvi]="!*.ly" [oodraw]="!*.@(sxd|std|sda|sdd|?(f)odg|otg)" [kpdf]="!*.@(?(e)ps|pdf)" [bibtex]="!*.aux" [netscape]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [emacs]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [rview]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [galeon]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [dillo]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [fbxine]="!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))" [oocalc]="!*.@(sxc|stc|xls?([bmx])|xlw|xlt?([mx])|[ct]sv|?(f)ods|ots)" [harbour]="!*.@([Pp][Rr][Gg]|[Cc][Ll][Pp])" [lodraw]="!*.@(sxd|std|sda|sdd|?(f)odg|otg)" [dvips]="!*.dvi" [ps2pdf]="!*.@(?(e)ps|pdf)" [kate]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [kid3-qt]="!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)" [pdftex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [gvim]="*.@([ao]|so|so.!(conf|*/*)|[rs]pm|gif|jp?(e)g|mp3|mp?(e)g|avi|asf|ogg|class)" [timidity]="!*.@(mid?(i)|rmi|rcp|[gr]36|g18|mod|xm|it|x3m|s[3t]m|kar)" [ogg123]="!*.@(og[ag]|m3u|flac|spx)" [lzgrep]="!*.@(tlz|lzma)" [ee]="!*.@(gif|jp?(e)g|miff|tif?(f)|pn[gm]|p[bgp]m|bmp|xpm|ico|xwd|tga|pcx)" [unlzma]="!*.@(tlz|lzma)" [lbunzip2]="!*.?(t)bz?(2)" [ooimpress]="!*.@(sxi|sti|pps?(x)|ppt?([mx])|pot?([mx])|?(f)odp|otp)" [xine]="!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))" [amaya]="!*.@(?([xX]|[sS])[hH][tT][mM]?([lL]))" [gv]="!*.@(@(?(e)ps|?(E)PS|pdf|PDF)?(.gz|.GZ|.bz2|.BZ2|.Z))" [kid3]="!*.@(mp[234c]|og[ag]|@(fl|a)ac|m4[abp]|spx|tta|w?(a)v|wma|aif?(f)|asf|ape)" [lilypond]="!*.ly" [modplug123]="!*.@(669|abc|am[fs]|d[bs]m|dmf|far|it|mdl|m[eo]d|mid?(i)|mt[2m]|oct|okt?(a)|p[st]m|s[3t]m|ult|umx|wav|xm)" [pbzcat]="!*.?(t)bz?(2)" [unxz]="!*.@(?(t)xz|tlz|lzma)" [playmidi]="!*.@(mid?(i)|cmf)" [lzcat]="!*.@(tlz|lzma)" [slitex]="!*.@(?(la)tex|texi|dtx|ins|ltx|dbj)" [aaxine]="!*@(.@(mp?(e)g|MP?(E)G|wm[av]|WM[AV]|avi|AVI|asf|vob|VOB|bin|dat|divx|DIVX|vcd|ps|pes|fli|flv|FLV|fxm|FXM|viv|rm|ram|yuv|mov|MOV|qt|QT|web[am]|WEB[AM]|mp[234]|MP[234]|m?(p)4[av]|M?(P)4[AV]|mkv|MKV|og[agmvx]|OG[AGMVX]|t[ps]|T[PS]|m2t?(s)|M2T?(S)|mts|MTS|wav|WAV|flac|FLAC|asx|ASX|mng|MNG|srt|m[eo]d|M[EO]D|s[3t]m|S[3T]M|it|IT|xm|XM)|+([0-9]).@(vdr|VDR))?(.@(crdownload|part))" [advi]="!*.dvi" [lzmore]="!*.@(tlz|lzma)" )
__expand_tilde_by_ref ()
{
if [[ ${!1-} == \~* ]]; then
eval $1="$(printf ~%q "${!1#\~}")";
fi
}
__get_cword_at_cursor_by_ref ()
{
local cword words=();
__reassemble_comp_words_by_ref "$1" words cword;
local i cur="" index=$COMP_POINT lead=${COMP_LINE:0:COMP_POINT};
if [[ $index -gt 0 && ( -n $lead && -n ${lead//[[:space:]]/} ) ]]; then
cur=$COMP_LINE;
for ((i = 0; i <= cword; ++i))
do
while [[ ${#cur} -ge ${#words[i]} && ${cur:0:${#words[i]}} != "${words[i]-}" ]]; do
cur="${cur:1}";
((index > 0)) && ((index--));
done;
if ((i < cword)); then
local old_size=${#cur};
cur="${cur#"${words[i]}"}";
local new_size=${#cur};
((index -= old_size - new_size));
fi;
done;
[[ -n $cur && ! -n ${cur//[[:space:]]/} ]] && cur=;
((index < 0)) && index=0;
fi;
local "$2" "$3" "$4" && _upvars -a${#words[@]} $2 ${words+"${words[@]}"} -v $3 "$cword" -v $4 "${cur:0:index}"
}
__load_completion ()
{
local -a dirs=(${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions);
local ifs=$IFS IFS=: dir cmd="${1##*/}" compfile;
[[ -n $cmd ]] || return 1;
for dir in ${XDG_DATA_DIRS:-/usr/local/share:/usr/share};
do
dirs+=($dir/bash-completion/completions);
done;
IFS=$ifs;
if [[ $BASH_SOURCE == */* ]]; then
dirs+=("${BASH_SOURCE%/*}/completions");
else
dirs+=(./completions);
fi;
local backslash=;
if [[ $cmd == \\* ]]; then
cmd="${cmd:1}";
$(complete -p "$cmd" 2>/dev/null || echo false) "\\$cmd" && return 0;
backslash=\\;
fi;
for dir in "${dirs[@]}";
do
[[ -d $dir ]] || continue;
for compfile in "$cmd" "$cmd.bash" "_$cmd";
do
compfile="$dir/$compfile";
if [[ -f $compfile ]] && . "$compfile" &> /dev/null; then
[[ -n $backslash ]] && $(complete -p "$cmd") "\\$cmd";
return 0;
fi;
done;
done;
[[ -v _xspecs[$cmd] ]] && complete -F _filedir_xspec "$cmd" "$backslash$cmd" && return 0;
return 1
}
__ltrim_colon_completions ()
{
if [[ $1 == *:* && $COMP_WORDBREAKS == *:* ]]; then
local colon_word=${1%"${1##*:}"};
local i=${#COMPREPLY[*]};
while ((i-- > 0)); do
COMPREPLY[i]=${COMPREPLY[i]#"$colon_word"};
done;
fi
}
__parse_options ()
{
local option option2 i IFS='
,/|';
option=;
local -a array=($1);
for i in "${array[@]}";
do
case "$i" in
---*)
break
;;
--?*)
option=$i;
break
;;
-?*)
[[ -n $option ]] || option=$i
;;
*)
break
;;
esac;
done;
[[ -n $option ]] || return 0;
IFS='
';
if [[ $option =~ (\[((no|dont)-?)\]). ]]; then
option2=${option/"${BASH_REMATCH[1]}"/};
option2=${option2%%[<{().[]*};
printf '%s\n' "${option2/=*/=}";
option=${option/"${BASH_REMATCH[1]}"/"${BASH_REMATCH[2]}"};
fi;
option=${option%%[<{().[]*};
printf '%s\n' "${option/=*/=}"
}
__reassemble_comp_words_by_ref ()
{
local exclude i j line ref;
if [[ -n $1 ]]; then
exclude="[${1//[^$COMP_WORDBREAKS]/}]";
fi;
printf -v "$3" %s "$COMP_CWORD";
if [[ -v exclude ]]; then
line=$COMP_LINE;
for ((i = 0, j = 0; i < ${#COMP_WORDS[@]}; i++, j++))
do
while [[ $i -gt 0 && ${COMP_WORDS[i]} == +($exclude) ]]; do
[[ $line != [[:blank:]]* ]] && ((j >= 2)) && ((j--));
ref="$2[$j]";
printf -v "$ref" %s "${!ref-}${COMP_WORDS[i]}";
((i == COMP_CWORD)) && printf -v "$3" %s "$j";
line=${line#*"${COMP_WORDS[i]}"};
[[ $line == [[:blank:]]* ]] && ((j++));
((i < ${#COMP_WORDS[@]} - 1)) && ((i++)) || break 2;
done;
ref="$2[$j]";
printf -v "$ref" %s "${!ref-}${COMP_WORDS[i]}";
line=${line#*"${COMP_WORDS[i]}"};
((i == COMP_CWORD)) && printf -v "$3" %s "$j";
done;
((i == COMP_CWORD)) && printf -v "$3" %s "$j";
else
for i in "${!COMP_WORDS[@]}";
do
printf -v "$2[i]" %s "${COMP_WORDS[i]}";
done;
fi
}
_allowed_groups ()
{
if _complete_as_root; then
local IFS='
';
COMPREPLY=($(compgen -g -- "$1"));
else
local IFS='
';
COMPREPLY=($(compgen -W "$(id -Gn 2>/dev/null || groups 2>/dev/null)" -- "$1"));
fi
}
_allowed_users ()
{
if _complete_as_root; then
local IFS='
';
COMPREPLY=($(compgen -u -- "${1:-$cur}"));
else
local IFS='
';
COMPREPLY=($(compgen -W "$(id -un 2>/dev/null || whoami 2>/dev/null)" -- "${1:-$cur}"));
fi
}
_apport-bug ()
{
local cur dashoptions prev param;
COMPREPLY=();
cur=`_get_cword`;
prev=${COMP_WORDS[COMP_CWORD-1]};
dashoptions='-h --help --save -v --version --tag -w --window';
case "$prev" in
ubuntu-bug | apport-bug)
case "$cur" in
-*)
COMPREPLY=($( compgen -W "$dashoptions" -- $cur ))
;;
*)
_apport_parameterless
;;
esac
;;
--save)
COMPREPLY=($( compgen -o default -G "$cur*" ))
;;
-w | --window)
dashoptions="--save --tag";
COMPREPLY=($( compgen -W "$dashoptions" -- $cur ))
;;
-h | --help | -v | --version | --tag)
return 0
;;
*)
dashoptions="--tag";
if ! [[ "${COMP_WORDS[*]}" =~ .*--save.* ]]; then
dashoptions="--save $dashoptions";
fi;
if ! [[ "${COMP_WORDS[*]}" =~ .*--window.* || "${COMP_WORDS[*]}" =~ .*\ -w\ .* ]]; then
dashoptions="-w --window $dashoptions";
fi;
case "$cur" in
-*)
COMPREPLY=($( compgen -W "$dashoptions" -- $cur ))
;;
*)
_apport_parameterless
;;
esac
;;
esac
}
_apport-cli ()
{
local cur dashoptions prev param;
COMPREPLY=();
cur=`_get_cword`;
prev=${COMP_WORDS[COMP_CWORD-1]};
dashoptions='-h --help -f --file-bug -u --update-bug -s --symptom \
-c --crash-file --save -v --version --tag -w --window';
case "$prev" in
apport-cli)
case "$cur" in
-*)
COMPREPLY=($( compgen -W "$dashoptions" -- $cur ))
;;
*)
_apport_parameterless
;;
esac
;;
-f | --file-bug)
param="-P --pid -p --package -s --symptom";
COMPREPLY=($( compgen -W "$param $(_apport_symptoms)" -- $cur))
;;
-s | --symptom)
COMPREPLY=($( compgen -W "$(_apport_symptoms)" -- $cur))
;;
--save)
COMPREPLY=($( compgen -o default -G "$cur*" ))
;;
-c | --crash-file)
COMPREPLY=($( compgen -G "${cur}*.apport"
compgen -G "${cur}*.crash" ))
;;
-w | --window)
dashoptions="--save --tag";
COMPREPLY=($( compgen -W "$dashoptions" -- $cur ))
;;
-h | --help | -v | --version | --tag)
return 0
;;
*)
dashoptions='--tag';
if ! [[ "${COMP_WORDS[*]}" =~ .*--save.* ]]; then
dashoptions="--save $dashoptions";
fi;
if ! [[ "${COMP_WORDS[*]}" =~ .*--window.* || "${COMP_WORDS[*]}" =~ .*\ -w\ .* ]]; then
dashoptions="-w --window $dashoptions";
fi;
if ! [[ "${COMP_WORDS[*]}" =~ .*--symptom.* || "${COMP_WORDS[*]}" =~ .*\ -s\ .* ]]; then
dashoptions="-s --symptom $dashoptions";
fi;
if ! [[ "${COMP_WORDS[*]}" =~ .*--update.* || "${COMP_WORDS[*]}" =~ .*\ -u\ .* ]]; then
dashoptions="-u --update $dashoptions";
fi;
if ! [[ "${COMP_WORDS[*]}" =~ .*--file-bug.* || "${COMP_WORDS[*]}" =~ .*\ -f\ .* ]]; then
dashoptions="-f --file-bug $dashoptions";
fi;
if ! [[ "${COMP_WORDS[*]}" =~ .*--crash-file.* || "${COMP_WORDS[*]}" =~ .*\ -c\ .* ]]; then
dashoptions="-c --crash-file $dashoptions";
fi;
case "$cur" in
-*)
COMPREPLY=($( compgen -W "$dashoptions" -- $cur ))
;;
*)
_apport_parameterless
;;
esac
;;
esac
}
_apport-collect ()
{
local cur prev;
COMPREPLY=();
cur=`_get_cword`;
prev=${COMP_WORDS[COMP_CWORD-1]};
case "$prev" in
apport-collect)
COMPREPLY=($( compgen -W "-p --package --tag" -- $cur))
;;
-p | --package)
COMPREPLY=($( apt-cache pkgnames $cur 2> /dev/null ))
;;
--tag)
return 0
;;
*)
if [[ "${COMP_WORDS[*]}" =~ .*\ -p.* || "${COMP_WORDS[*]}" =~ .*--package.* ]]; then
COMPREPLY=($( compgen -W "--tag" -- $cur));
else
COMPREPLY=($( compgen -W "-p --package --tag" -- $cur));
fi
;;
esac
}
_apport-unpack ()
{
local cur prev;
COMPREPLY=();
cur=`_get_cword`;
prev=${COMP_WORDS[COMP_CWORD-1]};
case "$prev" in
apport-unpack)
COMPREPLY=($( compgen -G "${cur}*.apport"
compgen -G "${cur}*.crash" ))
;;
esac
}
_apport_parameterless ()
{
local param;
param="$dashoptions $( apt-cache pkgnames $cur 2> /dev/null ) $( command ps axo pid | sed 1d ) $( _apport_symptoms ) $( compgen -G "${cur}*" )";
COMPREPLY=($( compgen -W "$param" -- $cur))
}
_apport_symptoms ()
{
local syms;
if [ -r /usr/share/apport/symptoms ]; then
for FILE in $(ls /usr/share/apport/symptoms);
do
if [[ ! "$FILE" =~ ^_.* && -n $(egrep "^def run\s*\(.*\):" /usr/share/apport/symptoms/$FILE) ]]; then
syms="$syms ${FILE%.py}";
fi;
done;
fi;
echo $syms
}
_available_interfaces ()
{
local PATH=$PATH:/sbin;
COMPREPLY=($({
if [[ ${1:-} == -w ]]; then
iwconfig
elif [[ ${1:-} == -a ]]; then
ifconfig || ip link show up
else
ifconfig -a || ip link show
fi
} 2>/dev/null | awk '/^[^ \t]/ { if ($1 ~ /^[0-9]+:/) { print $2 } else { print $1 } }'));
COMPREPLY=($(compgen -W '${COMPREPLY[@]/%[[:punct:]]/}' -- "$cur"))
}
_bashcomp_try_faketty ()
{
if type unbuffer &> /dev/null; then
unbuffer -p "$@";
else
if script --version 2>&1 | command grep -qF util-linux; then
script -qaefc "$*" /dev/null;
else
"$@";
fi;
fi
}
_cd ()
{
local cur prev words cword;
_init_completion || return;
local IFS='
' i j k;
compopt -o filenames;
if [[ -z ${CDPATH:-} || $cur == ?(.)?(.)/* ]]; then
_filedir -d;
return;
fi;
local -r mark_dirs=$(_rl_enabled mark-directories && echo y);
local -r mark_symdirs=$(_rl_enabled mark-symlinked-directories && echo y);
for i in ${CDPATH//:/'
'};
do
k="${#COMPREPLY[@]}";
for j in $(compgen -d -- $i/$cur);
do
if [[ ( -n $mark_symdirs && -L $j || -n $mark_dirs && ! -L $j ) && ! -d ${j#$i/} ]]; then
j+="/";
fi;
COMPREPLY[k++]=${j#$i/};
done;
done;
_filedir -d;
if ((${#COMPREPLY[@]} == 1)); then
i=${COMPREPLY[0]};
if [[ $i == "$cur" && $i != "*/" ]]; then
COMPREPLY[0]="${i}/";
fi;
fi;
return
}
_cd_devices ()
{
COMPREPLY+=($(compgen -f -d -X "!*/?([amrs])cd*" -- "${cur:-/dev/}"))
}
_command ()
{
local offset i;
offset=1;
for ((i = 1; i <= COMP_CWORD; i++))
do
if [[ ${COMP_WORDS[i]} != -* ]]; then
offset=$i;
break;
fi;
done;
_command_offset $offset
}
_command_offset ()
{
local word_offset=$1 i j;
for ((i = 0; i < word_offset; i++))
do
for ((j = 0; j <= ${#COMP_LINE}; j++))
do
[[ $COMP_LINE == "${COMP_WORDS[i]}"* ]] && break;
COMP_LINE=${COMP_LINE:1};
((COMP_POINT--));
done;
COMP_LINE=${COMP_LINE#"${COMP_WORDS[i]}"};
((COMP_POINT -= ${#COMP_WORDS[i]}));
done;
for ((i = 0; i <= COMP_CWORD - word_offset; i++))
do
COMP_WORDS[i]=${COMP_WORDS[i + word_offset]};
done;
for ((i; i <= COMP_CWORD; i++))
do
unset 'COMP_WORDS[i]';
done;
((COMP_CWORD -= word_offset));
COMPREPLY=();
local cur;
_get_comp_words_by_ref cur;
if ((COMP_CWORD == 0)); then
local IFS='
';
compopt -o filenames;
COMPREPLY=($(compgen -d -c -- "$cur"));
else
local cmd=${COMP_WORDS[0]} compcmd=${COMP_WORDS[0]};
local cspec=$(complete -p $cmd 2>/dev/null);
if [[ ! -n $cspec && $cmd == */* ]]; then
cspec=$(complete -p ${cmd##*/} 2>/dev/null);
[[ -n $cspec ]] && compcmd=${cmd##*/};
fi;
if [[ ! -n $cspec ]]; then
compcmd=${cmd##*/};
_completion_loader $compcmd;
cspec=$(complete -p $compcmd 2>/dev/null);
fi;
if [[ -n $cspec ]]; then
if [[ ${cspec#* -F } != "$cspec" ]]; then
local func=${cspec#*-F };
func=${func%% *};
if ((${#COMP_WORDS[@]} >= 2)); then
$func $cmd "${COMP_WORDS[-1]}" "${COMP_WORDS[-2]}";
else
$func $cmd "${COMP_WORDS[-1]}";
fi;
local opt;
while [[ $cspec == *" -o "* ]]; do
cspec=${cspec#*-o };
opt=${cspec%% *};
compopt -o $opt;
cspec=${cspec#$opt};
done;
else
cspec=${cspec#complete};
cspec=${cspec%%$compcmd};
COMPREPLY=($(eval compgen "$cspec" -- '$cur'));
fi;
else
if ((${#COMPREPLY[@]} == 0)); then
_minimal;
fi;
fi;
fi
}
_complete_as_root ()
{
[[ $EUID -eq 0 || -n ${root_command:-} ]]
}
_completion_loader ()
{
local cmd="${1:-_EmptycmD_}";
__load_completion "$cmd" && return 124;
complete -F _minimal -- "$cmd" && return 124
}
_configured_interfaces ()
{
if [[ -f /etc/debian_version ]]; then
COMPREPLY=($(compgen -W "$(command sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p' /etc/network/interfaces /etc/network/interfaces.d/* 2>/dev/null)" -- "$cur"));
else
if [[ -f /etc/SuSE-release ]]; then
COMPREPLY=($(compgen -W "$(printf '%s\n' /etc/sysconfig/network/ifcfg-* |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"));
else
if [[ -f /etc/pld-release ]]; then
COMPREPLY=($(compgen -W "$(command ls -B /etc/sysconfig/interfaces |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"));
else
COMPREPLY=($(compgen -W "$(printf '%s\n' /etc/sysconfig/network-scripts/ifcfg-* |
command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"));
fi;
fi;
fi
}
_count_args ()
{
local i cword words;
__reassemble_comp_words_by_ref "${1-}" words cword;
args=1;
for ((i = 1; i < cword; i++))
do
if [[ ${words[i]} != -* && ${words[i - 1]} != ${2-} || ${words[i]} == ${3-} ]]; then
((args++));
fi;
done
}
_dvd_devices ()
{
COMPREPLY+=($(compgen -f -d -X "!*/?(r)dvd*" -- "${cur:-/dev/}"))
}
_expand ()
{
case ${cur-} in
~*/*)
__expand_tilde_by_ref cur
;;
~*)
_tilde "$cur" || eval COMPREPLY[0]="$(printf ~%q "${COMPREPLY[0]#\~}")";
return ${#COMPREPLY[@]}
;;
esac
}
_filedir ()
{
local IFS='
';
_tilde "${cur-}" || return;
local -a toks;
local reset arg=${1-};
if [[ $arg == -d ]]; then
reset=$(shopt -po noglob);
set -o noglob;
toks=($(compgen -d -- "${cur-}"));
IFS=' ';
$reset;
IFS='
';
else
local quoted;
_quote_readline_by_ref "${cur-}" quoted;
local xspec=${arg:+"!*.@($arg|${arg^^})"} plusdirs=();
local opts=(-f -X "$xspec");
[[ -n $xspec ]] && plusdirs=(-o plusdirs);
[[ -n ${COMP_FILEDIR_FALLBACK-} || -z ${plusdirs-} ]] || opts+=("${plusdirs[@]}");
reset=$(shopt -po noglob);
set -o noglob;
toks+=($(compgen "${opts[@]}" -- $quoted));
IFS=' ';
$reset;
IFS='
';
[[ -n ${COMP_FILEDIR_FALLBACK-} && -n $arg && ${#toks[@]} -lt 1 ]] && {
reset=$(shopt -po noglob);
set -o noglob;
toks+=($(compgen -f ${plusdirs+"${plusdirs[@]}"} -- $quoted));
IFS=' ';
$reset;
IFS='
'
};
fi;
if ((${#toks[@]} != 0)); then
compopt -o filenames 2> /dev/null;
COMPREPLY+=("${toks[@]}");
fi
}
_filedir_xspec ()
{
local cur prev words cword;
_init_completion || return;
_tilde "$cur" || return;
local IFS='
' xspec=${_xspecs[${1##*/}]} tmp;
local -a toks;
toks=($(
compgen -d -- "$(quote_readline "$cur")" | {
while read -r tmp; do
printf '%s\n' $tmp
done
}
));
eval xspec="${xspec}";
local matchop=!;
if [[ $xspec == !* ]]; then
xspec=${xspec#!};
matchop=@;
fi;
xspec="$matchop($xspec|${xspec^^})";
toks+=($(
eval compgen -f -X "'!$xspec'" -- '$(quote_readline "$cur")' | {
while read -r tmp; do
[[ -n $tmp ]] && printf '%s\n' $tmp
done
}
));
[[ -n ${COMP_FILEDIR_FALLBACK:-} && ${#toks[@]} -lt 1 ]] && {
local reset=$(shopt -po noglob);
set -o noglob;
toks+=($(compgen -f -- "$(quote_readline "$cur")"));
IFS=' ';
$reset;
IFS='
'
};
if ((${#toks[@]} != 0)); then
compopt -o filenames;
COMPREPLY=("${toks[@]}");
fi
}
_fstypes ()
{
local fss;
if [[ -e /proc/filesystems ]]; then
fss="$(cut -d' ' -f2 /proc/filesystems)
$(awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null)";
else
fss="$(awk '/^[ \t]*[^#]/ { print $3 }' /etc/fstab 2>/dev/null)
$(awk '/^[ \t]*[^#]/ { print $3 }' /etc/mnttab 2>/dev/null)
$(awk '/^[ \t]*[^#]/ { print $4 }' /etc/vfstab 2>/dev/null)
$(awk '{ print $1 }' /etc/dfs/fstypes 2>/dev/null)
$([[ -d /etc/fs ]] && command ls /etc/fs)";
fi;
[[ -n $fss ]] && COMPREPLY+=($(compgen -W "$fss" -- "$cur"))
}
_get_comp_words_by_ref ()
{
local exclude flag i OPTIND=1;
local cur cword words=();
local upargs=() upvars=() vcur vcword vprev vwords;
while getopts "c:i:n:p:w:" flag "$@"; do
case $flag in
c)
vcur=$OPTARG
;;
i)
vcword=$OPTARG
;;
n)
exclude=$OPTARG
;;
p)
vprev=$OPTARG
;;
w)
vwords=$OPTARG
;;
*)
echo "bash_completion: $FUNCNAME: usage error" 1>&2;
return 1
;;
esac;
done;
while [[ $# -ge $OPTIND ]]; do
case ${!OPTIND} in
cur)
vcur=cur
;;
prev)
vprev=prev
;;
cword)
vcword=cword
;;
words)
vwords=words
;;
*)
echo "bash_completion: $FUNCNAME: \`${!OPTIND}':" "unknown argument" 1>&2;
return 1
;;
esac;
((OPTIND += 1));
done;
__get_cword_at_cursor_by_ref "${exclude-}" words cword cur;
[[ -v vcur ]] && {
upvars+=("$vcur");
upargs+=(-v $vcur "$cur")
};
[[ -v vcword ]] && {
upvars+=("$vcword");
upargs+=(-v $vcword "$cword")
};
[[ -v vprev && $cword -ge 1 ]] && {
upvars+=("$vprev");
upargs+=(-v $vprev "${words[cword - 1]}")
};
[[ -v vwords ]] && {
upvars+=("$vwords");
upargs+=(-a${#words[@]} $vwords ${words+"${words[@]}"})
};
((${#upvars[@]})) && local "${upvars[@]}" && _upvars "${upargs[@]}"
}
_get_cword ()
{
local LC_CTYPE=C;
local cword words;
__reassemble_comp_words_by_ref "${1-}" words cword;
if [[ -n ${2-} && -n ${2//[^0-9]/} ]]; then
printf "%s" "${words[cword - $2]}";
else
if ((${#words[cword]} == 0 && COMP_POINT == ${#COMP_LINE})); then
:;
else
local i;
local cur="$COMP_LINE";
local index="$COMP_POINT";
for ((i = 0; i <= cword; ++i))
do
while [[ ${#cur} -ge ${#words[i]} && ${cur:0:${#words[i]}} != "${words[i]}" ]]; do
cur="${cur:1}";
((index > 0)) && ((index--));
done;
if ((i < cword)); then
local old_size="${#cur}";
cur="${cur#${words[i]}}";
local new_size="${#cur}";
((index -= old_size - new_size));
fi;
done;
if [[ ${words[cword]:0:${#cur}} != "$cur" ]]; then
printf "%s" "${words[cword]}";
else
printf "%s" "${cur:0:index}";
fi;
fi;
fi
}
_get_first_arg ()
{
local i;
arg=;
for ((i = 1; i < COMP_CWORD; i++))
do
if [[ ${COMP_WORDS[i]} != -* ]]; then
arg=${COMP_WORDS[i]};
break;
fi;
done
}
_get_pword ()
{
if ((COMP_CWORD >= 1)); then
_get_cword "${@:-}" 1;
fi
}
_gids ()
{
if type getent &> /dev/null; then
COMPREPLY=($(compgen -W '$(getent group | cut -d: -f3)' -- "$cur"));
else
if type perl &> /dev/null; then
COMPREPLY=($(compgen -W '$(perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"')' -- "$cur"));
else
COMPREPLY=($(compgen -W '$(cut -d: -f3 /etc/group)' -- "$cur"));
fi;
fi
}
_have ()
{
PATH=$PATH:/usr/sbin:/sbin:/usr/local/sbin type $1 &> /dev/null
}
_included_ssh_config_files ()
{
(($# < 1)) && echo "bash_completion: $FUNCNAME: missing mandatory argument CONFIG" 1>&2;
local configfile i f;
configfile=$1;
local reset=$(shopt -po noglob);
set -o noglob;
local included=($(command sed -ne 's/^[[:blank:]]*[Ii][Nn][Cc][Ll][Uu][Dd][Ee][[:blank:]]\(.*\)$/\1/p' "${configfile}"));
$reset;
[[ -n ${included-} ]] || return;
for i in "${included[@]}";
do
if ! [[ $i =~ ^\~.*|^\/.* ]]; then
if [[ $configfile =~ ^\/etc\/ssh.* ]]; then
i="/etc/ssh/$i";
else
i="$HOME/.ssh/$i";
fi;
fi;
__expand_tilde_by_ref i;
set +o noglob;
for f in $i;
do
if [[ -r $f ]]; then
config+=("$f");
_included_ssh_config_files $f;
fi;
done;
$reset;
done
}
_init_completion ()
{
local exclude="" flag outx errx inx OPTIND=1;
while getopts "n:e:o:i:s" flag "$@"; do
case $flag in
n)
exclude+=$OPTARG
;;
e)
errx=$OPTARG
;;
o)
outx=$OPTARG
;;
i)
inx=$OPTARG
;;
s)
split=false;
exclude+==
;;
*)
echo "bash_completion: $FUNCNAME: usage error" 1>&2;
return 1
;;
esac;
done;
COMPREPLY=();
local redir="@(?([0-9])<|?([0-9&])>?(>)|>&)";
_get_comp_words_by_ref -n "$exclude<>&" cur prev words cword;
_variables && return 1;
if [[ $cur == $redir* || ${prev-} == $redir ]]; then
local xspec;
case $cur in
2'>'*)
xspec=${errx-}
;;
*'>'*)
xspec=${outx-}
;;
*'<'*)
xspec=${inx-}
;;
*)
case $prev in
2'>'*)
xspec=${errx-}
;;
*'>'*)
xspec=${outx-}
;;
*'<'*)
xspec=${inx-}
;;
esac
;;
esac;
cur="${cur##$redir}";
_filedir $xspec;
return 1;
fi;
local i skip;
for ((i = 1; i < ${#words[@]}; 1))
do
if [[ ${words[i]} == $redir* ]]; then
[[ ${words[i]} == $redir ]] && skip=2 || skip=1;
words=("${words[@]:0:i}" "${words[@]:i+skip}");
((i <= cword)) && ((cword -= skip));
else
((i++));
fi;
done;
((cword <= 0)) && return 1;
prev=${words[cword - 1]};
[[ -n ${split-} ]] && _split_longopt && split=true;
return 0
}
_installed_modules ()
{
COMPREPLY=($(compgen -W "$(PATH="$PATH:/sbin" lsmod |
awk '{if (NR != 1) print $1}')" -- "$1"))
}
_ip_addresses ()
{
local n;
case ${1-} in
-a)
n='6\?'
;;
-6)
n='6'
;;
*)
n=
;;
esac;
local PATH=$PATH:/sbin;
local addrs=$({
LC_ALL=C ifconfig -a || ip addr show
} 2>/dev/null |
command sed -e 's/[[:space:]]addr:/ /' -ne "s|.*inet${n}[[:space:]]\{1,\}\([^[:space:]/]*\).*|\1|p");
COMPREPLY+=($(compgen -W "$addrs" -- "${cur-}"))
}
_kernel_versions ()
{
COMPREPLY=($(compgen -W '$(command ls /lib/modules)' -- "$cur"))
}
_known_hosts ()
{
local cur prev words cword;
_init_completion -n : || return;
local options;
[[ ${1-} == -a || ${2-} == -a ]] && options=-a;
[[ ${1-} == -c || ${2-} == -c ]] && options+=" -c";
_known_hosts_real ${options-} -- "$cur"
}
_known_hosts_real ()
{
local configfile flag prefix="" ifs=$IFS;
local cur suffix="" aliases i host ipv4 ipv6;
local -a kh tmpkh=() khd=() config=();
local OPTIND=1;
while getopts "ac46F:p:" flag "$@"; do
case $flag in
a)
aliases='yes'
;;
c)
suffix=':'
;;
F)
configfile=$OPTARG
;;
p)
prefix=$OPTARG
;;
4)
ipv4=1
;;
6)
ipv6=1
;;
*)
echo "bash_completion: $FUNCNAME: usage error" 1>&2;
return 1
;;
esac;
done;
if (($# < OPTIND)); then
echo "bash_completion: $FUNCNAME: missing mandatory argument CWORD" 1>&2;
return 1;
fi;
cur=${!OPTIND};
((OPTIND += 1));
if (($# >= OPTIND)); then
echo "bash_completion: $FUNCNAME($*): unprocessed arguments:" "$(while (($# >= OPTIND)); do
printf '%s ' ${!OPTIND}
shift
done)" 1>&2;
return 1;
fi;
[[ $cur == *@* ]] && prefix=$prefix${cur%@*}@ && cur=${cur#*@};
kh=();
if [[ -v configfile ]]; then
[[ -r $configfile ]] && config+=("$configfile");
else
for i in /etc/ssh/ssh_config ~/.ssh/config ~/.ssh2/config;
do
[[ -r $i ]] && config+=("$i");
done;
fi;
local reset=$(shopt -po noglob);
set -o noglob;
if ((${#config[@]} > 0)); then
for i in "${config[@]}";
do
_included_ssh_config_files "$i";
done;
fi;
if ((${#config[@]} > 0)); then
local IFS='
';
tmpkh=($(awk 'sub("^[ \t]*([Gg][Ll][Oo][Bb][Aa][Ll]|[Uu][Ss][Ee][Rr])[Kk][Nn][Oo][Ww][Nn][Hh][Oo][Ss][Tt][Ss][Ff][Ii][Ll][Ee][ \t]+", "") { print $0 }' "${config[@]}" | sort -u));
IFS=$ifs;
fi;
if ((${#tmpkh[@]} != 0)); then
local j;
for i in "${tmpkh[@]}";
do
while [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; do
i=${BASH_REMATCH[1]}${BASH_REMATCH[3]};
j=${BASH_REMATCH[2]};
__expand_tilde_by_ref j;
[[ -r $j ]] && kh+=("$j");
done;
for j in $i;
do
__expand_tilde_by_ref j;
[[ -r $j ]] && kh+=("$j");
done;
done;
fi;
if [[ ! -v configfile ]]; then
for i in /etc/ssh/ssh_known_hosts /etc/ssh/ssh_known_hosts2 /etc/known_hosts /etc/known_hosts2 ~/.ssh/known_hosts ~/.ssh/known_hosts2;
do
[[ -r $i ]] && kh+=("$i");
done;
for i in /etc/ssh2/knownhosts ~/.ssh2/hostkeys;
do
[[ -d $i ]] && khd+=("$i"/*pub);
done;
fi;
if ((${#kh[@]} + ${#khd[@]} > 0)); then
if ((${#kh[@]} > 0)); then
for i in "${kh[@]}";
do
while read -ra tmpkh; do
((${#tmpkh[@]} == 0)) && continue;
set -- "${tmpkh[@]}";
[[ $1 == [\|\#]* ]] && continue;
[[ $1 == @* ]] && shift;
local IFS=,;
for host in $1;
do
[[ $host == *[*?]* ]] && continue;
host="${host#[}";
host="${host%]?(:+([0-9]))}";
COMPREPLY+=($host);
done;
IFS=$ifs;
done < "$i";
done;
COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur"));
fi;
if ((${#khd[@]} > 0)); then
for i in "${khd[@]}";
do
if [[ $i == *key_22_$cur*.pub && -r $i ]]; then
host=${i/#*key_22_/};
host=${host/%.pub/};
COMPREPLY+=($host);
fi;
done;
fi;
for i in ${!COMPREPLY[*]};
do
COMPREPLY[i]=$prefix${COMPREPLY[i]}$suffix;
done;
fi;
if [[ ${#config[@]} -gt 0 && -v aliases ]]; then
local -a hosts=($(command sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt][[:blank:]]\(.*\)$/\1/p' "${config[@]}"));
if ((${#hosts[@]} != 0)); then
COMPREPLY+=($(compgen -P "$prefix" -S "$suffix" -W '${hosts[@]%%[*?%]*}' -X '\!*' -- "$cur"));
fi;
fi;
if [[ -n ${COMP_KNOWN_HOSTS_WITH_AVAHI-} ]] && type avahi-browse &> /dev/null; then
COMPREPLY+=($(compgen -P "$prefix" -S "$suffix" -W "$(avahi-browse -cpr _workstation._tcp 2>/dev/null |
awk -F';' '/^=/ { print $7 }' | sort -u)" -- "$cur"));
fi;
if type ruptime &> /dev/null; then
COMPREPLY+=($(compgen -W "$(ruptime 2>/dev/null | awk '!/^ruptime:/ { print $1 }')" -- "$cur"));
fi;
if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; then
COMPREPLY+=($(compgen -A hostname -P "$prefix" -S "$suffix" -- "$cur"));
fi;
$reset;
if [[ -v ipv4 ]]; then
COMPREPLY=("${COMPREPLY[@]/*:*$suffix/}");
fi;
if [[ -v ipv6 ]]; then
COMPREPLY=("${COMPREPLY[@]/+([0-9]).+([0-9]).+([0-9]).+([0-9])$suffix/}");
fi;
if [[ -v ipv4 || -v ipv6 ]]; then
for i in "${!COMPREPLY[@]}";
do
[[ -n ${COMPREPLY[i]} ]] || unset -v "COMPREPLY[i]";
done;
fi;
__ltrim_colon_completions "$prefix$cur"
}
_longopt ()
{
local cur prev words cword split;
_init_completion -s || return;
case "${prev,,}" in
--help | --usage | --version)
return
;;
--!(no-*)dir*)
_filedir -d;
return
;;
--!(no-*)@(file|path)*)
_filedir;
return
;;
--+([-a-z0-9_]))
local argtype=$(LC_ALL=C $1 --help 2>&1 | command sed -ne "s|.*$prev\[\{0,1\}=[<[]\{0,1\}\([-A-Za-z0-9_]\{1,\}\).*|\1|p");
case ${argtype,,} in
*dir*)
_filedir -d;
return
;;
*file* | *path*)
_filedir;
return
;;
esac
;;
esac;
$split && return;
if [[ $cur == -* ]]; then
COMPREPLY=($(compgen -W "$(LC_ALL=C $1 --help 2>&1 |
while read -r line; do
[[ $line =~ --[A-Za-z0-9]+([-_][A-Za-z0-9]+)*=? ]] &&
printf '%s\n' ${BASH_REMATCH[0]}
done)" -- "$cur"));
[[ ${COMPREPLY-} == *= ]] && compopt -o nospace;
else
if [[ $1 == *@(rmdir|chroot) ]]; then
_filedir -d;
else
[[ $1 == *mkdir ]] && compopt -o nospace;
_filedir;
fi;
fi
}
_mac_addresses ()
{
local re='\([A-Fa-f0-9]\{2\}:\)\{5\}[A-Fa-f0-9]\{2\}';
local PATH="$PATH:/sbin:/usr/sbin";
COMPREPLY+=($(
{
LC_ALL=C ifconfig -a || ip link show
} 2>/dev/null | command sed -ne "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]].*/\1/p" -ne "s/.*[[:space:]]HWaddr[[:space:]]\{1,\}\($re\)[[:space:]]*$/\1/p" -ne "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]].*|\2|p" -ne "s|.*[[:space:]]\(link/\)\{0,1\}ether[[:space:]]\{1,\}\($re\)[[:space:]]*$|\2|p"
));
COMPREPLY+=($({
arp -an || ip neigh show
} 2>/dev/null | command sed -ne "s/.*[[:space:]]\($re\)[[:space:]].*/\1/p" -ne "s/.*[[:space:]]\($re\)[[:space:]]*$/\1/p"));
COMPREPLY+=($(command sed -ne "s/^[[:space:]]*\($re\)[[:space:]].*/\1/p" /etc/ethers 2>/dev/null));
COMPREPLY=($(compgen -W '${COMPREPLY[@]}' -- "$cur"));
__ltrim_colon_completions "$cur"
}
_minimal ()
{
local cur prev words cword split;
_init_completion -s || return;
$split && return;
_filedir
}
_modules ()
{
local modpath;
modpath=/lib/modules/$1;
COMPREPLY=($(compgen -W "$(command ls -RL $modpath 2>/dev/null |
command sed -ne 's/^\(.*\)\.k\{0,1\}o\(\.[gx]z\)\{0,1\}$/\1/p')" -- "$cur"))
}
_ncpus ()
{
local var=NPROCESSORS_ONLN;
[[ $OSTYPE == *linux* ]] && var=_$var;
local n=$(getconf $var 2>/dev/null);
printf %s ${n:-1}
}
_parse_help ()
{
eval local cmd="$(quote "$1")";
local line;
{
case $cmd in
-)
cat
;;
*)
LC_ALL=C "$(dequote "$cmd")" ${2:---help} 2>&1
;;
esac
} | while read -r line; do
[[ $line == *([[:blank:]])-* ]] || continue;
while [[ $line =~ ((^|[^-])-[A-Za-z0-9?][[:space:]]+)\[?[A-Z0-9]+([,_-]+[A-Z0-9]+)?(\.\.+)?\]? ]]; do
line=${line/"${BASH_REMATCH[0]}"/"${BASH_REMATCH[1]}"};
done;
__parse_options "${line// or /, }";
done
}
_parse_usage ()
{
eval local cmd="$(quote "$1")";
local line match option i char;
{
case $cmd in
-)
cat
;;
*)
LC_ALL=C "$(dequote "$cmd")" ${2:---usage} 2>&1
;;
esac
} | while read -r line; do
while [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; do
match=${BASH_REMATCH[0]};
option=${BASH_REMATCH[1]};
case $option in
-?(\[)+([a-zA-Z0-9?]))
for ((i = 1; i < ${#option}; i++))
do
char=${option:i:1};
[[ $char != '[' ]] && printf '%s\n' -$char;
done
;;
*)
__parse_options "$option"
;;
esac;
line=${line#*"$match"};
done;
done
}
_pci_ids ()
{
COMPREPLY+=($(compgen -W "$(PATH="$PATH:/sbin" lspci -n | awk '{print $3}')" -- "$cur"))
}
_pgids ()
{
COMPREPLY=($(compgen -W '$(command ps axo pgid=)' -- "$cur"))
}
_pids ()
{
COMPREPLY=($(compgen -W '$(command ps axo pid=)' -- "$cur"))
}
_pnames ()
{
local -a procs;
if [[ ${1-} == -s ]]; then
procs=($(command ps axo comm | command sed -e 1d));
else
local line i=-1 ifs=$IFS;
IFS='
';
local -a psout=($(command ps axo command=));
IFS=$ifs;
for line in "${psout[@]}";
do
if ((i == -1)); then
if [[ $line =~ ^(.*[[:space:]])COMMAND([[:space:]]|$) ]]; then
i=${#BASH_REMATCH[1]};
else
break;
fi;
else
line=${line:i};
line=${line%% *};
procs+=($line);
fi;
done;
if ((i == -1)); then
for line in "${psout[@]}";
do
if [[ $line =~ ^[[(](.+)[])]$ ]]; then
procs+=(${BASH_REMATCH[1]});
else
line=${line%% *};
line=${line##@(*/|-)};
procs+=($line);
fi;
done;
fi;
fi;
COMPREPLY=($(compgen -X "<defunct>" -W '${procs[@]}' -- "$cur"))
}
_quote_readline_by_ref ()
{
if [ -z "$1" ]; then
printf -v $2 %s "$1";
else
if [[ $1 == \'* ]]; then
printf -v $2 %s "${1:1}";
else
if [[ $1 == \~* ]]; then
printf -v $2 \~%q "${1:1}";
else
printf -v $2 %q "$1";
fi;
fi;
fi;
[[ ${!2} == \$* ]] && eval $2=${!2}
}
_realcommand ()
{
type -P "$1" > /dev/null && {
if type -p realpath > /dev/null; then
realpath "$(type -P "$1")";
else
if type -p greadlink > /dev/null; then
greadlink -f "$(type -P "$1")";
else
if type -p readlink > /dev/null; then
readlink -f "$(type -P "$1")";
else
type -P "$1";
fi;
fi;
fi
}
}
_rl_enabled ()
{
[[ "$(bind -v)" == *$1+([[:space:]])on* ]]
}
_root_command ()
{
local PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin;
local root_command=$1;
_command
}
_service ()
{
local cur prev words cword;
_init_completion || return;
((cword > 2)) && return;
if [[ $cword -eq 1 && $prev == ?(*/)service ]]; then
_services;
[[ -e /etc/mandrake-release ]] && _xinetd_services;
else
local sysvdirs;
_sysvdirs;
COMPREPLY=($(compgen -W '`command sed -e "y/|/ /" \
-ne "s/^.*\(U\|msg_u\)sage.*{\(.*\)}.*$/\2/p" \
${sysvdirs[0]}/${prev##*/} 2>/dev/null` start stop' -- "$cur"));
fi
}
_services ()
{
local sysvdirs;
_sysvdirs;
local IFS='
' reset=$(shopt -p nullglob);
shopt -s nullglob;
COMPREPLY=($(printf '%s\n' ${sysvdirs[0]}/!($_backup_glob|functions|README)));
$reset;
COMPREPLY+=($({
systemctl list-units --full --all ||
systemctl list-unit-files
} 2>/dev/null |
awk '$1 ~ /\.service$/ { sub("\\.service$", "", $1); print $1 }'));
if [[ -x /sbin/upstart-udev-bridge ]]; then
COMPREPLY+=($(initctl list 2>/dev/null | cut -d' ' -f1));
fi;
COMPREPLY=($(compgen -W '${COMPREPLY[@]#${sysvdirs[0]}/}' -- "$cur"))
}
_shells ()
{
local shell rest;
while read -r shell rest; do
[[ $shell == /* && $shell == "$cur"* ]] && COMPREPLY+=($shell);
done 2> /dev/null < /etc/shells
}
_signals ()
{
local -a sigs=($(compgen -P "${1-}" -A signal "SIG${cur#${1-}}"));
COMPREPLY+=("${sigs[@]/#${1-}SIG/${1-}}")
}
_split_longopt ()
{
if [[ $cur == --?*=* ]]; then
prev="${cur%%?(\\)=*}";
cur="${cur#*=}";
return 0;
fi;
return 1
}
_sysvdirs ()
{
sysvdirs=();
[[ -d /etc/rc.d/init.d ]] && sysvdirs+=(/etc/rc.d/init.d);
[[ -d /etc/init.d ]] && sysvdirs+=(/etc/init.d);
[[ -f /etc/slackware-version ]] && sysvdirs=(/etc/rc.d);
return 0
}
_terms ()
{
COMPREPLY+=($(compgen -W "$({
command sed -ne 's/^\([^[:space:]#|]\{2,\}\)|.*/\1/p' /etc/termcap
{
toe -a || toe
} | awk '{ print $1 }'
find /{etc,lib,usr/lib,usr/share}/terminfo/? -type f -maxdepth 1 |
awk -F/ '{ print $NF }'
} 2>/dev/null)" -- "$cur"))
}
_tilde ()
{
local result=0;
if [[ ${1-} == \~* && $1 != */* ]]; then
COMPREPLY=($(compgen -P '~' -u -- "${1#\~}"));
result=${#COMPREPLY[@]};
((result > 0)) && compopt -o filenames 2> /dev/null;
fi;
return $result
}
_uids ()
{
if type getent &> /dev/null; then
COMPREPLY=($(compgen -W '$(getent passwd | cut -d: -f3)' -- "$cur"));
else
if type perl &> /dev/null; then
COMPREPLY=($(compgen -W '$(perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"')' -- "$cur"));
else
COMPREPLY=($(compgen -W '$(cut -d: -f3 /etc/passwd)' -- "$cur"));
fi;
fi
}
_upvar ()
{
echo "bash_completion: $FUNCNAME: deprecated function," "use _upvars instead" 1>&2;
if unset -v "$1"; then
if (($# == 2)); then
eval $1=\"\$2\";
else
eval $1=\(\"\$"{@:2}"\"\);
fi;
fi
}
_upvars ()
{
if ! (($#)); then
echo "bash_completion: $FUNCNAME: usage: $FUNCNAME" "[-v varname value] | [-aN varname [value ...]] ..." 1>&2;
return 2;
fi;
while (($#)); do
case $1 in
-a*)
[[ -n ${1#-a} ]] || {
echo "bash_completion: $FUNCNAME:" "\`$1': missing number specifier" 1>&2;
return 1
};
printf %d "${1#-a}" &> /dev/null || {
echo bash_completion: "$FUNCNAME: \`$1': invalid number specifier" 1>&2;
return 1
};
[[ -n "$2" ]] && unset -v "$2" && eval $2=\(\"\$"{@:3:${1#-a}}"\"\) && shift $((${1#-a} + 2)) || {
echo bash_completion: "$FUNCNAME: \`$1${2+ }$2': missing argument(s)" 1>&2;
return 1
}
;;
-v)
[[ -n "$2" ]] && unset -v "$2" && eval $2=\"\$3\" && shift 3 || {
echo "bash_completion: $FUNCNAME: $1:" "missing argument(s)" 1>&2;
return 1
}
;;
*)
echo "bash_completion: $FUNCNAME: $1: invalid option" 1>&2;
return 1
;;
esac;
done
}
_usb_ids ()
{
COMPREPLY+=($(compgen -W "$(PATH="$PATH:/sbin" lsusb | awk '{print $6}')" -- "$cur"))
}
_user_at_host ()
{
local cur prev words cword;
_init_completion -n : || return;
if [[ $cur == *@* ]]; then
_known_hosts_real "$cur";
else
COMPREPLY=($(compgen -u -S @ -- "$cur"));
compopt -o nospace;
fi
}
_usergroup ()
{
if [[ $cur == *\\\\* || $cur == *:*:* ]]; then
return;
else
if [[ $cur == *\\:* ]]; then
local prefix;
prefix=${cur%%*([^:])};
prefix=${prefix//\\/};
local mycur="${cur#*[:]}";
if [[ ${1-} == -u ]]; then
_allowed_groups "$mycur";
else
local IFS='
';
COMPREPLY=($(compgen -g -- "$mycur"));
fi;
COMPREPLY=($(compgen -P "$prefix" -W "${COMPREPLY[@]}"));
else
if [[ $cur == *:* ]]; then
local mycur="${cur#*:}";
if [[ ${1-} == -u ]]; then
_allowed_groups "$mycur";
else
local IFS='
';
COMPREPLY=($(compgen -g -- "$mycur"));
fi;
else
if [[ ${1-} == -u ]]; then
_allowed_users "$cur";
else
local IFS='
';
COMPREPLY=($(compgen -u -- "$cur"));
fi;
fi;
fi;
fi
}
_userland ()
{
local userland=$(uname -s);
[[ $userland == @(Linux|GNU/*) ]] && userland=GNU;
[[ $userland == "$1" ]]
}
_variable_assignments ()
{
local cur=${1-};
if [[ $cur =~ ^([A-Za-z_][A-Za-z0-9_]*)=(.*)$ ]]; then
prev=${BASH_REMATCH[1]};
cur=${BASH_REMATCH[2]};
else
return 1;
fi;
case $prev in
TZ)
cur=/usr/share/zoneinfo/$cur;
_filedir;
for i in "${!COMPREPLY[@]}";
do
if [[ ${COMPREPLY[i]} == *.tab ]]; then
unset 'COMPREPLY[i]';
continue;
else
if [[ -d ${COMPREPLY[i]} ]]; then
COMPREPLY[i]+=/;
compopt -o nospace;
fi;
fi;
COMPREPLY[i]=${COMPREPLY[i]#/usr/share/zoneinfo/};
done
;;
TERM)
_terms
;;
LANG | LC_*)
COMPREPLY=($(compgen -W '$(locale -a 2>/dev/null)' -- "$cur"))
;;
*)
_variables && return 0;
_filedir
;;
esac;
return 0
}
_variables ()
{
if [[ $cur =~ ^(\$(\{[!#]?)?)([A-Za-z0-9_]*)$ ]]; then
if [[ $cur == '${'* ]]; then
local arrs vars;
vars=($(compgen -A variable -P ${BASH_REMATCH[1]} -S '}' -- ${BASH_REMATCH[3]}));
arrs=($(compgen -A arrayvar -P ${BASH_REMATCH[1]} -S '[' -- ${BASH_REMATCH[3]}));
if ((${#vars[@]} == 1 && ${#arrs[@]} != 0)); then
compopt -o nospace;
COMPREPLY+=(${arrs[*]});
else
COMPREPLY+=(${vars[*]});
fi;
else
COMPREPLY+=($(compgen -A variable -P '$' -- "${BASH_REMATCH[3]}"));
fi;
return 0;
else
if [[ $cur =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]; then
local IFS='
';
COMPREPLY+=($(compgen -W '$(printf %s\\n "${!'${BASH_REMATCH[2]}'[@]}")' -P "${BASH_REMATCH[1]}${BASH_REMATCH[2]}[" -S ']}' -- "${BASH_REMATCH[3]}"));
if [[ ${BASH_REMATCH[3]} == [@*] ]]; then
COMPREPLY+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}");
fi;
__ltrim_colon_completions "$cur";
return 0;
else
if [[ $cur =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*\]$ ]]; then
COMPREPLY+=("$cur}");
__ltrim_colon_completions "$cur";
return 0;
fi;
fi;
fi;
return 1
}
_xfunc ()
{
set -- "$@";
local srcfile=$1;
shift;
declare -F $1 &> /dev/null || __load_completion "$srcfile";
"$@"
}
_xinetd_services ()
{
local xinetddir=${BASHCOMP_XINETDDIR:-/etc/xinetd.d};
if [[ -d $xinetddir ]]; then
local IFS='
' reset=$(shopt -p nullglob);
shopt -s nullglob;
local -a svcs=($(printf '%s\n' $xinetddir/!($_backup_glob)));
$reset;
((!${#svcs[@]})) || COMPREPLY+=($(compgen -W '${svcs[@]#$xinetddir/}' -- "${cur-}"));
fi
}
command_not_found_handle ()
{
if [ -x /usr/lib/command-not-found ]; then
/usr/lib/command-not-found -- "$1";
return $?;
else
if [ -x /usr/share/command-not-found/command-not-found ]; then
/usr/share/command-not-found/command-not-found -- "$1";
return $?;
else
printf "%s: command not found\n" "$1" 1>&2;
return 127;
fi;
fi
}
dequote ()
{
eval printf %s "$1" 2> /dev/null
}
quote ()
{
local quoted=${1//\'/\'\\\'\'};
printf "'%s'" "$quoted"
}
quote_readline ()
{
local ret;
_quote_readline_by_ref "$1" ret;
printf %s "$ret"
}
yang@yang-virtual-machine:~$ export
declare -x COLORTERM="truecolor"
declare -x DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/1000/bus"
declare -x DESKTOP_SESSION="ubuntu"
declare -x DISPLAY=":0"
declare -x GDMSESSION="ubuntu"
declare -x GNOME_DESKTOP_SESSION_ID="this-is-deprecated"
declare -x GNOME_SETUP_DISPLAY=":1"
declare -x GNOME_SHELL_SESSION_MODE="ubuntu"
declare -x GNOME_TERMINAL_SCREEN="/org/gnome/Terminal/screen/40630108_222f_4e70_95c9_cfbd64160762"
declare -x GNOME_TERMINAL_SERVICE=":1.125"
declare -x GTK_MODULES="gail:atk-bridge"
declare -x HOME="/home/yang"
declare -x IM_CONFIG_PHASE="1"
declare -x LANG="zh_CN.UTF-8"
declare -x LANGUAGE="zh_CN:zh"
declare -x LESSCLOSE="/usr/bin/lesspipe %s %s"
declare -x LESSOPEN="| /usr/bin/lesspipe %s"
declare -x LOGNAME="yang"
declare -x LS_COLORS="rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:*.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:*.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.webp=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36:"
declare -x OLDPWD="/home/yang/桌面"
declare -x PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin"
declare -x PWD="/home/yang"
declare -x QT_ACCESSIBILITY="1"
declare -x QT_IM_MODULE="ibus"
declare -x SESSION_MANAGER="local/yang-virtual-machine:@/tmp/.ICE-unix/1223,unix/yang-virtual-machine:/tmp/.ICE-unix/1223"
declare -x SHELL="/bin/bash"
declare -x SHLVL="1"
declare -x SSH_AGENT_LAUNCHER="gnome-keyring"
declare -x SSH_AUTH_SOCK="/run/user/1000/keyring/ssh"
declare -x SYSTEMD_EXEC_PID="1245"
declare -x TERM="xterm-256color"
declare -x USER="yang"
declare -x USERNAME="yang"
declare -x VTE_VERSION="6800"
declare -x WAYLAND_DISPLAY="wayland-0"
declare -x XAUTHORITY="/run/user/1000/.mutter-Xwaylandauth.8YAFW1"
declare -x XDG_CONFIG_DIRS="/etc/xdg/xdg-ubuntu:/etc/xdg"
declare -x XDG_CURRENT_DESKTOP="ubuntu:GNOME"
declare -x XDG_DATA_DIRS="/usr/share/ubuntu:/usr/local/share/:/usr/share/:/var/lib/snapd/desktop"
declare -x XDG_MENU_PREFIX="gnome-"
declare -x XDG_RUNTIME_DIR="/run/user/1000"
declare -x XDG_SESSION_CLASS="user"
declare -x XDG_SESSION_DESKTOP="ubuntu"
declare -x XDG_SESSION_TYPE="wayland"
declare -x XMODIFIERS="@im=ibus"
yang@yang-virtual-machine:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
修改
环境变量的定义、修改、删除操作可以参考shell语法中变量那一节的内容。
为了将对环境变量的修改应用到未来所有环境下,可以将修改命令放到~/.bashrc
文件中。(目前应该不用修改什么吧?)
修改完~/.bashrc
文件后,记得执行source ~/.bashrc
,来将修改应用到当前的bash
环境下。
为何将修改命令放到~/.bashrc
,就可以确保修改会影响未来所有的环境呢?
- 每次启动
bash
,都会先执行~/.bashrc
。 - 每次ssh登陆远程服务器,都会启动一个
bash
命令行给我们。 - 每次
tmux
新开一个pane
,都会启动一个bash
命令行给我们。 - 所以未来所有新开的环境都会加载我们修改的内容。
常见环境变量
- 1.
HOME
:用户的家目录。 - 2.
PATH
:可执行文件(命令)的存储路径。路径与路径之间用:
分隔。当某个可执行文件同时出现在多个路径中时,会选择从左到右数第一个路径中的执行。下列所有存储路径的环境变量,均采用从左到右的优先顺序。 - 3.
LD_LIBRARY_PATH
:用于指定动态链接库(.so文件)的路径,其内容是以冒号分隔的路径列表。 - 4.
C_INCLUDE_PATH
:C语言
的头文件路径,内容是以冒号分隔的路径列表。 - 5.
CPLUS_INCLUDE_PATH
:CPP
的头文件路径,内容是以冒号分隔的路径列表。 - 6.
PYTHONPATH
:Python
导入包的路径,内容是以冒号分隔的路径列表。 - 7.
JAVA_HOME
:jdk
的安装目录。 - 8.
CLASSPATH
:存放Java
导入类的路径,内容是以冒号分隔的路径列表。
常用命令
Linux
命令非常多,本节讲解几个常用命令。其他命令依赖于大家根据实际操作环境,边用边查。
系统状况
1.top
:查看所有进程的信息(Linux
的任务管理器)
- 打开后,输入
M
:按使用内存排序 - 打开后,输入
P
:按使用CPU排序 - 打开后,输入
q
:退出
2.df -h
:查看硬盘使用情况
3.free -h
:查看内存使用情况
4.du -sh
:查看当前目录占用的硬盘空间
5.ps aux
:查看所有进程
yang@yang-virtual-machine:~$ top
top - 14:54:36 up 23 min, 1 user, load average: 0.04, 0.02, 0.05
任务: 293 total, 1 running, 292 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3889.8 total, 1309.1 free, 1174.0 used, 1406.8 buff/cache
MiB Swap: 3898.0 total, 3898.0 free, 0.0 used. 2439.5 avail Mem
进程号 USER PR NI VIRT RES SHR %CPU %MEM TIME+ COMMAND
1245 yang 20 0 4337296 258648 123776 S 0.0 6.5 0:17.92 gnome-+
1684 yang 20 0 1420568 236660 71160 S 0.0 5.9 0:05.18 snap-s+
1604 yang 20 0 861592 71444 55348 S 0.0 1.8 0:00.27 evolut+
1891 yang 20 0 533168 69668 52304 S 0.0 1.7 0:00.21 gsd-xs+
1733 yang 20 0 210524 69008 46028 S 0.0 1.7 0:00.40 Xwayla+
2878 yang 20 0 657680 66016 47992 S 0.3 1.7 0:03.15 gnome-+
3134 yang 20 0 2842212 64128 47408 S 0.0 1.6 0:00.19 gjs
1443 root 20 0 455316 53844 19824 S 0.0 1.4 0:04.91 packag+
895 root 20 0 948576 44032 20136 S 0.0 1.1 0:02.12 snapd
1284 yang 20 0 573540 39696 32564 S 0.0 1.0 0:00.14 goa-da+
1602 yang 20 0 297704 39304 30464 S 0.0 1.0 0:01.15 vmtool+
2434 yang 20 0 542636 37344 28072 S 0.0 0.9 0:00.11 update+
1458 yang 20 0 681580 33660 27892 S 0.0 0.8 0:00.17 evolut+
yang@yang-virtual-machine:~$ df -h
文件系统 容量 已用 可用 已用% 挂载点
tmpfs 389M 2.0M 387M 1% /run
/dev/sda3 98G 14G 79G 15% /
tmpfs 1.9G 0 1.9G 0% /dev/shm
tmpfs 5.0M 4.0K 5.0M 1% /run/lock
/dev/sda2 512M 5.3M 507M 2% /boot/efi
tmpfs 389M 4.7M 385M 2% /run/user/1000
/dev/sr0 3.6G 3.6G 0 100% /media/yang/Ubuntu 22.04.1 LTS amd64
yang@yang-virtual-machine:~$ free -h
total used free shared buff/cache available
内存: 3.8Gi 1.1Gi 1.3Gi 37Mi 1.4Gi 2.4Gi
交换: 3.8Gi 0B 3.8Gi
yang@yang-virtual-machine:~$ du -sh
693M .
yang@yang-virtual-machine:~$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.2 166736 11564 ? Ss 14:30 0:01 /sbin/init s
root 2 0.0 0.0 0 0 ? S 14:30 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< 14:30 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< 14:30 0:00 [rcu_par_gp]
root 5 0.0 0.0 0 0 ? I< 14:30 0:00 [netns]
root 7 0.0 0.0 0 0 ? I< 14:30 0:00 [kworker/0:0
root 9 0.0 0.0 0 0 ? I< 14:30 0:00 [kworker/0:1
root 10 0.0 0.0 0 0 ? I< 14:30 0:00 [mm_percpu_w
root 11 0.0 0.0 0 0 ? S 14:30 0:00 [rcu_tasks_r
root 12 0.0 0.0 0 0 ? S 14:30 0:00 [rcu_tasks_t
root 13 0.0 0.0 0 0 ? S 14:30 0:00 [ksoftirqd/0
root 14 0.0 0.0 0 0 ? I 14:30 0:00 [rcu_sched]
root 15 0.0 0.0 0 0 ? S 14:30 0:00 [migration/0
root 16 0.0 0.0 0 0 ? S 14:30 0:00 [idle_inject
root 18 0.0 0.0 0 0 ? S 14:30 0:00 [cpuhp/0]
root 19 0.0 0.0 0 0 ? S 14:30 0:00 [cpuhp/1]
root 20 0.0 0.0 0 0 ? S 14:30 0:00 [idle_inject
root 21 0.0 0.0 0 0 ? S 14:30 0:00 [migration/1
#太多了,省略
6.kill -9 pid
:杀死编号为pid
的进程
- 传递某个具体的信号:
kill -s SIGTERM pid
7.netstat -nt
:查看所有网络连接
8.w
:列出当前登陆的用户
9.ping www.baidu.com
:检查是否连网
yang@yang-virtual-machine:~$ netstat -nt
激活Internet连接 (w/o 服务器)
Proto Recv-Q Send-Q Local Address Foreign Address State
yang@yang-virtual-machine:~$ w
15:00:09 up 29 min, 1 user, load average: 0.12, 0.05, 0.04
USER TTY 来自 LOGIN@ IDLE JCPU PCPU WHAT
yang tty2 tty2 14:30 29:14 0.07s 0.06s /usr/libexec/g
yang@yang-virtual-machine:~$ ping www.baidu.com
PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=1 ttl=128 time=18.1 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=2 ttl=128 time=17.9 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=3 ttl=128 time=19.1 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=4 ttl=128 time=17.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=5 ttl=128 time=17.5 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=6 ttl=128 time=18.2 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=7 ttl=128 time=19.2 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=8 ttl=128 time=19.8 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=9 ttl=128 time=18.0 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=10 ttl=128 time=17.5 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=11 ttl=128 time=18.7 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=12 ttl=128 time=17.9 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=13 ttl=128 time=17.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=14 ttl=128 time=17.8 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=15 ttl=128 time=19.6 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=16 ttl=128 time=18.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=17 ttl=128 time=17.8 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=18 ttl=128 time=25.2 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=19 ttl=128 time=18.2 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=20 ttl=128 time=19.6 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=21 ttl=128 time=17.9 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=22 ttl=128 time=17.6 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=23 ttl=128 time=17.4 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=24 ttl=128 time=18.0 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=25 ttl=128 time=17.6 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=26 ttl=128 time=20.4 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=27 ttl=128 time=17.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=28 ttl=128 time=17.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=29 ttl=128 time=17.7 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=30 ttl=128 time=17.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=31 ttl=128 time=17.3 ms
64 bytes from 14.215.177.39 (14.215.177.39): icmp_seq=32 ttl=128 time=18.1 ms
^Z
[1]+ 已停止 ping www.baidu.com
yang@yang-virtual-machine:~$ kill -9 %1
[1]+ 已停止 ping www.baidu.com
yang@yang-virtual-machine:~$ jobs
[1]+ 已杀死 ping www.baidu.com
#电脑上的结果
C:\Users\yqq>ping www.baidu.com
正在 Ping www.a.shifen.com [14.215.177.38] 具有 32 字节的数据:
来自 14.215.177.38 的回复: 字节=32 时间=21ms TTL=54
来自 14.215.177.38 的回复: 字节=32 时间=21ms TTL=54
来自 14.215.177.38 的回复: 字节=32 时间=23ms TTL=54
来自 14.215.177.38 的回复: 字节=32 时间=21ms TTL=54
14.215.177.38 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 21ms,最长 = 23ms,平均 = 21ms
文件权限
1.chmod
:修改文件权限
chmod +x xxx
:给xxx
添加可执行权限chmod -x xxx
:去掉xxx
的可执行权限chmod 777 xxx
:将xxx
的权限改成777
chmod 777 xxx -R
:递归修改整个文件夹的权限
文件检索
1.find /path/to/directory/ -name '*.py'
:搜索某个文件路径下的所有*.py
文件
2.grep xxx
:从stdin
中读入若干行数据,如果某行中包含xxx
,则输出该行;否则忽略该行。
3.wc
:统计行数、单词数、字节数
- 既可以从
stdin
中直接读入内容;也可以在命令行参数中传入文件名列表; wc -l
:统计行数wc -w
:统计单词数wc -c
:统计字节数
yang@yang-virtual-machine:~$ wc -w huiwenzhishu.cpp
62 huiwenzhishu.cpp
yang@yang-virtual-machine:~$ wc -lwc huiwenzhishu.cpp
49 62 569 huiwenzhishu.cpp
yang@yang-virtual-machine:~$ wc -wcl huiwenzhishu.cpp
49 62 569 huiwenzhishu.cpp
4.tree
:展示当前目录的文件结构
tree /path/to/directory/
:展示某个目录的文件结构tree -a
:展示隐藏文件 (tree -a ~:很多文件)
yang@yang-virtual-machine:~$ tree ~/
/home/yang/
├── 123
├── 公共的
├── 模板
├── 视频
├── 图片
├── 文档
├── 下载
├── 音乐
├── 桌面
│ ├── hello.txt
│ ├── test1.sh
│ └── test.sh
├── hanshushuru.sh
├── hhhhh.txt
├── huiwenzhishu
├── huiwenzhishu.cpp
├── input
├── input.txt
├── output.txt
├── snap
│ ├── firefox
│ │ ├── 2088
│ │ ├── 2154
│ │ ├── common
│ │ └── current -> 1635
│ ├── snapd-desktop-integration
│ │ ├── 14
│ │ ├── 43
│ │ ├── common
│ │ └── current -> 43
│ └── snap-store
│ ├── 599
│ ├── common
│ └── current -> 599
├── test1.sh
├── test2.sh
├── test3.sh
├── test4.sh
├── test5.sh
├── test6.sh
├── test7.sh
├── test8.sh
├── test9.sh
├── test.sh
└── yang
├── 公共的
├── 视频
├── 文档
├── 音乐
├── hanshushuru.sh
├── hhhhh.txt
├── huiwenzhishu.cpp
├── input.txt
├── output.txt
├── snap
│ ├── firefox
│ │ ├── 2088
│ │ ├── 2154
│ │ └── common
│ ├── snapd-desktop-integration
│ │ ├── 14
│ │ ├── 43
│ │ ├── common
│ │ └── current
│ └── snap-store
│ ├── 599
│ ├── common
│ └── current
├── test1
├── test3.sh
├── test4.sh
├── test5.sh
├── test6.sh
├── test7.sh
├── test9.sh
├── test.sh
└── yang
├── 视频
├── hanshushuru.sh
├── hhhhh.txt
├── huiwenzhishu.cpp
├── input.txt
├── snap
│ ├── snapd-desktop-integration
│ │ ├── 14
│ │ ├── 43
│ │ ├── common
│ │ └── current
│ └── snap-store
│ ├── common
│ └── current
├── test3.sh
├── test4.sh
├── test5.sh
├── test6.sh
├── test7.sh
└── test9.sh
53 directories, 44 files
5.ag xxx
:搜索当前目录下的所有文件,检索xxx
字符串
yang@yang-virtual-machine:~$ ag h
test9.sh
1:#! /bin/bash
2:. test8.sh
4:echo My name is: $name
huiwenzhishu.cpp
2:#include<cmath>
7:bool isHuiwen(unsigned b);//回文
13: if(isPrime(x)&&isHuiwen(x)){
40:bool isHuiwen(unsigned b)
43: while(b>0){
test7.sh
1:#! /bin/bash
4:then
5: echo "arguments not valid"
8: echo "arguments valid"
test5.sh
3: echo "Hello $name"
12:echo "output = $output"
13:echo "return = $ret"
hanshushuru.sh
3: while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
9: then
10: echo 0
15: then
16: echo 0
21: echo $(expr $sum + $1)
25:echo $(func 10)
test4.sh
3: echo "hello $name"
12:echo "output = $output"
13:echo "return = $ret"
test6.sh
1:#! /bin/bash
5: echo $name
9:echo $name
test3.sh
1:while read name
10: echo $i
test.sh
1:#! /bin/bash
5:echo $(expr "$a" + "$b")
yang/test9.sh
1:#! /bin/bash
2:. test8.sh
4:echo My name is: $name
yang/huiwenzhishu.cpp
2:#include<cmath>
7:bool isHuiwen(unsigned b);//回文
13: if(isPrime(x)&&isHuiwen(x)){
40:bool isHuiwen(unsigned b)
43: while(b>0){
yang/test7.sh
1:#! /bin/bash
4:then
5: echo "arguments not valid"
8: echo "arguments valid"
yang/test5.sh
3: echo "Hello $name"
12:echo "output = $output"
13:echo "return = $ret"
yang/hanshushuru.sh
3: while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
9: then
10: echo 0
15: then
16: echo 0
21: echo $(expr $sum + $1)
25:echo $(func 10)
yang/test4.sh
3: echo "hello $name"
12:echo "output = $output"
13:echo "return = $ret"
yang/test6.sh
1:#! /bin/bash
5: echo $name
9:echo $name
yang/test3.sh
1:while read name
10: echo $i
yang/test.sh
1:#! /bin/bash
5:echo $(expr "$a" + "$b")
yang/yang/test9.sh
1:#! /bin/bash
2:. test8.sh
4:echo My name is: $name
yang/yang/huiwenzhishu.cpp
2:#include<cmath>
7:bool isHuiwen(unsigned b);//回文
13: if(isPrime(x)&&isHuiwen(x)){
40:bool isHuiwen(unsigned b)
43: while(b>0){
yang/yang/test7.sh
1:#! /bin/bash
4:then
5: echo "arguments not valid"
8: echo "arguments valid"
yang/yang/test5.sh
3: echo "Hello $name"
12:echo "output = $output"
13:echo "return = $ret"
yang/yang/hanshushuru.sh
3: while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]
9: then
10: echo 0
15: then
16: echo 0
21: echo $(expr $sum + $1)
25:echo $(func 10)
yang/yang/test4.sh
3: echo "hello $name"
12:echo "output = $output"
13:echo "return = $ret"
yang/yang/test6.sh
1:#! /bin/bash
5: echo $name
9:echo $name
yang/yang/test3.sh
1:while read name
10: echo $i
test1.sh
4: then
7: echo $i
test2.sh
1:while read name
3: echo $name
test8.sh
1:#! /bin/bash
桌面/hello.txt
1:theima cat jjjjj
桌面/test.sh
1:#! /bin/bash
2:echo "hello world!" #这是注释
3:echo hhh
桌面/test1.sh
1: zhe shi zhushi
2:echo "hello world"
8:echo "hello shell"
6.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个字符
yang@yang-virtual-machine:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/snap/bin
yang@yang-virtual-machine:~$ echo $PATH | cut -c 3,5
s/
yang@yang-virtual-machine:~$ echo $PATH | cut -c 3-5
sr/
yang@yang-virtual-machine:~$ echo *$PATH | cut -d ':' -f 3-5
/usr/sbin:/usr/bin:/sbin
yang@yang-virtual-machine:~$ echo *$PATH | cut -d ':' -f 3,5
/usr/sbin:/sbin
yang@yang-virtual-machine:~$ echo $*PATH | cut -d ':' -f 3,5
PATH
yang@yang-virtual-machine:~$ echo $PATH | cut -d ':' -f 3,5
/usr/sbin:/sbin
7.sort
:将每行内容按字典序排序
- 可以从stdin中读取多行数据
- 可以从命令行参数中读取文件名列表
8.xargs
:将stdin
中的数据用空格或回车分割成命令行参数
find . -name '*.py' | xargs cat | wc -l
:统计当前目录下所有python
文件的总行数
查看文件内容
1.re
:浏览文件内容
- 回车:下一行
- 空格:下一页
b
:上一页q
:退出
(用不了?)
yang@yang-virtual-machine:~$ re huiwenzhishu.cpp
**** huiwenzhishu.cpp (Win:0) -> noname2.txt (Koi:2)
yang@yang-virtual-machine:~$ re test.sh
**** test.sh (Win:0) -> noname2.txt (Koi:2)
yang@yang-virtual-machine:~$ re test.sh
**** test.sh (Win:0) -> noname2.txt (Koi:2)
2.less
:与more
类似,功能更全
- 回车:下一行
y
:上一行Page Down
:下一页?(效果下一行)Page Up
:上一页?(效果上一行)q
:退出
3.head -3 xxx
:展示xxx
的前3行内容
同时支持从stdin
读入内容
4.tail -3 xxx
:展示xxx
末尾3行内容
- 同时支持从
stdin
读入内容
yang@yang-virtual-machine:~$ head -9 huiwenzhishu.cpp
#include<iostream>
#include<cmath>
using namespace std;
bool isPrime(unsigned a);//质数
bool isHuiwen(unsigned b);//回文
int main()
yang@yang-virtual-machine:~$ tail -9 huiwenzhishu.cpp
{
int ret=0,t=b,d;
while(b>0){
d=b%10;
ret=ret*10+d;
b/=10;
}
return t==ret;
}
用户相关
1.history
:展示当前用户的历史操作。内容存放在~/.bash_history
中
yang@yang-virtual-machine:~$ history
1 ifconfig
2 ifconfig-a
3 ifconfig
4 sudo apt install net-tools
5 ifconfig
6 sudo apt install net-tools
7 ifconfig
8 sudo apt-get install openssh server
9 sudo apt-get install oenssh-server
10 sudo apt-get install openssh-server
11 ifconfig
12 sudo apt install openssh-server
13 sudo apt install openssh-client
14 sudo apt install openssh-server
15 sudo apt install openssh-client
16 sudo gedit /etc/ssh/ssh/_config
17 sudo gedit /etc/ssh/ssh_config
18 sudo gedit /etc/ssh/sshd_config
19 sudo /etc/init.d/ssh restart
20 ifconfig
21 sudo apt install openssh-server
22 sudo apt install openssh-client
23 sudo gedit /etc/ssh/ssh_config
24 sudo gedit /etc/ssh/sshd_config
25 sudo /etc/init.d/ssh restart
26 ping 192.168.232.128
27 ping
#很多,省略
工具
1.md5sum
:计算md5
哈希值
- 可以从
stdin
读入内容 - 也可以在命令行参数中传入文件名列表;
MD5算法常常被用来验证网络文件传输的完整性,防止文件被人篡改。MD5 全称是报文摘要算法(Message-Digest Algorithm 5),此算法对任意长度的信息逐位进行计算,产生一个二进制长度为128位(十六进制长度就是32位)的“指纹”(或称“报文摘要”),不同的文件产生相同的报文摘要的可能性是非常非常之小的。
yang@yang-virtual-machine:~$ md5sum test.sh
2d1b8bc298981e0fbd77317543f4b7c8 test.sh
yang@yang-virtual-machine:~$ md5sum test1.sh
8d9f25e440c4b9f987810b5d23708f9e test1.sh
2.time command
:统计command
命令的执行时间
yang@yang-virtual-machine:~$ time ls
123 文档 hhhhh.txt noname2.txt test3.sh test8.sh
公共的 下载 huiwenzhishu output.txt test4.sh test9.sh
模板 音乐 huiwenzhishu.cpp snap test5.sh test.sh
视频 桌面 input test1.sh test6.sh yang
图片 hanshushuru.sh input.txt test2.sh test7.sh
real 0m0.002s
user 0m0.000s
sys 0m0.002s
3.ipython3
:交互式python3
环境。可以当做计算器,或者批量管理文件。
! echo "Hello World"
:!
表示执行shell
脚本
yang@yang-virtual-machine:~$ ipython3
Python 3.10.6 (main, Nov 2 2022, 18:53:38) [GCC 11.3.0]
Type 'copyright', 'credits' or 'license' for more information
IPython 7.31.1 -- An enhanced Interactive Python. Type '?' for help.
In [1]: ! echo "hello world"
hello world
In [2]: echo "hello world"
File "<ipython-input-2-2c7123d6102b>", line 1
echo "hello world"
^
SyntaxError: invalid syntax
In [3]: q
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-e222fcdf3350> in <module>
----> 1 q
NameError: name 'q' is not defined
In [4]: ! exit
In [5]:
In [5]: exit
4.watch -n 0.1 command
:每0.1秒
执行一次command
命令
5.tar
:压缩文件
tar -zcvf xxx.tar.gz /path/to/file/*****
:压缩tar -zxvf xxx.tar.gz
:解压缩
6.diff xxx yyy
:查找文件xxx
与yyy
的不同点
yang@yang-virtual-machine:~$ diff test.sh test1.sh
1,3c1,8
< #! /bin/bash
< read a
< read b
---
> for ((i=1;i<=10;i++))
> do
> if [ `expr $i % 2` -eq 0 ]
> then
> continue
> fi
> echo $i
> done
5d9
< echo $(expr "$a" + "$b")
安装软件
sudo command
:以root
身份执行command
命令apt-get install xxx
:安装软件pip install xxx --user --upgrade
:安装python
包
九、租云服务器及配docker环境
(本来想在超算习堂docker 实战里面练习一下,但是第一步docker服务就进行不了)
概述
云平台的作用:
存放我们的docker
容器,让计算跑在云端。
获得公网IP
地址,让每个人可以访问到我们的服务。
任选一个云平台即可,推荐配置:
1核 2GB
(后期可以动态扩容,前期配置低一些没关系)- 网络带宽采用按量付费,最大带宽拉满即可(费用取决于用量,与最大带宽无关)
- 系统版本:
ubuntu 20.04 LTS
(推荐用统一版本,避免后期出现配置不兼容的问题)
租云服务器及安装docker之阿里云
创建工作用户acs
并赋予sudo
权限
登录到新服务器。打开AC Terminal,然后:
ssh root@xxx.xxx.xxx.xxx # xxx.xxx.xxx.xxx替换成新服务器的公网IP
创建acs
用户:
adduser acs # 创建用户acs
usermod -aG sudo acs # 给用户acs分配sudo权限
配置免密登录方式
退回AC Terminal,然后配置acs
用户的别名和免密登录,可以参考ssh登录
配置新服务器的工作环境
将AC Terminal的配置传到新服务器上:
scp .bashrc .vimrc .tmux.conf server_name: # server_name需要换成自己配置的别名
安装tmux
和docker
登录自己的服务器,然后安装tmux
:
sudo apt-get update
sudo apt-get install tmux
12
打开tmux
。(养成好习惯,所有工作都在tmux
里进行,防止意外关闭终端后,工作进度丢失)
然后在tmux
中根据docker
安装教程安装docker
即可。
租云服务器及安装docker之腾讯云
腾讯云 产业智变·云启未来 - 腾讯 (tencent.com)
创建工作用户acs
并赋予sudo
权限
登录到新服务器。打开AC Terminal,然后:
ssh root@xxx.xxx.xxx.xxx # 注意腾讯云登录的用户不是root,而是ubuntu
创建acs
用户:
adduser acs # 创建用户acs
usermod -aG sudo acs # 给用户acs分配sudo权限
配置免密登录方式
退回AC Terminal,然后配置acs用户的别名和免密登录,可以参考ssh登录
配置新服务器的工作环境
将AC Terminal的配置传到新服务器上:
scp .bashrc .vimrc .tmux.conf server_name: # server_name需要换成自己配置的别名
安装tmux
和docker
登录自己的服务器,然后安装tmux
:
sudo apt-get update
sudo apt-get install tmux
打开tmux
。(养成好习惯,所有工作都在tmux
里进行,防止意外关闭终端后,工作进度丢失)
然后在tmux
中根据docker
安装教程安装docker
即可。
租云服务器及安装docker之华为云
共建智能世界云底座-华为云 (huaweicloud.com)
创建工作用户acs
并赋予sudo
权限
登录到新服务器。打开AC Terminal,然后:
ssh root@xxx.xxx.xxx.xxx # xxx.xxx.xxx.xxx替换成新服务器的公网IP
创建acs
用户:
adduser acs # 创建用户acs
usermod -aG sudo acs # 给用户acs分配sudo权限
配置免密登录方式
退回AC Terminal,然后配置acs
用户的别名和免密登录,可以参考ssh——ssh登录
配置新服务器的工作环境
将AC Terminal的配置传到新服务器上:
scp .bashrc .vimrc .tmux.conf server_name: # server_name需要换成自己配置的别名
安装tmux
和docker
登录自己的服务器,然后安装tmux
:
sudo apt-get update
sudo apt-get install tmux
打开tmux
。(养成好习惯,所有工作都在tmux
里进行,防止意外关闭终端后,工作进度丢失)
然后在tmux
中根据docker
安装教程安装docker
即可。
docker教程
将当前用户添加到docker
用户组
为了避免每次使用docker
命令都需要加上sudo
权限,可以将当前用户加入安装中自动创建的docker
用户组(可以参考官方文档):
sudo usermod -aG docker $USER
镜像(images)
1.docker pull ubuntu:20.04
:拉取一个镜像
2.docker images
:列出本地所有镜像
3.docker image rm ubuntu:20.04
或 docker rmi ubuntu:20.04
:删除镜像ubuntu:20.04
4.docker [container] commit CONTAINER IMAGE_NAME:TAG
:创建某个container
的镜像
5.docker save -o ubuntu_20_04.tar ubuntu:20.04
:将镜像ubuntu:20.04
导出到本地文件ubuntu_20_04.tar
中
6.docker load -i ubuntu_20_04.tar
:将镜像ubuntu:20.04
从本地文件ubuntu_20_04.tar
中加载出来
容器(container)
1.docker [container] create -it ubuntu:20.04
:利用镜像ubuntu:20.04创建一个容器。
2.docker ps -a
:查看本地的所有容器
3.docker [container] start CONTAINER
:启动容器
4.docker [container] stop CONTAINER
:停止容器
5.docker [container] restart CONTAINER
:重启容器
6.docker [contaienr] run -itd ubuntu:20.04
:创建并启动一个容器
7.docker [container] attach CONTAINER
:进入容器
- 先按
Ctrl-p
,再按Ctrl-q可以挂起容器
8.docker [container] exec CONTAINER COMMAND
:在容器中执行命令
9.docker [container] rm CONTAINER
:删除容器
10.docker container prune
:删除所有已停止的容器
11.docker export -o xxx.tar CONTAINER
:将容器CONTAINER
导出到本地文件xxx.tar
中
12.docker import xxx.tar image_name:tag
:将本地文件xxx.tar
导入成镜像,并将镜像命名为image_name:tag
13.docker export/import
与docker save/load
的区别:
export/import
会丢弃历史记录和元数据信息,仅保存容器当时的快照状态save/load
会保存完整记录,体积更大
14.docker top CONTAINER
:查看某个容器内的所有进程
15.docker stats
:查看所有容器的统计信息,包括CPU、内存、存储、网络等信息
16.docker cp xxx CONTAINER:xxx
或 docker cp CONTAINER:xxx xxx
:在本地和容器间复制文件
17.docker rename CONTAINER1 CONTAINER2
:重命名容器
18.docker update CONTAINER --memory 500MB
:修改容器限制
实战
进入AC Terminal
,然后:
scp /var/lib/acwing/docker/images/docker_lesson_1_0.tar server_name: # 将镜像上传到自己租的云端服务器
ssh server_name # 登录自己的云端服务器
docker load -i docker_lesson_1_0.tar # 将镜像加载到本地
docker run -p 20000:22 --name my_docker_server -itd docker_lesson:1.0 # 创建并运行docker_lesson:1.0镜像
docker attach my_docker_server # 进入创建的docker容器
passwd # 设置root密码
去云平台控制台中修改安全组配置,放行端口20000
。
返回AC Terminal
,即可通过ssh
登录自己的docker
容器:
ssh root@xxx.xxx.xxx.xxx -p 20000 # 将xxx.xxx.xxx.xxx替换成自己租的服务器的IP地址
然后,可以仿照上节课内容,创建工作账户acs
。
最后,可以参考ssh——ssh登录配置docker
容器的别名和免密登录。
小Tips
如果apt-get
下载软件速度较慢,可以参考清华大学开源软件镜像站中的内容,修改软件源。
补充
1. linux命令的分类
- 查看内部命令:
- help
- enable
- type
- 禁用内部命令:
- enanble -n
- 查看外部命令
- 适用于大多数Linux外部命令
--help
- 适用于大多数Linux外部命令
yang@yang-virtual-machine:~$ --help
--help:未找到命令
yang@yang-virtual-machine:~$ enable
enable .
enable :
enable [
enable alias
enable bg
enable bind
enable break
enable builtin
enable caller
enable cd
enable command
enable compgen
enable complete
enable compopt
enable continue
enable declare
enable dirs
enable disown
enable echo
enable enable
enable eval
enable exec
enable exit
enable export
enable false
enable fc
enable fg
enable getopts
enable hash
enable help
enable history
enable jobs
enable kill
enable let
enable local
enable logout
enable mapfile
enable popd
enable printf
enable pushd
enable pwd
enable read
enable readarray
enable readonly
enable return
enable set
enable shift
enable shopt
enable source
enable suspend
enable test
enable times
enable trap
enable true
enable type
enable typeset
enable ulimit
enable umask
enable unalias
enable unset
enable wait
yang@yang-virtual-machine:~$ help
GNU bash,版本 5.1.16(1)-release (x86_64-pc-linux-gnu)
这些 shell 命令是内部定义的。请输入 `help' 以获取一个列表。
输入 `help 名称' 以得到有关函数`名称'的更多信息。
使用 `info bash' 来获得关于 shell 的更多一般性信息。
使用 `man -k' 或 `info' 来获取不在列表中的命令的更多信息。
名称旁边的星号(*)表示该命令被禁用。
job_spec [&] history [-c] [-d 偏移量] [n] 或 his>
(( 表达式 )) if 命令; then 命令; [ elif 命令; th>
. 文件名 [参数] jobs [-lnprs] [任务声明 ...] 或 job>
: kill [-s 信号声明 | -n 信号编号 | >
[ 参数... ] let 参数 [参数 ...]
[[ 表达式 ]] local [option] 名称[=值] ...
alias [-p] [名称[=值] ... ] logout [n]
bg [任务声明 ...] mapfile [-d 分隔符] [-n 计数] [-O>
bind [-lpvsPSVX] [-m 键映射] [-f 文> popd [-n] [+N | -N]
break [n] printf [-v var] 格式 [参数]
builtin [shell 内建 [参数 ...]] pushd [-n] [+N | -N | 目录]
caller [表达式] pwd [-LP]
case 词 in [模式 [| 模式]...) 命令 ;> read [-ers] [-a 数组] [-d 分隔符] [>
cd [-L|[-P [-e]] [-@]] [目录] readarray [-d 定界符] [-n 计数] [->
command [-pVv] 命令 [参数 ...] readonly [-aAf] [名称[=值] ...] 或 >
compgen [-abcdefgjksuv] [-o option] > return [n]
complete [-abcdefgjksuv] [-pr] [-DEI> select NAME [in 词语 ... ;] do 命令>
compopt [-o|+o 选项] [-DEI] [名称 ..> set [--abefhkmnptuvxBCHP] [-o 选项>
continue [n] shift [n]
coproc [名称] 命令 [重定向] shopt [-pqsu] [-o] [选项名 ...]
declare [-aAfFgiIlnrtux] [-p] [name[> source 文件名 [参数]
dirs [-clpv] [+N] [-N] suspend [-f]
disown [-h] [-ar] [任务声明 ... | pi> test [表达式]
echo [-neE] [参数 ...] time [-p] 管道
enable [-a] [-dnps] [-f 文件名] [名> times
eval [参数 ...] trap [-lp] [[参数] 信号声明 ...]
exec [-cl] [-a name] [command [argum> true
exit [n] type [-afptP] 名称 [名称 ...]
export [-fn] [名称[=值] ...] 或 expo> typeset [-aAfFgiIlnrtux] [-p] name[>
false ulimit [-SHabcdefiklmnpqrstuvxPT] >
fc [-e 编辑器名] [-lnr] [起始] [终结> umask [-p] [-S] [模式]
fg [任务声明] unalias [-a] 名称 [名称 ...]
for 名称 [in 词语 ... ] ; do 命令; d> unset [-f] [-v] [-n] [名称 ...]
for (( 表达式1; 表达式2; 表达式3 ));> until 命令; do 命令; done
function 名称 { 命令 ; } 或 name () > variable - 一些 shell 变量的名称>
getopts optstring name [arg ...] wait [-fn] [-p var] [id ...]
hash [-lr] [-p 路径名] [-dt] [名称 .> while 命令; do 命令; done
help [-dms] [模式 ...] { 命令 ; }
yang@yang-virtual-machine:~$ type
反斜杠"\”:强制换行
2.主机名称命令
查看当前主机的完整名称
hostname
yang@yang-virtual-machine:~$ hostname
yang-virtual-machine
临时设置主机名
hostname 主机名
永久设置主机名
hostnamectl set-hostname 主机名
或
vi /etc/hostname(设置完后需重启系统才生效)
按i键先删除旧主机名,再输入新主机名(只有第一行有效)
按ESC键,再按SHIFT + “:” 组合键,输入 wq ,再按回车键退出
3.查看系统版本
查看当前系统版本信息
cat /etc/redhat-releasecat
或
cat /etc/*release
yang@yang-virtual-machine:~$ cat /etc/redhat-releasecat
cat: /etc/redhat-releasecat: 没有那个文件或目录
yang@yang-virtual-machine:~$ cat /etc/*release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.1 LTS"
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
所以是后者
查看当前内核版本
uname -r
yang@yang-virtual-machine:~$ uname -r
5.15.0-56-generic
yang@yang-virtual-machine:~$ uname
Linux
4.网卡修改相关命令
临时修改网卡IP
ifconfig ens33 192.168.80.3/24
或
ifconfig ens33 192.168.80.3 netmask 255.255.255.0
永久修改网卡IP永久修改网卡IP
vi /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet #设置网卡类型,“Ethernet”表示以太网
DEVICE=ens33 #设置网卡的名称
ONBOOT=yes #设置网卡是否在 Linux 操作系统启动时激活
IPADDR=192.168.80.3 #设置网卡的 IP 地址
NETMASK=255.255.255.0 #设置网卡的子网掩码
GATEWAY=192.168.80.2 #设置网卡的默认网关地址
DNS1=192.168.80.2 #设置DNS服务器的 IP 地址
重启网卡
systemctl restart network #重启所有的网卡
yang@yang-virtual-machine:~$ systemctl restart network
Failed to restart network.service: Unit network.service not found.
ifdown ens33 ; ifup ens33
ifdown ens33 #关闭某个网卡
ifup ens33 #启动某个网卡
ifconfig ens33 down #临时禁用某个网卡
ifconfig ens33 up #重新激活某个网卡(不会更新IP地址)
查看网卡地址
ifconfig
或
ip a
yang@yang-virtual-machine:~$ ifconfig
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.232.128 netmask 255.255.255.0 broadcast 192.168.232.255
inet6 fe80::616e:e7af:5a9:43ab prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:6a:da:4b txqueuelen 1000 (以太网)
RX packets 5616 bytes 6378746 (6.3 MB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 3427 bytes 280617 (280.6 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 1000 (本地环回)
RX packets 839 bytes 75342 (75.3 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 839 bytes 75342 (75.3 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
yang@yang-virtual-machine:~$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:0c:29:6a:da:4b brd ff:ff:ff:ff:ff:ff
altname enp2s1
inet 192.168.232.128/24 brd 192.168.232.255 scope global dynamic noprefixroute ens33
valid_lft 1158sec preferred_lft 1158sec
inet6 fe80::616e:e7af:5a9:43ab/64 scope link noprefixroute
valid_lft forever preferred_lft forever
添加静态路由条目
临时添加路由(重启network服务失效)
方法一:
route add -net 192.168.3.0/24 gw 192.168.8.2 [dev ens33]
-net:指定目标网段的地址
gw:指定下一跳路由器的 IP 地址
dev: 为路由指定的输出接口
查看路由表条目
route -n
yang@yang-virtual-machine:~$ route
内核 IP 路由表
目标 网关 子网掩码 标志 跃点 引用 使用 接口
default _gateway 0.0.0.0 UG 100 0 0 ens33
link-local 0.0.0.0 255.255.0.0 U 1000 0 0 ens33
192.168.232.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
yang@yang-virtual-machine:~$ route -n
内核 IP 路由表
目标 网关 子网掩码 标志 跃点 引用 使用 接口
0.0.0.0 192.168.232.2 0.0.0.0 UG 100 0 0 ens33
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 ens33
192.168.232.0 0.0.0.0 255.255.255.0 U 100 0 0 ens33
删除静态路由条目
route del -net 192.168.3.0/24
方法二:
ip route add 192.168.15.0/24 via 192.168.80.2 [dev ens33]
永久添加路由(重启network服务生效)
方法一:
vi /etc/sysconfig/static-routes
any net any gw 192.168.80.2
any net 192.168.3.0/24 gw 192.168.80.2
any net 10.0.0.0 netmask 255.0.0.0 gw 192.168.80.2
any host 192.168.100.100 gw 192.168.80.2
systemctl restart network
方法二:
vim /etc/sysconfig/network-scripts/route-ens33
default via 192.168.80.2 dev ens33 #默认路由,另一种格式 0.0.0.0/0 192.168.14.254 dev ens33
10.211.6.0/24 via 192.168.80.2 dev ens33
192.168.100.200 via 192.168.14.254 dev ens33
systemctl restart network
测试网络连接
ping
traceroute (静态跟踪):需要安装
mtr (动态跟踪)
5.开启关闭系统
重启系统
reboot√
init 6√
shutdown -r now√
关机
poweroff√
init 0√
shutdown -h now√
取消重启
shutdown -c(来不及取消)
6.ls补充
- **-l:**以长格式(Long) 显示文件和目录的列表,包括权限、大小、最后更新时间等详细信息。11命令与1s -1功能相同
- **-a:**显示所有(All)子目录和文件的信息,包括名称以点号“. "开头的隐藏目录和隐藏文件。
- **-A:**与-a选项的作用基本类似,但有两个特殊隐藏目录不会显示,即表示当前目录的“.”和表示父目录的“…”。
- **-d:**显示目录(Directory)本身的属性,而不是显示目录中的内容。
- -h: 以更人性化(Human)的方式显示目录或文件的大小,默认的大小单位为字节(B),使用-h选项后将显示为KB、MB等单位。此选项需要结合-1选项一- 起使用。
- **-R:**以递归(Recursive) 的方式显示指定目录及其子目录中的所有内容。
- –color: 在字符模式中以颜色区分不同的文件。默认已开启
- -i: 显示文件和目录的inode号。
通常情况下:
- 深蓝色表示目录√
- 白色表示一般文件√
- 绿色表示可执行的文件√
- 黄色表示设备文件
- 红色表示压缩文件√
用ls -l命令查看某一个目录会得到一个7个字段的列表
■ 第1字段:文件属性字
第一个字符代表文件的类型:
“-”表示该文件是一个普通文件
“d”表示该文件是一个目录
“l”表示该文件是一个软链接文件。类似于Window下的快捷方式
第1个字符的后面9个字母表示该文件或目录的权限位:
r表示度(查看、下载)、w表示写(添加、更改、删除、上传)、x表示执行(运行文件、切换目录)
其中前三个表示文件拥有者(属主)的权限,中间三个表示文件所属组拥有的权限,最后三个表示其他用户拥有的权限
■ 第2字段:文件硬链接数
如果一个文件不是目录,此时这一字段表示这个文件所具有的硬链接数
如果是一个目录,则第2字段表示该目录所含子目录的个数
如果新建一个空目录,这个目录的第二字段就是2,表示该目录下有两个子目录
■ 第3字段:文件\目录拥有者
■ 第4字段:文件\目录拥有者所在的组
■ 第5字段:文件所占用的空间(默认以字节为单位)
如果是一个目录,则表示该目录的大小,而不是目录以及它下面的文件的总大小。
Linux系统中一切皆为文件,因此目录也是一种文件。
■ 第6字段:文件\目录最近访问或修改时间
■ 第7字段:文件名
如果是一个符号链接(软链接文件),那么会有一个“->”箭头符号,后面根一个它指向的文件名
结合通配符
- “?”: 代表任意一个字符,有且一个字符;
- “*”: 代表任意数个字符,可以是0个或者1个或者多个;
- “【】”: 表示可以匹配字符组中的任意一个字符
超算实训Linux基础入门
快捷键
Tab : 命令补全,当你忘记某个命令的全称时可以只输入它的开头的一部分,然后按下 Tab 键就可以得到提示或者帮助完成。
Ctrl+c : 强行终止当前程序。
Ctrl+d : 键盘输入结束或退出终端。
Ctrl+s : 暂停当前程序,暂停后按下任意键恢复运行。(感觉ctrl+q才可以退出,其他键没有效果)
Ctrl+z : 将当前程序放到后台运行(bg),恢复到前台为命令fg。
Ctrl+a : 将光标移至输入行头,相当于Home键。
Ctrl+e : 将光标移至输入行末,相当于End键。
Ctrl+k : 删除从光标所在位置到行末。
Alt+Backspace : 向前删除一个单词。
**Ctrl+**Shift+PgUp : 将终端显示向上滚动。(Shift+PgUp输入A)[在两个里面都是这样,与旁边文档不一致]
Ctrl+Shift+PgDn : 将终端显示向下滚动。(Shift+PgDn输入B)[在两个里面都是这样,与旁边文档不一致]
帮助手册
在 Linux 环境中,如果你对某个命令感到疑惑,可以使用man命令来获取帮助,它是Manual pages的缩写。用户可以通过执行man命令调用手册页。
你可以使用如下方式来获得某个命令的说明和使用方式的详细介绍:
$ man <command_name>
软件安装-apt
APT(Advanced Package Tool)是一款适用于Unix和Linux系统的安装包管理工具。它可以自动下载,配置,安装软件包,因此简化了管理软件的过程。APT由几个名字以“apt-”打头的程序组成。apt-get、apt-cache 和apt-cdrom是处理软件包的命令行工具。
既然是一个安装包管理工具,APT会在本地维护一个软件包列表,列表里会有软件依赖信息的记录,并且会定期从软件源服务器下载最新的软件包列表。当需要进行安装操作时,可以使用 apt-get 工具在本地列表中搜索相关软件信息,并根据这些信息在相关服务器下载软件安装。
1) 搜索 :
如果想在安装前确认是否软件库有这个软件:
sudo apt-cache search somesoftware
结果就会显示软件的相关信息。
2) 安装 :
安装只需要执行这样的命令即可:
sudo apt-get install htop
当然它还有许多参数,例如在软件被破坏时重新安装:
sudo apt-get --reinstall install htop
3) 更新:
软件版本也会不断的更迭,我们在安装前往往需要进行更新,例如:
更新软件源:
sudo apt-get update
更新软件包:
sudo apt-get upgrade
需要注意的是依赖关系。
4) 卸载 :
卸载一个软件也很简单:
sudo apt-get remove htop
如果连配置文件也想一并删除:
sudo apt-get purge htop
用户权限管理
Linux 是一个多用户的操作系统,所有用户共享一些主机的资源,但他们也分别有自己的用户空间,用于存放各自的文件。由于 Linux 的 用户管理 和 权限机制,不同用户不可以轻易地查看、修改彼此的文件。
查看用户
$ whoami
输出:
当前伪终端的用户名
创建用户
首先使用adduser命令创建用户并设置密码:
$ sudo adduser <user>
su,su- 与 sudo :
$ su <user>
切换到用户 user,执行时需要输入目标用户的密码。
$ sudo <cmd>
以特权级别运行 cmd 命令,要求当前用户属于 sudo 组,且需要输入当前用户的密码。
$ su - <user>
切换用户,同时环境变量也会跟着改变成目标用户的环境变量。
查看用户组
$ groups user
输出为 用户 : 用户组。
删除用户
$ sudo deluser user --remove-home
删除用户比较简单。
文件权限管理
查看文件权限
ls
命令不仅可以列出并显示当前目录的文件,还可以用来查看文件的权限。
$ ls -l
输出:
文件类型和权限 链接数 所有者 所属用户组 文件大小 最后修改时间 文件名
这里特别解释一下文件类型和权限:
第一位是指文件类型,例如 ‘d’ 表示目录, '-'表示普通文件,等等。
后面的九位可以分成三组,每组三位分别表示读权限/写权限/执行权限,三组分别对应的是 拥有者权限/所属用户组权限/其他用户权限。
首先,我们可以用touch命令创建一个新的文件,然后再进行以下测试。
变更文件所有者
$ sudo chown [-R] new_owner file
sudo命令在之前提到过,是权限命令。
-R(注意大写)选项表示连同子目录中的所有文件,都更改所有者。
修改文件权限
有两种方式对文件权限进行修改:
第一种方式:二进制数字表示。每个文件的三组权限对应一个 “rwx”,每一位可以用 0 或 1 表示是否有权限,例如只有读和写权限的话就是 “rw-” - “110”,所以"rwx"对应的二进制"111"就是十进制的7。
所以将 file 文件权限改为 “rwx------” 的命令是:
$ chmod 700 file
第二种方式:加减赋值表示。假设一开始 file 文件的权限是 “rwxr–r–” 完成上述同样的效果,还可以:
$ chmod go-rr file
g、o 还有 u 分别表示 group、others 和 user,+ 和 - 分别表示增加和去掉相应的权限。
ehpc@adcc9a5674fd:~/Desktop$ ls -l
total 24
-rwxr-xr-x 1 ehpc ehpc 483 4月 11 2020 code.desktop
-rwxr-xr-x 1 ehpc ehpc 9259 5月 17 2019 firefox.desktop
-rw-rw-r-- 1 ehpc ehpc 0 12月 4 09:49 test.sh
-rwxr-xr-x 1 ehpc ehpc 3641 7月 28 2019 vim.desktop
-rwxr-xr-x 1 ehpc ehpc 545 6月 7 2019 终端.desktop
ehpc@adcc9a5674fd:~/Desktop$ chmod 700 test.sh
ehpc@adcc9a5674fd:~/Desktop$ ls -l
total 24
-rwxr-xr-x 1 ehpc ehpc 483 4月 11 2020 code.desktop
-rwxr-xr-x 1 ehpc ehpc 9259 5月 17 2019 firefox.desktop
-rwx------ 1 ehpc ehpc 0 12月 4 09:49 test.sh
-rwxr-xr-x 1 ehpc ehpc 3641 7月 28 2019 vim.desktop
-rwxr-xr-x 1 ehpc ehpc 545 6月 7 2019 终端.desktop
ehpc@adcc9a5674fd:~/Desktop$ chmod 755 test.sh
ehpc@adcc9a5674fd:~/Desktop$ ls -l
total 24
-rwxr-xr-x 1 ehpc ehpc 483 4月 11 2020 code.desktop
-rwxr-xr-x 1 ehpc ehpc 9259 5月 17 2019 firefox.desktop
-rwxr-xr-x 1 ehpc ehpc 0 12月 4 09:49 test.sh
-rwxr-xr-x 1 ehpc ehpc 3641 7月 28 2019 vim.desktop
-rwxr-xr-x 1 ehpc ehpc 545 6月 7 2019 终端.desktop
ehpc@adcc9a5674fd:~/Desktop$ chmod go-rr test.sh
ehpc@adcc9a5674fd:~/Desktop$ ls -l
total 24
-rwxr-xr-x 1 ehpc ehpc 483 4月 11 2020 code.desktop
-rwxr-xr-x 1 ehpc ehpc 9259 5月 17 2019 firefox.desktop
-rwx--x--x 1 ehpc ehpc 0 12月 4 09:49 test.sh
-rwxr-xr-x 1 ehpc ehpc 3641 7月 28 2019 vim.desktop
-rwxr-xr-x 1 ehpc ehpc 545 6月 7 2019 终端.desktop
ehpc@adcc9a5674fd:~/Desktop$ chmod go+rrww test.sh
ehpc@adcc9a5674fd:~/Desktop$ ls -l
total 24
-rwxr-xr-x 1 ehpc ehpc 483 4月 11 2020 code.desktop
-rwxr-xr-x 1 ehpc ehpc 9259 5月 17 2019 firefox.desktop
-rwxrwxrwx 1 ehpc ehpc 0 12月 4 09:49 test.sh
-rwxr-xr-x 1 ehpc ehpc 3641 7月 28 2019 vim.desktop
-rwxr-xr-x 1 ehpc ehpc 545 6月 7 2019 终端.desktop
目录及文件操作
在linux中,我们使用cd 命令来切换目录,使用**.** 表示当前目录,… 表示上一级目录, - 表示上一次所在目录,~ 通常表示当前用户的 home 目录。使用 pwd 命令可以获取当前所在路径(绝对路径)。
例如,进入上一级目录:
$ cd ..
搭配之前提及的快捷键 Tab 可以大大提高效率。
基本文件操作:
创建
文件:
在这里,我们可以先简单地使用 touch 命令来创建一个新的空白文件。
例如:
$ touch myfile
目录:
使用 mkdir 命令可以创建一个新的目录。
创建名为“ mydir ”的空目录:
$ mkdir mydir
复制
文件:
使用 cp(copy)命令复制一个文件到指定目录。
例如:
$ cp myfile ../../mydir
目录:
在复制文件的基础上加上 -r 参数即可。
例如:
$ cp -r dir mydir
删除
文件:
使用 rm(remove files or directories)命令删除一个文件:
$ rm test
目录:
同样,删除目录也是需要加上 -r 参数。
移动及重命名
移动文件和对文件重命名都使用 mv 命令。
mv 源目录文件 目的目录:
$ mv myfile mydir
注意,这里mv命令是剪切文件。
mv 旧的文件名 新的文件名:
$ mv myfile myfile1
编辑文件
Linux系统存在许多编辑器,例如vim,emacs,nano等等,在这里我们使用nano编辑器来打开文件:
$ nano myfile
vim编辑器功能非常强大,但随之而来的是它的学习难度并不简单,然而编辑器的使用又是必不可少的一部分,所以在这里建议您先去学习一门编辑器的基本使用方法。
搜索文件
which
which只从环境变量指定的路径中去搜索文件,所以我们常常使用which来判断是否安装了某个软件。
例如:
$ which nano
whereis
一个比较简单的搜索命令,它直接从数据库而不是硬盘查询,而且只能搜索特定的文件。所以,它的搜索很快。
locate
在这里要先介绍" /var/lib/mlocate/mlocate.db "数据库,因为 locate 命令就是通过这个数据库查找的。这个数据库由系统每天定时维护更新,所以有时候需要手动执行 updatedb 命令来更新数据库。
例如,查找 /usr 及其子目录下所有以 a 开头的文件:
$ locate /usr/a
find
find命令是一个功能非常强大的命令,它可以根据文件的各个属性来搜索,在此只介绍其简单的搜索。其基本命令格式为:
find [path] [option] [action]
例如,在 /usr/ 目录下搜索名字为 myfile 的文件或目录:
$ sudo find /usr/ -name myfile
文件解压缩
rar
rar是一种在windows常见的文件压缩格式,但是在linux下必须先安装才能使用。由于在linux中rar命令参数非常多,在此只介绍一些基本操作。
1)创建压缩文件:
rar a ehpc.rar ./Desktop/
这是将ehpc目录打包成ehpc.rar
2)使用 a 参数添加文件进压缩包:
rar a ehpc.rar file
3)使用 d 参数删除文件:
rar d ehpc.rar file
4)使用 l 参数查看文件:
rar l ehpc.rar
5)解压分为两种,一种是 x 参数解压,这样会保持压缩文件的目录结构;另一种是 e 参数解压,将所有文件解压到当前目录:
unrar x ehpc.rar
unrar e ehpc.rar
yang@yang-virtual-machine:~$ rar a test.rar ./test/
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Evaluation copy. Please register.
Creating archive test.rar
Adding ./test/input.txt OK
Adding ./test/test9.sh OK
Adding ./test/test7.sh OK
Adding ./test/test5.sh OK
Adding ./test/test4.sh OK
Adding ./test/test6.sh OK
Adding ./test/test3.sh OK
Adding ./test/hhhhh.txt OK
Adding ./test/noname2.txt OK
Adding ./test/test.sh OK
Adding ./test/output.txt OK
Adding ./test/test1.sh OK
Adding ./test/test2.sh OK
Adding ./test/input OK
Adding ./test/test8.sh OK
Done
yang@yang-virtual-machine:~$ ls
公共的 视频 文档 音乐 hanshushuru.sh huiwenzhishu.cpp test yang
模板 图片 下载 桌面 huiwenzhishu snap test.rar
yang@yang-virtual-machine:~$ rar l test.rar
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Archive: test.rar
Details: RAR 5
Attributes Size Date Time Name
----------- --------- ---------- ----- ----
-rw-rw-r-- 4 2022-12-05 22:50 test/input.txt
-rwxr-xr-x 48 2022-12-05 22:50 test/test9.sh
-rwxrwxr-x 204 2022-12-05 22:50 test/test7.sh
-rwxrwxr-x 134 2022-12-05 22:50 test/test5.sh
-rwxr-xr-x 126 2022-12-05 22:50 test/test4.sh
-rwxrwxr-x 76 2022-12-05 22:50 test/test6.sh
-rwxrwxr-x 213 2022-12-05 22:50 test/test3.sh
-rw-rw-r-- 0 2022-12-05 23:07 test/hhhhh.txt
-rw-rw-r-- 53 2022-12-06 15:39 test/noname2.txt
-rwxrwxr-x 53 2022-12-05 22:50 test/test.sh
-rw-rw-r-- 2 2022-12-05 22:50 test/output.txt
-rwxrwxrwx 107 2022-12-05 22:50 test/test1.sh
-rwxrwxr-x 37 2022-12-05 22:50 test/test2.sh
-rw-rw-r-- 4 2022-12-05 22:50 test/input
-rw-rw-r-- 24 2022-12-05 22:50 test/test8.sh
----------- --------- ---------- ----- ----
1085 15
yang@yang-virtual-machine:~$ rar d test.rar test/input
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Deleting from test.rar
Deleting test/input
Done
yang@yang-virtual-machine:~$ rar l test.rar
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Archive: test.rar
Details: RAR 5
Attributes Size Date Time Name
----------- --------- ---------- ----- ----
-rw-rw-r-- 4 2022-12-05 22:50 test/input.txt
-rwxr-xr-x 48 2022-12-05 22:50 test/test9.sh
-rwxrwxr-x 204 2022-12-05 22:50 test/test7.sh
-rwxrwxr-x 134 2022-12-05 22:50 test/test5.sh
-rwxr-xr-x 126 2022-12-05 22:50 test/test4.sh
-rwxrwxr-x 76 2022-12-05 22:50 test/test6.sh
-rwxrwxr-x 213 2022-12-05 22:50 test/test3.sh
-rw-rw-r-- 0 2022-12-05 23:07 test/hhhhh.txt
-rw-rw-r-- 53 2022-12-06 15:39 test/noname2.txt
-rwxrwxr-x 53 2022-12-05 22:50 test/test.sh
-rw-rw-r-- 2 2022-12-05 22:50 test/output.txt
-rwxrwxrwx 107 2022-12-05 22:50 test/test1.sh
-rwxrwxr-x 37 2022-12-05 22:50 test/test2.sh
-rw-rw-r-- 24 2022-12-05 22:50 test/test8.sh
----------- --------- ---------- ----- ----
1081 14
yang@yang-virtual-machine:~$ rar a test.rar ./test/input
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Evaluation copy. Please register.
Updating archive test.rar
Adding ./test/input OK
Done
yang@yang-virtual-machine:~$ rar l test.rar
RAR 5.50 Copyright (c) 1993-2017 Alexander Roshal 11 Aug 2017
Trial version Type 'rar -?' for help
Archive: test.rar
Details: RAR 5
Attributes Size Date Time Name
----------- --------- ---------- ----- ----
-rw-rw-r-- 4 2022-12-05 22:50 test/input.txt
-rwxr-xr-x 48 2022-12-05 22:50 test/test9.sh
-rwxrwxr-x 204 2022-12-05 22:50 test/test7.sh
-rwxrwxr-x 134 2022-12-05 22:50 test/test5.sh
-rwxr-xr-x 126 2022-12-05 22:50 test/test4.sh
-rwxrwxr-x 76 2022-12-05 22:50 test/test6.sh
-rwxrwxr-x 213 2022-12-05 22:50 test/test3.sh
-rw-rw-r-- 0 2022-12-05 23:07 test/hhhhh.txt
-rw-rw-r-- 53 2022-12-06 15:39 test/noname2.txt
-rwxrwxr-x 53 2022-12-05 22:50 test/test.sh
-rw-rw-r-- 2 2022-12-05 22:50 test/output.txt
-rwxrwxrwx 107 2022-12-05 22:50 test/test1.sh
-rwxrwxr-x 37 2022-12-05 22:50 test/test2.sh
-rw-rw-r-- 24 2022-12-05 22:50 test/test8.sh
-rw-rw-r-- 4 2022-12-05 22:50 test/input
----------- --------- ---------- ----- ----
1085 15
zip
zip也是在windows和linux使用率比较高的文件压缩格式。
1)创建压缩包:
zip -r -o ehpc.zip ./Desktop
其中,-r 参数表示递归,所以上面命令是打包ehpc目录进压缩包;-o 参数表示输出到ehpc.zip压缩文件。
2)使用 -e 参数进行加密:
zip -r -e -o ehpc.zip ./Desktop
需要注意的是,由于编码问题linux下和windows下的文本文件可能会不同,如果希望在linux压缩的文件在windows下正常解压,可以加上 -l 参数。
3)查看与解压
解压很简单:
unzip ehpc.zip
查看只需加上 -l 参数:
unzip -l ehpc.zip
“.zip” 格式压缩命令:
zip [选项] 压缩包名 源文件或源目录
选项:
-r
:压缩目录[root@hepingfly hepingfly]# zip mytxt.zip abc.txt abd.txt bcd.txt adding: abc.txt (deflated 6%) adding: abd.txt (stored 0%) adding: bcd.txt (stored 0%) # 把三个 txt 文件压缩成一个 zip 文件
“.zip” 格式解压缩命令:
unzip [选项] 压缩包名
选项:
-d
:指定解压缩位置
yang@yang-virtual-machine:~$ zip -r -o test.zip ./test
adding: test/ (stored 0%)
adding: test/input.txt (stored 0%)
adding: test/test9.sh (deflated 4%)
adding: test/test7.sh (deflated 22%)
adding: test/test5.sh (deflated 28%)
adding: test/test4.sh (deflated 25%)
adding: test/test6.sh (deflated 22%)
adding: test/test3.sh (deflated 52%)
adding: test/hhhhh.txt (stored 0%)
adding: test/noname2.txt (deflated 8%)
adding: test/test.sh (deflated 8%)
adding: test/output.txt (stored 0%)
adding: test/test1.sh (deflated 16%)
adding: test/test2.sh (deflated 11%)
adding: test/input (stored 0%)
adding: test/test8.sh (stored 0%)
yang@yang-virtual-machine:~$ unzip -l test.zip
Archive: test.zip
Length Date Time Name
--------- ---------- ----- ----
0 2022-12-07 11:07 test/
4 2022-12-05 22:50 test/input.txt
48 2022-12-05 22:50 test/test9.sh
204 2022-12-05 22:50 test/test7.sh
134 2022-12-05 22:50 test/test5.sh
126 2022-12-05 22:50 test/test4.sh
76 2022-12-05 22:50 test/test6.sh
213 2022-12-05 22:50 test/test3.sh
0 2022-12-05 23:07 test/hhhhh.txt
53 2022-12-06 15:39 test/noname2.txt
53 2022-12-05 22:50 test/test.sh
2 2022-12-05 22:50 test/output.txt
107 2022-12-05 22:50 test/test1.sh
37 2022-12-05 22:50 test/test2.sh
4 2022-12-05 22:50 test/input
24 2022-12-05 22:50 test/test8.sh
--------- -------
1085 16 files
yang@yang-virtual-machine:~$ zip -r test1.zip ./test/
adding: test/ (stored 0%)
adding: test/input.txt (stored 0%)
adding: test/test9.sh (deflated 4%)
adding: test/test7.sh (deflated 22%)
adding: test/test5.sh (deflated 28%)
adding: test/test4.sh (deflated 25%)
adding: test/test6.sh (deflated 22%)
adding: test/test3.sh (deflated 52%)
adding: test/hhhhh.txt (stored 0%)
adding: test/noname2.txt (deflated 8%)
adding: test/test.sh (deflated 8%)
adding: test/output.txt (stored 0%)
adding: test/test1.sh (deflated 16%)
adding: test/test2.sh (deflated 11%)
adding: test/input (stored 0%)
adding: test/test8.sh (stored 0%)
yang@yang-virtual-machine:~$ ls
公共的 图片 音乐 huiwenzhishu test yang
模板 文档 桌面 huiwenzhishu.cpp test1.zip
视频 下载 hanshushuru.sh snap test.zip
yang@yang-virtual-machine:~$ unzip -d ./test test.zip
Archive: test.zip
creating: ./test/test/
extracting: ./test/test/input.txt
inflating: ./test/test/test9.sh
inflating: ./test/test/test7.sh
inflating: ./test/test/test5.sh
inflating: ./test/test/test4.sh
inflating: ./test/test/test6.sh
inflating: ./test/test/test3.sh
extracting: ./test/test/hhhhh.txt
inflating: ./test/test/noname2.txt
inflating: ./test/test/test.sh
extracting: ./test/test/output.txt
inflating: ./test/test/test1.sh
inflating: ./test/test/test2.sh
extracting: ./test/test/input
extracting: ./test/test/test8.sh
yang@yang-virtual-machine:~$ ls
公共的 图片 音乐 huiwenzhishu test yang
模板 文档 桌面 huiwenzhishu.cpp test1.zip
视频 下载 hanshushuru.sh snap test.zip
yang@yang-virtual-machine:~$ ls ./test
hhhhh.txt noname2.txt test1.sh test4.sh test7.sh test.sh
input output.txt test2.sh test5.sh test8.sh
input.txt test test3.sh test6.sh test9.sh
yang@yang-virtual-machine:~$ ls ./test/test
hhhhh.txt noname2.txt test2.sh test5.sh test8.sh
input output.txt test3.sh test6.sh test9.sh
input.txt test1.sh test4.sh test7.sh test.sh
tar
实际上,在linux中用得更多的是tar工具。tar 原本只是一个打包工具,没有压缩功能,需要配合其他具有压缩功能而没有打包功能的工具进行打包压缩。
1)创建一个 tar 包:
tar -cf ehpc.tar ./Desktop
其中,-c 参数表示创建,-f 参数表示指定文件名,必须跟在文件名之前。
可以发现这个tar包和原大小相同。
2)查看一个 tar 包:
tar -tf ehpc.tar
3)解包一个 tar 包到指定目录:
tar -xf ehpc.tar -C ehpcdir
上面我们说了tar需要配合其他工具进行压缩,其实一般只需要加一个参数就可以了。这里以gzip为例:
tar -czf ehpc.tar.gz ./
解压缩:
tar -xzf ehpc.tar.gz
tar 命令参数还有很多,在此仅作简单介绍。可以通过man手册查看更多帮助。
更好理解:
“.tar” 格式的打包和解打包都使用 tar 命令,区别只是选项不同。打包不压缩
“.tar” 格式打包命令:
tar [选项] [-f 压缩包名] 源文件或目录
选项:
-c
:打包
-f
:指定压缩包的文件名。压缩包的扩展名是用来给管理员识别格式的,所以一定要正确指定扩展名。
-v
:显示打包文件过程“.tar” 格式解打包命令:
tar [选项] 压缩包
选项:
-x
:解打包
-f
:指定压缩包的文件名
-v
:显示解打包文件过程
yang@yang-virtual-machine:~$ tar -cvf test.tar ./test
./test/
./test/input.txt
./test/test9.sh
./test/test7.sh
./test/test5.sh
./test/test4.sh
./test/test6.sh
./test/test3.sh
./test/hhhhh.txt
./test/noname2.txt
./test/test.sh
./test/output.txt
./test/test1.sh
./test/test2.sh
./test/input
./test/test8.sh
yang@yang-virtual-machine:~$ ls
公共的 视频 文档 音乐 hanshushuru.sh huiwenzhishu.cpp test yang
模板 图片 下载 桌面 huiwenzhishu snap test.tar
yang@yang-virtual-machine:~$ tar -xfv test.tar ./test
tar: v:无法 open: 没有那个文件或目录
tar: Error is not recoverable: exiting now
yang@yang-virtual-machine:~$ tar -xvf test.tar ./test
./test/
./test/input.txt
./test/test9.sh
./test/test7.sh
./test/test5.sh
./test/test4.sh
./test/test6.sh
./test/test3.sh
./test/hhhhh.txt
./test/noname2.txt
./test/test.sh
./test/output.txt
./test/test1.sh
./test/test2.sh
./test/input
./test/test8.sh
yang@yang-virtual-machine:~$ ls
公共的 视频 文档 音乐 hanshushuru.sh huiwenzhishu.cpp test yang
模板 图片 下载 桌面 huiwenzhishu snap test.tar
yang@yang-virtual-machine:~$ ls ./test
hhhhh.txt noname2.txt test2.sh test5.sh test8.sh
input output.txt test3.sh test6.sh test9.sh
input.txt test1.sh test4.sh test7.sh test.sh
管道与一些文本命令
管道是一种通信机制,它可以将前一个进程的输出作为下一个进程的输入。所以它常常用来进行进程间(也包括socket进行网络通信)的通信。不过,在这里我们首先介绍一些linux终端执行命令的知识。
&& 和 ||
当我们希望同时输入多条命令时,可能还希望对某几个命令的结果进行判断。例如,如果存在某个文件,就把它删除,如果不存在则什么也不做。而 && 和 || 就提供了这种判断的功能。
&& 表示如果前一个命令返回的状态为0(这些状态码有一套默认的规定),则执行后一个命令,否则不执行。而 || 则与之相反。
例如我们常常使用 which 命令来判断是否安装了某个命令:
which rar>/dev/null && echo "Installed."
当然也可以结合使用:
which rar>/dev/null && echo "Installed." || echo "Not installed"
which vim>/dev/null && echo "Installed." || echo "Not installed"
可以将/dev/null看作"黑洞". 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到. 然而, /dev/null对命令行和脚本都非常的有用.
用处:
禁止标准输出. 1 cat $filename >/dev/null # 文件内容丢失,而不会输出到标准输出.
禁止标准错误. 2>/dev/null 这样错误信息[标准错误]就被丢到太平洋去了.
管道
通常我们在命令行中使用匿名管道,由分隔符 | 表示,而命名管道更常出现在源代码中。
例如:
ls -a | grep mysql
这个命令就是先执行 ls -a 命令,然后将输出结果作为输入执行grep mysql命令在其中查找包含mysql的文件。
下面介绍几个常用的命令,配合管道使用可以提高效率。
1) grep :
一个很常用的命令。使用者可以通过其与正则表达式配合实现很高效的查找,不过在这里先简单介绍一下。
在上面我们已经有一个使用 grep 命令的例子了,实际上我们还可以直接使用:
grep -r "ehpc" ~
搜索 ~ 目录下所有包含"ehpc"的文件。
2) wc :
统计并输出一个文件中行、字节等数据的数目。其中,-l 参数表示行数,-c 参数表示字节数。
结合管道使用,统计文件的个数:
ls -a | wc -l
3) uniq :
在上面的统计中,我们可能会想要除去一些重复行以免影响结果,这时候我们可以使用 uniq 命令:
cat words | uniq
值得注意的是,uniq只除去连续重复的的行,如果希望全文达到同样的效果我们往往会先使用 sort 命令进行排序,即:
cat words | sort | uniq
Linux uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用。
uniq 可检查文本文件中重复出现的行列。
语法
uniq [-cdu][-f<栏位>][-s<字符位置>][-w<字符位置>][--help][--version][输入文件][输出文件]
参数:
- -c或–count 在每列旁边显示该行重复出现的次数。
- -d或–repeated 仅显示重复出现的行列。
- -f<栏位>或–skip-fields=<栏位> 忽略比较指定的栏位。
- -s<字符位置>或–skip-chars=<字符位置> 忽略比较指定的字符。
- -u或–unique 仅显示出一次的行列。
- -w<字符位置>或–check-chars=<字符位置> 指定要比较的字符。
- –help 显示帮助。
- –version 显示版本信息。
- [输入文件] 指定已排序好的文本文件。如果不指定此项,则从标准读取数据;
- [输出文件] 指定输出的文件。如果不指定此选项,则将内容显示到标准输出设备(显示终端)。
Linux sort 命令用于将文本文件内容加以排序。
sort 可针对文本文件的内容,以行为单位来排序。
语法
sort [-bcdfimMnr][-o<输出文件>][-t<分隔字符>][+<起始栏位>-<结束栏位>][--help][--verison][文件][-k field1[,field2]]
参数说明:
- -b 忽略每行前面开始出的空格字符。
- -c 检查文件是否已经按照顺序排序。
- -d 排序时,处理英文字母、数字及空格字符外,忽略其他的字符。
- -f 排序时,将小写字母视为大写字母。
- -i 排序时,除了040至176之间的ASCII字符外,忽略其他的字符。
- -m 将几个排序好的文件进行合并。
- -M 将前面3个字母依照月份的缩写进行排序。
- -n 依照数值的大小排序。
- -u 意味着是唯一的(unique),输出的结果是去完重了的。
- -o<输出文件> 将排序后的结果存入指定的文件。
- -r 以相反的顺序来排序。
- -t<分隔字符> 指定排序时所用的栏位分隔字符。
- +<起始栏位>-<结束栏位> 以指定的栏位来排序,范围由起始栏位到结束栏位的前一栏位。
- –help 显示帮助。
- –version 显示版本信息。
- [-k field1[,field2]] 按指定的列进行排序。
文本处理
sort
在之前出现过很多次的命令,顾名思义它的功能是排序。当然,它可以根据不同的标准来排序,例如:
默认为字典排序:
ls -a | sort
反转排序:
ls -a | sort -r
yang@yang-virtual-machine:~$ ls -a | sort
.
..
123
公共的
模板
视频
图片
文档
下载
音乐
桌面
.bash_history
.bash_logout
.bashrc
.cache
.config
hanshushuru.sh
input
input.txt
.lesshst
.local
output.txt
.profile
snap
.sudo_as_admin_successful
test1
test1.sh
test2.sh
test3.sh
test4.sh
test5.sh
test6.sh
test7.sh
test8.sh
test9.sh
test.sh
.viminfo
yang@yang-virtual-machine:~$ ls -a
. 下载 hanshushuru.sh .sudo_as_admin_successful test7.sh
.. 音乐 input test1 test8.sh
123 桌面 input.txt test1.sh test9.sh
公共的 .bash_history .lesshst test2.sh test.sh
模板 .bash_logout .local test3.sh .viminfo
视频 .bashrc output.txt test4.sh
图片 .cache .profile test5.sh
文档 .config snap test6.sh
yang@yang-virtual-machine:~$ ls -a | sort -r
.viminfo
test.sh
test9.sh
test8.sh
test7.sh
test6.sh
test5.sh
test4.sh
test3.sh
test2.sh
test1.sh
test1
.sudo_as_admin_successful
snap
.profile
output.txt
.local
.lesshst
input.txt
input
hanshushuru.sh
.config
.cache
.bashrc
.bash_logout
.bash_history
桌面
音乐
下载
文档
图片
视频
模板
公共的
123
..
.
col
相信许多程序员在实际中都会遇到类似于将程序代码中的tab转空格的需要,而linux提供了tab和空格相互转换的命令 col。
在这里,-x 参数表示将 tab 转换成空格,而 -h 参数则相反。
例如:
cat myFile | col -x | cat -A
tr
替换操作(删除操作也可以视为一种替换操作)也是文本处理常用的操作之一。
如果是要删除,可以使用 -d 参数:
echo "Hello world!" | tr -d "el"
这样会删除"Hello world!"中所有的“e”和“l”。
再例如将小写转换成大写:
echo "Hello world!" | tr '[a-z]' '[A-Z]'
paste
这个命令可以简单地合并文件。(将文件合并后输出,不改变文件)
例如将数据以 ‘;’ 为分隔符合并(默认的分隔符为Tab):
paste -d ';' data1 data2 data3
重定向
将标准输出、标准错误等信息输出到指定文件中,就是重定向。
重定向
重定向是通过 ‘>’ 和 ‘>>’ 等操作符完成的,(当然也有’<‘和’<<’,前者是覆盖,后者是追加),其实将标准输出看作一个文件的话,将命令输出导向到另一个文件自然也是没问题的。
例如:
echo “Hello world!” > output
结合管道:
cat words | sort | uniq >> output
文件描述符
除了标准输出,我们还经常需要重定向标准错误,在此就必须提到标准输入、标准输出和标准错误的文件描述符。在linux中,它们的文件描述符分别是0、1、2,我们可以通过这几个描述符来完成我们想要的操作。
我们可以这样来将标准输出和标准错误重定向到同一个文件:
cat words | sort | uniq > output 2>&1
其中,&表示后面的是标准输出而不是一个文件名为1的文件,而这里的重定向顺序也是不能改变的。
也可以这么做:
cat words | sort | uniq &> output
永久重定向以及“丢弃”输出
我们很容易想到如果我们想不断将标准输出重定向到某个文件,难道需要在每一个命令后面加上重定向命令?当然是不需要的,linux提供了永久重定向的方法。当然,这里的永久也并不是那么永久。
我们可以这样做:
exec 1> output
其中 exec 命令的作用是用新的进程去替换旧的进程,或者指定重定向。
有时候我们仅仅希望执行命令而不想要其输出,这时候我们可以将输出重定向到空设备 **/dev/null **:
cat words | sort | uniq 1>/dev/null 2>&1
这样输出结果就没有啦。
进程的基本操作
前台/后台切换
我们在之前的学习中已经知道终止一个在前台运行的进程的快捷键是 ctrl + c 。同样,我们在之前也已经知道将我们当前进程停止并转到后台的快捷键是 ctrl + z。那么,如何让我们的进程在前台与后台之间切换呢?
我们可以通过 & 这个符号,让我们的命令在后台中运行。
例如:
ls &
这样命令就会在后台自己运行了。
那么当我们如何查看在后台的工作呢?
可以使用:
jobs
这时我们可以看到每行是这样的格式:
[1] + suspended ...(command)
其中,第一列的数字表示job编号,也就是转到后台的工作的编号,第二列如果是 ‘+’ 表示的是这是最后一个被转入后台的工作, ‘-’ 的话则是倒数第二个,其他的话在这列没有符号。第三列表示状态,而后面则是命令本身。
那么我们突然想要把工作从后台拿回前台怎么办呢?
可以使用:
fg %jobid
例如, fg %1
如果只是希望其在后台运行的话,可以:
bg %jobid
终止
终止命令比较简单,但是在参数上我们可以通过选择信号值来决定以何种方式终止程序,信号值可以这样查看:
kill -l
所以可以这样终止程序:
kill -signal pid
或者
kill -signal %jobid
kill语法
kill [-s <信息名称或编号>][程序] 或 kill [-l <信息编号>]
参数说明:
- -l <信息编号> 若不加<信息编号>选项,则 -l 参数会列出全部的信息名称。
- -s <信息名称或编号> 指定要送出的信息。
- [程序] [程序]可以是程序的PID或是PGID,也可以是工作编号。
使用 kill -l 命令列出所有可用信号。
最常用的信号是:
- 1 (HUP):重新加载进程。
- 9 (KILL):杀死一个进程。
- 15 (TERM):正常停止一个进程。
实例
杀死进程
# kill 12345
强制杀死进程
# kill -KILL 123456
发送SIGHUP信号,可以使用一下信号
# kill -HUP pid
彻底杀死进程
# kill -9 123456
显示信号
# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
杀死指定用户所有进程
#kill -9 $(ps -ef | grep hnlinux) //方法一 过滤出hnlinux用户进程 #kill -u hnlinux //方法二
进程管理
top
top 命令是我们常常使用查看工具,它可以实时查看系统的一些关键信息的变化。
top 命令的输出比较多,下面逐一介绍:
第一行:
当前程序名称 当前系统时间 机器启动时间 系统用户数量 1分钟内、5分钟内和15分钟内cpu平均负载
第二行:
进程总数 正在运行的进程数 休眠的进程数 停止的进程数 僵尸进程数
第三行:
- 用户空间占用CPU百分比
- 内核空间占用CPU百分比
- 用户空间优先级变化的进程占用CPU百分比
- 空闲CPU百分比
- 等待IO的CPU时间百分比
- 硬中断占用CPU的百分比
- 软中断占用CPU的百分比
- 虚拟 CPU 等待物理 CPU 的时间的百分比
第四行:
- 物理内存总量
- 使用物理内存总量
- 空闲内存总量
- 缓存内存总量
第五行:
- 交换区总量
- 使用交换区总量
- 空闲交换区总量
- 缓冲交换区总量
然后就是许多行进程的信息了,以下按顺序分别对应:
- PID:进程id
- USER:进程所属用户
- PR:进程动态优先级值
- NI:进程静态优先级值
- VIRT:进程使用虚拟内存总数
- RES:进程使用物理内存数
- SHR:进程共享内存大小
- S:进程状态
- %CPU:CPU利用率
- %MEM:内存利用率
- TIME+:进程活跃总时间
- COMMAND:进程运行名
我们甚至可以与这个程序交互,例如输入k的话系统会提示进一步输入信号值以及pid号以杀死一个进程,更多的信息可以查看帮助手册。
ehpc@2f13360ae39d:~/Desktop$ top
top - 20:09:10 up 384 days, 3:41, 0 users, load average: 0.24, 0.15, 0.06
Tasks: 48 total, 1 running, 47 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.1 sy, 0.0 ni, 99.5 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32874740 total, 13129796 free, 2178640 used, 17566304 buff/cache
KiB Swap: 969960 total, 968728 free, 1232 used. 30313000 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
70 xrdp 20 0 39144 14724 4660 S 2.3 0.0 0:39.80 xrdp
73 ehpc 20 0 1560664 76424 38220 S 0.7 0.2 0:11.02 Xorg
325 ehpc 20 0 220776 6916 6212 S 0.3 0.0 0:00.22 at-spi2-+
345 ehpc 20 0 1616460 39532 29664 S 0.3 0.1 0:00.58 mate-set+
354 ehpc 20 0 588460 36092 26784 S 0.3 0.1 0:01.02 marco
375 ehpc 20 0 578460 37944 28512 S 0.3 0.1 0:00.40 mate-pan+
411 ehpc 20 0 571264 37728 28612 S 0.3 0.1 0:00.37 wnck-app+
1 root 20 0 18372 3224 2952 S 0.0 0.0 0:00.04 bash
27 root 20 0 72296 3412 2672 S 0.0 0.0 0:00.00 sshd
55 root 20 0 67752 3896 3216 S 0.0 0.0 0:00.00 xrdp-ses+
60 xrdp 20 0 25460 2404 1812 S 0.0 0.0 0:00.00 xrdp
65 root 20 0 18504 3256 2964 S 0.0 0.0 0:00.00 bash
[1]+ Stopped top
(这个命令进行了,机子很卡)
ps
你一定经常看见 ps aux
这个命令将会列出所有的进程信息。
我们还往往配合 grep 和正则表达式使用。
例如:
ps aux | grep slurm
那么,打印出来的都是什么信息呢?
- F:进程的标志(process flags),当 flags 值为 1 则表示此子程序只是 fork 但没有执行 exec,为 4 表示此程序使用 root 权限
- USER:进程拥有者
- PID:进程ID
- PPID:父进程的PID
- SID:session 的ID
- TPGID:前台进程组的ID
- %CPU:进程占用的CPU百分比
- %MEM:占用内存的百分比
- NI:进程的 NICE 值
- VSZ:进程使用虚拟内存大小
- RSS:驻留内存中页的大小
- TTY:终端ID
- S or STAT:进程状态
- WCHAN:正在等待的进程资源
- START :启动进程的时间
- TIME:进程消耗CPU的时间
- COMMAND:命令的名称和参数
我们还可以用这样的命令去查看进程树:
pstree
ehpc@2f13360ae39d:~/Desktop$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18372 3224 pts/0 Ss 19:50 0:00 bash /bin/sta
root 27 0.0 0.0 72296 3412 ? Ss 19:50 0:00 /usr/sbin/ssh
root 55 0.0 0.0 67752 3896 pts/0 S 19:50 0:00 /usr/sbin/xrd
xrdp 60 0.0 0.0 25460 2404 pts/0 S 19:50 0:00 /usr/sbin/xrd
root 65 0.0 0.0 18504 3256 pts/0 S+ 19:50 0:00 bash
xrdp 70 3.2 0.0 39144 14724 pts/0 S 19:51 0:23 /usr/sbin/xrd
root 71 0.0 0.0 67752 3184 pts/0 S 19:51 0:00 /usr/sbin/xrd
ehpc 72 0.0 0.0 11796 3132 pts/0 S 19:51 0:00 /bin/bash /ho
ehpc 73 0.8 0.2 1560664 76672 pts/0 Sl 19:51 0:06 /usr/lib/xorg
ehpc 97 0.0 0.0 125236 3744 pts/0 Sl 19:51 0:00 /usr/sbin/xrd
ehpc 114 0.0 0.0 45840 2388 pts/0 S 19:51 0:00 dbus-launch -
ehpc 115 0.0 0.0 49792 2860 ? Ss 19:51 0:00 /usr/bin/dbus
ehpc 204 0.0 0.0 45840 2284 pts/0 S 19:51 0:00 /usr/bin/dbus
ehpc 205 0.0 0.0 50408 4032 ? Ss 19:51 0:00 /usr/bin/dbus
ehpc 214 0.0 0.0 11300 320 ? Ss 19:51 0:00 /usr/bin/ssh-
ehpc 289 0.0 0.1 1808608 53284 pts/0 Sl 19:51 0:00 mate-session
ehpc@2f13360ae39d:~/Desktop$ ps aux | grep slurm
ehpc 580 0.0 0.0 13340 1064 pts/1 S+ 20:03 0:00 grep --color=auto slurm
ehpc@2f13360ae39d:~/Desktop$ pstree
bash─┬─at-spi-bus-laun─┬─dbus-daemon
│ └─3*[{at-spi-bus-laun}]
├─at-spi2-registr───2*[{at-spi2-registr}]
├─bash
├─brisk-menu───3*[{brisk-menu}]
├─clock-applet───3*[{clock-applet}]
├─2*[dbus-daemon]
├─2*[dbus-launch]
├─dconf-service───2*[{dconf-service}]
├─gvfs-afc-volume───3*[{gvfs-afc-volume}]
├─gvfs-goa-volume───2*[{gvfs-goa-volume}]
├─gvfs-gphoto2-vo───2*[{gvfs-gphoto2-vo}]
├─gvfs-mtp-volume───2*[{gvfs-mtp-volume}]
├─gvfs-udisks2-vo───2*[{gvfs-udisks2-vo}]
├─gvfsd─┬─gvfsd-trash───2*[{gvfsd-trash}]
│ └─2*[{gvfsd}]
├─gvfsd-metadata───2*[{gvfsd-metadata}]
├─mate-indicator-───3*[{mate-indicator-}]
├─mate-screensave───3*[{mate-screensave}]
├─mate-terminal─┬─bash───pstree
│ └─4*[{mate-terminal}]
├─notification-ar───3*[{notification-ar}]
├─pulseaudio───{pulseaudio}
├─sshd
├─trashapplet───3*[{trashapplet}]
├─wnck-applet───3*[{wnck-applet}]
├─xrdp───xrdp
└─xrdp-sesman───xrdp-sesman─┬─Xorg───17*[{Xorg}]
├─bash─┬─mate-session─┬─caja───3*[{caja}]
│ │ ├─indicator-appli───2*[{+
│ │ ├─indicator-power───3*[{+
│ │ ├─indicator-sessi───3*[{+
│ │ ├─marco───3*[{marco}]
│ │ ├─mate-maximus───3*[{mat+
│ │ ├─mate-panel───3*[{mate-+
│ │ ├─mate-settings-d───4*[{+
│ │ ├─nm-applet───3*[{nm-app+
│ │ └─19*[{mate-session}]
│ └─ssh-agent
└─xrdp-chansrv───{xrdp-chansrv}
使用 kill -l 命令列出所有可用信号。
最常用的信号是:
- 1 (HUP):重新加载进程。
- 9 (KILL):杀死一个进程。
- 15 (TERM):正常停止一个进程。
实例
杀死进程
# kill 12345
强制杀死进程
# kill -KILL 123456
发送SIGHUP信号,可以使用一下信号
# kill -HUP pid
彻底杀死进程
# kill -9 123456
显示信号
# kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
杀死指定用户所有进程
#kill -9 $(ps -ef | grep hnlinux) //方法一 过滤出hnlinux用户进程 #kill -u hnlinux //方法二
进程管理
top
top 命令是我们常常使用查看工具,它可以实时查看系统的一些关键信息的变化。
top 命令的输出比较多,下面逐一介绍:
第一行:
当前程序名称 当前系统时间 机器启动时间 系统用户数量 1分钟内、5分钟内和15分钟内cpu平均负载
第二行:
进程总数 正在运行的进程数 休眠的进程数 停止的进程数 僵尸进程数
第三行:
- 用户空间占用CPU百分比
- 内核空间占用CPU百分比
- 用户空间优先级变化的进程占用CPU百分比
- 空闲CPU百分比
- 等待IO的CPU时间百分比
- 硬中断占用CPU的百分比
- 软中断占用CPU的百分比
- 虚拟 CPU 等待物理 CPU 的时间的百分比
第四行:
- 物理内存总量
- 使用物理内存总量
- 空闲内存总量
- 缓存内存总量
第五行:
- 交换区总量
- 使用交换区总量
- 空闲交换区总量
- 缓冲交换区总量
然后就是许多行进程的信息了,以下按顺序分别对应:
- PID:进程id
- USER:进程所属用户
- PR:进程动态优先级值
- NI:进程静态优先级值
- VIRT:进程使用虚拟内存总数
- RES:进程使用物理内存数
- SHR:进程共享内存大小
- S:进程状态
- %CPU:CPU利用率
- %MEM:内存利用率
- TIME+:进程活跃总时间
- COMMAND:进程运行名
我们甚至可以与这个程序交互,例如输入k的话系统会提示进一步输入信号值以及pid号以杀死一个进程,更多的信息可以查看帮助手册。
ehpc@2f13360ae39d:~/Desktop$ top
top - 20:09:10 up 384 days, 3:41, 0 users, load average: 0.24, 0.15, 0.06
Tasks: 48 total, 1 running, 47 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.1 sy, 0.0 ni, 99.5 id, 0.1 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 32874740 total, 13129796 free, 2178640 used, 17566304 buff/cache
KiB Swap: 969960 total, 968728 free, 1232 used. 30313000 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
70 xrdp 20 0 39144 14724 4660 S 2.3 0.0 0:39.80 xrdp
73 ehpc 20 0 1560664 76424 38220 S 0.7 0.2 0:11.02 Xorg
325 ehpc 20 0 220776 6916 6212 S 0.3 0.0 0:00.22 at-spi2-+
345 ehpc 20 0 1616460 39532 29664 S 0.3 0.1 0:00.58 mate-set+
354 ehpc 20 0 588460 36092 26784 S 0.3 0.1 0:01.02 marco
375 ehpc 20 0 578460 37944 28512 S 0.3 0.1 0:00.40 mate-pan+
411 ehpc 20 0 571264 37728 28612 S 0.3 0.1 0:00.37 wnck-app+
1 root 20 0 18372 3224 2952 S 0.0 0.0 0:00.04 bash
27 root 20 0 72296 3412 2672 S 0.0 0.0 0:00.00 sshd
55 root 20 0 67752 3896 3216 S 0.0 0.0 0:00.00 xrdp-ses+
60 xrdp 20 0 25460 2404 1812 S 0.0 0.0 0:00.00 xrdp
65 root 20 0 18504 3256 2964 S 0.0 0.0 0:00.00 bash
[1]+ Stopped top
(这个命令进行了,机子很卡)
ps
你一定经常看见 ps aux
这个命令将会列出所有的进程信息。
我们还往往配合 grep 和正则表达式使用。
例如:
ps aux | grep slurm
那么,打印出来的都是什么信息呢?
- F:进程的标志(process flags),当 flags 值为 1 则表示此子程序只是 fork 但没有执行 exec,为 4 表示此程序使用 root 权限
- USER:进程拥有者
- PID:进程ID
- PPID:父进程的PID
- SID:session 的ID
- TPGID:前台进程组的ID
- %CPU:进程占用的CPU百分比
- %MEM:占用内存的百分比
- NI:进程的 NICE 值
- VSZ:进程使用虚拟内存大小
- RSS:驻留内存中页的大小
- TTY:终端ID
- S or STAT:进程状态
- WCHAN:正在等待的进程资源
- START :启动进程的时间
- TIME:进程消耗CPU的时间
- COMMAND:命令的名称和参数
我们还可以用这样的命令去查看进程树:
pstree
ehpc@2f13360ae39d:~/Desktop$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 18372 3224 pts/0 Ss 19:50 0:00 bash /bin/sta
root 27 0.0 0.0 72296 3412 ? Ss 19:50 0:00 /usr/sbin/ssh
root 55 0.0 0.0 67752 3896 pts/0 S 19:50 0:00 /usr/sbin/xrd
xrdp 60 0.0 0.0 25460 2404 pts/0 S 19:50 0:00 /usr/sbin/xrd
root 65 0.0 0.0 18504 3256 pts/0 S+ 19:50 0:00 bash
xrdp 70 3.2 0.0 39144 14724 pts/0 S 19:51 0:23 /usr/sbin/xrd
root 71 0.0 0.0 67752 3184 pts/0 S 19:51 0:00 /usr/sbin/xrd
ehpc 72 0.0 0.0 11796 3132 pts/0 S 19:51 0:00 /bin/bash /ho
ehpc 73 0.8 0.2 1560664 76672 pts/0 Sl 19:51 0:06 /usr/lib/xorg
ehpc 97 0.0 0.0 125236 3744 pts/0 Sl 19:51 0:00 /usr/sbin/xrd
ehpc 114 0.0 0.0 45840 2388 pts/0 S 19:51 0:00 dbus-launch -
ehpc 115 0.0 0.0 49792 2860 ? Ss 19:51 0:00 /usr/bin/dbus
ehpc 204 0.0 0.0 45840 2284 pts/0 S 19:51 0:00 /usr/bin/dbus
ehpc 205 0.0 0.0 50408 4032 ? Ss 19:51 0:00 /usr/bin/dbus
ehpc 214 0.0 0.0 11300 320 ? Ss 19:51 0:00 /usr/bin/ssh-
ehpc 289 0.0 0.1 1808608 53284 pts/0 Sl 19:51 0:00 mate-session
ehpc@2f13360ae39d:~/Desktop$ ps aux | grep slurm
ehpc 580 0.0 0.0 13340 1064 pts/1 S+ 20:03 0:00 grep --color=auto slurm
ehpc@2f13360ae39d:~/Desktop$ pstree
bash─┬─at-spi-bus-laun─┬─dbus-daemon
│ └─3*[{at-spi-bus-laun}]
├─at-spi2-registr───2*[{at-spi2-registr}]
├─bash
├─brisk-menu───3*[{brisk-menu}]
├─clock-applet───3*[{clock-applet}]
├─2*[dbus-daemon]
├─2*[dbus-launch]
├─dconf-service───2*[{dconf-service}]
├─gvfs-afc-volume───3*[{gvfs-afc-volume}]
├─gvfs-goa-volume───2*[{gvfs-goa-volume}]
├─gvfs-gphoto2-vo───2*[{gvfs-gphoto2-vo}]
├─gvfs-mtp-volume───2*[{gvfs-mtp-volume}]
├─gvfs-udisks2-vo───2*[{gvfs-udisks2-vo}]
├─gvfsd─┬─gvfsd-trash───2*[{gvfsd-trash}]
│ └─2*[{gvfsd}]
├─gvfsd-metadata───2*[{gvfsd-metadata}]
├─mate-indicator-───3*[{mate-indicator-}]
├─mate-screensave───3*[{mate-screensave}]
├─mate-terminal─┬─bash───pstree
│ └─4*[{mate-terminal}]
├─notification-ar───3*[{notification-ar}]
├─pulseaudio───{pulseaudio}
├─sshd
├─trashapplet───3*[{trashapplet}]
├─wnck-applet───3*[{wnck-applet}]
├─xrdp───xrdp
└─xrdp-sesman───xrdp-sesman─┬─Xorg───17*[{Xorg}]
├─bash─┬─mate-session─┬─caja───3*[{caja}]
│ │ ├─indicator-appli───2*[{+
│ │ ├─indicator-power───3*[{+
│ │ ├─indicator-sessi───3*[{+
│ │ ├─marco───3*[{marco}]
│ │ ├─mate-maximus───3*[{mat+
│ │ ├─mate-panel───3*[{mate-+
│ │ ├─mate-settings-d───4*[{+
│ │ ├─nm-applet───3*[{nm-app+
│ │ └─19*[{mate-session}]
│ └─ssh-agent
└─xrdp-chansrv───{xrdp-chansrv}