概述
文章目录
- 本文的目的是提升linux shell脚本的功力,以及熟悉spark-submit提交的具体流程
- spark-sumbit*
- 第一段
- 背景知识
- 综合案例
- 解读
- 第二段
- 背景知识
- 解读
- 第三段
- 背景知识
- 解读
- 总结语
本文的目的是提升linux shell脚本的功力,以及熟悉spark-submit提交的具体流程
spark-sumbit*
#!/usr/bin/env bash
if [ -z "${SPARK_HOME}" ]; then
source "$(dirname "$0")"/find-spark-home
fi
# disable randomized hash for string in Python 3.3+
export PYTHONHASHSEED=0
exec "${SPARK_HOME}"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"
第一段
if [ -z "${SPARK_HOME}" ]; then
source "$(dirname "$0")"/find-spark-home
fi
背景知识
-
双引号
"${SPARK_HOME}" 与 ${SPARK_HOME} 这样写是等效的,均代表获取环境变量中的SPARK_HOME所引用的值
在shell中 “$USER” 与 $USER 其代表的值是一样的。 加不加并不会记录到变量中,也不会添加到字符串中,其代表的一个根本的含义就是 定义 变量的意思。默认情况下,在shell编程中,不带双引号的都会被当作字符串来处理。这个惯例比较特殊。反正与一般意义上的高级编程语言不太一致。(读者可以自己揣摩一下单引号会得出什么样的结论)
#!/bin/bash if [ $USER = "$USER" ];then echo "eq" # 执行eq else echo "neq" fi
-
if(空格)[(空格)-[a-z](空格)(string)(空格)];then 语法
这个是常见的shell 字符串条件判断的格式,-z代表不存在,请注意空格是必填的,这个是跟处理shell脚本的编译器设置的语法解析器有关,或者说内置的正则表达式就是这么获取条件匹配的
在方括号内退出码为0(exit 0即正常退出)则执行then后面的语句,否则执行其他分支homewell:/home/hadoop/shareh$ cat /etc/passwd | grep abc homewell:/home/hadoop/shareh$ echo $? 1
比较其原型 是test命令
-
source命令(直接copy命令)
有人说是点(.)命令,也就是执行目标文件中的命令,但是source 不会执行生成子shell(概念要理清,这个子shell代表这创建一个新的进程被父进程管理环境变量)
如果读者学过C++或者C,都会接触宏(#define)关键字,代表者代码在编译的时候直接把代码copy到引用了宏定义的代码段中,或者类似于C++中的内联函数,都是代码的直接copy.可以看 综合案例
因此可以使用另一个脚本中暴露(export)的变量,因为相当于把另一脚本中的代码,直接copy到当前脚本中
参考1
参考2 -
dirname 命令
获取指定虚拟目录的父目录
homewell:/home/hadoop/shareh$ dirname /home/hadoop/shareh/ /home/hadoop homewell:/home/hadoop/shareh$ dirname /home/hadoop/shareh/abc abc/ abcd/ abc.sh homewell:/home/hadoop/shareh$ dirname /home/hadoop/shareh/abc.sh /home/hadoop/shareh
-
位置参数
$0是调用程序的时候第一个字符串,通常与程序名一致,往往有些博客简单地把它理解成程序名,这样理解是很受伤的,很容易误伤,针对这种情况。希望读者能区分不同场景来理解(查看本案例)
$1是第一个参数,$2是第二个参数
5.案例
#!/bin/bash echo "$0:""$0" echo "$1:""$1" # 超过10个参数的用{}包裹起来,否则 $10 == "$1" + "0" echo "第十个参数""${10}"
# 第一 全路径方式 homewell:~$ /home/homewell/shell1/testdoller.sh 23 $0:/home/homewell/shell1/testdoller.sh $1:23 # 全局变量方式(同上是一致的) homewell:~/shell1$ export SHELLTEST_HOME="/home/homewell/shell1" homewell:~/shell1$ export PATH="$SHELLTEST_HOME:$PATH" homewell:~/shell1$ testdoller.sh 1235 $0:/home/homewell/shell1/testdoller.sh $1:1235 # 第二种 通过相对路径1 homewell:~$ shell1/testdoller.sh 124 $0:shell1/testdoller.sh $1:124 # 第二种 通过相对路径2 homewell:~$ ./shell1/testdoller.sh 124 $0:./shell1/testdoller.sh $1:124 # 第三种 直接以./方式执行 homewell:~$ cd shell1/ homewell:~/shell1$ ./testdoller.sh 125 $0:./testdoller.sh $1:125 # 第四种 通过sh 命令执行 homewell:~/shell1$ sh testdoller.sh 126 $0:testdoller.sh $1:126
扩展内容 其他内置的跟$有关的位置参数
综合案例
-rwxr-xr-x 1 zhangll zhangll 184 10月 2 21:14 pid2.sh*
-rwxrwxrwx 1 zhangll zhangll 1292 10月 2 21:40 pid.sh*
pid.sh
#!/bin/bash
表示当前shell
echo "pid.sh当前shell pid进程($$):$$"
echo "pid.sh当前shell最近一个后台进程pid($!):" "$!"
echo "pid.sh前面一个命令的退出码 ($?) : $?"
# 执行当前的目录路径下的pid2.sh
echo "-------------./pid2.sh--------------"
./pid2.sh
echo "pid.sh当前进程打印 pid2中的pid2暴露的变量($PID2): $PID2"
echo "-------------查看(子进程)的一些特性------------"
# 向外暴露a变量,在父进程中无法查看,只有在子shell中能看
export a=1
echo "pid.sh当前shell显示a 变量($a):"$a
(export b=2; echo "子进程查看父进程暴露的(a):""$a";echo "子进程暴露的变量($b):""$b";echo "子进程打印的进程($$):""$$";echo "子进程($BASHPID):$BASHPID")
echo "pid.sh 在 (子进程之后)当前shell最近一个后台进程pid2($!):" "$!"
echo "pid.sh当前shell显示子进程暴露的b变量($b) : $b"
echo "------------(./pid2.sh &)------------"
./pid2.sh &
echo "pid.sh 在 (./pid2.sh &)最近一个后台进程pid2($!):" "$!"
echo "pid.sh当前进程打印 pid2中的pid2暴露的变量($PID2): $PID2"
echo "-----------source pid2.sh -----------"
source ./pid2.sh
echo "pid.sh source pid2.sh 之后当前进程打印 pid2中的pid2暴露的变量($PID2): $PID2"
exit 0
pid2.sh
#!/bin/bash
echo "######pid2.sh 打印的 ($$):$$"
echo "######pid2.sh 打印的 ($BASHPID):$BASHPID"
echo "######pid2.sh 打印的最近一个后台进程 ($!):$!"
export PID2=30
执行结果
pid.sh当前shell pid进程($$):9553
pid.sh当前shell最近一个后台进程pid($!):
pid.sh前面一个命令的退出码 ($?) : 0
-------------./pid2.sh--------------
######pid2.sh 打印的 ($$):9554
######pid2.sh 打印的 ($BASHPID):9554
######pid2.sh 打印的最近一个后台进程 ($!):
pid.sh当前进程打印 pid2中的pid2暴露的变量($PID2):
-------------查看(子进程)的一些特性------------
pid.sh当前shell显示a 变量($a):1
子进程查看父进程暴露的(a):1
子进程暴露的变量($b):2
子进程打印的进程($$):9553
子进程($BASHPID):9555
pid.sh 在 (子进程之后)当前shell最近一个后台进程pid2($!):
pid.sh当前shell显示子进程暴露的b变量($b) :
------------(./pid2.sh &)------------
######pid2.sh 打印的 ($$):9556
######pid2.sh 打印的 ($BASHPID):9556
######pid2.sh 打印的最近一个后台进程 ($!):
pid.sh 在 (./pid2.sh &)最近一个后台进程pid2($!): 9556
pid.sh当前进程打印 pid2中的pid2暴露的变量($PID2):
-----------source pid2.sh -----------
######pid2.sh 打印的 ($$):9553
######pid2.sh 打印的 ($BASHPID):9553
######pid2.sh 打印的最近一个后台进程 ($!):9556
pid.sh source pid2.sh 之后当前进程打印 pid2中的pid2暴露的变量($PID2): 30
可以发现
- $! 代表当前shell进程空间最近一个执行的后台进程的id,并不会获取父进程空间的最近一次后台进程pid
后台进程与子进程的区别 - ()括号包裹的虽然是开启了一个新的空间,但是其进程id与父亲的一致,但是在其内暴露(export)的变量,父进程无法获取
- $$ 并非代表当前shell的pid,
解读
不管以./spark-submit 还是 直接执行spark-submit,当不存在SPARK_HOME环境变量的时候,就执行当前目录(spark-submit所在目录)中的find-spark-home命令
很显然find-spark-home 要做的工作肯定是设置一个 SPARK_HOME 环境变量用来给后期使用
第二段
# disable randomized hash for string in Python 3.3+
export PYTHONHASHSEED=0
背景知识
-
export 暴露/导出
该关键词在nodejs/js/c/c++中会经常出现,代表这给调用该脚本的环境(脚本/shell环境)暴露一个变量,这个变量将会在当前进程空间中使用,包括子进程空间,但是不会影响父进程空间的变量
解读
很显然暴露了一个PYTHONHASHSEED (python hash seed)
这个是设置一个python随机
中的seed值,当改值为0的时候,代表着关闭随机hash种子,意味着对相同字符串多次使用hash函数,得到的是相同的值,这里可能考虑到pyspark上会调用hash值产生不必要的麻烦,比如spark中的group by 算子,由于可能数据在不同节点上,因此不同节点上会启动不同的python环境(可以理解成python session),python3.2.3之后就默认开启python环境的hash值,这意味着不同环境下的相同字符串,会默认在字符串前面添加一个盐值,防止DOS拒绝服务攻击手段,防止链表太长,降低性能。然后在group by 的相同字符串可能会在不同机器上输出不同 内容,因此为了能够保证数据一致性,需要关闭这个值
地址
第三段
exec "${SPARK_HOME}"/bin/spark-class org.apache.spark.deploy.SparkSubmit "$@"
背景知识
-
exec 命令 参数
代表当前命令与参数 直接覆盖当前shell内容,这个是最暴力的宏替换,不过会暴露当前的用户变量(局部变量)与全局变量
案例见 Linux shell 整理之 复合命令行篇(四)
-
exec 永久重定向操作
案例见 Linux shell 整理之 复合命令行篇(四)
-
双引号
同第一段 1)
解读
因此第三段的意思就是使用spark_home/bin/spark-class 并且传递两个参数
第一个是 org.apache.spark.deploy.SparkSubmit
第二个是 " @ " 代 表 当 前 s h e l l 执 行 所 窜 入 的 参 数 个 体 集 合 的 列 表 , 根 据 实 际 情 况 当 然 可 以 用 " @" 代表当前shell 执行所窜入的参数个体集合的列表,根据实际情况当然可以用 " @"代表当前shell执行所窜入的参数个体集合的列表,根据实际情况当然可以用""来代替。$@ 代表着把输入参数作为多个个体存在,而 $ 可以作为一个单独的个体存在
总结语
纸上得来终觉浅,绝知此事要躬行。简简单单3句话,其涵盖的内容,不是一两句话能够得出来的。当你用心去体会的时候,你会发现,原来一切都这么简单明白
最后
以上就是重要钢铁侠为你收集整理的spark-submit 到底做了什么的全部内容,希望文章能够帮你解决spark-submit 到底做了什么所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复