linux学习记录

资料:

Linux 黑马程序员_bilibili

AcWing Linux基础课

可能是东半球最全面易懂的 Tmux 使用教程!

Shell 教程 | 菜鸟教程 (runoob.com)

超算习堂vim入门教程

超算习堂 Linux入门基础

Linux的基本操作(一) - 星辰大海6 - 博客园 (cnblogs.com)

(5条消息) Linux中的Git(过程 + 总结)_VVPU的博客-CSDN博客_git linux

还有一些零零散散的…

(实训内容与其他知识点有重复)

文章目录

  • linux学习记录
    • 资料:
    • 一、
      • 1.操作系统概述
      • 2.初识linux
      • 3.虚拟机介绍
      • 3.安装
      • 4.远程连接linux系统
      • 5.WSL(Windows Subsystem for Linux)
      • 6.虚拟机快照
    • 二、
      • 1.linux目录结构
        • (1)Linux的目录结构
        • (2)linux路径的描述方式
      • 2.Linux命令入门
        • (1)Linux命令基础
        • (2)ls命令入门
        • (3)ls命令的参数和选项
      • 3.目录切换相关命令(cd/pwd)
      • 4.相对路径绝对路径和特殊路径符
      • 5.创建目录命令(mkdir命令)
    • 补:一些快捷键
      • 6.文件操作命令1(touch-cat-more)
      • 7.文件操作命令2(cp-mv-rm)
      • 8.grep、wc、管道符
      • 9.which、find命令
      • 10.echo、tail、重定向符
    • 三、vi/vim和tmux
      • 1.vi/vim
        • 1.1vim学习
        • 1.2 超算习堂实训
          • 1.2.1基本模式
          • 1.2.2 普通模式--游标移动
          • 1.2.3普通模式--文档编辑
          • 1.2.5 命令模式
          • 1.2.6进阶命令
      • 2.tmux
        • 2.1 什么是Tmux
        • 2.2 基本用法
        • 2.3 会话管理
        • 2.4 **最简操作流程**
        • 2.5 窗格操作
        • 2.6 窗口管理
        • 2.7 其他命令
    • 四、shell
      • 1. 概述
      • 2. 注释
      • 3.变量
        • 定义变量
        • 使用变量
        • 只读变量
        • 删除变量
        • 变量类型
        • 字符串
      • 4.默认变量
      • 5.数组
      • 关联数组
      • 6.expr命令
      • 7.read命令
      • 8.echo命令
      • 9.printf命令
      • 10.test命令与判断符号[]
      • 11.判断语句
      • 12.循环语句
      • 13.函数
      • 14.exit命令
      • 15.文件重定向
      • 16.引入外部脚本
    • 五、ssh
      • ssh登录
      • scp传文件
    • 六、git
      • git基本概念
      • git常用命令
        • 文件的四种状态
    • 七、thrift
      • 1.什么是thrift
      • 2.使用步骤
        • 2.1 定义接口
        • 2.2 server服务端
        • 2.3 client请求端
    • 八、管道、环境变量与常用命令
      • 管道
      • 环境变量
      • 常用命令
    • 补充
      • 1. **linux命令的分类**
      • 2.主机名称命令
      • 3.查看系统版本
      • 4.网卡修改相关命令
      • 5.开启关闭系统
      • 6.ls补充
      • 结合通配符
    • 超算实训Linux基础入门
      • 快捷键
      • 软件安装-apt
      • 用户权限管理
        • 查看用户
        • 创建用户
        • 查看用户组
        • 删除用户
      • 文件权限管理
        • 查看文件权限
        • 变更文件所有者
        • 修改文件权限
      • 目录及文件操作
      • 搜索文件
      • 文件解压缩
        • rar
        • zip
        • tar
      • 管道与一些文本命令
        • && 和 ||
        • 管道
      • 文本处理
      • 重定向
      • 进程的基本操作
      • kill语法
      • 进程管理
      • 进程管理

一、

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)

