shell notes

Lec 01: Shell

1. shell 的基本操作

当你刚刚打开 Shell 的时候,你会发现这样一段提示符:

1
invo1lution:~$
  • ~ 的意思是 home。
  • $ 的意思是目前的身份不是 root 用户。

如果要传参数的话,我们可以使用单引号/双引号将其包括,也可以使用转移符号进行处理。比方说我要创建一个叫 “Denny Qi” 的文件夹,就可以写:

1
invo1lution: mkdir Denny\ Qi

类似于 echo mkdir 这样的指令都是一段 shell 可以解释执行的尖端代码。如果某个指令并不是 shell 了解的关键字,它会咨询环境变量 $PATH。这里举一个例子:

1
2
3
4
5
6
missing:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
missing:~$ which echo
/bin/echo
missing:~$ /bin/echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

2. 在 shell 中导航

这个已经很熟悉了。你可以通过 pwd 来获取当前目录。

2.1 ls

关于 ls

  1. 你可以通过 -l 来显示详细信息
  2. 通过 -h 来用 K/M/G 等看得懂的单位表示文件大小。
  3. 你可以通过 -a 来显示以 . 开头的隐藏文件。

合起来就是 ls -lah
这里举一个 ls -l 的例子:

1
2
missing:~$ ls -l /home
drwxr-xr-x 1 missing users 4096 Jun 15 2019 missing

下面的九个字母分别代表文件所有者/用户组/其它所有人 的权限。如果你想进入某个文件夹,就需要具备它和它父文件夹的搜索权限,为了列出它,用户就需要对其有读权限。

3. shell 的文本操作

3.1 cat

你可以通过 cat hello.cpp 把文件里的东西输出到终端。

3.2 echo

你可以通过 echo hi > main.cpp 来往文件里写东西

3.3 Nano

关于 Nano,这里列出一些基本功能:

1
2
3
4
5
6
7
8
9
10
11
12
$ nano hello.cpp
GNU nano 6.4 hello.cpp
#include <iostream>
int main () {
std::cout << "Hello World!" << std::endl;
return 0;
}


[ 已读取 5 行 ]
^G 帮助 ^O 写入 ^W 搜索 ^K 剪切 ^T 执行命令 ^C 位置
^X 离开 ^R 读档 ^\ 替换 ^U 粘贴 ^J 对齐 ^/ 跳行

其中例如 ^X 的意思就是 Ctrl + X,而 Alt + X 就是 M-x。

3.4 cp/mv

你可以通过 cp src dest 来把 src 挪到 dest 里面。如果 src 是一个目录,就需要 -r 来表示递归复制。

另外,你可以通过 mv src dest 来直接移动文件/目录,而且**不需要-r**。

4. 程序间创造连接

4.1 输入输出重定向

在 Linux 系统里,一个程序默认有三条输入输出的通道:

  • 通道 0 表示标准输入 (stdin / std::cin)
  • 通道 1 表示标准输出 (stdout / std::cout)
  • 通道 2 表示标准错误 (stderr / std::cerr)
    在 shell 里,我们可以把这三个通道重定向到文件 (类似于 freopen)。例如,如果我们要从 1.in 里读数据,输出到 1.out 里,并把标准错误写到 1.err 里,可以这样:
1
2
3
4
5
6
7
$ ./a.out <1.in >1.out 2>1.err
$ ls
1.err
1.in
1.out
a.out
hello.cpp

务必注意:如果一个被输出文件在执行命令前已经存在了,那么它会在程序执行前先被清空。如果你不想让它被清空,而是想让程序输出到文件末尾,可以用 >> 代替 >

有时候我们想要把 stdoutstderr 的内容都输出到同一个文件里,这时候可以用 2>&1

5. 一个功能强大的工具

root 即根用户,它想干什么都可以。但是我们不能登录之,因为这样的话某些错误的操作可能直接毁掉系统。所以我们使用 sudo 指令取代之。

有一件事情是必须作为根用户才能做得,就是往 sysfs 文件(包含内核参数)中写入内容。你的系统的很多信息都挂载在 /sys 下。

例如,你的屏幕亮度就在 /sys/class/backlight 文件中。

这里有一个重点,看下面这个例子:

1
2
3
4
5
6
$ sudo find -L /sys/class/backlight -maxdepth 2 -name '*brightness*'
/sys/class/backlight/thinkpad_screen/brightness
$ cd /sys/class/backlight/thinkpad_screen
$ sudo echo 3 > brightness
An error occurred while redirecting file 'brightness'
open: Permission denied

这是因为 | > < 是通过 shell 执行的,后者在设置 echo sudo 之前尝试打开 brightness,所以失败了。

你可以使用 $ echo 3 | sudo tee brightness 作为替代。

6. 后台运行

如果我们想同时在一个终端里运行多个指令,就可以用后台运行模式启动命令。只要在想运行的指令后面加一个 & 就行。

1
2
3
$ ./a.out &
[1] 64661
$

有的时候我们开着一个程序,但希望切到另一个程序。这时候可以先用 Ctrl+Z 把程序暂停运行。如果你想回到原来的程序,可以使用 fg 命令。

1
2
3
4
5
6
7
8
9
10
11
12
$ python3
Python 3.10.6 (main, Aug 3 2022, 17:39:45) [GCC 12.1.1 20220730] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> Ctrl+Z
[1]+ 已停止 python3
$ cat data
123 4566 7788
$ fg
python3
>>> 123 + 4566 + 7788
12477
>>>

7. 一些工具命令

一些工具命令

  • seq 起始 终止:打印出起始到终止的所有整数(闭区间)。
  • sort: 对输入以行为单位排序。
  • sed 's/查找内容/替换内容/g' :将输入里的所有查找内容替换为替换内容。
  • grep 查找内容:在输入里查找查找内容。
  • which 命令:输出命令的绝对路径。whereis 也有类似的功能。
  • ps:输出这个终端里正在执行的程序(包含 shell 和 ps 本身)。
  • kill 进程编号、killall 程序名称:发出信号让对应进程终止。
  • kill -9 进程编号、killall 程序名称:发出信号让对应进程强行立即终止。

8. 参考资料

  1. MIT Missing-Semester Lec01
  2. ACM Class Wiki, shell