tulip notes
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Star-Lord

希望一天成为大师的学徒
首页
  • 学习笔记

    • 《Vue》
  • 踩坑日记

    • JavaScript
  • MQ
  • Nginx
  • IdentityServer
  • Redis
  • Linux
  • Java
  • SpringBoot
  • SpringCloud
  • MySql
  • docker
  • 算法与设计模式
  • 踩坑与提升
  • Git
  • GitHub技巧
  • Mac
  • 网络
  • 项目构建合集
  • 一些技巧
  • 面试
  • 一些杂货
  • 友情链接
  • 项目发布
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 各种MQ

  • Nginx

  • IdentityServer

  • Redis

  • Linux

    • Linux简介
    • Linux中一些常用命令
    • Linux中的文件复制与查找
    • 初识shell
    • shell-续与查看文件内容
    • 查看进程与shell
    • 查找数据与压缩
    • 再探shell
      • 切换与开启子shell
        • 切换
        • 开启子shell
        • 优缺点
      • shell命令的后台执行
        • 使用 & 符号
        • 使用 nohup 命令
      • shell的内建与非内建命令
        • 内建命令
        • 非内建命令
    • Linux系统中各个文件的作用
    • 【开发常用】Java开发必看
    • 【开发常用】软件安装利器
  • 中间件
  • Linux
EffectTang
2024-07-06
目录

再探shell

# 再探shell

我们在使用终端登录器(如xshell等)登录系统后,使用的是系统默认的shell,之前说过,一个linux系统中通常会有多个不同类型的shell,那我们怎么使用不同的shell,或者说开启多个shell?

它们的实现都很简单。

# 切换与开启子shell

# 切换

要切换首先,我们要知道系统中装了哪些类型的shell。可通过如下命令查看:

chsh -l
# 以下是输出
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
# 该电脑系统 有4中不同的shell
1
2
3
4
5
6
7

上述命令,会把shell命令,对应的位置也一并输出,而我们要切换,直接输入对应shell即可,比如,我们要切换成sh

/bin/sh
# 执行该命令后 会发现前置提示变化了
# 会有新的命令提示输出
sh-4.2# 
1
2
3
4

不同类型的shell可能有不同的变化。

如果你要切换回去,直接exit即可

sh-4.2# exit
# 以下是输出
exit
1
2
3

exit后,又会变为默认的shell。

# 开启子shell

开启新的shell(或者说开启子shell)也很简单,直接bash即可。开启后,通过ps -f或者ps --forest可查看开启状态。

 bash
 # bash之后 没有明显的输出
 ps --forest
 # 以下为输出
  PID TTY          TIME CMD
21232 pts/0    00:00:00 bash
25847 pts/0    00:00:00  \_ bash
26382 pts/0    00:00:00      \_ ps
1
2
3
4
5
6
7
8

通过ps --forest可以查看到,我们开启了一个新的shell,也就是所谓的子shell。退出也一样,直接exit即可。

# 优缺点

在Linux中,从父shell中创建一个子shell主要是为了解决一些特定的需求和情境,特别是当需要在独立的环境中执行命令或脚本时。子shell提供了与父shell相对隔离的环境,允许在其中进行临时的修改而不影响父shell的状态。下面详细讨论其优势和不足:

  • 优点:
  1. 环境隔离: 子shell有自己的环境变量和状态,这意味着在子shell中所做的任何更改(如修改环境变量、设置临时路径等)都不会影响到父shell。这对于测试和调试非常有用,因为你可以在子shell中实验不同的配置而不必担心破坏现有的shell环境。
  2. 资源管理: 子shell可以拥有自己的进程ID和资源限制,这使得系统可以更好地管理和控制各个shell的资源消耗。
  3. 安全性和权限: 子shell可以以不同的用户身份运行,提供额外的安全层。例如,你可以以root身份在父shell中运行,但在子shell中降权运行脚本,以减少潜在的安全风险。
  4. 脚本和命令执行: 许多脚本和命令在执行时会创建子shell来运行特定任务,特别是在管道和重定向中,子shell能够确保每个命令在自己的上下文中运行,避免相互干扰。
  5. 并行处理: 子shell可以并行运行,从而提高处理效率。例如,当你使用&将任务放到后台运行时,实际上是在创建一个子shell来执行该任务。
  • 缺点:
  1. 资源开销: 创建子shell会占用额外的系统资源,包括内存和CPU时间。虽然现代系统通常可以轻松处理这种开销,但在资源受限的环境下,频繁创建子shell可能会成为性能瓶颈。
  2. 变量传递限制: 如前所述,子shell中的环境变量更改不会反映到父shell中。这在某些情况下可能是期望的行为,但在需要持久化变量更改时就会成为一个问题。例如,如果你在子shell中使用export命令设置了一个变量,这个变量在子shell结束后就消失了,除非采取特殊措施将其传递回父shell。
  3. 复杂性增加: 对于复杂的脚本和命令链,子shell的使用可以增加理解流程的难度。特别是对于新手,子shell的概念和行为可能不是直观的。
  4. 调试困难: 由于子shell的隔离特性,调试有时会变得复杂。例如,如果你在一个子shell中遇到了问题,可能需要在那个特定的上下文中进行调试,而这可能比在单一shell环境中更难。

