source命令与./命令

本文详细介绍了bash shell内置命令source的功能及用法,解释了source与直接执行脚本的区别,特别是对于环境变量的影响。并通过实例展示了如何使用source命令来更新当前shell环境。

参考: https://www.cnblogs.com/general001/articles/2420089.html

source 命令是 bash shell 的内置命令,从 C Shell 而来。
source 命令的另一种写法是点符号,用法和 source 相同,从Bourne Shell而来。
source 命令可以强行让一个脚本去立即影响当前的环境
source 命令会强制执行脚本中的全部命令,而忽略文件的权限。
source 命令通常用于重新执行刚修改的初始化文件,如 .bash_profile 和 .profile 等等。
source 命令可以影响执行脚本的父shell的环境,而 export 则只能影响其子shell的环境。

使用方法举例:
$source ~/.bashrc
或者:
$. ~/.bashrc
执行后 ~/.bashrc 中的内容立即生效。
一个典型的用处是,在使用 Android 的 mm 等相关命令时,需要先执行以下命令:
$cd <android source path>
$source ./build/envsetup.sh   或者  $. ./build/envsetup.sh

source命令(从 C Shell 而来)是bash shell的内置命令。点命令,就是个点符号,(从Bourne Shell而来)是source的另一名称。同样的,当前脚本中设置的变量也将作为脚本的环境,source(或点)命令通常用于重新执行刚修改的初始化文件,如 .bash_profile 和 .profile 等等。例如,如果在登录后对 .bash_profile 中的 EDITER 和 TERM 变量做了修改,则能用source命令重新执行 .bash_profile 中的命令而不用注销并重新登录。
source命令的作用就是用来执行一个脚本,那么:
source a.sh 同直接执行 ./a.sh 有什么不同呢,比如你在一个脚本里export $KKK=111 ,如果你用./a.sh执行该脚本,执行完毕后,你运行 echo $KKK ,发现没有值,如果你用source来执行 ,然后再echo ,就会发现KKK=111。因为调用./a.sh来执行shell是在一个子shell里运行的,所以执行后,结果并没有反应到父shell里,不过source不同,他就是在本shell中执行的,所以能看到结果。
“.”点命令是shell的一个内部命令,它从指定的shell 文件中读入所有命令语句并在当前进程中执行。 因此当多个shell进程(父子进程或无关进程均可)共享一组变量值时,就可以将这些变量赋值语句定义到一个shell文件里,并在需要这些变量值的程序中使用点语句来引用这个shell文件,从而实现变量值共享(对这些变量值的修改仅涉及到这个shell文件)。但要注意的是,这个shell文件不能包括含有位置参数的语句,即不能接受$1、$2等命令行参数。
从上面可以看出,其实点命令相当于c语言里面的#include。点命令还有另一个写法:source。下面我们将举例来说明。
我们先写一个简单的shell脚本文件,暂且命名为file1吧:
#! /bin/bash
a="hi"
echo $a
我们先来执行一下这个shell脚本,打开终端,敲入:  ./file1
结果是什么,你应该也看到了吧:
bash: ./file1: Permission denied
为什么呢。我们先不管这个吧,先看一下,另一个结果:
. ./file1(注意啊,两个点之间有个空格的哦,要不就成了上一级目录了,如果你不嫌麻烦的话,也可以写source  ./file1)这个的结果呢,跟前面就不一样了,正如我们所愿的,输出了hi。

./file1,直接执行,需要另起shell进程,而你似乎还没有这个权限(这个改一下就OK了,后面再说),而用点命令就不一样了(注意啊,./file这里的点可不是点命令里的点啊,我就被这个问题困扰了很久,汗死,竟然忘了点还有当前目录的意思,大家b4我吧),点命令会在当前的shell下执行。补充说一下怎么改一下file1的权限,让我们可以在按shell脚本来执行:   chmod +x file1
再执行一下./file1,是不是OK了?再来看另一个例子吧。首先脚本文件file1
#! /bin/bash
a="hi"
脚本文件file2(与file1在同一个目录下)
#! /bin/bash
./file1
echo $a
记得改一下file1的权限啊,要不./file1就没法执行了。执行一下看看结果。什么都没有,是吧。我们再改一下file2,这回用一下咱们的点命令
#! /bin/bash
. ./file1
echo $a
怎么样结果不一样了吧。(原谅我实在太懒了,只能举这么简短的例子了,呵呵)。这个例子应该还是能说明点问题的吧。如果不用点命令的话,会另起shell进程,而启动这个进行的时候,它会建立自己的进程环境(暂且这么叫它吧),然后在这个进行结束的时候,它所建立的环境也随之被销毁。而且点命令就不一样了,它会把点命令所带的shell脚本里的所以内容带到当前的shell进程里,在本程序里,就是变量a了。
废话了这么多,其实好像把点命令想像成C里的#include就OK了,呵呵。不过经过这么折腾,还是学到了一点东西的,至少知道了.不仅有点命令的作用,更有当前目录的意思(冷啊,该补一下linux基础了)。

为什么在shell脚本里面export的环境变量,在set里面竟然看不到。
为什么在shell脚本里面用export设置环境变量之后,当shell执行完了,用set命令看不到呢?但是你如果直接在终端里export 环境变量用set是看到的。

一个shell脚本test.sh的内容为:
#!/bin/bash
      export AA=123
