Linux命令-Source

本文详细介绍了Linux中source命令的作用及用法,包括如何使配置文件中的更改立即生效,如何区别source与sh命令的不同之处,并给出了实际应用场景。

重学linux,发现还是有很多有趣又实用的命令,比如source

作用

在当前bash环境下读取并执行FileName中的命令。简单来说就是将设置在文件中的配置信息马上生效,比如你设了一个alias,或者一个PATH如果你不source修改的文件的话,只有等下次重启后才能生效,如果你source了就马上生效了。

意思就是环境可以执行你环境所支持的所有命令组合的文件,也就是当你写了一个脚本文件的时候,可以通过source命令去执行。

使用范例:

source filename
# 或者
. filename

就是.命令。

简单使用

如使用Hexo搭建的博客,通常需要先清理,在生成,最后部署或者开本地服务,一连串的命令如下(这里只是举一个例子,通常脚本文件不会这么短):

hexo c && hexo g && hexo d/s

这时候就可以新建一个可执行文件如hexo_s,并把上述代码输入其中。就可以通过source hexo_s的去执行一连串的操作。

区分

sh filepath

sh filepath会重新简历一个子shell,在子shell中执行脚本里面的语句,该子shell继承父shell的环境变量,但子shell是新建的,其改变的变量不会被带回父shell,除非使用export

source filename

source filename就是简单地读取file中的所有语句,没有建立新的子shell。那么脚本里面所有新建、改变变量的语句都会保存在当前shell里面。因为不会建立新的子shell,变量的值都可以直接取到:

# ming @ ming-virtual-machine in ~/demo [20:32:48]
$ cat hwinfo
type=x86
provider=vm
model=vm
product=center
date=20140918

输出如下:

# ming @ ming-virtual-machine in ~/demo [20:33:16]
$ source hwinfo > /dev/null&& echo $product
center

这里的&&的含义是,当左边的命令执行成功时,才会执行右边的命令;||就相反,左边的命令执行失败,才执行右边的命令。