# shell命令的后台执行

Linux中,如果碰到某个文件特别复杂体积特别大,我们进行解压时,通常情况是——我们无法执行其他命令,只有等待解压命令执行完毕才可以执行其他命令。这很低效率而且对使用者很不友好,为了解决这一问题,开发者设计了一个后台模式,可以将shell命令进行后台执行。

后台执行:允许你将进程置于后台运行,从而让你可以继续使用终端进行其他操作,而不必等待当前命令执行完毕。后台模式对于运行长时间任务、耗时的脚本或不需要即时交互的程序尤其有用。对于命令行来说就是,执行一个shell命令后,可以立即执行下一个shell命令,前者会在后台继续执行,直到完成。

# 使用 & 符号

实现命令的后台执行,在命令的末尾添加一个&符号可以让命令在后台运行。例如:

sleep 15
# 使用该命令后 经过15s后,你才能继续执行下一条指令
sleep 30 &
# 以下是输出
[1] 27569
# 加上 & 后,则不必等待,能立即执行下一条
1
2
3
4
5
6

在命令尾部加上&再执行的命令,会被放到后台执行,同时输出对应的进程号。通过ps可以看到

ps
# 以下是输出
  PID TTY          TIME CMD
 6048 pts/0    00:00:00 bash
27569 pts/0    00:00:00 sleep
32581 pts/0    00:00:00 ps
1
2
3
4
5
6

当然,你也可以通过另一个命令来查看,jobs,该命令可以显示出当前运行在后台模式中的所有用户的进程(作业)。

jobs
# 以下是输出
[1]+  运行中               sleep 30 &
1
2
3

# 使用 nohup 命令

很多时候,我们都会用到命令后台执行,最常用的情况就是项目发布,比如——发布Java项目,使用jar命令,再加上&来将一个.jar文件置于后台执行。因为我们使用了&符号,理论上应该在我们断开终端连接后继续运行。

但是,通常情况却是,jar命令在断开终端连接后中断了。这其中的原因主要是该命令或进程没有正确地忽略SIGHUP信号。SIGHUP(Signal HangUp)信号是在终端会话结束时发送给所有相关联进程的信号。当用户注销或关闭SSH会话时,系统默认会发送SIGHUP信号给与该会话相关的所有进程。如果没有特别处理,进程接收到SIGHUP信号后会默认终止。

为了避免这种情况,有几种方法可以确保你的.jar文件在后台运行,并且在终端断开连接后还能继续运行,其中一种就是nohup,nohup(no hang up)命令可以防止进程在终端断开连接(例如,当你注销或关闭SSH会话)时终止。使用方法如下:

nohup java -jar your_jar_file.jar &
1

注意:nohup它会在当前工作目录下生成一个名为nohup.out的文件,用来记录命令的标准输出和标准错误,除非你重定向它们到其他地方。

# shell的内建与非内建命令

在Linux shell环境中,命令可以大致分为两类:内建命令(built-in commands)和非内建命令(external commands)。

# 内建命令

内建命令是shell本身的一部分,它们直接由shell解释器执行,不需要创建新的进程。这些命令通常与shell的环境控制和脚本编写密切相关。

比如:cd和exit命令都内建于bash shell。可以利用type命令来了解某个命令是否是内建的。

type cd 
# 以下是输出
cd 是 shell 内嵌
1
2
3

因为内建命令,它们是作为shell工具的组成部分存在。所以,在执行时,不需要借助外部程序文件来运行,此外它们也不需要fork一个新进程来执行,所以执行效率高。

但内建命令的功能相对有限,主要聚焦于shell环境管理和流程控制,所以开发者们还设计了非内建命令。

# 非内建命令

非内建命令,或者说外部命令,有时候也被称为文件系统命令,是存在于bash shell之外的程序。它们并不是shell程序的一部分。外部命令程序通常位于/bin、/usr/bin、/sbin或/usr/sbin中。

比如:ps就是一个外部命令。

type ps
# 以下是输出
ps 是 /usr/bin/ps
1
2
3

大多数的系统工具和实用程序,如ls, cat, grep, find等,都是非内建命令。它们主要用于执行复杂任务,如文件操作、网络管理、系统监控等。

但它们每次执行都需要创建新进程,会涉及到fork和exec系统调用,因为效率比内建命令慢。

注意:虽然非内建命令的执行,会创建新进程,但并不是新的shell(子shell)。

用执行ls为例,虽然创建了一个子进程,但这个子进程执行的是ls命令,而不是一个新的Shell实例。除非你明确地在命令行中运行sh、bash或其他Shell解释器,否则不会创建一个子Shell。例如,当你使用bash -c "ls"这样的命令时,确实会创建一个临时的子Shell来执行ls命令

上次更新: 2025/04/23, 16:23:16
查找数据与压缩
Linux系统中各个文件的作用

← 查找数据与压缩 Linux系统中各个文件的作用→

最近更新
01
面向切面跟自定义注解的结合
05-22
02
时间跟其他数据的序列化
05-19
03
数据加密与安全
05-17
更多文章>
Theme by Vdoing | Copyright © 2023-2025 EffectTang
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式