前言:

  通过对spark集群脚本的研读, 对一些重要的shell脚本技巧, 做下笔记.

*). 取当前脚本的目录

sbin=`dirname "$0"`
sbin=`cd "$sbin"; pwd`

代码评注:
# 以上代码为获取执行脚本所在的目录的常用技巧
# sbin=$(dirname $0) 返回可能是相对路径, 比如./
# sbin=$(cd $sbin; pwd) 采用pwd, 来返回脚本所在目录的绝对路径

*). 循环遍历脚本参数

while (( "$#" )); do
  case $1 in
    --with-tachyon)
      TACHYON_STR="--with-tachyon"
    ;;
  esac
  shift
done

代码评注:
# 这是段遍历脚本参数的常见代码片段
# shell脚本中$#表示参数个数
# 由于$0是脚本名称本身占据, 因此脚本对参数的遍历从$1开始, 借助shift变量左移, 方便了对变长参数列表的遍历
# 基于事件的xml解析方式, 当采用pull方式去遍历的时候, 差不多也是类似的代码结构
# 当然需要注意, shift处理参数变量之后, 对后续脚本代码处理变量是有影响的(负作用), 因此最佳实践是集中处理脚本参数

*). 引入配置脚本

. "$sbin/spark-config.sh"

代码评注:
# shell脚本中'.' 等同于source, 把调用脚本作为调用方脚本的自身的一部分执行, source <shell_file>通常用于导入应用的配置参数
# source/exec/fork 外部脚本的区别, 详见这篇

*). 默认参数处理

if [ "$SPARK_MASTER_PORT" = "" ]; then
  SPARK_MASTER_PORT=7077
fi

代码评注:
# 对变量默认值的处理方式
# 注意对变量添加"", if [ $SPARK_MASTER_PORT = "" ] 会报错误: "[: =: unary operator expected"
# 类似的代码可采用-z $SPARK_MASTER_PORT的方式

if [ -z $SPARK_MASTER_PORT ]; then
  SPARK_MASTER_PORT=7077
fi

*) 对变量的高级处理

this="${BASH_SOURCE-$0}"

代码评注:
# ${BASH_SOURCE-$0}, 属于特殊用法, 用于获取脚本名称, 那为何不用$(basename $0), 如脚本注释里谈到了, 遇到软接连, $(basename $0)就不行了
# 其次${BASH_SOURCE-$0}, 它属于${VAR_NAME:-DEFAULT_VALUE}这种变量语法的简写
# 比如, ${name:-"lilei"}, 如果name没有定义, 则默认返回为"lilei", 若name定义了, 则返回${name}值

*) 对软链接的处理

# resolve links - $0 may be a softlink
common_bin=$(cd -P -- "$(dirname -- "$this")" && pwd -P)
script="$(basename -- "$this")"

代码评注:
# 无论是"cd -P", 还是"pwd -P", -P参数表明若遇到soft link, 则取soft link对应的真实目录/文件

*) set -a/a的使用

set -a
. "${use_conf_dir}/spark-env.sh"
set +a

代码评注:
# set -a, 把执行的变量自动export, set +a, 则把关闭该功能
# 可以简单理解为, 把脚本的本地变量, 都默认添加了export修饰

*). $!的使用和pid文件的使用

nohup nice -n $SPARK_NICENESS "$SPARK_PREFIX"/bin/spark-class $command "$@" \
>> "$log" 2>&1 < /dev/null &
newpid=$!
echo $newpid > $pid

代码评注:
# nohup 表示进程脱离session运行
# nice -n 用于调整进程nice值
# 2>&1 表示把标准错误(stderr, 2)关联到标准输出(stdout, 1), 可以简写为 &>
# $!表示上一个shell命令(后台运行)的pid
# echo $newpid > $pid (代表文件), 是把进程pid写入到进程的pid文件中去
# 很多服务(比如apache)会选择把自身的pid(进程id)写入到pid文件中去, 至于为何这么做? 各有各的应用场景, 下面的kill -0就应用到了

*). kill -0 的使用, 检测进程是否存在, 重入(误判)问题

if [ -f $pid ]; then
  if kill -0 `cat $pid` > /dev/null 2>&1; then
    echo $command running as process `cat $pid`. Stop it first.
    exit 1
  fi
fi

代码评注:
# kill -0 <pid> 只是简单的向进程发送一个signal(不影响进程运行), 用来检测进程是否存在, 存在(echo $? => 0), 不存在(echo $? => 1)
# if [ -f $pid ] 判断pid文件是否存在, cat $pid, 则是获取pid值, 这与上面pid文件相吻合
# kill -0 `cat $pid` > /dev/null 2>&1 后面的'> /dev/null 2>&1'用于去掉不必要信息到控制台
疑问:
# 重入问题: 有点类似tcp的问题, socket占据的四元组(src: ip+port, dest: ip+port), 遗留的tcp包, 对后续重新复用port的socket造成的干扰
# 假设: pid写入到pid文件后, 然后进程退出, 然后有后续的新进程占据了这个pid, 那么脚本根据这个pid判断之前的进程是否存活就没意义了, 由此导致误判
# linux kernel对pid的分配采用了延时再分配的策略, pid被复用而导致重判, 这个需要注意

*). 并发+wait使用

for slave in `cat "$HOSTLIST"|sed "s/#.*$//;/^$/d"`; do
  ssh $SPARK_SSH_OPTS $slave $"${@// /\\ }" \
    2>&1 | sed "s/^/$slave: /" &
  if [ "$SPARK_SLAVE_SLEEP" != "" ]; then
    sleep $SPARK_SLAVE_SLEEP
  fi