<think>我们已知系统中存在的是 `linux-source-5.15.0.tar.bz2`,而用户尝试解压的是 `linux-source-6.8.0-85.tar.bz2`。因此,错误的原因是版本不匹配。 用户的上一条命令是:`tar xf linux-source-$(uname -r | sed 's/-generic//').tar.bz2` 而 `uname -r` 的输出可能是 `6.8.0-85-generic`,经过sed处理后变成 `6.8.0-85`,所以命令试图解压的文件名为 `linux-source-6.8.0-85.tar.bz2`,但实际系统中存在的是 `linux-source-5.15.0.tar.bz2`。 解决方案有两种: 1. 安装与当前运行内核版本匹配的源码包(即6.8.0-85对应的源码包),然后解压。 2. 如果系统中已安装的是5.15.0版本的源码包,那么应该使用这个存在的文件来解压。 但根据用户提供的信息,系统中存在的是`linux-source-5.15.0.tar.bz2`,而当前运行的内核版本是6.8.0-85?这不太可能,因为通常安装的源码包版本与运行的内核版本应该一致。所以我们需要先确认: 步骤1:确认当前运行的内核版本 步骤2:确认系统中已安装的源码包版本 用户已经通过`dpkg -l`和`ls`命令得知系统中存在`linux-source-5.15.0.tar.bz2`,那么我们需要检查当前运行的内核版本是否也是5.15.0?如果是,那么问题就是命令中sed的处理方式不正确。 分析命令:`uname -r | sed 's/-generic//'` 假设`uname -r`输出:`5.15.0-91-generic` 执行sed后:`5.15.0-91`,然后命令尝试解压`linux-source-5.15.0-91.tar.bz2`,但实际文件是`linux-source-5.15.0.tar.bz2`,所以不匹配。 因此,我们需要调整命令中的sed部分,去掉的是架构后缀(如-generic)以及可能的小版本号(如-91)?实际上,源码包的名字通常是主版本号(如5.15.0),不包含后面的小版本号。 所以正确的做法是:只保留主版本号(即前两部分数字,如5.15.0),去掉后面的所有内容。 我们可以使用如下命令获取主版本号: uname -r | sed -E 's/-[a-z]+-[0-9]+$//' # 结果会是5.15.0 或者更简单的: uname -r | cut -d '-' -f1,2 # 以-分割,取前两部分 但是注意,例如`5.15.0-91-generic`,取前两部分就是`5.15.0-91`,还是包含小版本号。而源码包名字是`linux-source-5.15.0.tar.bz2`,所以我们需要去掉小版本号。 实际上,源码包的版本号格式是:主版本.次版本.修订版本,后面的小版本号(如-91)是发行版自己加的,在源码包名字中不包含。 因此,我们需要从`uname -r`中提取出主版本号(即前三个数字部分)。然而,`uname -r`的输出可能是:5.15.0-91-generic,那么主版本号是5.15.0。 我们可以这样提取: uname -r | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-a-z0-9]*/\1/' 但更简单且安全的方法是:先去掉后缀(-generic等),然后去掉末尾的小版本号(即最后一个-后面的数字部分),但这样复杂。 其实,在安装源码包时,我们安装的是`linux-source-5.15.0`,所以文件名就是`linux-source-5.15.0.tar.bz2`。因此,我们只需要从`uname -r`中提取前三个数字(即5.15.0)即可。 但是,`uname -r`输出的第一个数字部分可能有不同的段数,例如4.4.0,或者5.15.0,或者6.8.0。所以我们可以这样: uname -r | sed 's/^\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-].*/\1/' 这个命令会匹配开头的数字.数字.数字,然后后面的内容全部去掉。 然而,在用户提供的例子中,运行内核版本是6.8.0-85?但系统中存在的源码包是5.15.0,这很奇怪。所以我们需要先确认: 执行:`uname -r` 得到什么?如果确实是6.8.0-85,那么系统中应该有linux-source-6.8.0.tar.bz2,但实际上用户只有5.15.0。 因此,更可能的情况是:用户使用的是5.15.0的内核,但`uname -r`输出的是5.15.0-xx-generic,而用户系统中存在的源码包是5.15.0版本的。 所以,我们建议用户先检查当前内核版本和已安装源码包版本是否匹配。 具体步骤: 1. 获取当前内核版本: current_kernel=$(uname -r) echo $current_kernel # 例如:5.15.0-91-generic 2. 从当前内核版本中提取主版本号(不带小版本号): main_version=$(echo $current_kernel | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-].*/\1/') # 或者:main_version=$(echo $current_kernel | cut -d '-' -f1,2 | cut -d '.' -f1-3) # 但注意:cut -d '-' -f1,2 得到的是5.15.0-91,然后我们还需要去掉-91?所以不如用sed。 3. 检查系统中是否存在该主版本号的源码包文件: ls /usr/src/linux-source-$main_version.tar.bz2 4. 如果存在,则解压: tar xf /usr/src/linux-source-$main_version.tar.bz2 但是,用户之前使用的命令是在当前目录下解压,而源码包实际在/usr/src/下,所以应该指定路径。 根据用户之前的错误信息,他是在当前目录下执行解压,但文件并不在当前目录,而是在/usr/src/下。 所以,正确的解压命令应该是: tar xf /usr/src/linux-source-$main_version.tar.bz2 因此,结合以上,我们可以写: tar xf /usr/src/linux-source-$(uname -r | sed 's/\([0-9]\+\.[0-9]\+\.[0-9]\+\)[-].*/\1/').tar.bz2 但是,如果用户系统中存在的是5.15.0,而他的内核版本也是5.15.0-xx,那么这个命令就可以正确提取出5.15.0。 然而,用户之前尝试解压的是6.8.0-85,说明他的内核版本可能是6.8.0-85,但系统中没有这个版本的源码包,而有的是5.15.0。这可能是用户安装错了源码包版本?或者运行的内核版本与源码包版本不一致。 因此,我们需要先确认:当前运行的内核版本对应的源码包是否已安装? 如果用户希望使用当前运行内核的源码,那么应该安装对应版本的源码包。 如果用户希望使用系统中已存在的5.15.0源码包,那么他需要确保这是正确的版本(可能他就是要用5.15.0,而当前运行的内核是5.15.0,只是命令提取的版本号有问题)。 所以,我们分两种情况: 情况一:用户系统中已安装的源码包版本(5.15.0)正是当前运行内核的源码包(即当前内核版本是5.15.0系列) 解决方案:使用正确的提取主版本号的方式,并指定路径解压。 情况二:用户当前运行的内核版本是6.8.0,但系统中没有安装对应的源码包,只有5.15.0的源码包 解决方案:安装6.8.0的源码包,然后再解压。 步骤: 1. 确定当前内核版本: $ current_kernel=$(uname -r) $ echo $current_kernel 2. 如果输出是5.15.0-xx形式,那么我们可以用5.15.0的源码包。 $ sudo tar xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 3. 如果输出是6.8.0-xx形式,那么需要安装6.8.0的源码包: $ sudo apt update $ sudo apt install linux-source-6.8.0 4. 然后解压新安装的源码包: $ sudo tar xf /usr/src/linux-source-6.8.0.tar.bz2 -C /usr/src/ 注意:源码包安装后位于/usr/src/目录下。 但是,用户之前执行命令时没有使用sudo,而且没有指定路径。所以,我们建议用户: - 确保源码包已经安装(通过apt) - 在/usr/src/目录下解压(因为源码包就在那里) 另外,用户原来的命令: tar xf linux-source-$(uname -r | sed 's/-generic//').tar.bz2 有两个问题: 1. 没有使用sudo(如果需要的话) 2. 没有指定路径(源码包在/usr/src下) 3. 版本号提取方式不对(应该提取主版本号,而不是简单去掉-generic) 因此,我们推荐的做法是: 步骤1:安装与当前内核版本对应的源码包(如果还未安装) 先获取主版本号: main_version=$(uname -r | grep -Po '^\d+\.\d+\.\d+') 然后安装: sudo apt install linux-source-$main_version 步骤2:解压源码包(在/usr/src目录下): sudo tar -xf /usr/src/linux-source-$main_version.tar.bz2 -C /usr/src/ 步骤3:创建符号链接(可选,方便使用): sudo ln -s /usr/src/linux-source-$main_version /usr/src/linux-$(uname -r | sed 's/-generic//') 注意:如果第二步解压时提示文件已存在(因为解压会生成一个目录),可以不用创建链接,或者根据需要使用。 现在,针对用户的情况(系统中已经有linux-source-5.15.0.tar.bz2,但当前内核版本未知),我们给出具体的诊断步骤: 1. 运行:`uname -r`,假设输出为:5.15.0-91-generic 2. 提取主版本号:5.15.0 3. 检查/usr/src/下是否存在linux-source-5.15.0.tar.bz2(用户说存在) 4. 解压:sudo tar -xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 因此,用户应该执行: sudo tar -xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 但是,如果用户当前内核版本是6.8.0,那么他需要安装6.8.0的源码包。 所以,我们首先确认当前内核版本: current_kernel=$(uname -r) main_version=$(echo $current_kernel | grep -Eo '^[0-9]+\.[0-9]+\.[0-9]+') 然后,检查源码包是否存在: if [ -f "/usr/src/linux-source-${main_version}.tar.bz2" ]; then sudo tar -xf "/usr/src/linux-source-${main_version}.tar.bz2" -C /usr/src/ else echo "需要先安装linux-source-${main_version}包" sudo apt install linux-source-${main_version} sudo tar -xf "/usr/src/linux-source-${main_version}.tar.bz2" -C /usr/src/ fi 但是,用户可能没有安装对应版本的源码包,所以第二步可能会失败,因此先安装。 因此,完整步骤如下: 1. 获取主版本号 2. 安装源码包(如果还没有安装) 3. 解压 由于用户已经明确系统中有linux-source-5.15.0.tar.bz2,但不知道当前内核版本,所以先确认当前内核版本。 如果当前内核版本的主版本号是5.15.0,那么直接解压即可。 如果当前内核版本的主版本号不是5.15.0,那么需要安装对应版本的源码包。 根据用户提供的信息,我们假设用户希望解压的是当前内核对应的源码包。 因此,我们给出两种解决方案: 解决方案一:如果用户当前运行的内核版本是5.15.0系列,则可以直接解压已存在的5.15.0源码包(注意版本号匹配,即主版本号相同) 步骤: 1. 确保当前内核版本主版本号为5.15.0(运行`uname -r`查看) 2. 执行解压:`sudo tar xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/` 解决方案二:通用方法(推荐) 步骤: 1. 获取当前内核主版本号: main_version=$(uname -r | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') 2. 安装该版本的源码包(如果未安装): sudo apt update sudo apt install linux-source-${main_version} 3. 解压源码包到/usr/src/目录: sudo tar xf /usr/src/linux-source-${main_version}.tar.bz2 -C /usr/src/ 注意:第二步安装源码包后,源码包文件会出现在/usr/src/下。 如果用户系统中已经安装了该源码包,第二步会提示已经是最新版,不会重新下载。 根据用户的情况,他系统中已经有一个5.15.0的源码包,但当前内核版本可能是6.8.0?如果是这样,那么他需要安装6.8.0的源码包。 因此,我们建议用户采用通用方法。 总结命令如下: main_version=$(uname -r | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+') sudo apt update sudo apt install linux-source-${main_version} sudo tar xf /usr/src/linux-source-${main_version}.tar.bz2 -C /usr/src/ 这样就能保证源码包版本与当前运行内核版本一致。 如果用户坚持使用已存在的5.15.0源码包,而不管当前运行的内核版本,那么可以直接解压: sudo tar xf /usr/src/linux-source-5.15.0.tar.bz2 -C /usr/src/ 但这样可能导致源码包版本与内核版本不一致,在后续操作(如编译模块)时可能出问题。 所以,我们推荐安装与当前运行内核版本一致的源码包。 注意:如果apt仓库中没有当前内核版本的源码包怎么办?这种情况可能需要手动下载源码。 因此,我们提供: 步骤三:如果安装失败(即apt找不到包),则手动下载: 手动下载地址:https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-${main_version}.tar.xz 然后解压到/usr/src/linux-${main_version}目录 但这里我们假设用户使用的是Ubuntu发行版,通常通过apt安装源码包。 最后,关于用户最初命令的修正: 不要在当前目录下执行,因为源码包在/usr/src下,而且需要root权限。 所以,用户最初命令可以修改为: sudo tar xf /usr/src/linux-source-$(uname -r | grep -oE '^[0-9]+\.[0-9]+\.[0-9]+').tar.bz2 -C /usr/src/ 但前提是源码包已经存在。为了避免不存在的情况,建议先安装。 因此,我们给用户的最终建议是:按照通用方法安装并解压。 另外,如果用户只是想编译模块,那么还可以使用以下方法安装当前内核的源码: sudo apt install linux-headers-$(uname -r) 但这安装的是头文件,不是完整源码。 综上所述,我们给出详细的解决方案。 </think>### 解决 `tar xf` 解压时出现 "No such file or directory" 错误 根据您提供的信息(系统中存在 `linux-source-5.15.0.tar.bz2`,但命令尝试解压 `linux-source-6.8.0-85.tar.bz2`),问题原因是**内核版本不匹配**。以下是完整解决方案: --- ### 步骤 1:确认当前内核版本与源码包匹配 ```bash # 查看当前运行的内核版本 uname -r # 列出已安装的源码包 ls /usr/src | grep linux-source dpkg -l | grep linux-source ``` - 若输出显示当前内核为 `5.15.0-xx` 但源码包是 `linux-source-5.15.0.tar.bz2`,则版本匹配 - 若当前内核为 `6.8.0-xx` 但只有 `5.15.0` 源码包,需安装匹配的新源码包 --- ### 步骤 2:解决方案 A(版本匹配时) 当当前内核主版本为 `5.15.0` 时(如 `5.15.0-91-generic`): ```bash # 提取主版本号 (5.15.0) main_ver=$(uname -r | grep -Po '\d+\.\d+\.\d+') # 带路径解压源码包 sudo tar xf /usr/src/linux-source-${main_ver}.tar.bz2 -C /usr/src/ ``` $$ \text{解压路径} = \frac{\text{/usr/src}}{\text{kernel-source}} $$ --- ### 步骤 3:解决方案 B(版本不匹配时) 若当前内核是 `6.8.0-xx` 但缺少对应源码包: ```bash # 安装匹配的源码包 (示例为 6.8.0) main_ver=$(uname -r | grep -Po '\d+\.\d+\.\d+') sudo apt update sudo apt install linux-source-${main_ver} # 解压新安装的源码包 sudo tar xf /usr/src/linux-source-${main_ver}.tar.bz2 -C /usr/src/ ``` --- ### 关键原理说明 1. **版本号解析公式**: $$ \text{主版本号} = \lfloor \text{uname -r} \rfloor_{\text{前三位}} $$ - 命令 `uname -r | grep -Po '\d+\.\d+\.\d+'` 精确提取 `X.Y.Z` 格式主版本 2. **路径要求**: - 源码包默认位置:`/usr/src/linux-source-X.Y.Z.tar.bz2` - 必须使用绝对路径解压,否则会在当前目录查找[^2] 3. **版本一致性**: - 编译内核模块时源码版本必须与运行内核严格匹配 - 不匹配会导致模块加载失败或系统不稳定[^1] --- ### 验证解压结果 ```bash # 检查解压后的目录 ls -d /usr/src/linux-source-$(uname -r | grep -Po '\d+\.\d+\.\d+')* ``` ### 替代方案(若无对应源码包) ```bash # 1. 手动下载官方源码 wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.15.tar.xz # 2. 使用 apt-get source 获取 sudo apt-get build-dep linux-image-$(uname -r) sudo apt-get source linux-image-$(uname -r) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欧恩意

如有帮助,感谢打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值