当我们执行test.sh的时候,是当前终端所在的shell fork一个子shell然后执行test.sh的,执行完了再返回终端所在的shell。明白这点,就容易理解了,我们在test.sh设置了AA环境变量,它只在fork出来的这个子shell中生效,子shell只能继承父shell的环境变量,而不能修改父shell的环境变量,所以test.sh结束后,父进程的环境就覆盖回去。所以在test.sh之后完之后,我们用set命令是看不了AA这个环境变量的值的。
那有什么办法可以让脚本的环境变量在脚本执行之后仍然对当前终端存在呢?用sorcue 或者.(dot) 。明确告诉shell不要fork执行脚本,而是在当前的shell执行,这样环境变量就可以保存下来了。
source命令用法:
source Filename (通常用“.”来代替)
source test.sh 与 .test.sh是等效的。
【补充】
source命令与shell scripts的区别是,
source在当前bash环境下执行命令,而scripts是启动一个子shell来执行命令。这样如果把设置环境变量(或alias等等)的命令写进scripts中,就只会影响子shell,无法改变当前的BASH,所以通过文件(命令列)设置环境变量时,要用source 命令。

不积跬步,无以至千里;不积小流,无以成江海! 千里之行,始于足下。改变现在,就是改变未来。改变未来,从现在开始。

<think>我们正在讨论的是Linux/ROS环境中的source命令,特别是针对source./devel/setup.bash的作用。根据用户提供的引用内容,可以看出用户遇到了重复添加source命令.bashrc文件的问题,并且想了解这个source命令的具体功能。需要解释source./devel/setup.bash在ROS开发环境中的作用。在ROS开发中,当我们构建一个工作空间(例如使用catkin_make)后,会在工作空间的devel目录下生成一个setup.bash脚本。这个脚本的作用是设置当前工作空间的环境变量,使得ROS的相关命令能够识别该工作空间中的包、节点等。具体来说,执行source./devel/setup.bash会:1.将当前工作空间的路径添加到ROS_PACKAGE_PATH环境变量中,这样ROS命令(如rosrun,roslaunch)就能找到这个工作空间中的包。2.设置一些构建系统相关的环境变量,比如CATKIN_SETUP_UTILS_ARGS等。3.如果工作空间中包含消息和服务,它还会生成并添加消息和服务的运行时依赖。在用户提供的引用中,提到通过将source命令添加到.bashrc文件中,可以避免每次打开终端都需要手动source的问题。因为.bashrc会在每次打开新的bash终端时自动执行。但是,需要注意的是,如果多次执行echo"source...">>~/.bashrc,就会导致.bashrc文件中出现重复的source行。这虽然不会导致错误(因为重复source同一个文件是安全的),但会减慢终端启动速度,而且不够优雅。另外,引用[1]中用户遇到了一个错误提示,这是因为在.bashrc中写入的路径不正确(可能是路径中有空格或者路径不存在)。注意在引用[1]中,用户写的是:source~/catkin_ws/devel/setup.bash而错误信息是:bash:source~/catkin_ws/devel/setup.bash:Nosuchfileordirectory这里有一个明显的错误:在source和路径之间缺少空格,应该是用户写成了“source~”(连在一起)了。但用户说是因为多次添加导致重复,而错误可能另有原因(比如路径中的目录不存在)。总结用户问题:source./devel/setup.bash的作用是设置ROS工作空间的环境,使得后续ROS命令可以工作。为了避免每次打开终端都手动执行,可以将其添加到.bashrc文件中,但要注意路径正确且避免重复添加。下面我将按照要求用中文回答,并添加LaTeX格式(如果有数学表达式的话,但这个问题中可能没有,所以可能用不上数学表达式,但如果有变量描述,我们会用$...$)和生成相关问题。</think> ### `source ./devel/setup.bash` 在ROS/Linux环境中的作用分析 在ROS开发环境中,`source ./devel/setup.bash` 命令承担着**关键的环境配置功能**,其主要作用和执行流程如下: #### **核心功能实现** 1. **工作空间环境初始化** - 加载当前ROS工作空间(如`~/catkin_ws`)的编译结果 - 在终端会话中设置必要的环境变量: ``` $ export ROS_PACKAGE_PATH="${ROS_PACKAGE_PATH}:${workspace_path}" $ export PATH="$PATH:${workspace_path}/devel/lib" ``` 2. **功能包发现机制** - 使`rosrun`, `roslaunch`等命令能够识别工作空间内的自定义功能包 - 将工作空间的`devel/share`目录加入ROS的包搜索路径 3. **消息/服务依赖注入** - 自动加载自定义的`.msg`, `.srv`消息类型定义 - 为Python模块生成`__init__.py`文件实现模块导入 #### **系统运行原理** 通过Bash的`source`命令: ```mermaid graph TB A[source命令] --> B[解析setup.bash] B --> C[设置环境变量] C --> D[修改PATH/ROS_PACKAGE_PATH] D --> E[注册功能包] E --> F[注册消息/服务] ``` #### **典型应用场景** 1. **开发环境配置** 编译工作空间后首次使用: ```bash $ cd ~/catkin_ws $ catkin_make # 编译ROS工作空间 $ source devel/setup.bash # 激活当前工作空间环境 ``` 2. **自动化配置(通过.bashrc)** 为避免每次重启终端重复执行(如引用[2][3]所述): ```bash $ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc ``` 这会导致每次开启新终端时自动加载环境(注意避免重复添加导致冲突)[^1][^3]。 #### **常见问题处理** - **路径错误**:若报错`No such file or directory`(引用[1]),需检查: 1. 工作空间是否成功编译生成`devel`目录 2. `.bashrc`中路径是否包含多余空格(如`source~/...`应为`source ~/...`) 3. 文件权限问题:`ls -l devel/setup.bash`验证可执行权限 - **重复加载**:多次执行`echo ... >> ~/.bashrc`会导致启动缓慢,解决: ```bash $ sed -i '/setup.bash/d' ~/.bashrc # 删除旧条目 $ echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc ``` > **实际应用示例**:在配置好的环境中运行节点 > ```bash > $ roslaunch my_package node.launch # 无需每次source即可执行 > ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值