(补充:命令可以是下面四种形式之一:

  1. 是一个可执行程序,就像我们所看到的位于目录/usr/bin 中的文件一样。 属于这一类的程序,可以编译成二进制文件,诸如用 C 和 C++语言写成的程序, 也可以是由脚本语言写成的程序,比如说 shell,perl,python,ruby,等等。

  2. 是一个内建于 shell 自身的命令。bash 支持若干命令,内部叫做 shell 内部命令 (builtins)。例如,本地环境中的 cd 命令,就是一个 shell 内部命令。which cd没有结果

  3. 是一个 shell 函数。这些是小规模的 shell 脚本,它们混合到环境变量中。 比如上面讲到的 cd 命令,在实验楼环境中就是一个 shell 函数。

  4. 是一个命令别名。我们可以定义自己的命令,建立在其它命令之上。

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/word1/word2/g:将全文的word1替换为word2(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的常规替换命令主要由sc完成,但替换命令之后,会进入插入模式,按下ESC即可返回普通模式,替换命令部分如下:(感觉就是命令模式下按s键会删除光标所在位置的字符,ns删除光标所在开始的n个字符,c$删除从光标开始到行尾的所有字符,c0删除从本行开头到光标的所有字符

指令 说明
s 用输入的正文替换游标所在的字符
ns 用输入的正文替换游标右侧n个字符
c$ 用输入的正文替换从游标开始到行尾的所有字符
c0 用输入的正文替换从本行开始到游标的所有字符

删除

Vim的删除命令主要由dx完成,如下:

指令 说明
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 文件名mn行写入文件
  • :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/gstr2替换行中出现的所有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 使用教程

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 的最简操作流程。

  1. 新建会话 tmux new -s my_session
  2. 在 Tmux 窗口运行所需的程序。
  3. 按下快捷键 Ctrl+b d 将会话分离。
  4. 下次使用时,重新连接到会话 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/bashecho "文件名:"$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/bashecho "文件名:"$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/bashecho "文件名:"$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
01 2 3 4
1 2 3 4
commandabc

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的子串。如果POSITIONLENGTH为负数,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=4echo `expr $a \> $b`  # 输出0,>需要转义
echo `expr $a '<' $b`  # 输出1,也可以将特殊字符用引号引起来 单引号,双引号都可以
echo `expr $a '>=' $b`  # 输出0
echo `expr $a \<\= $b`  # 输出1c=0
d=5echo `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"
#结果
hinihao
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 ]
thenecho ${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=4if ! [ "$a" -lt "$b" ]
thenecho ${a} ">=" ${b}
elseecho ${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=4if [ $a -eq 1 ]
thenecho ${a}等于1
elif [ $a -eq 2 ]
thenecho ${a}等于2
elif [ $a -eq 3 ]
thenecho ${a}等于3
elseecho 其他
fi

结果:

其他

case…esac形式
类似于C/C++中的switch语句。

命令格式:

case $变量名称 in值1)语句1语句2...;;  # 类似于C/C++中的break值2)语句1语句2...;;*)  # 类似于C/C++中的default语句1语句2...;;
esac

尝试:

a=4case $a in1)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
doecho $i
donefor file in `ls`
doecho $file
donefor i in $(seq 2 11)
do echo $i
done    for i in {a..z}
do      echo $i
done    for i in {a...z} #应该两个点
doecho $i
donefor i in {1...10} #应该两个点
doecho $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++))
doecho $i
done

结果:输出1-10,每个数占一行

while…do…done循环
命令格式:

while condition
do语句1语句2...
done

尝试:

while read name #文件结束符为Ctrl+d,输入文件结束符后read指令返回false。
doecho $name
done

until…do…done循环

  • 条件为真结束

命令格式:

until condition
do语句1语句2...
done

尝试:

#当用户输入yes或者YES时结束,否则一直等待读入。
until [ "${word}" == "yes" ] || [ "${word}" == "YES" ]
doread -p "Please input yes/YES to stop this program: " word
done

break命令

  • 跳出当前一层循环,注意与C/C++不同的是:break不能跳出case语句。

示例:

while read name
dofor ((i=1;i<=10;i++))docase $i in8)break # 跳出for循环;;*)echo $i;;esacdone
done

该示例每读入非EOF的字符串,会输出一遍1-7
该程序可以输入Ctrl+d文件结束符来结束,也可以直接用Ctrl+c杀掉该进程。

continue命令

  • 跳出当前循环。
for ((i=1;i<=10;i++))
doif [ `expr $i % 2` -eq 0 ]thencontinuefiecho $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=yangecho "Hello $name"
}func #Hello yang

获取 return值和stdout

  • 不写return时,默认return 0

尝试:

func() {name=yangecho "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) + ... + 0word=""while [ "${word}" != 'y' ] && [ "${word}" != 'n' ]doread -p "要进入func($1)函数吗?请输入y/n:" worddoneif [ "$word" == 'n' ]thenecho 0return 0fi  if [ $1 -le 0 ] thenecho 0return 0fi  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/bashfunc() {local name=yangecho $name
}
funcecho $name

结果:

yang#空行

第一行为函数内的name变量,第二行为函数外调用name变量,会发现此时该变量不存在。

14.exit命令

  • exit命令用来退出当前shell进程,并返回一个退出状态;使用$?可以接收这个退出状态。
  • exit命令可以接受一个整数值作为参数,代表退出状态。如果不指定,默认状态值是 0。
  • exit退出状态只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。

创建脚本test7.sh,内容如下:

#! /bin/bashif [ $# -ne 1 ]  # 如果传入参数个数等于1,则正常退出;否则非正常退出。
thenecho "arguments not valid"exit 1
elseecho "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/bashread a
read becho $(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/bashname=yang

然后创建test9.sh,内容为:

#! /bin/bash
. test8.shecho 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 yqqHostName 192.168.232.168User yangHost myserver2Hostname 192.168.232.28User yang

之后再使用服务器时,可以直接使用别名yqqmyserver2

密钥登录
创建密钥:

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/advantage1 更新可以立即应用。
这些更新中有 1 个是标准安全更新。
要查看这些附加更新,请运行:apt list --upgradableLast 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
9yang@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等参数尽量加在sourcedestination之前。

使用scp配置其他服务器的vimtmux

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 file1 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.txtyang@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 distributed1 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 line1 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 +0800add a new linecommit f2e8319b208df2a09c3a65b3a64490f2c6b616a8
Author: yang <1473641801@qq.com>
Date:   Wed Dec 7 20:24:30 2022 +0800add a word distributedcommit a84c814296045ab8b17e14d74cbcd32ad5606326
Author: yang <1473641801@qq.com>
Date:   Wed Dec 7 20:14:13 2022 +0800add 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 +0800add a word distributedcommit a84c814296045ab8b17e14d74cbcd32ad5606326
Author: yang <1473641801@qq.com>
Date:   Wed Dec 7 20:14:13 2022 +0800add 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.txtyang@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.txtyang@yang-virtual-machine:~/gitrepository$ git commit readme.txt -m "delete readme.txt"
[master eda9b0f] delete readme.txt1 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.txtyang@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教程

  • thrift官网
  • 上课代码地址

(不懂啊,是要干嘛)

Linux基础之thrift_老帅比阿的博客

1.什么是thrift

thrift是一个编译器,它的作用是让我们在开发项目时,让不同服务器之间的函数能相互调用,并且它能调用不同语言之间的函数。比如我们在客户端用的是python,但我们可以利用thrift调用服务端写的c++函数。

2.使用步骤

2.1 定义接口

首先我们需要定义一个.thrift文件,里面写着服务器交互用到内容。
比如我们实现一个匹配系统,当我们客户端有个用户需要加入匹配时,
我们就需要向服务端请求一个函数,add_user,当我们要取消匹配时,就调用一个remove_user函数。

所以我们就需要定义一些和add_user函数和remove_user函数的一些内容。详细要求看官方文档要求。

namespace cpp match_servicestruct 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文件的总行数,其中findxargswc等命令可以参考常用命令这一节内容。

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 ,这个例子我没有想到,应该平时都用不到的吧。

Linux xargs 命令 | 菜鸟教程 (runoob.com)

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-} == \~* ]]; theneval $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:]]/} ) ]]; thencur=$COMP_LINE;for ((i = 0; i <= cword; ++i))dowhile [[ ${#cur} -ge ${#words[i]} && ${cur:0:${#words[i]}} != "${words[i]-}" ]]; docur="${cur:1}";((index > 0)) && ((index--));done;if ((i < cword)); thenlocal 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};dodirs+=($dir/bash-completion/completions);done;IFS=$ifs;if [[ $BASH_SOURCE == */* ]]; thendirs+=("${BASH_SOURCE%/*}/completions");elsedirs+=(./completions);fi;local backslash=;if [[ $cmd == \\* ]]; thencmd="${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";docompfile="$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 == *:* ]]; thenlocal colon_word=${1%"${1##*:}"};local i=${#COMPREPLY[*]};while ((i-- > 0)); doCOMPREPLY[i]=${COMPREPLY[i]#"$colon_word"};done;fi
}
__parse_options ()
{ local option option2 i IFS='
,/|';option=;local -a array=($1);for i in "${array[@]}";docase "$i" in ---*)break;;--?*)option=$i;break;;-?*)[[ -n $option ]] || option=$i;;*)break;;esac;done;[[ -n $option ]] || return 0;IFS='
';if [[ $option =~ (\[((no|dont)-?)\]). ]]; thenoption2=${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 ]]; thenexclude="[${1//[^$COMP_WORDBREAKS]/}]";fi;printf -v "$3" %s "$COMP_CWORD";if [[ -v exclude ]]; thenline=$COMP_LINE;for ((i = 0, j = 0; i < ${#COMP_WORDS[@]}; i++, j++))dowhile [[ $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";elsefor i in "${!COMP_WORDS[@]}";doprintf -v "$2[i]" %s "${COMP_WORDS[i]}";done;fi
}
_allowed_groups ()
{ if _complete_as_root; thenlocal IFS='
';COMPREPLY=($(compgen -g -- "$1"));elselocal IFS='';COMPREPLY=($(compgen -W             "$(id -Gn 2>/dev/null || groups 2>/dev/null)" -- "$1"));fi
}
_allowed_users ()
{ if _complete_as_root; thenlocal IFS='
';COMPREPLY=($(compgen -u -- "${1:-$cur}"));elselocal 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.* ]]; thendashoptions="--save $dashoptions";fi;if ! [[ "${COMP_WORDS[*]}" =~ .*--window.* || "${COMP_WORDS[*]}" =~ .*\ -w\ .* ]]; thendashoptions="-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.* ]]; thendashoptions="--save $dashoptions";fi;if ! [[ "${COMP_WORDS[*]}" =~ .*--window.* || "${COMP_WORDS[*]}" =~ .*\ -w\ .* ]]; thendashoptions="-w --window $dashoptions";fi;if ! [[ "${COMP_WORDS[*]}" =~ .*--symptom.* || "${COMP_WORDS[*]}" =~ .*\ -s\ .* ]]; thendashoptions="-s --symptom $dashoptions";fi;if ! [[ "${COMP_WORDS[*]}" =~ .*--update.* || "${COMP_WORDS[*]}" =~ .*\ -u\ .* ]]; thendashoptions="-u --update $dashoptions";fi;if ! [[ "${COMP_WORDS[*]}" =~ .*--file-bug.* || "${COMP_WORDS[*]}" =~ .*\ -f\ .* ]]; thendashoptions="-f --file-bug $dashoptions";fi;if ! [[ "${COMP_WORDS[*]}" =~ .*--crash-file.* || "${COMP_WORDS[*]}" =~ .*\ -c\ .* ]]; thendashoptions="-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.* ]]; thenCOMPREPLY=($( compgen -W "--tag" -- $cur));elseCOMPREPLY=($( 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 ]; thenfor FILE in $(ls /usr/share/apport/symptoms);doif [[ ! "$FILE" =~ ^_.* && -n $(egrep "^def run\s*\(.*\):" /usr/share/apport/symptoms/$FILE) ]]; thensyms="$syms ${FILE%.py}";fi;done;fi;echo $syms
}
_available_interfaces ()
{ local PATH=$PATH:/sbin;COMPREPLY=($({if [[ ${1:-} == -w ]]; theniwconfigelif [[ ${1:-} == -a ]]; thenifconfig || ip link show upelseifconfig -a || ip link showfi} 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; thenunbuffer -p "$@";elseif script --version 2>&1 | command grep -qF util-linux; thenscript -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//:/'
'};dok="${#COMPREPLY[@]}";for j in $(compgen -d -- $i/$cur);doif [[ ( -n $mark_symdirs && -L $j || -n $mark_dirs && ! -L $j ) && ! -d ${j#$i/} ]]; thenj+="/";fi;COMPREPLY[k++]=${j#$i/};done;done;_filedir -d;if ((${#COMPREPLY[@]} == 1)); theni=${COMPREPLY[0]};if [[ $i == "$cur" && $i != "*/" ]]; thenCOMPREPLY[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++))doif [[ ${COMP_WORDS[i]} != -* ]]; thenoffset=$i;break;fi;done;_command_offset $offset
}
_command_offset ()
{ local word_offset=$1 i j;for ((i = 0; i < word_offset; i++))dofor ((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++))doCOMP_WORDS[i]=${COMP_WORDS[i + word_offset]};done;for ((i; i <= COMP_CWORD; i++))dounset 'COMP_WORDS[i]';done;((COMP_CWORD -= word_offset));COMPREPLY=();local cur;_get_comp_words_by_ref cur;if ((COMP_CWORD == 0)); thenlocal IFS='
';compopt -o filenames;COMPREPLY=($(compgen -d -c -- "$cur"));elselocal cmd=${COMP_WORDS[0]} compcmd=${COMP_WORDS[0]};local cspec=$(complete -p $cmd 2>/dev/null);if [[ ! -n $cspec && $cmd == */* ]]; thencspec=$(complete -p ${cmd##*/} 2>/dev/null);[[ -n $cspec ]] && compcmd=${cmd##*/};fi;if [[ ! -n $cspec ]]; thencompcmd=${cmd##*/};_completion_loader $compcmd;cspec=$(complete -p $compcmd 2>/dev/null);fi;if [[ -n $cspec ]]; thenif [[ ${cspec#* -F } != "$cspec" ]]; thenlocal 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 "* ]]; docspec=${cspec#*-o };opt=${cspec%% *};compopt -o $opt;cspec=${cspec#$opt};done;elsecspec=${cspec#complete};cspec=${cspec%%$compcmd};COMPREPLY=($(eval compgen "$cspec" -- '$cur'));fi;elseif ((${#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 ]]; thenCOMPREPLY=($(compgen -W "$(command sed -ne 's|^iface \([^ ]\{1,\}\).*$|\1|p'             /etc/network/interfaces /etc/network/interfaces.d/* 2>/dev/null)"             -- "$cur"));elseif [[ -f /etc/SuSE-release ]]; thenCOMPREPLY=($(compgen -W "$(printf '%s\n'             /etc/sysconfig/network/ifcfg-* |command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"));elseif [[ -f /etc/pld-release ]]; thenCOMPREPLY=($(compgen -W "$(command ls -B             /etc/sysconfig/interfaces |command sed -ne 's|.*ifcfg-\([^*].*\)$|\1|p')" -- "$cur"));elseCOMPREPLY=($(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++))doif [[ ${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 ]]; thenreset=$(shopt -po noglob);set -o noglob;toks=($(compgen -d -- "${cur-}"));IFS=' ';$reset;IFS='
';elselocal 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)); thencompopt -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; doprintf '%s\n' $tmpdone}));eval xspec="${xspec}";local matchop=!;if [[ $xspec == !* ]]; thenxspec=${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' $tmpdone}));[[ -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)); thencompopt -o filenames;COMPREPLY=("${toks[@]}");fi
}
_fstypes ()
{ local fss;if [[ -e /proc/filesystems ]]; thenfss="$(cut -d'    ' -f2 /proc/filesystems)$(awk '! /\*/ { print $NF }' /etc/filesystems 2>/dev/null)";elsefss="$(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 "$@"; docase $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 ]]; docase ${!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]/} ]]; thenprintf "%s" "${words[cword - $2]}";elseif ((${#words[cword]} == 0 && COMP_POINT == ${#COMP_LINE})); then:;elselocal i;local cur="$COMP_LINE";local index="$COMP_POINT";for ((i = 0; i <= cword; ++i))dowhile [[ ${#cur} -ge ${#words[i]} && ${cur:0:${#words[i]}} != "${words[i]}" ]]; docur="${cur:1}";((index > 0)) && ((index--));done;if ((i < cword)); thenlocal old_size="${#cur}";cur="${cur#${words[i]}}";local new_size="${#cur}";((index -= old_size - new_size));fi;done;if [[ ${words[cword]:0:${#cur}} != "$cur" ]]; thenprintf "%s" "${words[cword]}";elseprintf "%s" "${cur:0:index}";fi;fi;fi
}
_get_first_arg ()
{ local i;arg=;for ((i = 1; i < COMP_CWORD; i++))doif [[ ${COMP_WORDS[i]} != -* ]]; thenarg=${COMP_WORDS[i]};break;fi;done
}
_get_pword ()
{ if ((COMP_CWORD >= 1)); then_get_cword "${@:-}" 1;fi
}
_gids ()
{ if type getent &> /dev/null; thenCOMPREPLY=($(compgen -W '$(getent group | cut -d: -f3)' -- "$cur"));elseif type perl &> /dev/null; thenCOMPREPLY=($(compgen -W '$(perl -e '"'"'while (($gid) = (getgrent)[2]) { print $gid . "\n" }'"'"')' -- "$cur"));elseCOMPREPLY=($(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[@]}";doif ! [[ $i =~ ^\~.*|^\/.* ]]; thenif [[ $configfile =~ ^\/etc\/ssh.* ]]; theni="/etc/ssh/$i";elsei="$HOME/.ssh/$i";fi;fi;__expand_tilde_by_ref i;set +o noglob;for f in $i;doif [[ -r $f ]]; thenconfig+=("$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 "$@"; docase $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 ]]; thenlocal 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))doif [[ ${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 "$@"; docase $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)); thenecho "bash_completion: $FUNCNAME: missing mandatory argument CWORD" 1>&2;return 1;fi;cur=${!OPTIND};((OPTIND += 1));if (($# >= OPTIND)); thenecho "bash_completion: $FUNCNAME($*): unprocessed arguments:" "$(while (($# >= OPTIND)); doprintf '%s ' ${!OPTIND}shiftdone)" 1>&2;return 1;fi;[[ $cur == *@* ]] && prefix=$prefix${cur%@*}@ && cur=${cur#*@};kh=();if [[ -v configfile ]]; then[[ -r $configfile ]] && config+=("$configfile");elsefor 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)); thenfor i in "${config[@]}";do_included_ssh_config_files "$i";done;fi;if ((${#config[@]} > 0)); thenlocal 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)); thenlocal j;for i in "${tmpkh[@]}";dowhile [[ $i =~ ^([^\"]*)\"([^\"]*)\"(.*)$ ]]; doi=${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 ]]; thenfor 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)); thenif ((${#kh[@]} > 0)); thenfor i in "${kh[@]}";dowhile 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)); thenfor i in "${khd[@]}";doif [[ $i == *key_22_$cur*.pub && -r $i ]]; thenhost=${i/#*key_22_/};host=${host/%.pub/};COMPREPLY+=($host);fi;done;fi;for i in ${!COMPREPLY[*]};doCOMPREPLY[i]=$prefix${COMPREPLY[i]}$suffix;done;fi;if [[ ${#config[@]} -gt 0 && -v aliases ]]; thenlocal -a hosts=($(command sed -ne 's/^[[:blank:]]*[Hh][Oo][Ss][Tt][[:blank:]]\(.*\)$/\1/p' "${config[@]}"));if ((${#hosts[@]} != 0)); thenCOMPREPLY+=($(compgen -P "$prefix"                 -S "$suffix" -W '${hosts[@]%%[*?%]*}' -X '\!*' -- "$cur"));fi;fi;if [[ -n ${COMP_KNOWN_HOSTS_WITH_AVAHI-} ]] && type avahi-browse &> /dev/null; thenCOMPREPLY+=($(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; thenCOMPREPLY+=($(compgen -W             "$(ruptime 2>/dev/null | awk '!/^ruptime:/ { print $1 }')"             -- "$cur"));fi;if [[ -n ${COMP_KNOWN_HOSTS_WITH_HOSTFILE-1} ]]; thenCOMPREPLY+=($(compgen -A hostname -P "$prefix" -S "$suffix" -- "$cur"));fi;$reset;if [[ -v ipv4 ]]; thenCOMPREPLY=("${COMPREPLY[@]/*:*$suffix/}");fi;if [[ -v ipv6 ]]; thenCOMPREPLY=("${COMPREPLY[@]/+([0-9]).+([0-9]).+([0-9]).+([0-9])$suffix/}");fi;if [[ -v ipv4 || -v ipv6 ]]; thenfor 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 == -* ]]; thenCOMPREPLY=($(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;elseif [[ $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]+)?(\.\.+)?\]? ]]; doline=${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; dowhile [[ $line =~ \[[[:space:]]*(-[^]]+)[[:space:]]*\] ]]; domatch=${BASH_REMATCH[0]};option=${BASH_REMATCH[1]};case $option in -?(\[)+([a-zA-Z0-9?]))for ((i = 1; i < ${#option}; i++))dochar=${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 ]]; thenprocs=($(command ps axo comm | command sed -e 1d));elselocal line i=-1 ifs=$IFS;IFS='
';local -a psout=($(command ps axo command=));IFS=$ifs;for line in "${psout[@]}";doif ((i == -1)); thenif [[ $line =~ ^(.*[[:space:]])COMMAND([[:space:]]|$) ]]; theni=${#BASH_REMATCH[1]};elsebreak;fi;elseline=${line:i};line=${line%% *};procs+=($line);fi;done;if ((i == -1)); thenfor line in "${psout[@]}";doif [[ $line =~ ^[[(](.+)[])]$ ]]; thenprocs+=(${BASH_REMATCH[1]});elseline=${line%% *};line=${line##@(*/|-)};procs+=($line);fi;done;fi;fi;COMPREPLY=($(compgen -X "<defunct>" -W '${procs[@]}' -- "$cur"))
}
_quote_readline_by_ref ()
{ if [ -z "$1" ]; thenprintf -v $2 %s "$1";elseif [[ $1 == \'* ]]; thenprintf -v $2 %s "${1:1}";elseif [[ $1 == \~* ]]; thenprintf -v $2 \~%q "${1:1}";elseprintf -v $2 %q "$1";fi;fi;fi;[[ ${!2} == \$* ]] && eval $2=${!2}
}
_realcommand ()
{ type -P "$1" > /dev/null && { if type -p realpath > /dev/null; thenrealpath "$(type -P "$1")";elseif type -p greadlink > /dev/null; thengreadlink -f "$(type -P "$1")";elseif type -p readlink > /dev/null; thenreadlink -f "$(type -P "$1")";elsetype -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;elselocal 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 ]]; thenCOMPREPLY+=($(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 == --?*=* ]]; thenprev="${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 != */* ]]; thenCOMPREPLY=($(compgen -P '~' -u -- "${1#\~}"));result=${#COMPREPLY[@]};((result > 0)) && compopt -o filenames 2> /dev/null;fi;return $result
}
_uids ()
{ if type getent &> /dev/null; thenCOMPREPLY=($(compgen -W '$(getent passwd | cut -d: -f3)' -- "$cur"));elseif type perl &> /dev/null; thenCOMPREPLY=($(compgen -W '$(perl -e '"'"'while (($uid) = (getpwent)[2]) { print $uid . "\n" }'"'"')' -- "$cur"));elseCOMPREPLY=($(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"; thenif (($# == 2)); theneval $1=\"\$2\";elseeval $1=\(\"\$"{@:2}"\"\);fi;fi
}
_upvars ()
{ if ! (($#)); thenecho "bash_completion: $FUNCNAME: usage: $FUNCNAME" "[-v varname value] | [-aN varname [value ...]] ..." 1>&2;return 2;fi;while (($#)); docase $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";elseCOMPREPLY=($(compgen -u -S @ -- "$cur"));compopt -o nospace;fi
}
_usergroup ()
{ if [[ $cur == *\\\\* || $cur == *:*:* ]]; thenreturn;elseif [[ $cur == *\\:* ]]; thenlocal prefix;prefix=${cur%%*([^:])};prefix=${prefix//\\/};local mycur="${cur#*[:]}";if [[ ${1-} == -u ]]; then_allowed_groups "$mycur";elselocal IFS='
';COMPREPLY=($(compgen -g -- "$mycur"));fi;COMPREPLY=($(compgen -P "$prefix" -W "${COMPREPLY[@]}"));elseif [[ $cur == *:* ]]; thenlocal mycur="${cur#*:}";if [[ ${1-} == -u ]]; then_allowed_groups "$mycur";elselocal IFS='
';COMPREPLY=($(compgen -g -- "$mycur"));fi;elseif [[ ${1-} == -u ]]; then_allowed_users "$cur";elselocal 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_]*)=(.*)$ ]]; thenprev=${BASH_REMATCH[1]};cur=${BASH_REMATCH[2]};elsereturn 1;fi;case $prev in TZ)cur=/usr/share/zoneinfo/$cur;_filedir;for i in "${!COMPREPLY[@]}";doif [[ ${COMPREPLY[i]} == *.tab ]]; thenunset 'COMPREPLY[i]';continue;elseif [[ -d ${COMPREPLY[i]} ]]; thenCOMPREPLY[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_]*)$ ]]; thenif [[ $cur == '${'* ]]; thenlocal 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)); thencompopt -o nospace;COMPREPLY+=(${arrs[*]});elseCOMPREPLY+=(${vars[*]});fi;elseCOMPREPLY+=($(compgen -A variable -P '$' -- "${BASH_REMATCH[3]}"));fi;return 0;elseif [[ $cur =~ ^(\$\{[#!]?)([A-Za-z0-9_]*)\[([^]]*)$ ]]; thenlocal 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]} == [@*] ]]; thenCOMPREPLY+=("${BASH_REMATCH[1]}${BASH_REMATCH[2]}[${BASH_REMATCH[3]}]}");fi;__ltrim_colon_completions "$cur";return 0;elseif [[ $cur =~ ^\$\{[#!]?[A-Za-z0-9_]*\[.*\]$ ]]; thenCOMPREPLY+=("$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 ]]; thenlocal 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 $?;elseif [ -x /usr/share/command-not-found/command-not-found ]; then/usr/share/command-not-found/command-not-found -- "$1";return $?;elseprintf "%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_PATHC语言的头文件路径,内容是以冒号分隔的路径列表。
  • 5.CPLUS_INCLUDE_PATHCPP的头文件路径,内容是以冒号分隔的路径列表。
  • 6.PYTHONPATHPython导入包的路径,内容是以冒号分隔的路径列表。
  • 7.JAVA_HOMEjdk的安装目录。
  • 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:~$ toptop - 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 -htotal        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:~$ w15: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=5414.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.cpp49  62 569 huiwenzhishu.cpp
yang@yang-virtual-machine:~$ wc -wcl huiwenzhishu.cpp49  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.sh53 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: $namehuiwenzhishu.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 $nametest3.sh
1:while read name
10:                echo $itest.sh
1:#! /bin/bash
5:echo $(expr "$a" + "$b")yang/test9.sh
1:#! /bin/bash
2:. test8.sh
4:echo My name is: $nameyang/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 $nameyang/test3.sh
1:while read name
10:                echo $iyang/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: $nameyang/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 $nameyang/yang/test3.sh
1:while read name
10:                echo $itest1.sh
4:    then
7:    echo $itest2.sh
1:while read name
3:  echo $nametest8.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:~$ history1  ifconfig2  ifconfig-a3  ifconfig4  sudo apt install net-tools5  ifconfig6  sudo apt install net-tools7  ifconfig8  sudo apt-get install openssh server9  sudo apt-get install oenssh-server10  sudo apt-get install openssh-server11  ifconfig12  sudo apt install openssh-server13  sudo apt install openssh-client14  sudo apt install openssh-server15  sudo apt install openssh-client16  sudo gedit /etc/ssh/ssh/_config17  sudo gedit /etc/ssh/ssh_config18  sudo gedit /etc/ssh/sshd_config19  sudo /etc/init.d/ssh restart20  ifconfig21  sudo apt install openssh-server22  sudo apt install openssh-client23  sudo gedit /etc/ssh/ssh_config24  sudo gedit /etc/ssh/sshd_config25  sudo /etc/init.d/ssh restart26  ping 192.168.232.12827  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.shreal   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 worldIn [2]: echo "hello world"File "<ipython-input-2-2c7123d6102b>", line 1echo "hello world"^
SyntaxError: invalid syntaxIn [3]: q
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-3-e222fcdf3350> in <module>
----> 1 qNameError: name 'q' is not definedIn [4]: ! exitIn [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:查找文件xxxyyy的不同点

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之阿里云

阿里云-为了无法计算的价值 (aliyun.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登录

配置新服务器的工作环境
将AC Terminal的配置传到新服务器上:

scp .bashrc .vimrc .tmux.conf server_name:  # server_name需要换成自己配置的别名

安装tmuxdocker
登录自己的服务器,然后安装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需要换成自己配置的别名

安装tmuxdocker
登录自己的服务器,然后安装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需要换成自己配置的别名

安装tmuxdocker
登录自己的服务器,然后安装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.04docker 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/importdocker save/load的区别:

  • export/import会丢弃历史记录和元数据信息,仅保存容器当时的快照状态
  • save/load会保存完整记录,体积更大

14.docker top CONTAINER:查看某个容器内的所有进程
15.docker stats:查看所有容器的统计信息,包括CPU、内存、存储、网络等信息

16.docker cp xxx CONTAINER:xxxdocker 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
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 文件名] [名>  timeseval [参数 ...]                        trap [-lp] [[参数] 信号声明 ...]exec [-cl] [-a name] [command [argum>  trueexit [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 命令; donefunction 名称 { 命令 ; } 或 name () >  variable - 一些 shell 变量的名称>getopts optstring name [arg ...]       wait [-fn] [-p var] [id ...]hash [-lr] [-p 路径名] [-dt] [名称 .>  while 命令; do 命令; donehelp [-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 1500inet 192.168.232.128  netmask 255.255.255.0  broadcast 192.168.232.255inet6 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 0TX packets 3427  bytes 280617 (280.6 KB)TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536inet 127.0.0.1  netmask 255.0.0.0inet6 ::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 0TX 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 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::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 1000link/ether 00:0c:29:6a:da:4b brd ff:ff:ff:ff:ff:ffaltname enp2s1inet 192.168.232.128/24 brd 192.168.232.255 scope global dynamic noprefixroute ens33valid_lft 1158sec preferred_lft 1158secinet6 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 helpEvaluation copy. Please register.Creating archive test.rarAdding    ./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.rarRAR 5.50   Copyright (c) 1993-2017 Alexander Roshal   11 Aug 2017
Trial version             Type 'rar -?' for helpArchive: test.rar
Details: RAR 5Attributes      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                    15yang@yang-virtual-machine:~$ rar d test.rar test/inputRAR 5.50   Copyright (c) 1993-2017 Alexander Roshal   11 Aug 2017
Trial version             Type 'rar -?' for helpDeleting from test.rar
Deleting test/input
Done
yang@yang-virtual-machine:~$ rar l test.rarRAR 5.50   Copyright (c) 1993-2017 Alexander Roshal   11 Aug 2017
Trial version             Type 'rar -?' for helpArchive: test.rar
Details: RAR 5Attributes      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                    14yang@yang-virtual-machine:~$ rar a test.rar ./test/inputRAR 5.50   Copyright (c) 1993-2017 Alexander Roshal   11 Aug 2017
Trial version             Type 'rar -?' for helpEvaluation copy. Please register.Updating archive test.rarAdding    ./test/input                                                OK
Done
yang@yang-virtual-machine:~$ rar l test.rarRAR 5.50   Copyright (c) 1993-2017 Alexander Roshal   11 Aug 2017
Trial version             Type 'rar -?' for helpArchive: test.rar
Details: RAR 5Attributes      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 ./testadding: 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.zipLength      Date    Time    Name
---------  ---------- -----   ----0  2022-12-07 11:07   test/4  2022-12-05 22:50   test/input.txt48  2022-12-05 22:50   test/test9.sh204  2022-12-05 22:50   test/test7.sh134  2022-12-05 22:50   test/test5.sh126  2022-12-05 22:50   test/test4.sh76  2022-12-05 22:50   test/test6.sh213  2022-12-05 22:50   test/test3.sh0  2022-12-05 23:07   test/hhhhh.txt53  2022-12-06 15:39   test/noname2.txt53  2022-12-05 22:50   test/test.sh2  2022-12-05 22:50   test/output.txt107  2022-12-05 22:50   test/test1.sh37  2022-12-05 22:50   test/test2.sh4  2022-12-05 22:50   test/input24  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.zipcreating: ./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$ toptop - 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$ toptop - 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}

linux个人学习记录相关推荐

  1. Linux的学习记录。

    linux基础学习.(第一天 本人用的是centos7 声明:此博客用来记录每一天的学习,会努力坚持的更新下去.希望能跟初学linux的小伙伴们一起分享当天所得. 也请小伙伴们多多指正博客中的错误!! ...

  2. Zabbix3.2下Template App Zabbix Server+Template OS Linux Item学习记录

    就是Zabbix server默认的78个Item学习记录,返回值是在我自己的虚拟机上通过zabbix_get或者zabbix_agentd获取的,zabbix internal check的item ...

  3. Linux+shell学习记录和思维导图

    由于shell和Linux学习分不开,所以干脆一起结合起来学习,顺便用思维导图工具做一个记录. 学习的关键在于对着教程敲代码. 学习工具 思维导图工具Xmind:以前一直用百度脑图做一些简单的记录,但 ...

  4. linux c++ 学习记录

    此文章用以记录所有在使用Linux c++中遇到的问题,方便自己以后查找解决方案. 由于笔者算法的开发和仿真大多都是使用windows 平台, linux 主要是为了测试systemc code,为了 ...

  5. Linux驱动学习记录-6.设备树的LED驱动

    这一章使用第五章的设备树知识来写led驱动 1.修改设备树 在根节点下面添加子节点 alphaled {#address-cells = <1>;#size-cells = <1&g ...

  6. Linux驱动学习记录 cpu主频

    以imx6ull芯片为例 imx6ull芯片主频是792MHz 查看cpu信息 cat /proc/cpuinfo proc/cpuinfo processor : 0 model name : AR ...

  7. Linux命令学习记录(六)

    用户管理命令,以root权限使用 adduser:添加新用户名 passwd:修改密码 deluser:删除用户 群组管理命令,以root权限使用 addgroup:添加群组 usermod:修改用户 ...

  8. linux命令学习记录一

    1.tree -L 1 /        -L 1 (数字1) 表示显示"/"下目录的层次,1表示一层 CentOS6.5下tree命令-bash: tree: command n ...

  9. [奔跑吧 Linux内核][学习记录]编译内核-实验1-2-[环境以及参考]

    1.下载的版本 VMware  workstation player v16.2.4 Ubuntu v22.04.1 Linux kernel v5.19 2.参考的文章 环境安装 [干货]win10 ...

最新文章

  1. 【Windows 逆向】使用 CE 工具挖掘关键数据内存真实地址 ( 逐层分析分析 静态地址 到 动态地址 的寻址 + 偏移 过程 ) ★
  2. php 之 在win10-64 上搭建开发环境
  3. mfc程序转化为qt_智慧虎超:小程序如何为珠宝行业助力?低频商品的高频转化你懂吗...
  4. 简谈Redis的线程模型
  5. Android中使用WebChromeClient显示Openlayers加载本地GeoJson文件显示地图(跨域问题解决)
  6. 中科大分布式算法教案.pdf
  7. 编译服务器home文件夹,离线安装FastDFS-过程填坑
  8. Node爬取简书首页文章
  9. MySQL数据库备份工具mysqldump的使用(转)
  10. java学习(12):i++和++i的区别
  11. AliOS Things图形界面开发指南
  12. 搭建卷积神经网络怎么确定参数_汽车冲压模具中拉延件各参数要怎么确定?本文教你确定方法!...
  13. python datetime datetime
  14. Windows单机之Weblogic 12c受管服务器配置
  15. 2019 年容器安全最新现状研究报告:意识普遍低,责任归属难!
  16. 用计算机弹起风了歌词,起风了歌词
  17. mapper报Cannot find class: com/kuang/dao/UserMapper
  18. chrome无法从该网站添加应用、扩展程序和用户脚本
  19. layui单选框verify_layui lay-verify form表单自定义验证规则详解
  20. Android Studio 配置翻译工具

热门文章

  1. 少儿C++编程从入门到进阶 信奥学奥赛从启蒙到NOI、ACM-ICPC(一)
  2. 谁“偷”走了我的雨伞
  3. 【视频分享】尚硅谷HTML5前端视频_Vue核心技术视频
  4. 详解matplotlib的color配置
  5. 现实与理想(中国台湾大学彭明辉)
  6. cesium实现相机绕地旋转效果
  7. 宝鲲财经:外汇技术精髓
  8. 漫画:什么是 “幼态持续” ?
  9. Git生成生成公钥和私钥
  10. PYNQ入门(2)——启动系统及例程查看