菜鸟科技网

Linux启动命令sh如何正确使用?

sh 是一个非常基础且重要的命令,理解它对于掌握 Linux/Unix 系统至关重要。

Linux启动命令sh如何正确使用?-图1
(图片来源网络,侵删)

核心概念:sh 是什么?

sh 的全称是 Bourne Shell,由 Stephen Bourne 在 AT&T 的贝尔实验室开发,它是 Unix 系统中最古老、最经典的命令行解释器(Shell)之一。

在现代 Linux 系统中,/bin/sh 通常不是一个真正的 Bourne Shell 程序,而是一个指向另一个兼容 Shell 的符号链接,最常见的情况是,它指向了 bash (Bourne-Again Shell) 或 dash (Debian Almquist Shell)。

  • 在 Debian/Ubuntu 系统上/bin/sh 通常指向 dashdash 是一个更轻量、更快速的 Shell,专注于遵循 POSIX 标准,常用于系统启动脚本等对性能要求高的场景。
  • 在 CentOS/RHEL/Fedora 系统上/bin/sh 通常指向 bash

关键点:当你运行 sh 命令时,你其实是在启动一个兼容 Bourne Shell 语法的 Shell 环境,这个环境可能是 bash,也可能是 dash,或者其他兼容的 Shell。


sh 命令的主要用途

sh 命令主要有以下几种用法:

Linux启动命令sh如何正确使用?-图2
(图片来源网络,侵删)

运行 Shell 脚本文件

这是 sh 最常见的用途,它会读取指定的脚本文件,并逐行执行其中的命令。

语法:

sh [选项] 脚本文件名 [参数...]

示例: 假设你有一个名为 hello.sh 的脚本,内容如下:

#!/bin/bash
echo "Hello, World!"
echo "第一个参数是: $1"
echo "脚本的进程ID是: $$"

执行方式:

Linux启动命令sh如何正确使用?-图3
(图片来源网络,侵删)
# 给脚本执行权限(虽然用 sh 执行不一定需要,但这是好习惯)
chmod +x hello.sh
# 使用 sh 命令执行
$ sh hello.sh Linux

输出:

Hello, World!
第一个参数是: Linux
脚本的进程ID是: 12345  # 这个ID会变化

重要区别:sh script.sh vs ./script.sh

  • sh hello.sh

    • 会启动一个新的 sh 进程(可能是 dashbash)。
    • 这个新进程会读取并执行 hello.sh 文件。
    • 不会使用 hello.sh 文件第一行的 shebang (#!/bin/bash) 指定的解释器,它强制使用 sh 命令指定的 Shell。
  • ./hello.sh

    • 首先会检查 hello.sh 文件第一行的 shebang (#!/bin/bash)。
    • 然后启动一个 bash 进程来执行这个脚本。
    • 需要 hello.sh 文件拥有可执行权限 (chmod +x hello.sh)。

sh script.sh 是“用 sh 来运行脚本”,而 ./script.sh 是“让脚本自己决定用哪个 Shell 来运行自己”。

交互式 Shell

你也可以直接输入 sh 命令来进入一个交互式的 Shell 环境。

示例:

$ sh
$ # 现在你进入了 sh 的命令行环境
$ echo "我在 sh 环境中"
我在 sh 环境中
$ $PATH  # 打印环境变量
/usr/local/bin:/usr/bin:/bin
$ exit    # 退出 sh 环境
exit
$ # 你回到了原来的 Shell

这个用法相对较少,因为大多数人更习惯使用功能更强大的 bash(直接输入 bashEnter 键)。

执行单条命令

你可以像使用 bash 或其他 Shell 一样,用 sh 来执行单个命令。

示例:

$ sh -c 'echo "This is a single command"'
This is a single command

-c 选项告诉 sh 将后面的字符串作为一个完整的命令来执行,这在编程中非常有用,例如在 C 语言或 Python 中通过 system() 函数调用 Shell 命令时。


常用选项

sh 命令支持一些有用的选项:

选项 全称 描述
-c --command 从一个字符串中读取并执行命令。
-s --stdin 从标准输入读取并执行命令,当没有给出文件名参数时很有用。
-v --verbose 在读取输入时,将其内容显示到标准错误输出,用于调试脚本。
-x --xtrace 在执行命令之前,将其显示到标准错误输出。这是最常用的调试选项
-n --noexec 只进行语法检查,但不实际执行命令,用于检查脚本是否有语法错误。

调试选项示例 (-x)

假设有一个有问题的脚本 debug.sh

#!/bin/bash
for i in 1 2 3
do
  echo "Processing item $i"
  # 故意写一个错误的命令
  my_command $i
done

执行它:

$ sh debug.sh
Processing item 1
debug.sh: line 5: my_command: command not found
Processing item 2
debug.sh: line 5: my_command: command not found
Processing item 3
debug.sh: line 5: my_command: command not found

使用 -x 选项执行,可以看到每一步的执行过程:

$ sh -x debug.sh
+ for i in 1 2 3
+ echo 'Processing item 1'
Processing item 1
+ my_command 1
debug.sh: line 5: my_command: command not found
+ for i in 1 2 3
+ echo 'Processing item 2'
Processing item 2
+ my_command 2
debug.sh: line 5: my_command: command not found
+ for i in 1 2 3
+ echo 'Processing item 3'
Processing item 3
+ my_command 3
debug.sh: line 5: my_command: command not found

号开头的行就是 sh -x 显示的执行步骤,非常有助于定位问题。


shbash 的关键区别

虽然 sh 通常指向 bash,但当你显式调用 sh 时,脚本会以POSIX 模式运行,这会导致一些行为与 bash 不同。

特性 sh (POSIX 模式) bash (默认模式)
函数定义 funcname() { commands; } function funcname() { commands; }funcname() { commands; }
数组 不支持 支持 (my_array=(a b c))
[[ ... ]] 不支持,只能用 [ ... ]test 支持,更强大、更安全(推荐使用)。
echo -e 不支持 -e 解释转义字符。 支持 -e 选项。
$RANDOM 没有这个内置变量。 有,用于生成随机数。
source 命令 没有 source,使用 来执行脚本。 两者都有,source 更易读。

示例:数组

# 在 bash 中可以
$ bash -c 'arr=(a b c); echo ${arr[1]}'
b
# 在 sh 中会报错
$ sh -c 'arr=(a b c); echo ${arr[1]}'
sh: arr=(a b c): bad array substitution
方面 描述
身份 sh 是一个命令,用于启动一个兼容 Bourne Shell 语法的 Shell 环境,在现代 Linux 上,它通常是 bashdash 的一个链接。
主要用途 执行 Shell 脚本 (sh script.sh),强制使用 sh 环境。
调试脚本,使用 -x 选项追踪执行流程。
执行单条字符串命令 (sh -c '...')。
核心原则 兼容性sh 旨在提供最大程度的 POSIX 标准兼容性,而 bash 在此基础上增加了许多更方便、更强大的功能。
何时使用 - 当你明确需要一个轻量级、严格遵循标准的 Shell 时。
- 当你运行的系统脚本(如 /etc/init.d/ 下的脚本)指定了 #!/bin/sh 时,应该用 sh 执行。
- 当你不确定目标系统上 bash 是否可用,或者需要确保脚本的可移植性时,应该为脚本编写 sh 兼容的语法。

对于日常使用,bash 更为流行和强大,但在系统管理、编写需要高度兼容性的脚本时,理解并正确使用 sh 至关重要。

分享:
扫描分享到社交APP
上一篇
下一篇