sourceshell脚本
① 用sh、./、source执行Shell脚本到底有何不同
要解答这个看似简单的问题,需要先复习一下linux系统里“命令”这个词的含义。
Linux系统中的命令有两种:一是内置册没命令,是Shell与生俱来的一部分,比如最基础的 cd 、 echo 、 kill 等;二是外部命令,包含已编译的实用程序以及Shell脚本两种,它们两者又可以统称为可执行文件(executables)。我们平时常用的大多数看起来像“内置(自带)命令”的命令,其实都是/usr/bin及其他目录下的已编译程序,如 ls 、 ps 、 grep 等。
可见,外部命令的实体并不存在于Shell中,而是在调用时才从对应的位置加载。如果用户调用命令时没有提供路径的话,Shell通过PATH环境变量来定位外部命令的路径。
如果在PATH给定的路径仍然找不到命令,Shell就会返回"command not found"。这也就解释了为什么在Linux下安装完JDK之后,总是要将$JAVA_HOME/bin写入PATH——用户肯定不想每次调用JDK提供的命令时都要先cd到JDK的安装路径,或者把路径写得清清楚楚。
按照上文所述,我们平时自己写的Shell脚本也是外部命令。下面在/tmp/test目录下直接创建一个文件: touch my_script.sh ,并在其中写几句简单的话。
然后以不同的方式执行这个脚本。
这段示例的信息量蛮大的,下面以Q&A的形式逐个解决问题。
并没有,只是表示相对路径(即当前目录)而已, ./my_script.sh 即在当前目录/tmp/test执行my_script.sh脚本。用绝对路径和用相对路径执行脚本是等价的,因此可以干脆将它们打包统称为“./方式”,以与“sh方式”区分开来。
在./方式下,当前Shell进程会使用fork系统调用产生一个子Shell进程,并使用execve系统调用让OS在子Shell进程中执行脚本。execve系统调用必然会检查脚本文件的权限,而新touch出来的文件权限是 -rw-r--r-- ,并没有可执行(x)权限,所以会报Permission denied。如果把权限改正,那么它的执行结果与sh方式是相同的。
sh方式的不同点在于,OS会通过 sh 命令的调用直接产生一个新的Shell进程,并将 my_script.sh 当作命令行参数传进去。新的Shell进程就会读取、解释并执行该脚本,而OS不关心该文件到底是什么,自然也就不要求可执行权限,只要求读权限就可以了。
Linux与Windows不同,如果用户不指定路径,那么就会直接跳过对当前路径的检查,直接按照PATH来查找。而PATH里自然是没有当前路径的,command not found就顺理成章了。也就是说,加 ./ 是为了告诉Shell:“我已经确定我要执行的东西在当前路径了”。
看官可能会问,干脆在PATH里直接加上当前路径(即 . ),不就可以免去打 ./ 的麻烦了吗?Linux非常不推荐这样做,安全风险极大。举个极端的例子:一个普通用户在自己的家目录新建了一个名为ls的脚本,但里面的内容是 rm -rf /* 。然后root用户来到该用户的家目录,并执行ls命令,如果PATH里有当前路径的话,结果可想而知。
source是Shell(准确地说是Bash)的内置命令,在Bourne Shell中的等价命令是一个点 . ,即点命令州带纳。用source命令执行脚本文件时,是在当前Shell进程中执行,而不是像./与sh方式一样在新的Shell进程中执行,因此早先设置的变量在脚本里是可以读取到的。
source一般不用来执行业务脚本,最常见用途是在某些初始化脚本修改之后使其立即生效,即 source /etc/profile 这样。
shebang是指脚本文件中以字符 #! 开头的第一行,它用来指定这个脚行滑本该用哪种解释器来解释。上文中出现的 #!/bin/sh 就表示应该使用sh(在这里就是Bash)来解释它。
需要注意,只有./方式执行脚本才会读取shebang并调用指定的解释器,而“sh方式”(sh当然可以换成任意其他的解释器)会忽略shebang。举个例子,新建一个python脚本,但是shebang仍然故意错写:
如果执行 ./my_script.py 的话,会报语法错误,因为Bash不能解释Python;执行 python my_script.py 是正常的,因为会直接用Python解释器。若把shebang改回正确的 #!/usr/bin/python ,那么两种方式都能正常执行。
实际上,shebang甚至可以写成任意外部命令(当然不推荐这样做)。举个有趣的栗子,创建脚本rm_self.sh:
执行 sh rm_self.sh ,会输出"I am still here!",并且rm_self.sh文件本身还在。但若是执行 ./rm_self.sh ,则没有任何输出,并且rm_self.sh文件本身消失了。
② shell脚本执行source报错
在Ubuntu 16.04机器在执行shell脚本时,报source: not found
原因是shell脚本执培困行的时候配稿念用的不是bash,而是dash,可以使用下面方法修改。
出现对话框后,选择no,再查看一次
重新执行脚本敬塌,问题解决
③ linux下的Source命令的基本功能
source命令用法:source FileName
作用:在当前bash环境下读取并执行FileName中的命令。
注:该命令通常用命令".”来替代。
使用范例:
1、source filename
2、. filename#(中间有空格)
source命令(从 C Shell 而来)是bash shell的内置命令。点命令,就是个点符号,(从Bourne Shell而来)是source的另一名称。
同样的,当前脚本中配置的变量也将作为脚本的环境,source(或点)命令通常用于重新执行刚修改的初始化文档,如 .bash_profile 和 .profile 等等。
例如,假如在登录后对 .bash_profile 中的 EDITER 和 TERM 变量做了修改,则能够用source命令重新执行 .bash_profile 中的命令而不用注销并重新登录。
比如在一个脚本里export $KKK=111,假如用./a.sh执行该脚本,执行完毕后,运行echo $KKK,发现没有值,假如用source来执行 ,然后再echo,就会发现KKK=111。
因为调用./a.sh来执行shell是在一个子shell里运行的,所以执行后,结构并没有反应到父shell里,但是source不同他就是在本shell中执行的,所以能够看到结果。
source命令(从 C Shell 而来)是bash shell的内置命令。点命令,就是一个点符号,(从Bourne Shell而来)是source的另一名称。
这两个命令都以一个脚本为参数,该脚本将作为当前shell的环境执行,即不会启动一个新的子进程。所有在脚本中设置的变量将成为当前Shell的一部分。
文件建立好之后,以后每次编译核心,只需要在/usr/src/linux-2.4.20下输入source make_command就行了。这个文件也完全可以做成脚本,只需稍加改动即可。
shell编程中的命令有时和C语言是一样的。&&表示与,||表示或。把两个命令用&&联接起来,如make mrproper && make menuconfig,表示要第一个命令执行成功才能执行第二个命令。
对执行顺序有要求的命令能保证一旦有错误发生,下面的命令不会盲目地继续执行。
④ SHELL脚本运行的几种方法以及区别
给脚本加上执行权限chmod
u+x
a.sh,
而后就可以直接用全路径来执行脚本了,比如当前文件夹下用./a.sh,如果如果脚本所在目录在path环境变量之中,
则直接用a.sh即可(这和运行我们自己编写的程序是一个道理)sh/bash
./a.sh
这种情况不需要脚本具有执行权限以上两种执行方式都是在子shell中执行的,也就是说当前shell需要启动另外一个shell,用来执行a.sh内的命令source
./a.sh
.
./a.sh(注意前面的
.
)以上两种执行方式是在当前shell下执行,并不需要建立子shellsource和
.
命令的作用:用来执行一个脚本
前两种方式和后两种方式的另外区别:如果你在一个脚本里export
$kkk=111
,如果你用./a.sh执行该脚本,执行完毕后,你运行
echo
$kkk
,发现没有值,如果你用source来执行
,然后再echo
,就会发现kkk=111。因为调用./a.sh来执行shell是在一个子shell里运行的,所以执行后,结构并没有反应到父shell里,但是
source不同它就是在本shell中执行的,所以可以看到结果。
⑤ Linux中source命令的使用方式
source 命令 是一个内置的 shell 命令 ,用于从当前shell会话中的文件读取和执行命令。source命令通常用于保留、更改当前shell中的环境变量。简而言之,source一个 脚本 ,将会在当前shell中运行execute命令。
source命令可用于:
刷新当前的shell环境
在当前环境使用source执行Shell 脚本
从脚本中导入环境中一个Shell函数
从另一个Shell脚本中读取变量
source命令的语法
source命令它需要一个文件,如果提供了参数,那么将用作传递脚本的位置参数。
source FILENAME [ARGUMENTS]
也可以使用.替代source命令:
. FILENAME [ARGUMENTS]
如何使用source命令
1. 刷新当前的shell环境
可以在当前的shell环境中定义一个别名。为ls -al定义一个别名为ll:
[root@localhost ~]# echo "alias ll='ls -al'" >> ~/.bashrc
在~/.bashrc文件中定义完别名,可以使用source命令刷新当前shell环境:
[root@localhost ~]# source ~/.bashrc
现在可以使用ll别名列出当前目录里所有文件了,包括隐藏文件。
2. 在当前环境使用source执行Shell脚本
Shell脚本不知道蚂首你在当前Shell环境中定义的变量。source命令可用于在当前会话中执行你的Shell脚本。
下面在定义一个变量:
[root@localhost ~]# website=https://www. linux probe.com
创建一个脚本:
[root@localhost ~]# vim web.sh
#!/bin/bash
echo $website
使用source在当前shell会话中执闷仿数行它:
[root@localhost ~]# source web.shhttps://www.linuxprobe.com
当使用sh运行脚本时,找不到环境中定义的变量:
3. 从脚本中导入环境中一个Shell函数
首先创建一个脚本,定义一个函数:
[root@localhost ~]# vim func.sh
#!/bin/bash
foo(){
echo "test function!"
}
要在当前的shell会话中导入上述脚本的功能,使用下面命令:
[root@localhost ~]# source func.sh
下面在终端中执行以下func.sh脚本中的foo函数试试:
[root@localhost ~]# foo
test function!
source完脚本之后,可以看到在当前回话的终端中可以执行脚本里面的函数。
4. 从另一个Shell脚本中读取变量
首先创建带有一些变量的shell脚本,请输入:
[root@localhost ~]# vim var.sh
#!/bin/bash
a=1
b=2
c=3
再创大岁建一个脚本,该脚本读取上一个脚本var.sh中的变量:
[root@localhost ~]# vim read.sh
#!/bin/bash
source ~/var.sh
echo $a
echo $b
echo $c
在脚本中首先使用source将var.sh中的变量到处到当前回话,然后echo显示变量值。下面执行read.sh看一下:
5. 读取并执行命令
source命令可以从文件读取和执行命令。下面的一个文本文件中带有两个命令,使用source命令运行该文件,看看是否会执行里面的命令。
下面创建一个文件cmd.txt,保存两个命令:
[root@localhost ~]# cat cmd.txt
ip ad
date
下面使用source执行这个文件:
[root@localhost ~]# source cmd.txt
总结
source命令在当前shell中执行脚本,而exec命令在新的shell中运行。
⑥ python 以source方式调用shell脚本,发现参数没有正确传入. 命令行下则没有问题
[willie@localhost pys]$ python a.py
this is a test shell with arguments
arg1 = a; arg2 = b;
以上是运行结果,感觉没什么问题啊
⑦ shell命令中用source 和sh(或者bash)执行脚本的区别,以及export的作用
用户登录到Linux系统后,系统将启动一个用户shell,我们暂且称这个shell为shell父。在这个shell父中,可以使用shell命令或声明变量,也可以创建并运行shell脚本程序。
当使用sh或者bash运行shell脚本程序时,系统将创建一个子shell,我们暂且称为shell子。此时,系统中将有两个shell,一个是登录时系统启动的shell父,另一个是系统为运行脚本程序创建的shell子。
当一个脚本程序运行完毕,脚本shell子将终止,返回到执行该脚本之前的shell父。这时脚本中创建的变量或者环境变量(export的变量)是在shell子中创建的,只在shell子中有效,在shell父中是无法访问的source(或者.)的作用是文件包含,当使用source运行脚本程序时,系统并不会创建子shell,而是将脚本中的命令放到shell父中运行,这时脚本中创建的变量或者环境变量(export的变量)相当于是在shell父中创建的,在shell父中是可以访问的。
因此使用source执行修改后的配置文件会直接生效,不需要重启export 的作用是为当前shell设置环境变量,这样变量在其子shell也可以访问,当然,在其父shell中还是无法访问的普通的变量只在当前shell中可以访问,在父shell或者子shell中都无法访问。
export 也是 bash 的一个内置命令。它主要是用来将父 shell 里的变量导出供子 shell 使用。
它有如下特征:
⑧ 如何在shell脚本中修改添加替换指定文件中的内容
1、可以借助.shell命令执行另一个脚本文件或者用变量保存。比如a.sh和b.sh,a.sh中调用b.sh的代码,一起输出"hello world"的字符串。b.sh的代码如下echo " world!"。
⑨ 如何获得sh或source执行的shell脚本位置
1) 支持从其他目录执行,如 source xxx/yyy/test.sh
1) 支持 sh 和 source 执行
2) 支持路径中有空格
3) 支持 zsh 跟 bash
#!/bin/sh
if [ "$0" = "bash" ]; then
cd "$(dirname "$BASH_SOURCE")"
CUR_FILE=$(pwd)/$(basename "$BASH_SOURCE")
CUR_DIR=$(dirname "$CUR_FILE")
cd - > /dev/null
else
echo "$0" | grep -q "$PWD"
if [ $? -eq 0 ]; then
CUR_FILE=$0
else
CUR_FILE=$(pwd)/$0
fi
CUR_DIR=$(dirname "$CUR_FILE")
fi
echo $CUR_DIR
⑩ 执行shell脚本三种方法的区别:(sh、exec、source)
使用$ sh script.sh执行脚本时,当前shell是父进程,生成一个子shell进程,在子shell中执行脚本。脚本执行完毕,退出子shell,回到当前shell。
./script.sh与 sh script.sh等效。
使用$ source script.sh方式,在当前上下文中执行脚本,不会生成新的进程。脚本执行完毕,回到当前shell。
source方式也叫点命令。
. script.sh与 source script.sh等效。
使用exec command方式,会用command进程替换当前shell进程,并且保持PID不变。执行完毕,直接退出,不回到之前的shell环境。
二、测试验证
vi loop.sh
显示当前进程
sh的方式:执行loop.sh打印执行进程
source方式:执行loop.sh打印执行进程
exec方式:执行loop.sh打印执行进程
按下ctrl+C
sh方式:父进程是6770,执行loop.sh时的子进程是13736。执行完毕后回到父进程shell。
source方式:父进程和子进程都是6770(执行时没有新的进程),执行完毕会回到父进程shell。
exec方式:进程PID没有改变都是6770,执行完毕(ctrl+C强制关闭)时直接退出了shell。脚本执行时替换了父进程的shell,执行完毕后直接退出,没有回到之前的shell。