done wait 

代码评注:
# shell脚本没有多线程的概念, 且默认执行子shell是阻塞的, 因此只能通过后台运行多个子进程来模拟
# ssh $slave "<command> " & 是把ssh命令放在后台运行
# wait, 是指等待所有的后台进程结束, 才继续进行下去
# 这是很好的并发CountDownLatch的编程实践

*). sed命令使用

sed "s/#.*$//;/^$/d"
sed "s/^/$slave: /"

代码评注:
# 使用流编辑器sed, 对文本内容进行替换和删除, 赞sed

shell 脚本实战笔记(10)--spark集群脚本片段念念碎的更多相关文章

  1. Spark 个人实战系列(1)--Spark 集群安装

    前言: CDH4不带yarn和spark, 因此需要自己搭建spark集群. 这边简单描述spark集群的安装过程, 并讲述spark的standalone模式, 以及对相关的脚本进行简单的分析. s ...

  2. Spark集群测试

    1. Spark Shell测试 Spark Shell是一个特别适合快速开发Spark原型程序的工具,可以帮助我们熟悉Scala语言.即使你对Scala不熟悉,仍然可以使用这一工具.Spark Sh ...

  3. Spark 集群安装部署

    安装准备 Spark 集群和 Hadoop 类似,也是采用主从架构,Spark 中的主服务器进程就叫 Master(standalone 模式),从服务器进程叫 Worker Spark 集群规划如下 ...

  4. 《Apache kafka实战》读书笔记-管理Kafka集群安全之ACL篇

    <Apache kafka实战>读书笔记-管理Kafka集群安全之ACL篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 想必大家能看到这篇博客的小伙伴,估计你对kaf ...

  5. Spark学习笔记5:Spark集群架构

    Spark的一大好处就是可以通过增加机器数量并使用集群模式运行,来扩展计算能力.Spark可以在各种各样的集群管理器(Hadoop YARN , Apache Mesos , 还有Spark自带的独立 ...

  6. Spark集群基于Zookeeper的HA搭建部署笔记(转)

    原文链接:Spark集群基于Zookeeper的HA搭建部署笔记 1.环境介绍 (1)操作系统RHEL6.2-64 (2)两个节点:spark1(192.168.232.147),spark2(192 ...

  7. Spark学习笔记--Linux安装Spark集群详解

    本文主要讲解如何在Linux环境下安装Spark集群,安装之前我们需要Linux已经安装了JDK和Scala,因为Spark集群依赖这些.下面就如何安装Spark进行讲解说明. 一.安装环境 操作系统 ...

  8. zhihu spark集群,书籍,论文

    spark集群中的节点可以只处理自身独立数据库里的数据,然后汇总吗? 修改 我将spark搭建在两台机器上,其中一台既是master又是slave,另一台是slave,两台机器上均装有独立的mongo ...

  9. Spark集群-Standalone 模式

    Spark 集群相关 table td{ width: 15% } 来源于官方, 可以理解为是官方译文, 外加一点自己的理解. 版本是2.4.4 本篇文章涉及到: 集群概述 master, worke ...

随机推荐

  1. queue_01

    A.添加/移除 void queue::push(elemValue); // 尾部添加 viud queue::pop();  // 尾部移除 B.随机存取 C.数据存取 T queue::back ...

  2. STL_算法_中使用的函数对象

    写在前面: STL算法中的 函数对象的功能: (1).都是提供一种比较的函数,比较相邻的左右两个值的 相等/大小 等的关系, (2).返回值都是bool :该返回值 貌似是指明 遍历元素是否还要继续往 ...

  3. jq的attr()与prop()之间区别

    1.attr() 一直存在,prop() 仅存在于 jq-1.6 及其之后 2.新版本jq使用细节: 2.1 自定义添加至dom节点的属性,用attr获取 2.2 表单类checked.selecte ...

  4. hdoj2476 String painter

    题意:有一刷子,能将区间内涂成同一字母.给出src,dst串,问最少涂几次? 用dp[i][j]表示区间[i,j]内最少涂的次数.len=1,2时很明显.len=3时,dp[i][j]要么就在dp[i ...

  5. 关于pthread_cond_wait()使用的理解

    pthread_cond_wait()是linux多线程同步实现的一种方法,表示等待某一个线程共享变量满足了某种情况时 线程才能继续执行 pthread_cond_wait()之后的代码,如下面的示例 ...

  6. 最短路-Prim算法 dijkstra算法

    HDU-1233 #include <iostream> #define INF 1000000 using namespace std; ][]; ]; ]; ]; ]; int mai ...

  7. hdu 6395 Sequence (简单矩乘)

    P/n大多数情况是不变的, 取值只有$O(\sqrt{P})$种, 可以用$p/(p/i)$跳过重复的值, 复杂度$O(logn\sqrt{P})$ 要注意 P跟模数P有冲突 要特判p/i==0和p/ ...

  8. Java compiler level does not match the version of the installed Java project facet.解决方法

    右键项目“Properties”,在弹出的“Properties”窗口左侧,单击“Project Facets”,打开“Project Facets”页面. 在页面中的“Java”下拉列表中,选择相应 ...

  9. 11g adg 环境搭建实施手册-0908

    11g adg 环境搭建实施手册-0908 2017年8月30日 9:16 11g adg 环境搭建实施手册-0824 2017年8月24日 10:18 ####################### ...

  10. HDOJ1008

    #include "iostream" using namespace std; int main() { ) { int n; cin >> n; ) break; ...