初识shell
# 初识shell
还记得shell的定义吗?shell是一种特殊的交互式工具——接收我们输入的命令,解析后调用系统中对应资源完成某个任务或者执行某个程序的工具。它通常是在用户登录终端时就启动。登录时系统启动的shell依赖于用户账户的配置。
# 命令提示符
之前说过,linux中有多种不同类型的shell,那我们怎么看我们当前使用的是哪种呢?最简单的方法就是看命令提示符或者看/etc/passwd
文件中的记录。
cat -n /etc/passwd
# 以下是部分输出
1 root:x:0:0:root:/root:/bin/bash
2 bin:x:1:1:bin:/bin:/sbin/nologin
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
4 adm:x:3:4:adm:/var/adm:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
6 sync:x:5:0:sync:/sbin:/bin/sync
7 shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
8 halt:x:7:0:halt:/sbin:/sbin/halt
# /etc/passwd 文件包含了系统中所有用户的账号信息,其中包括默认shell的信息。每一行代表一个用户,而该行中的最后一个字段就是该用户的默认shell路径。 root 用户的默认shell 就是 bash shell
#或者你也可以尝试 以下命令来查看 系统默认的shell
echo $SHELL
/bin/bash
# 该系统默认的shell 是bash shell(这也是大多数linux系统默认的shell类型)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
不同的Shell可能会有不同默认的命令提示符。命令提示符是用来指示Shell准备接受用户输入的符号,它虽然不是Shell命令的一部分,但对于用户交互而言非常重要。其主要作用包括但不限于以下几个方面:
- 指示输入状态:最直接的作用是提示用户系统已经准备好接受命令输入。显示的不同符号(如
$
对于普通用户,#
对于超级用户)还能即时反映当前登录用户的权限级别。 - 提供上下文信息:命令提示符通常包含丰富的上下文信息,如当前用户的名字、主机名、工作目录路径等,帮助用户了解当前操作的环境和位置,这对于在多用户或多主机环境下工作尤为重要。
- 提高效率:熟悉命令提示符的用户可以通过提示符快速识别自己的位置和环境,无需额外命令即可决定下一步操作,从而提升命令行操作的效率。
- 定制化和个性化:用户可以根据个人偏好或工作需求定制命令提示符,比如添加颜色编码、显示Git分支、时间戳等,使提示符更加符合个人习惯或工作流程。
下面就介绍几个常见的Shell及其默认提示符的例子:
- Bash Shell:
- 对于普通用户,默认提示符通常是美元符号
$
。 - 对于超级用户(root用户),默认提示符通常是井号
#
。
- 对于普通用户,默认提示符通常是美元符号
- Zsh Shell:
- Zsh的默认提示符可能看起来比Bash的更复杂,它通常包含用户名、主机名、当前工作目录等信息,并且可以根据用户配置高度定制。(
Mac上的默认shell
似乎就是zsh)
- Zsh的默认提示符可能看起来比Bash的更复杂,它通常包含用户名、主机名、当前工作目录等信息,并且可以根据用户配置高度定制。(
- C Shell (csh/tcsh):
- C Shell的默认提示符对于普通用户也是
%
或$
,而对于超级用户则是#
。
- C Shell的默认提示符对于普通用户也是
- Fish Shell:
- Fish Shell的默认提示符通常只显示一个普通的>` 符号,但它也支持非常丰富的提示符定制,可以显示彩色的、包含各种上下文信息的提示。
# bash手册
大多数Linux发行版自带用以查找shell命令及其他GNU工具信息的在线手册。熟悉手册对使用各种Linux工具大有裨益,尤其是在你要弄清各种命令行参数的时候。
man 命令用来访问存储在Linux系统上的手册页面。在想要查找的工具的名称前面输入man 命令,就可以找到那个工具相应的手册条目。
比如:
man bash
之后就会显示如下信息:
BASH(1) General Commands Manual BASH(1)
NAME
bash - GNU Bourne-Again SHell
SYNOPSIS
bash [options] [file]
COPYRIGHT
Bash is Copyright (C) 1989-2011 by the Free Software Foundation, Inc.
DESCRIPTION
Bash is an sh-compatible command language interpreter that executes commands read from the standard input or from a file. Bash also incorporates use‐
ful features from the Korn and C shells (ksh and csh).
Bash is intended to be a conformant implementation of the Shell and Utilities portion of the IEEE POSIX specification (IEEE Standard 1003.1). Bash can
.........
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在使用 man bash
命令查看Bash的手册页后,你可以通过以下按键进行翻页操作:
- 向下翻页:按空格键(Space)或 Page Down 键可以向下翻动一页。
- 向上翻页:按 b 键(在某些系统中可能需要按 Page Up 键)可以向上翻动一页。
- 搜索关键词:在任何时候,你可以输入
/keyword
(其中 "keyword" 是你想查找的内容)并按回车来进行向前搜索。按下 n 键会跳到下一个匹配项,而 N 键则会跳到上一个匹配项。 - 移动到页首或页尾:按
Home
键可以快速跳到手册页的开头,按End
键可以跳到手册页的结尾。 - 退出:按 q 键可以随时退出
man
命令,返回到命令行界面。
以上操作是在大多数Linux终端环境中通用的,但根据所使用的终端模拟器或特定系统的配置,某些快捷键可能有所不同。
# 文件系统与路径
shell指令常常会包含一些路径参数,要想正确是使用它们,首先就要对Linux中的文件系统的路径有一个正确的认识。
它跟windows最大的区别就是,Linux 系统摒弃了Windows中使用盘符(如C:, D:\等)的方式来组织磁盘和文件系统,转而采用单一的根目录(/)结构,之所以如此设计,主要是因为以下几个原因(原因有很多,这里只列出其中较为重要的几个):
- 统一的文件系统视图:Linux的设计哲学之一是提供一个一致且透明的文件系统层次结构。通过将所有文件和目录组织在一个统一的树形结构下,用户和程序可以以相同的方式访问任何位置的文件,无论它们位于哪个物理磁盘上。这简化了路径管理和文件访问逻辑,使得跨磁盘的文件操作更为直观。
- 灵活的挂载点:Linux允许用户将磁盘分区或存储设备挂载到文件系统树的任意目录下,而不是固定于特定的盘符。这种机制提供了极高的灵活性,可以根据需要动态调整存储布局,例如将/home目录单独放在一个分区,/var/log放在另一个高速磁盘上以优化性能,或是临时挂载外部存储设备到任意目录。
- 简化系统管理:单一的根目录结构简化了系统管理任务,尤其是在涉及到备份、恢复和迁移时。管理员不需要单独考虑每个盘符的内容,而是可以一次性处理整个文件系统,或对特定挂载点进行操作,这在自动化脚本和配置管理中尤为有用。
- 历史和兼容性:Linux和其他类UNIX系统沿袭了早期UNIX系统的文件系统设计理念,其中根目录结构是核心组成部分。这种设计已经经过数十年的实践检验,证明了其在多种应用场景下的有效性和适应性。
- 网络透明性:Linux和UNIX系统设计之初就强调网络和分布式计算的能力。单一的文件系统树使得网络文件系统(如NFS)的集成变得自然,远程文件系统可以如同本地文件系统一部分那样被挂载和访问,增强了系统的网络透明性和可扩展性。
- 安全性和权限控制:Linux的权限模型是基于用户、组和文件/目录权限的。单一的根目录结构配合严格的权限控制,使得系统管理员可以精细地控制对不同资源的访问,避免了因盘符导致的权限管理复杂性,提高了系统的整体安全性。
- 支持多种文件系统类型:Linux支持多种文件系统类型(如ext4, XFS, Btrfs等),并且可以在同一个系统中同时使用这些不同类型的文件系统。单一的根目录结构配合挂载点机制,使得用户可以灵活地在不同场景下选择最合适的文件系统,而不需要担心盘符分配的问题。
- 脚本和自动化:在Linux中,大量管理任务通过脚本自动化完成。单一的根目录和明确的挂载点使得脚本编写更加简单直接,因为路径不会因磁盘变化而变化,这有利于保持脚本的稳定性和跨环境的兼容性。
综上所述,Linux采用单一的根目录和挂载点机制,旨在提供一个简单、灵活、统一且高效的文件管理系统,适应现代计算环境的多样需求。
注意:在Linux中,路径分隔符使用的是——正斜线(/)在文件路径中划分目录。在Linux中,反斜线用来标识转义字符,要是用在文件路径中的话会导致各种各样的问题。
如:/usr/tmp
# 常见的目录
常见的目录名均基于文件系统层级标准(filesystem hierarchy standard,FHS)。很多Linux发行版都遵循了FHS。这样一来,你就能够在任何兼容FHS的Linux系统中轻而易举地查找文件。
换句话说,无论你使用的是Ubuntu、Fedora、Debian还是其他主流Linux发行版,你都会发现它们的主要目录结构非常相似,包括但不限于以下常见的目录:
目录 | 用途 |
---|---|
/ | 虚拟目录的根目录。通常不会在这里存储文件 |
/bin | 二进制目录,存放许多用户级的GNU工具。(或者说存放系统的基本用户命令) |
/boot | 启动目录,存放启动文件 |
/dev | 设备目录,Linux在这里创建设备节点 |
/etc | 系统配置文件目录 |
/home | 主目录,Linux在这里创建用户目录 |
/lib | 库目录,存放系统和应用程序的库文件 |
/media | 媒体目录,可移动媒体设备的常用挂载点 |
/mnt | 挂载目录,另一个可移动媒体设备的常用挂载点 |
/opt | 可选目录,常用于存放第三方软件包和数据文件 |
/proc | 进程目录,存放现有硬件及当前进程的相关信息 |
/root | root用户的主目录 |
/sbin | 系统二进制目录,存放许多GNU管理员级工具(主要用于系统管理任务) |
/run | 运行目录,存放系统运行时的运行数据 |
/srv | 服务目录,存放本地服务的相关文件 |
/sys | 系统目录,存放系统硬盘信息的相关文件 |
/tmp | 临时目录,可以在该目录中创建和删除临时工作文件 |
/usr | 用户二进制目录,大量用户级的GNU工具和数据文件都存储在这里(用户程序和数据的只读文件,安装程序的主要目录) |
/var | 可变目录,用以存放经常变化的文件,比如日志文件、邮件队列、网页内容等。 |
了解完毕后,你可能想问,那平时安装软件通常装在哪个目录呢?通常来说,安装软件应该遵循FHS指南,在适当的系统目录下安装软件。现如今,我们装软件一般在/usr
,或者/opt
这两个目录。
- /usr/local: 这是预留给用户手动安装软件的地方。当你从源代码编译安装软件,并且希望它对所有用户可用时,/usr/local/bin、/usr/local/lib等是理想的安装位置。
- /opt: 如果软件是第三方提供的,并且你希望保持其独立于系统的其他部分,可以安装在/opt目录下。这里通常用于存放完整的软件包,每个软件可以在/opt内有自己的子目录。
不太建议将软件安装在/home目录,该目录:主要用于存储用户的个人文件和配置。每个用户都有自己的家目录,如/home/username,这是他们个人数据、文档、桌面配置等的存放地点。
为什么不建议安装在/home目录下?
- 权限问题: 在/home目录下安装软件可能导致权限冲突,因为该目录通常归用户个人所有,而非root用户。这可能限制了软件对系统资源的访问。
- 软件管理混乱: 使用包管理器(如apt、yum等)时,软件依赖和卸载管理会更加便捷。直接在/home下安装可能会绕过这些管理工具,导致软件包管理混乱。
- 系统维护: 将软件安装在系统目录(如/usr/local)允许更好的系统级监控和维护,而家目录安装的软件可能不在系统管理员的常规检查范围内,增加系统维护的复杂性。
了解一定的文件系统知识后,我们就要开始学习真正的shell指令了
# 常用命令简介
# cd移动
常见命令cd,来自英文词组change directory的缩写,其功能是更改当前所处的工作目录,路径可以是绝对路径,也可以是相对路径,若省略不写则会跳转至当前使用者的家目录。
cd /home
# 切换到用户家目录
cd ~
2
3
单点符,(.),表示当前目录
双点符,(..),表示当前目录的父目录
# ls列出
ls命令来自英文单词list的缩写,中文译为“列出”,其功能是显示目录中的文件及其属性信息。
ls
# 默认会列出当前文件夹下的文件与文件夹
ls -F
# 能区分文件夹与目录的区别 目录会在后加上(/),可执行文件会在后加(*)
# 当然现在一些彩色终端仿真器 会用不同颜色区分 文件类型
2
3
4
5
它显示了当前目录下的文件和目录,但并没有将全部都显示出来。Linux经常采用隐藏文件来保存配置信息。在Linux上,隐藏文件
通常是文件名以点号开始的文件。这些文件并没有在默认的ls命令输出中显示出来,因此我们称其为隐藏文件。如果要显示,则需要用参数-a
ls -a
# 会将隐藏文件一起展示
2
如果你想要该文件(或文件夹)更多的信息,则需要使用参数-l
ls -l
# 之后会看到类似如下格式的输出
总用量 8
-rwxr-xr-x 1 root root 388 12月 20 23:29 demo.sh
-rw-r--r-- 1 root root 2482 12月 20 23:32 rpm.txt
2
3
4
5
以下是简要介绍:
首字符表示文件类型,比如目录(d)、文件(-)、字符型文件(c)或块设备(b)
后9个字符表示文件或目录的权限,分为三组,每组三个字符分别代表文件所有者的权限、所属组的权限和其他用户的权限。字符可以是
-
(表示无权限),r
(读权限),w
(写权限)接下来是-文件的硬链接总数
文件属主的用户名
文件属组的组名
文件的大小(以字节为单位,Byte)
文件的上次修改时间
文件名或文件目录
# ls列出-过滤
有时使用ls,产生的输出会显得过多,如果你只想看该目录是否包含某个文件,此时便会很麻烦。该怎么办呢?有类似查找的功能吗?有的,开发者,早已为ls设计了支持筛选的功能。
ls -l mytest
# 只会输出mytest的相关信息
2
如果你不知道确切的文件名,也可以使用模糊匹配模式。
- 问号(?):代表任意一个字符
- 星号(*):代表零个或者任意多个字符
ls -l my*file
# 会将开头为my 且用file结尾的所有文件 按长格式列出
2
当然还有其他的匹配模式,比如“元字符通配符”,这里就不展开介绍了
ls -l my_[ai]file
#
ls -l f[a-z]file
2
3
文件的创建对于任何一个系统来说都极为重要,或者说不可或缺。那linxu中如何新建文件呢?下面介绍主要的3中方式。
# touch创建文件
touch命令创建了你指定的新文件,并将你的用户名作为文件的属主。注意,文件的大小是零,因为touch命令只创建了一个空文件
touch myfile
# 这样便创建了一个大小为 0B,名为 myfile的空文件
2
touch命令还能同时创建多个文件,此外它还可用来改变文件的修改时间。这个操作并不需要改变文件的内容。
# 创建多个文件
touch a1 a2
# 直接对现有文件使用touch 即可
# -rw-r--r-- 1 root root 0 6月 10 17:43 myfile
touch myfile
# -rw-r--r-- 1 root root 0 6月 10 17:52 myfile
2
3
4
5
6
7
# >或>>重定向运算符
如果你想仅仅创建一个空文件,可以使用重定向运算符 >
,后面紧跟你想创建的文件名。这会创建一个新文件(如果文件不存在),或者清空已有文件(如果文件已存在)。
> newA.txt
# 或者在前面加一个空格(加不加空格效果相同)
> newA.txt
2
3
执行上述命令后,newfile.txt
就会被创建(或清空,如果之前存在)。
如果你希望在创建文件的同时写入一些初始内容。这时,可以结合 echo
命令或其他命令的输出与重定向运算符一起使用。
或者说如果你想在不覆盖原有内容的基础上向文件追加内容,可以使用双大于号 >>
作为重定向运算符。
echo "hello world" >> Bfile.txt
总结:如果你想开始一个新的文件或完全替换文件内容,就使用 >
;如果你想在现有文件中添加内容而不丢失已有的数据,就使用 >>
。
# 文本编辑器创建
使用vi,或vim创建一个文件,并在编辑界面输入内容,最后进行保存即可。
vim newFile.txt
# 使用该命令后 会进入newFile.txt的内容编辑界面
2
编辑完成后进行保存,到此文件创建完成。
# cp复制文件
在文件系统中将文件和目录从一个位置复制到另一个位置可谓家常便饭。而完成这一任务的在Linux中就是cp。
它来自英文单词copy的缩写,中文译为“复制”,其功能是复制文件或目录。cp命令能够将一个或多个文件或目录复制到指定位置,亦常用于文件的备份工作。-r参数用于递归操作,复制目录时若忘记添加则会直接报错;-f参数则用于当目标文件已存在时会直接覆盖而不再询问。这两个参数尤为常用。
语法格式:cp 参数 源文件名 目标文件名。
cp myfile ./username/myfile
# 将myfile文件复制到 当前文件夹username下 并命名为myfile
2
那如果目标位置存在一个名称相同的文件,它的执行结果是覆盖还是不成功?覆盖了,它会把原有内容追加到名称相同的文件中吗?
当使用cp
命令时,如果目标位置存在同名文件,默认情况下是否会覆盖,这实际上取决于你的Linux系统配置以及是否使用了特定的命令行选项。如果不使用任何特定于覆盖的选项,且系统未对cp
命令进行别名设置(比如将其默认设置为cp -i
),那么cp
命令在目标位置存在同名文件时,会直接覆盖目标文件,且不会提示。
那遇到相同文件时,怎么让它提示呢?很简单,加上参数-i即可。
cp -i myfile ./username/myfile
# 这样遇到相同的文件 它就会询问是否覆盖
#如果你想覆盖 且不提示 则使用-f
cp -f myfile ./username/myfile
2
3
4
5
cp的参数选项有很多,比如:-r,它的威力也强大且常用。可以用它在一条命令中递归地复制整个目录的内容,换句话说就是它能复制目录。
cp -r ssr ./sugar
# 将ssr文件夹 复制到 当前目录中的sugar文件夹中
2
当然,cp也支持多个文件一起复制
cp File1.txt File2.txt /tmp
cp的参数还有一些,这里就不一一列举了。
# ln链接文件
链接是文件系统的一个重要特性,它允许用户创建一个文件或目录的多个入口点。链接有两种主要类型:硬链接(hard link)和软链接(符号链接,symbolic link 或 symlink),每种都有其特定的用途和行为。
- 硬链接(Hard Link)
原理:硬链接是在文件系统层面上创建的,它实际上是一个指向原始文件inode(索引节点)的新条目。这意味着硬链接与原文件共享相同的inode和存储数据块,因此它们是完全等效的。修改任何一个链接都会影响到所有链接到同一inode的文件。
特点:
硬链接不能链接到目录(出于避免循环引用和数据损坏的考虑)。
只能在同一个文件系统内创建,不能跨文件系统。
删除原始文件不会影响硬链接,只要还有一个硬链接存在,文件数据就依然可访问。
硬链接具有相同的权限、所有权和时间戳,因为它们本质上是同一个文件的不同名称。
软链接(Symbolic Link)
原理:软链接是一个特殊的文件,它包含的是对另一个文件或目录的路径名。不同于硬链接直接指向inode,软链接更像是Windows中的快捷方式,保存的是目标文件的路径文本。
特点:
- 软链接可以指向任何文件或目录,包括不存在的文件或目录,此时尝试访问会失败。
- 可以跨文件系统创建,不受文件系统限制。
- 可以链接到目录。
- 如果原始文件被删除或移动,软链接可能会失效,因为它们只是保存了原始位置的路径。
- 软链接有自己的inode和权限设置,独立于目标文件。
应用场景
- 硬链接常用于备份重要文件,防止误删,或在不占用额外磁盘空间的情况下提供文件的多个访问点。
- 软链接适合于创建快捷方式,方便访问深层目录中的文件,或在不同位置或不同环境间共享配置文件,同时允许灵活性,如指向可能变动的文件路径。
创建链接的命令
使用ln
命令可以创建链接。基本语法如下:
- 创建硬链接:
ln source_file target_link
- 创建软链接:
ln -s source_file target_link
在同一文件系统内,指的是文件或者目录位于同一个磁盘分区上,并且该分区采用了相同的文件系统类型(如ext4, xfs, btrfs等)。
举例说明:
假设你有一个Linux系统,它有一个硬盘划分为两个分区:
/dev/sda1
和/dev/sda2
。
/dev/sda1
上挂载为根目录/
,并且格式化为ext4文件系统。/dev/sda2
上挂载为/home
,同样使用ext4文件系统。如此一来,就相当于有两个文件系统
- 根目录
/
下的所有文件和目录(比如/etc
,/var
,/bin
等)都属于同一个文件系统内,因为它们都在/dev/sda1
分区上,并且都是ext4文件系统。/home
目录下的所有用户主目录(如/home/user1
,/home/user2
)也属于同一个文件系统内,尽管它们挂载点不同,但因为它们同属/dev/sda2
分区上的ext4文件系统。如果尝试在
/home
目录下为根目录/etc
下的一个文件创建一个硬链接,这将是不允许的,因为硬链接要求链接的源文件和目标文件必须位于同一文件系统中
# mv移动或重命名
mv命令可以将文件和目录移动到另一个位置或重新命名。这里需要着重强调的是,mv只会影响文件名和位置,并不会影响文件的inode编号和时间戳。
mv file1 file2
# 将文件夹file1 进行重命名
mv fi1 ./sugar
# 将文件夹fi1 复制到 sugar文件夹中
mv -i file2 ./sugar
# 将文件夹file2 复制到 sugar中 如果有重名则提示 是否覆盖
mv -f /home/* .
#将/home目录中所有的文件都移动到当前工作目录中,若遇到文件已存在则直接覆盖
2
3
4
5
6
7
8
当然,mv的参数也不止只有这几个,其他的就不展开介绍了