title: nifi.sh 脚本解读
date: 2020-05-21
categories:

  • Apache NIFI
    tags:
  • Apache NIFI
    author: 张诚
    location: BeiJing
    publish: true
    sticky:

整个脚本分为三部分,第一部分是确定NIFI各个路径 目录的确定,设置环境变量,第二部分是方法区。第三部分是脚本逻辑代码的入口,初略的根据传参不同区执行不同的方法。以下脚本有详细注释:

  1. #!/bin/sh
  2. # ==========================
  3. # 1、查找文件的路径 start
  4. # ==========================
  5. # 由于MacOS X、FreeBSD和其他一些系统缺少gnu readlink,我们使用了基于以下StackOverflow注释http://stackoverflow.com/a/1116890/888876的更可移植的方法
  6. ## 特殊变量 当前脚本的文件名
  7. TARGET_FILE=$0
  8. #跳转到当前脚本所在的目录
  9. cd $(dirname $TARGET_FILE)
  10. ## TARGET_FILE=nifi.sh
  11. TARGET_FILE=$(basename $TARGET_FILE)
  12. ## 遍历(可能的)符号链接链 -L filename,判断文件是否问链接文件
  13. while [ -L "$TARGET_FILE" ]
  14. do
  15. TARGET_FILE=$(readlink $TARGET_FILE)
  16. cd $(dirname $TARGET_FILE)
  17. TARGET_FILE=$(basename $TARGET_FILE)
  18. done
  19. # pwd -P 显示出实际路径,而非使用连接(link)路径。
  20. PHYS_DIR=$(pwd -P)
  21. # 脚本所在目录
  22. SCRIPT_DIR=$PHYS_DIR
  23. PROGNAME=$(basename "$0")
  24. # ==========================
  25. # 查找文件的路径 end
  26. # ==========================
  27. # 执行nifi-env.sh 设置了NIFI的目录环境变量
  28. . "${SCRIPT_DIR}/nifi-env.sh"
  29. # ==========================
  30. #/2、方法区 start
  31. # ==========================
  32. warn() {
  33. echo "${PROGNAME}: $*"
  34. }
  35. die() {
  36. warn "$*"
  37. exit 1
  38. }
  39. # 检测特殊的操作系统,然后做一些特殊操作
  40. detectOS() {
  41. # Cygwin是一个在windows平台上运行的类UNIX模拟环境
  42. cygwin=false;
  43. # AIX,是IBM专有的UNIX操作系统
  44. aix=false;
  45. # AS400是IBM早期推出的商用小型机
  46. os400=false;
  47. # Darwin是由苹果电脑于2000年所释出的一个开放原始码操作系统
  48. darwin=false;
  49. case "$(uname)" in
  50. CYGWIN*)
  51. cygwin=true
  52. ;;
  53. AIX*)
  54. aix=true
  55. ;;
  56. OS400*)
  57. os400=true
  58. ;;
  59. Darwin)
  60. darwin=true
  61. ;;
  62. esac
  63. # For AIX, set an environment variable
  64. if ${aix}; then
  65. export LDR_CNTRL=MAXDATA=0xB0000000@DSA
  66. echo ${LDR_CNTRL}
  67. fi
  68. # In addition to those, go around the linux space and query the widely
  69. # adopted /etc/os-release to detect linux variants
  70. if [ -f /etc/os-release ]; then
  71. . /etc/os-release
  72. fi
  73. }
  74. unlimitFD() {
  75. # Use the maximum available, or set MAX_FD != -1 to use that
  76. # 判断 ${MAX_FD}有没有被赋值 条件成立则没有赋值
  77. if [ "x${MAX_FD}" = "x" ]; then
  78. MAX_FD="maximum"
  79. fi
  80. # 如果可能的话,提升文件描述符的最大数量
  81. if [ "${os400}" = "false" ] && [ "${cygwin}" = "false" ]; then
  82. MAX_FD_LIMIT=$(ulimit -H -n)
  83. if [ "${MAX_FD_LIMIT}" != 'unlimited' ]; then
  84. if [ $? -eq 0 ]; then
  85. if [ "${MAX_FD}" = "maximum" -o "${MAX_FD}" = "max" ]; then
  86. # use the system max
  87. MAX_FD="${MAX_FD_LIMIT}"
  88. fi
  89. ulimit -n ${MAX_FD} > /dev/null
  90. # echo "ulimit -n" `ulimit -n`
  91. if [ $? -ne 0 ]; then
  92. warn "Could not set maximum file descriptor limit: ${MAX_FD}"
  93. fi
  94. else
  95. warn "Could not query system maximum file descriptor limit: ${MAX_FD_LIMIT}"
  96. fi
  97. fi
  98. fi
  99. }
  100. # 找到要执行的JVM
  101. locateJava() {
  102. # 设置Java虚拟机
  103. if $cygwin ; then
  104. [ -n "${JAVA}" ] && JAVA=$(cygpath --unix "${JAVA}")
  105. [ -n "${JAVA_HOME}" ] && JAVA_HOME=$(cygpath --unix "${JAVA_HOME}")
  106. fi
  107. if [ "x${JAVA}" = "x" ] && [ -r /etc/gentoo-release ] ; then
  108. JAVA_HOME=$(java-config --jre-home)
  109. fi
  110. if [ "x${JAVA}" = "x" ]; then
  111. if [ "x${JAVA_HOME}" != "x" ]; then
  112. if [ ! -d "${JAVA_HOME}" ]; then
  113. die "JAVA_HOME is not valid: ${JAVA_HOME}"
  114. fi
  115. JAVA="${JAVA_HOME}/bin/java"
  116. else
  117. warn "JAVA_HOME not set; results may vary"
  118. JAVA=$(type java)
  119. JAVA=$(expr "${JAVA}" : '.* \(/.*\)$')
  120. if [ "x${JAVA}" = "x" ]; then
  121. die "java command not found"
  122. fi
  123. fi
  124. fi
  125. # 如果命令是 env, tools.jar classes.jar也加到 classpath
  126. if [ "$1" = "env" ]; then
  127. [ "x${TOOLS_JAR}" = "x" ] && [ -n "${JAVA_HOME}" ] && TOOLS_JAR=$(find -H "${JAVA_HOME}" -name "tools.jar")
  128. [ "x${TOOLS_JAR}" = "x" ] && [ -n "${JAVA_HOME}" ] && TOOLS_JAR=$(find -H "${JAVA_HOME}" -name "classes.jar")
  129. if [ "x${TOOLS_JAR}" = "x" ]; then
  130. warn "Could not locate tools.jar or classes.jar. Please set manually to avail all command features."
  131. fi
  132. fi
  133. }
  134. # 初始化
  135. init() {
  136. # 确定是否需要执行特殊的操作系统处理
  137. detectOS
  138. # 如果可能的话,不限制文件描述符的数量
  139. unlimitFD
  140. # 找到要执行的JVM
  141. locateJava "$1"
  142. }
  143. # 将nifi安装为service
  144. install() {
  145. detectOS
  146. if [ "${darwin}" = "true" ] || [ "${cygwin}" = "true" ]; then
  147. echo 'Installing Apache NiFi as a service is not supported on OS X or Cygwin.'
  148. exit 1
  149. fi
  150. SVC_NAME=nifi
  151. if [ "x$2" != "x" ] ; then
  152. SVC_NAME=$2
  153. fi
  154. # since systemd seems to honour /etc/init.d we don't still create native systemd services
  155. # yet...
  156. initd_dir='/etc/init.d'
  157. SVC_FILE="${initd_dir}/${SVC_NAME}"
  158. if [ ! -w "${initd_dir}" ]; then
  159. echo "Current user does not have write permissions to ${initd_dir}. Cannot install NiFi as a service."
  160. exit 1
  161. fi
  162. # Create the init script, overwriting anything currently present
  163. cat <<SERVICEDESCRIPTOR > ${SVC_FILE}
  164. #!/bin/sh
  165. #
  166. # Licensed to the Apache Software Foundation (ASF) under one or more
  167. # contributor license agreements. See the NOTICE file distributed with
  168. # this work for additional information regarding copyright ownership.
  169. # The ASF licenses this file to You under the Apache License, Version 2.0
  170. # (the "License"); you may not use this file except in compliance with
  171. # the License. You may obtain a copy of the License at
  172. #
  173. # http://www.apache.org/licenses/LICENSE-2.0
  174. #
  175. # Unless required by applicable law or agreed to in writing, software
  176. # distributed under the License is distributed on an "AS IS" BASIS,
  177. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  178. # See the License for the specific language governing permissions and
  179. # limitations under the License.
  180. #
  181. # chkconfig: 2345 20 80
  182. # description: Apache NiFi is a dataflow system based on the principles of Flow-Based Programming.
  183. #
  184. # Make use of the configured NIFI_HOME directory and pass service requests to the nifi.sh executable
  185. NIFI_HOME=${NIFI_HOME}
  186. bin_dir=\${NIFI_HOME}/bin
  187. nifi_executable=\${bin_dir}/nifi.sh
  188. \${nifi_executable} "\$@"
  189. SERVICEDESCRIPTOR
  190. if [ ! -f "${SVC_FILE}" ]; then
  191. echo "Could not create service file ${SVC_FILE}"
  192. exit 1
  193. fi
  194. # Provide the user execute access on the file
  195. chmod u+x ${SVC_FILE}
  196. # If SLES or OpenSuse...
  197. if [ "${ID}" = "opensuse" ] || [ "${ID}" = "sles" ]; then
  198. rm -f "/etc/rc.d/rc2.d/S65${SVC_NAME}"
  199. ln -s "/etc/init.d/${SVC_NAME}" "/etc/rc.d/rc2.d/S65${SVC_NAME}" || { echo "Could not create link /etc/rc.d/rc2.d/S65${SVC_NAME}"; exit 1; }
  200. rm -f "/etc/rc.d/rc2.d/K65${SVC_NAME}"
  201. ln -s "/etc/init.d/${SVC_NAME}" "/etc/rc.d/rc2.d/K65${SVC_NAME}" || { echo "Could not create link /etc/rc.d/rc2.d/K65${SVC_NAME}"; exit 1; }
  202. echo "Service ${SVC_NAME} installed"
  203. # Anything other fallback to the old approach
  204. else
  205. rm -f "/etc/rc2.d/S65${SVC_NAME}"
  206. ln -s "/etc/init.d/${SVC_NAME}" "/etc/rc2.d/S65${SVC_NAME}" || { echo "Could not create link /etc/rc2.d/S65${SVC_NAME}"; exit 1; }
  207. rm -f "/etc/rc2.d/K65${SVC_NAME}"
  208. ln -s "/etc/init.d/${SVC_NAME}" "/etc/rc2.d/K65${SVC_NAME}" || { echo "Could not create link /etc/rc2.d/K65${SVC_NAME}"; exit 1; }
  209. echo "Service ${SVC_NAME} installed"
  210. fi
  211. }
  212. run() {
  213. BOOTSTRAP_CONF_DIR="${NIFI_HOME}/conf"
  214. BOOTSTRAP_CONF="${BOOTSTRAP_CONF_DIR}/bootstrap.conf";
  215. BOOTSTRAP_LIBS="${NIFI_HOME}/lib/bootstrap/*"
  216. # 运行NiFi时使用的用户名。此值将在Windows上被忽略。在bootstrap.conf中 run.as= 配置
  217. run_as_user=$(grep '^\s*run.as' "${BOOTSTRAP_CONF}" | cut -d'=' -f2)
  218. # 如果以用户身份运行与启动流程相同,则忽略此配置
  219. if [ "${run_as_user}" = "$(whoami)" ]; then
  220. unset run_as_user
  221. fi
  222. if $cygwin; then
  223. if [ -n "${run_as_user}" ]; then
  224. echo "The run.as option is not supported in a Cygwin environment. Exiting."
  225. exit 1
  226. fi;
  227. NIFI_HOME=$(cygpath --path --windows "${NIFI_HOME}")
  228. NIFI_LOG_DIR=$(cygpath --path --windows "${NIFI_LOG_DIR}")
  229. NIFI_PID_DIR=$(cygpath --path --windows "${NIFI_PID_DIR}")
  230. BOOTSTRAP_CONF=$(cygpath --path --windows "${BOOTSTRAP_CONF}")
  231. BOOTSTRAP_CONF_DIR=$(cygpath --path --windows "${BOOTSTRAP_CONF_DIR}")
  232. BOOTSTRAP_LIBS=$(cygpath --path --windows "${BOOTSTRAP_LIBS}")
  233. BOOTSTRAP_CLASSPATH="${BOOTSTRAP_CONF_DIR};${BOOTSTRAP_LIBS}"
  234. if [ -n "${TOOLS_JAR}" ]; then
  235. TOOLS_JAR=$(cygpath --path --windows "${TOOLS_JAR}")
  236. BOOTSTRAP_CLASSPATH="${TOOLS_JAR};${BOOTSTRAP_CLASSPATH}"
  237. fi
  238. else
  239. if [ -n "${run_as_user}" ]; then
  240. if ! id -u "${run_as_user}" >/dev/null 2>&1; then
  241. echo "The specified run.as user ${run_as_user} does not exist. Exiting."
  242. exit 1
  243. fi
  244. fi;
  245. BOOTSTRAP_CLASSPATH="${BOOTSTRAP_CONF_DIR}:${BOOTSTRAP_LIBS}"
  246. if [ -n "${TOOLS_JAR}" ]; then
  247. BOOTSTRAP_CLASSPATH="${TOOLS_JAR}:${BOOTSTRAP_CLASSPATH}"
  248. fi
  249. fi
  250. echo
  251. echo "Java home: ${JAVA_HOME}"
  252. echo "NiFi home: ${NIFI_HOME}"
  253. echo
  254. echo "Bootstrap Config File: ${BOOTSTRAP_CONF}"
  255. echo
  256. #在后台运行'start',因为进程将继续运行,监视NiFi。所有其他命令都将很快终止,所以要等待它们
  257. #设置目录的参数
  258. # java程序启动参数 -D 在System类中通过getProperties()得到的一串系统属性
  259. BOOTSTRAP_LOG_PARAMS="-Dorg.apache.nifi.bootstrap.config.log.dir='${NIFI_LOG_DIR}'"
  260. BOOTSTRAP_PID_PARAMS="-Dorg.apache.nifi.bootstrap.config.pid.dir='${NIFI_PID_DIR}'"
  261. BOOTSTRAP_CONF_PARAMS="-Dorg.apache.nifi.bootstrap.config.file='${BOOTSTRAP_CONF}'"
  262. # 去掉一下注釋就允许调试NIFI进程 (或者在bootstrap.conf中取消注释)
  263. #BOOTSTRAP_DEBUG_PARAMS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=8000"
  264. BOOTSTRAP_DIR_PARAMS="${BOOTSTRAP_LOG_PARAMS} ${BOOTSTRAP_PID_PARAMS} ${BOOTSTRAP_CONF_PARAMS}"
  265. run_nifi_cmd="'${JAVA}' -cp '${BOOTSTRAP_CLASSPATH}' -Xms12m -Xmx24m ${BOOTSTRAP_DIR_PARAMS} ${BOOTSTRAP_DEBUG_PARAMS} ${BOOTSTRAP_JAVA_OPTS} org.apache.nifi.bootstrap.RunNiFi $@"
  266. if [ -n "${run_as_user}" ]; then
  267. # 为运行提供SCRIPT_DIR并执行ni -env。
  268. run_nifi_cmd="sudo -u ${run_as_user} sh -c \"SCRIPT_DIR='${SCRIPT_DIR}' && . '${SCRIPT_DIR}/nifi-env.sh' && ${run_nifi_cmd}\""
  269. fi
  270. if [ "$1" = "run" ]; then
  271. # 使用exec将PID切换到RunNiFi java进程,而不是将其作为子进程( 前台运行nifi,Ctrl-C就停止NIFI)
  272. # exec命令 用于调用并执行指令的命令。exec命令通常用在shell脚本程序中,可以调用其他的命令。如果在当前终端中使用命令,则当指定的命令执行完毕后会立即退出终端。
  273. run_nifi_cmd="exec ${run_nifi_cmd}"
  274. fi
  275. # Linux eval命令用于重新运算求出参数的内容。
  276. # eval可读取一连串的参数,然后再依参数本身的特性来执行。
  277. if [ "$1" = "start" ]; then
  278. ( eval "cd ${NIFI_HOME} && ${run_nifi_cmd}" & )> /dev/null 1>&-
  279. else
  280. eval "cd ${NIFI_HOME} && ${run_nifi_cmd}"
  281. fi
  282. EXIT_STATUS=$?
  283. # 稍等(3秒),等待日志记录完成,然后回显新行。
  284. # 我们这样做是为了避免在运行命令后,日志在控制台被吐出来,然后返回给用户
  285. sleep 3
  286. echo
  287. }
  288. main() {
  289. init "$1"
  290. run "$@"
  291. }
  292. # ==========================
  293. # 方法区 end
  294. # ==========================
  295. # ==========================
  296. # 3、入口 start
  297. # ==========================
  298. # 判断 $1 第一个参数是什么
  299. # 其中install 将nifi安装为service
  300. # start 启动
  301. # stop 停止
  302. # run
  303. # status
  304. # dump
  305. # env
  306. # restart 重启
  307. # $@ 传全部参数
  308. case "$1" in
  309. install)
  310. install "$@"
  311. ;;
  312. start|stop|run|status|dump|env)
  313. main "$@"
  314. ;;
  315. restart)
  316. init
  317. run "stop"
  318. run "start"
  319. ;;
  320. *)
  321. echo "Usage nifi {start|stop|run|restart|status|dump|install}"
  322. ;;
  323. esac

公众号

关注公众号 得到第一手文章/文档更新推送。

nifi-sh - 图1