1991年10月5日,Linus Torvalds 在互联网上发布消息,宣布他本身开发的内核系统诞生了。他将内核源代码保存在芬兰最大的 FTP 网站上,命名为 Linux,取义 Linus's Minix,并向全世界全部人公布。这也使得10月5日成为一个特殊的日子,以至以后的许多 Linux 版本都选择在这个日子发布。固然,现在的 Linux 一词被递归定义为 Linux is not Unix。linux
Linux 是一套无偿使用和自由传播的类 Unix 操做系统,严格来讲,Linux 一词仅指其操做系统内核,不包括任何附加软件。但现在 Linux 拥有数不胜数的发行版本,广义上它们均可以叫作 Linux,典型表明如 Debian 系列、RedHat 系列、Arch 系列和 SUSE 系列等,它们也都有着各自的侧重和坚持。正则表达式
尽管咱们使用 Windows 或 OS X 操做系统的时候可能不会很在乎桌面环境,但在 Linux 下咱们将须要考虑选择一个中意的桌面环境——也许是多个——或者在某些状况下,彻底没必要安装桌面环境,这是很是灵活且自由的。桌面环境多是由大量组件构成的完整套件,也可能仅仅只是一个简单的窗口管理器,但不管如何,它们的核心目标都是为用户提供一个直观易用的可视化环境和视觉工做区。著名的大型桌面环境 Gnome 和 KDE 提供了杰出的图形表现和丰富的功能组件,轻量桌面环境如 Xfce、mate 和 lxde 等也算是“麻雀虽小,五脏俱全”,更有其余一些专一简洁、美观或是高效的桌面环境可选,所以咱们说 Linux 的桌面环境的选择是“灵活且自由”的。算法
Linux 系统内核并不包括图形服务。想要使用图形环境,必须先安装 X11
,即 X Window 系统,它是最先应用于传统 Unix 系统的图形用户接口,工做于内核与桌面环境之间。这使得 Linux 拥有丰富的桌面环境以供选取。尽管桌面环境可能有风格迥异的设计,但大致上都应包括登陆管理器、窗口管理器、应用启动器等组件,可能还包括一套开箱即用的软件套件,如编辑器、浏览器和终端模拟器等。大部分状况下,在使用桌面发行版的安装镜像正确安装系统后,桌面环境都已经预装并正常工做了。shell
这里以 Manjaro 操做系统为例,简要说明系统安装步骤数据库
从 Manjaro 官网 的下载页面选择合适的版本并将 iso
镜像文件下载到本地(以 KDE 版本为例)。vim
若是使用虚拟机,则此时新建一个虚拟机,将刚才下载的 iso
镜像装载到虚拟机上启动;若要经过U盘安装到本地机器,则可用 Rufus 软件载入镜像并以 DD
模式写入U盘,而后重启计算机,注意正确设置 BIOS 以从U盘启动。浏览器
在 Manjaro 的启动页面进行相关设置,若在接下来的步骤中出现驱动问题,可重回此步并将 driver
项设为 non-free
。安全
进入 live
系统后,启动安装程序,按照提示配置好各项参数,最后点击安装便可。bash
安装完成后,重启计算机并移除U盘,在 Grub 页面选择刚刚安装的 Manjaro 操做系统。服务器
Linux 使用的磁盘分区格式为 ext4
,而 Windows 并不支持(不会显示在资源管理器中)这种格式,所以对于双系统的用户来讲,Linux 系统所占用的磁盘空间须要合理分配。Linux 将文件系统组织为一个树形结构,与 Windows 以盘符区分的方式有所不一样,Linux 的全部目录都是 /
目录的子目录,这个 /
目录称为根目录。对于管理多个分区的 Linux 来讲,它将各个磁盘分区挂载到不一样的目录下,分区的全部文件目录都经过挂载到的目录来访问,所以对于 Linux 文件系统来讲,分区管理是透明的。此外,对于U盘、CD等可移动介质,Linux 也是经过即时挂载、过后卸载的方式管理,这是 Linux 在文件系统上区别于 Windows 的一大特色。
Linux 普通文件系统分区格式通常用 ext4
,而用做交换区的 swap
分区则有专用的 swap
格式,提供与 Windows 虚拟页面文件相似的虚拟内存功能,只不过 Linux 的作法更加完全。这个分区的大小通常设为与物理内存大小相等。
咱们刚才提到,Linux 的目录树是从惟一的一个 /
目录出发,这彷佛预示着,Linux 不能如 Windows 那样用不一样的盘符来分隔不一样种类的文件,但状况偏偏相反,因为 Linux 有挂载点这一说,虽然从文件系统层面上看,全部文件都组织在一个目录树下,但从物理分区上讲,在目录树上的任一节点均可以挂载不一样的分区,这就使得不管如何进行分区,Linux 的文件系统除了选择一个节点挂载它们以外无需做出任何更改,而且能够实现多个 Linux 系统在某个节点共享同一份数据,或者在操做系统每次启动时为它挂载不一样的分区,从而实现每次运行时均可以使用不一样的数据。
另外,在 Linux 的文件系统中,以 .
开头的文件名被认为是隐藏文件,更特殊的,./
和 ../
分别意味着 当前目录 和 上级目录 ,它们不是实际存在的文件,仅表明两个入口。事实上,Linux 隐藏文件的设定并不是为了对某些文件进行保密,而只是将不须要显示在前台的文件加上标记,它们一般是系统和一些软件的资源文件或应用数据目录,而且用户不须要在前台看到它们。
NFS - 网络文件系统,是一套可扩展、高性能、高质量的共享文件系统,只需从一个或多个服务器上创建数据仓库,多个客户端便可经过用户接口访问数据并加载到本地空间,如同本地的可插拔文件系统通常。它与普通文件系统惟一的区别在于其 I/O 请求是跨越网络完成的。
Linux 有运行级别的概念,目前来讲定义了七种运行级别:
这些运行级别分别对应着不一样的服务组,这些服务项在开机时由 init
负责启动,通常这些都存储在 /etc/rc.d/rcN.d/
目录下,但有些系统并不遵循这个标准——好比 Arch。通常来讲,用户经常使用的默认运行级别为3和5——做为服务器时一般为3,做为桌面操做系统一般使用5——当咱们须要执行一些特殊操做时,可能须要手动进入单用户状态,如重置 root
用户密码等。
注:
若要恢复删除的系统文件,请进入救援模式而不是单用户模式,由于单用户模式也须要从硬盘引导启动!
不要将系统默认启动状态设为0或6,不然系统将没法正常启动,切记!
Linux 系统的一个很是重要的工具就是 shell,它是 Linux 用户操做计算机的桥梁,其本质是一个命令解释器(CLI),文字模式下系统启动后进入的界面就是 shell,而在图形界面中一般要经过 终端模拟器 来进入。所谓终端,指的就是这种经过 shell 进行用户交互的软件。在 KDE 下,咱们使用 Konsole 终端模拟器。著名的终端模拟器还有 Terminal、Yakuake 等。而选择好终端模拟器后,咱们还须要选择一个 shell ——默认状况下,系统预设 shell 是 bash ——个人选择是 Zsh。
前面提到,shell 是一个命令解释器,那么它的工做就很好定义了:接收用户输入的命令,执行它们,并输出执行结果。这就是典型的 shell 的工做模式。shell 不少预置命令都由两个字母构成——事实上,若非键盘上只有26个字母,可能如今的命令就只有一个字母了——这些命令可以执行简单的文件目录管理。
# 切换工做目录 cd ~/Documents # 列出目录下的文件/目录列表 ls [-alh] # 显示当前工做目录 pwd [-P] # 更新文件的修改日期,通常用来建立文件 touch main.c # 建立目录 mkdir test # 移动和复制文件,可用于重命名 mv a.c test/ mv a.c b.c cp a.c a.c.back # 删除文件或目录 rm a.c rm -r test/ # 建立连接文件,相似 Windows 快捷方式 ln -s ~/Documents/clang # 列出文件内容 cat a.c # 回显命令,可显示环境变量 echo Hello, $HOME.'\n'This is my Path:'\n'$PATH
除了一些特殊命令外,shell 中运行的命令一般都是实际存在的程序,shell 会从用户的 PATH
环境变量中定义的路径查找命令并执行,路径之间以 :
分隔。一般,PATH
环境变量并不包括 当前目录,所以,若要执行目录下的程序,应以 ./
开头。
做为命令解释器,shell 除了可以解释执行用户输入的指令外,也可以执行脚本文件。下例是一个典型的 shell 脚本:
#!/usr/bin/bash # 我是注释 # 巧了,我也是 echo "Currently working in `pwd`" echo "Host: `hostname`" ret=yes ping -c 2 www.baidu.com > /dev/null || ret=no echo "Am I online? $ret" echo "Now running: $0" figlet -f standard "The end."
要运行这个脚本,能够为它指定一个解释器:
bash xxx.sh
也能够先赋予它 可执行权限
,再直接执行:
chmod +x xxx.sh ./xxx.sh。
一个特殊的脚本是,shell
在用户目录下保存的名为 .bashrc
的文件(或 .zshrc
等),它是属于 shell
的一个资源文件,这意味着每次启动用户的 shell
时,它都会预先寻找并分析此文件的内容,并执行相应的初始化命令。常见的用法包括在此文件中添加别名定义、添加环境变量配置等。
# ~/.bashrc alias ll='ls -alF' alias df='df -h' export PATH=PATH:$HOME/.local/bin
远程终端 Telnet 和 SSH,顾名思义,它们提供了终端远程访问的服务,其中 Telnet 因彻底不加密、采用明文传输而一般只用于受信网络,如企业内部网络、局域网络等,而 SSH 采用非对称加密算法保证了交互链接的安全性,适用于公开网络。两者在功能使用上相似,这里只讨论 SSH 链接方式。Telnet 有时也用来测试端口的连通性。
要在客户端使用 SSH 链接到服务器,首先要确保服务端已正确配置了 sshd
服务。以 CentOS 7 服务器为例,安装并配置 sshd
:
# 安装 sshd yum install openssh-server -y # 启动服务 systemctl start sshd # 修改 sshd 配置 nano /etc/ssh/sshd_config # 这里通常须要取消注释 PasswordAuthentication yes 行 # 以容许经过用户密码远程登陆 # 重启服务 systemctl restart sshd
按照惯例,咱们不以 root
用户登陆。事实上,不少状况下,远程 root
用户登陆也是默认禁用的。若服务器还没有添加非 root
用户,可以使用如下命令添加:
# -G 指定附加用户组,-g 指定主要用户组 useradd -m -G wheel dog # 设置新用户密码 passwd dog
到这里,服务器端的 sshd
配置已经完成了,只要在防火墙中开放服务端口,远程客户端就能够链接。不论您的服务器系统使用 iptables
仍是 firewalld
,默认状况下它们都已经开放了22端口,也就是 sshd
服务的默认端口。若有例外,或您要使用其余端口,请稳步防火墙相关文档。那么如何从客户端链接到服务器系统呢?第一种方法是使用用户密码登陆。
# 使用 用户名@主机地址 的形式,能够是ip地址或域名 ssh dog@192.168.1.2 # 或用 -l 指定用户名 ssh 192.168.1.2 -l dog # 使用 -p 指定链接端口 ssh dog@192.168.1.2 -p 22
更懒一点,若是不但愿每次都输入冗长的用户名和主机地址,还能够选择将它们保存在 ssh
配置文件中:
# 编辑配置文件 nano ~/.ssh/config
按如下格式填写远程服务信息:
Host superuser Hostname 192.168.1.2 User root Port 24 Host dog Hostname 192.168.1.2 User dog Port 22
此时就能够分别使用 ssh superuser
和 ssh dog
命令链接远程终端了——固然,密码仍是要输入的。若是连密码也懒得输入怎么办呢?这就不得不说咱们的第二种链接方式了:密钥登陆。事实上,SSH 服务自己就是使用非对称加密确保其链接的安全性,天然也就拥有经过密钥对完成登陆的功能。要实现公/私钥登陆,须要进行如下配置:
# 客户端生成 rsa 密钥对 ssh-keygen -t rsa # 这里会要求输入密码,如无需密码可留空 # 若是设置了密码,则每次登陆都要先输入密钥密码 # 下面将本地生成的公钥上传至服务器 ssh-copy-id dog # 这里将会要求输入密码,并极可能会是您最后一次密码登陆,珍惜吧
本地的 ~/.ssh
目录下将会多出两个文件 id_rsa
和 id_rsa.pub
,分别存储私钥和公钥,请必定记住不要泄露您的私钥。服务器的 ~/.ssh
目录下也会多出一个 authorized_keys
文件,用以保存全部受信任的客户端的公钥信息。
除了远程登陆外,scp
命令还提供了在本地机器和远程主机之间传送文件和目录的方法。
# 将当前目录下的文件复制到远程主机的主目录下 scp main.c dog@192.168.1.2:. # 从远程主机复制整个目录到本地,并指定端口 scp -r -P 22 dog:./minecraft .
在计算机集群配置过程当中,有时可能也会用到
ssh-keyscan
命令来大规模收集集群内全部主机信息,并将这些信息复制到各机器目录下,以实现集群内任意两台机器之间都可以无密码互访。ssh
还能够用于从内网主机链接到公网主机并创建隧道,从而实现内网穿透的功能。而为了确保链接的持续性,通常会使用拥有自动重连功能的autossh
代替ssh
。有时,您也能够从客户端经由主机A链接到主机B——若是有必要的话。另外,您还可使用sshfs
命令来挂载远程文件系统,这与 NFS 类似。相关命令使用方法请参阅 SSH 手册页和相关文档。
对于任意一个目录,执行 ls -hl
命令并观察其输出,咱们将看到,每一个项目以前都有一个由十位字符构成的字符串,这表明了一个文件(或目录)的类型和权限。其形式为 -rwxr-xr-x
,第一位表明类型(-/d/l/c/b/s/p),后面九位每三个一组,每位分别表明其读、写、可执行权限,每组分别表示所属用户、所属组和全部人的权限。
Linux 中用户与组的概念比 Windows 要深入得多,除普通用户外,最常涉及的是 root
用户和 wheel
组。在 Linux 下,root
用户是系统的最高管理员,拥有操做任何文件目录的权限,也就有着误操做致使系统崩溃的风险,也可能因执行恶意程序致使系统被劫持,所以通常状况下,咱们不会以 root
身份做业。但与此同时,不少任务又须要这些权限才能执行,好比安装应用或更改启动项,因而 sudo
命令提出了一种普通用户临时获取 root
权限的可能,它容许用户临时获取权限来执行某些操做,而且能够配置用户/组使用 root
身份能够执行哪些操做。通常状况下,做为桌面版用户,咱们也没必要去细分这些权限,因此能够简单地将本身加入到 wheel
组便可拥有 sudo
的权限,wheel
组正是预设的拥有 sudo
权限的组。
与 Windows 系统不一样,尽管 Linux 也容许用户直接运行可执行文件,但这些软件一般会由于依赖问题等缘由而不能正常工做。查找和安装应用软件最好的方式是经过软件仓库,不一样的发行版一般会有不一样的软件仓库,咱们称之为 源,用来查找和下载安装软件包并解决依赖关系的工具称为 包管理器,如 Ubuntu 使用 apt
和 dpkg
,CentOS 使用 yum
和 rpm
,Manjaro 使用 pacman
等。
咱们刚才屡次说起 依赖,简单来讲就是指某个包使用了另外一个包提供的接口,于是须要该包的支持才能运行,故安装某个包可能同时须要为它安装全部的依赖,卸载某个包又要考虑有没有哪些包是依赖它而运行的,同时还要注意是否存在多个包依赖着同一个包的不一样版本。这些检查和操做是必要的,不然长此以往你将不知道本身的系统上哪些包是无用的,哪些是不可或缺的,也就不敢轻易安装和卸载应用了。
用户获取软件包的来源一般是官方或官方信任的镜像站点,这些一般叫作软件仓库或 源。做为天朝子民,为了加速软件包的下载,咱们每每会选择国内的镜像源,如清华源、中科大源、华为云等。更改系统镜像源的操做这里不做细讲,咱们以 apt
和 pacman
为例,简要介绍软件安装、卸载和搜索等操做。
# 更新数据库 sudo apt update sudo pacman -Sy # 以更新软件包的方式更新系统 sudo apt upgrade sudo pacman -Su # 安装 vim sudo apt install vim sudo pacman -S vim # 卸载 libreoffice sudo apt remove libreoffice* sudo pacman -R libreoffice*
Linux 终端若没法承担文字编辑任务,便担不得强大之名。事实上,若论终端文字编辑工具,nano
、vim
、Emacs
均为此类,但 nano
侧重简单易用,而 vim
和 Emacs
则拥有着强大的功能。较之 Emacs
提供了丰富的组合键,vim
则更倾向于使用单键执行操做。若您更喜欢 Emacs
的优雅,请暂且移步 Emacs
教程;若您与我一样选择 vim
,欢迎继续阅读。
在终端下启动 vim
# 启动 vim [并打开文件 xxx.sh] vim [xxx.sh]
vim
各类模式
启动 vim
后,默认进入的是 NORMAL
模式,即普通模式(有时也称命令模式),在此模式下能够移动输入光标,执行单键命令,并可键入 :
激活底部命令模式。在此模式下,h
/j
/k
/l
分别表示左/下/上/右。当按下 i
/a
(I
/A
) 时,将从当前光标所在字符之前/后(行首/行尾)进入 INSERT
模式,即插入模式。若按下 v
/V
/Ctrl
+v
时进入 VISUAL
/ VISUAL LINE
/ VISUAL BLOCK
模式,即视图模式。在普通模式下,还能够按 x
/d
执行删除、按 y
执行复制、按 gg
/G
/^
/$
跳转至开头/结尾/行首/行尾、按 u
/Ctrl
+r
执行撤销/重作操做。
在 INSERT
模式下可以执行字符输入操做,完成输入后按 Esc
结束。在 VISUAL
模式下能够移动光标进行文本选取,并进一步执行 d
/y
等完成删除/复制等操做。在任何模式下,您均可以按 Esc
返回到普通模式,并请记住,vim
区分大小写,所以时刻注意您的键盘状态!
在使用 vim
编辑文档和代码时,请注意在普通模式和插入模式之间灵活切换,以将输入操做碎片化,从而可以更灵活地执行撤销与重作操做,由于 vim
将每次从进入插入模式开始,到按 Esc
回到普通模式的一整个过程认为是一次插入操做。当编辑完成后,能够键入 :wq
或 :x
来保存文件并退出 vim
。若是要丢弃修改,不保存而直接退出,能够键入 :q!
。
vim
查找与替换
在普通模式下,按下键盘上的 /
键即进入查找模式,此时在底部会显示键入信息,支持正则表达式,按下 Enter
完成键入并跳转到查找到的高亮结果。如需暂时关闭高亮,请在底部命令模式下执行 nohl
命令。
vim
的替换命令更增强大。其基本格式为 :[range]s/from/to/[flags]
,其中冒号表示进入底部命令模式,range
表示范围(行),from
表示查找目标,能够是正则表达式,to
表示替换成的字符串,flag
表示选项:g
-替换全部 / c
-替换前确认 / e
-忽略错误。例:
# 将每一行的全部 `Flag` 替换为 `flag` :%s/Flag/flag/g # 将第6行的第一个 `int` 替换为 `double` :6s/int/double/ # 将从第8行到倒数第5行的全部数字替换为 `num` :8,$-4s/[0-9]\+/num/g # 将光标所在行的下一行的全部单词删除 :.+1s/[a-z|A-Z]\+//g
vim
多文件编辑
多窗口模式:在终端中键入 vim -o2 [xxx.cpp [yyy.cpp]]
可将视图水平分割成上下两个窗口,若参数使用大写字母 O
则为竖直分割。此外,在 vim
的普通模式下,键入 :split
可水平分割为上下两个窗口查看当前文件,或键入 :vsplit
竖直分割。固然,若 split
命令有参数,则尝试打开文件。在多窗口状态下,按下组合键 Ctrl
+w
激活窗口操做,此时可按 h
/j
/k
/l
切换窗口,并可按 r
/R
/x
/X
交换窗口位置。
多标签模式:在终端中键入 vim -p2 [xxx.cpp [yyy.cpp]]
可激活 vim
的多标签页模式,或在 vim
中执行 :tabe [file.txt]
创建新的标签页(并在新标签页中打开文件 file.txt
)。在此状态下,键入 gt
/gT
可顺序/逆序遍历标签页。
vimrc
资源文件
与 shell
相似,vim
在启动时会载入一个资源文件,并分析执行资源文件中预约义的全部命令。这通常包括 vim
的个性化设置如视图布局和主题等,还会有一些 vim
插件的配置数据,有时咱们也会在其中编写一些按键映射和函数定义,用以执行一些自动化操做,特别是编译和运行程序。要配置一个适合于本身的 vimrc
文件,请移步相关教程和文档,这里不做赘述。
众所周知,C语言程序调试分两步走:码代码、跑程序,固然,这是由于中间一系列步骤都被各大 IDE 简化了。即便如今,手里握着 Linux 的咱们依旧能够选择使用 IDE,而且咱们也确实有许多优秀的候选项。不过这篇文章并不是介绍这些 IDEs for Linux,做为开箱即用的软件套件,它们几乎不须要被介绍。即便您仍是但愿选择一个 IDE,最好也了解一下背后的过程。
简单来讲,C语言从代码到目标程序的构建过程分为预处理、编译、汇编、连接四步,在没有 IDE 帮助的情形下,咱们就须要手动完成这些操做。幸运的是,编译器一般容许咱们忽略中间的具体步骤,直接从输入源代码到输出目标程序。天然,咱们也能够选择输出中间文件,这在不少状况下每每十分必要。假如咱们如今已经拥有一个使用 vim
或其余任何编辑器编写的源代码文件 hello.c
,咱们能够在 shell
中使用 GCC 工具(GNU Compiler Collection)完成编译操做:
# 若无 GCC 套件,先安装 sudo apt install gcc sudo pacman -S gcc # 将 hello.c 编译成目标程序(`-o` 选项可指定输出文件名) gcc hello.c [-o hello.out] # 执行编译输出的可执行文件(参数) ./a.out [argument list] # 只进行到汇编,输出 obj 文件 gcc -c hello.c [-o hello.o] # 只进行到编译,输出汇编代码文件 gcc -S hello.c [-o hello.s] # 只做预处理,从标准输出展现结果(可重定向到文件) gcc -E hello.c [> hello.txt] # 编译过程当中产生调试信息 gcc -g hello.c # 显示全部警告信息 gcc -Wall hello.c # 优化级别 [0-4] gcc -O2 hello.c # 更多用法请参考 `man gcc`
在进行大型项目、多文件的软件开发过程当中,逐个编译源文件是很是不明智的,这时候能够考虑采用
makefile
自动化编译过程,经过分析文件之间的依赖关系,确保全部文件保持最新,同时又不执行冗余的操做。好比当某一个或多个文件更改时,没必要从新处理全部源代码,而只须要从新编译修改的文件和引用它的文件。如您正有相关需求,请移步makefile
相关文档。
到这里,咱们已经完成了将源代码构建为目标程序的过程,若是编译时加入了调试信息,那么如今可使用 gdb
进行调试工做——尽管这也许会至关麻烦。咱们能够经过 gdb -h
和 man gdb
命令来获取它的参数和命令以及其余介绍,这里给出一个示例。
# 启动 gdb (并打开目标程序) gdb [a.out]
gdb
相关命令:
(gdb) file a.out 载入可执行文件 (gdb) list 列出源代码 (gdb) break 6 在第六行添加断点 (gdb) run hello world argu3 argu4 运行待调试程序并给出参数列表 (gdb) print str 输出当前变量 str 的值 (gdb) next 执行下一条语句,不进入函数 (gdb) step 执行下一条语句,进入函数内部 (gdb) display i 监视变量 i (gdb) continue 继续运行,直到下一个断点 (gdb) delete 1 删除编号为1的断点 (gdb) delete display 1 删除编号为1的监视点 (gdb) kill 终止程序执行 (gdb) quit 退出调试器
暂停笔于此,若有谬误,欢迎指正!