第5章 贝壳里的树莓派
树莓派的图形化桌面算不上精美,如果真想用图形化界面进行办公,那么你恐怕会失望。用树莓派的浏览器打开网站上的视频,很可能会遭遇页面加载缓慢和视频播放卡顿等情况。如果想打开多个窗口工作,那么桌面很容易崩溃。毕竟,树莓派的性能不高,而计算机图形的呈现相当消耗资源。幸好,Linux提供了一种更易与树莓派互动的方式——Shell。
5.1 初试Shell
打开终端,桌面上就会出现一个黑色背景的窗口,窗口上显示着:
pi@raspberrypi:~ $
这里的pi是用户名,raspberrypi是计算机的名字,$是命令提示符。如果敲击键盘,那么字符会显示在$提示符的后面,形成一串文本形式的命令。在英文中,Shell是贝壳之类的外壳。在Linux中,所谓的Shell,就是运行在终端中的文本互动程序。Shell分析文本输入,然后把文本转换成相应的计算机动作。用户透过Shell这个“壳”,来触及电脑。贝壳里的Shell,如图5-1所示。
图5-1 贝壳里的Shell
在后面的内容中,将用$来表示Linux系统Shell的命令提示符,例如输入date命令:
$date
date用于日期时间的相关功能。按Enter键后,Shell会显示系统的当前时间。
Shell看起来简陋,但实际上比图形化桌面强大得多。Linux操作系统继承自UNIX操作系统。无论是Linux操作系统,还是UNIX操作系统,最初都只提供了Shell这一种用户操作界面。如果你习惯了这种文本操作方式,会渐渐体会到它的好处。
5.2 用命令了解树莓派
为了展示Shell的功能,首先介绍一些命令,用于查询系统信息,例如CPU的型号、内存的大小、IP地址等。这些命令可以让你更加了解树莓派的硬件,另一方面,你也可以借此机会体验一下Shell。
1.Linux通用查询命令
Linux系统提供了各种各样的命令。在Shell中输入这些命令可以实现许多功能。首先用lscpu命令来查询CPU的信息:
$lscpu
终端窗口中就会打印出CPU的信息:
Architecture: armv7l Byte Order: Little Endian CPU(s): 4 On-line CPU(s) list: 0-3 Thread(s) per core: 1 Core(s) per socket: 4 Socket(s): 1 Model name: ARMv7 Processor rev 4 (v7l) CPU max MHz: 1200.0000 CPU min MHz: 600.0000
可以看到,这个树莓派用的是4核的ARM处理器,最高频率可以达到1200MHz。
然后,可以用free命令来了解内存的使用状况:
$free -h
在使用上面的命令时,增加了-h的选项(option)。通过给命令增加选项,可以改变命令的行为方式。这里的字母h是human readable的意思。如果不使用-h选项,那么free命令会以字节为单位显示结果。有了-h选项,free可以将结果转换成更适合显示的单位。
Shell打印的结果如下:
total used free shared buffers cached Mem: 862M 739M 122M 14M 44M 397M -/+ buffers/cache: 298M 563M Swap: 99M 0B 99M
可以看到,内存总量是862MB,其他列中还显示了已用和可用的内存空间。通过增加选项,Linux命令的功能变得更加丰富。
再看SD卡的存储情况,用命令fdisk:
$sudo fdisk -l
命令fdisk用于显示磁盘信息。选项-l表示列出所有磁盘。可以看到命令前面增加了sudo。某些命令的运行需要特殊权限,而sudo提供了以系统管理员的身份来执行后面的命令,即fdisk -l。结果的最后两行如下:
Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 131071 122880 60M c W95 FAT32 (LBA) /dev/mmcblk0p2 1310723031859130187520 14.4G 83 Linux
整个SD卡被分成了两个分区,其中的一个分区有60MB,专门用于树莓派的开机启动;另一个分区用于储存其他的所有数据。
使用lsusb,可以找到所有的USB外设:
$lsusb
Shell将打印:
Bus 001 Device 005: ID 0e8f:2517 GreenAsia Inc. Bus 001 Device 006: ID 045e:0750 Microsoft Corp. Wired Keyboard 600 Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
使用uname命令,可以打印出操作系统的信息:
$uname -a
选项-a表示显示所有的相关信息。Shell将打印:
Linux raspberrypi 4.1.19-v7+ #858 SMP Tue Mar 15 15:56:00 GMT 2016 armv7l GNU/Linux
这里的系统使用的内核是Linux 4.1.19版本,而内核的发布时间是2016年3月15日。
最后,用ifconfig命令来查看网络接口:
$ifconfig
命令运行结果如下:
eth0 Link encap:Ethernet HWaddr b8:27:eb:d8:ed:f4 inet6 addr: fe80::9b8b:c0de:d083:6ddd/64 Scope:Link UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:65536 Metric:1 RX packets:243 errors:0 dropped:0 overruns:0 frame:0 TX packets:243 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:19020 (18.5 KiB) TX bytes:19020 (18.5 KiB) wlan0 Link encap:Ethernet HWaddr b8:27:eb:8d:b8:a1 inet addr:192.168.0.108 Bcast:192.168.0.255 Mask:255.255.255.0 inet6 addr: fe80::ba27:ebff:fe8d:b8a1/64 Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:45926 errors:0 dropped:4268 overruns:0 frame:0 TX packets:10469 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:26867855 (25.6 MiB) TX bytes:1360267 (1.2 MiB)
其中eth0代表了以太网接口,wlan0代表了Wi-Fi接口,而lo是虚拟出来的本地接口,用来表示本机。在连接上网的接口中,我们可以看到该接口的IP地址等信息。例如wlan0的IP地址是192.168.0.108。因为没有插网线,所以eth0并没有IP地址。
2.树莓派专用查询命令
除通用的Linux命令外,树莓派还提供了vcgencmd命令,用于和树莓派硬件直接互动。比如在Shell中执行:
$vcgencmd measure_temp
在上面的命令中,第二段的measure_temp是命令的参数。参数是选项之外另一种给命令提供额外信息的方式。上面的命令将返回CPU的温度:
temp=51.5'C
用下面的命令测量树莓派的核心电压:
$vcgencmd measure_volts core
返回电压值:
volt=1.2000V
5.3 什么是Shell
Shell是UNIX系统提供的文本交互界面。你只要用键盘输入命令就可以和操作系统交互,但这还是不够具体。说到底,Shell其实是一个运行着的程序。这个程序接收到你两次单击“Enter”键之间的输入,就会对输入的文本进行分析,比如下面这个命令:
$free -h
包括空格在内总共7个字符。Shell程序通过空格区分出命令的不同部分。第一个部分是命令名,剩下的部分是选项和参数。在这个例子中,Shell会进一步分析第二个部分,发现这一部分的开头是“-”字符,从而知道它是一个选项。
有了命令名,Shell下一步就要执行该命令名对应的动作。这听起来就像是在戏剧舞台上,演员按照脚本演戏。Shell命令可以分为如下三类。
●Shell内建函数(built-in function)。
●可执行文件(executable file)。
●别名(alias)。
Shell的内建函数是保存在Shell内部的脚本。相对应地,可执行文件是保存在Shell之外的脚本。Shell必须在系统中找到对应命令名的可执行文件,才能正确执行。我们可以用绝对路径来告诉Shell可执行文件所在的位置。所谓路径,是指一个文件在存储空间的位置,例如:
/bin/date
这个路径表明date这个可执行文件位于根目录下的bin文件夹内。
如果用户只给出了命令名,而没有给出准确的位置,那么Shell必须自行搜索一些特殊的位置,也就是所谓的默认路径。Shell会执行第一个和命令名相同名字的可执行文件。这就相当于,Shell帮我们自动补齐了可执行文件的位置信息。我们可以通过which命令来确定命令名对应的是哪个可执行文件:
$which date
别名就是给某个命令起的一个简称,以后在Shell中就可以通过这个简称来调用对应的命令。在Shell中,我们可以用alias来定义别名:
$alias freak="free -h"
Shell会记住我们的别名定义。以后在这个Shell中输入命令freak时,都将等价于输入free -h。
在Shell中,可以通过type命令来了解命令的类型。如果一个命令是可执行文件,那么type将打印出文件的路径。
$type date $type pwd
总的来说,Shell就是根据空格和其他特殊符号,来让电脑理解并执行用户要求的动作。到了后面,我们还将看到Shell中的其他特殊符号。
5.4 Shell的选择
Shell是文本解释器程序的统称,所以包括了不止一种Shell。常见的Shell有sh、bash、ksh、rsh、csh等。在树莓派中,就安装了sh和bash两个Shell解释器。sh的全名是Bourne Shell,其中Bourne就是这个Shell的作者。而bash的全名是Bourne Again Shell。在UNIX系统中流行的是sh,而bash作为sh的改进版本,提供了更加丰富的功能。一般来说,都推荐使用bash作为默认的Shell。树莓派及其他Linux系统中广泛安装了sh,都是出于兼容历史程序的目的。
我们可以通过下面的命令来查看当前的Shell类型:
$echo $SHELL
echo用于在终端打印文本,而$是一个新的Shell特殊符号,它提示Shell,后面跟随的不是一般的文本,而是用于存储数据的变量。Shell会根据变量名找到真正的文本,并替换到变量所在的位置。SHELL变量存储了当前使用的Shell的信息,可以在bash中用sh命令启动,用exit命令从中退出。
5.5 命令的选项和参数
我们已经看到,一行命令里还可以包含着选项和参数。总的来说,选项用于控制命令的行为,而参数说明了命令的作用对象,例如:
$uname -m
在上面的命令中,选项-m影响了命令uname的行为,导致uname输出了树莓派的CPU型号。如果不是受该选项的影响,那么uname输出的将是Linux。我们不妨把每个命令看作多功能的瑞士军刀,而选项使命令可以在不同的功能间切换。由一个“-”引领一个英文字母,这称为短选项。多个短选项的字母可以合在一起,跟在同一个“-”后面。比如,下面的两个命令是等价的:
$uname -m -r $uname -mr
此外还有一种长选项,是用“--”引领一个英文单词,比如:
$date --version
上面的命令将输出date程序的版本信息。
如果说选项控制了瑞士军刀的行为,那么参数就提供了瑞士军刀发挥用途的原材料。以echo命令为例,它能把字符打印到终端。它选择打印的对象,正是它的参数:
$echo hello
有的时候,选项也会携带变量,以便说明选项行为的原材料,比如:
$sudo date --set="1999-01-01 08:00:00"
选项“--set”用于设置时间,用等号连接的就是它的参数。date会把日期设置成这一变量所代表的日期。如果用短选项,那么就要用空格取代等号了:
$sudo date -s "1999-01-01 08:00:00"
值得注意的是,Shell对空格敏感。当参数信息中包含了空格时,我们需要用引号把参数包裹起来,以便Shell能识别出这是一个整体。
选项和参数都是提供给命令的附加信息,因此,命令最终会拿这些字符串做什么,是由命令自己决定的。因此,有时会发现一些特异的选项或参数用法。这个时候,就要从文档中寻找答案。
5.6 如何了解一个陌生的命令
每一个Linux系统都带有一套完善的文档用于解释每个命令的用途。你可以用下面三个命令来调用某个命令的文档信息。
1.whatis
$whatis ls
whatis命令的作用是用很简短的一句话来介绍命令。
2.man
$man ls
man会返回命令的帮助手册。对于大部分Linux自带的命令来说,作者编写时,都会写一个帮助文档,告诉用户怎样使用这个命令。man可以说是我们了解Linux最好的百科全书,它不仅告诉你Linux自带的命令的功能,还可以查询Linux的系统文件和系统调用。如果想要深入学习Linux,就必须要懂得如何用man来查询相关文档。
3.info
$info ls
info将返回更详细的帮助信息。
5.7 Shell小窍门
使用Shell时应用一些小窍门,可以让你事半功倍。
1.命令补齐
大多数的Shell都有命令补齐的功能。当你在$的后面输入命令的一部分时,比如“dat”,按Tab键,Linux会把它补充成为“date”。在这个过程中,Shell会搜索该命令名的所有可能。如果只有一种可能,那么Shell就会把该文件名补齐。如果不止一种,那么第一次按Tab键会没有反应,第二次按Tab键时,终端会打印出所有可能的命令名。比如输入“da”,按两次Tab键后,终端输出:
dash date
这样的提示,能帮你想起自己想要输入的命令。
2.文件名补齐
不止是命令名,如果输入的是作为参数的文件名,Linux也可以帮你补齐。比如,当前目录下有a.txt文件。当你输入到ls a.t的时候,按Tab键,Shell会帮你补齐该文件名,即lsa.txt。
3.历史命令
在Shell中,可以用向上箭头,或history命令来查看之前输入的命令。
$history
4.中止与暂停命令
当一个命令运行时,如果中途想要停止它,那么可以用快捷键Ctrl+C。如果只是想暂时停止,那么可以使用快捷键Ctrl+Z。中止与暂停应用了Linux中的信号(Signal)机制,笔者将在第23章介绍。