Nutch 的启动脚本分析 & Linux Shell

#!/bin/bash

# 第一行一定要指明系统需要哪种shell解释该shell程序
#
# The Nutch command script
#
# Environment Variables
#
#   NUTCH_JAVA_HOME The java implementation to use. Overrides JAVA_HOME.
#
#   NUTCH_HEAPSIZE The maximum amount of heap to use, in MB. 
#                   Default is 1000.
#
#   NUTCH_OPTS      Extra Java runtime options.
#

###################################################################################################
#
# 注释目的: 学习 Linux Shell 的语法,并了解 Nutch 的程序入口,类及其主函数
#
# 创建注释: By CZH in CUG, China, 2009-05-02
#
# 更新注释: By CZH in CUG, China, 2009-05-02
#
# Email:    [email protected]
#
# Blog:       http://hi.baidu.com/xxai/blog/item/c0570417c19721094a90a7ad.html
#
###################################################################################################

#####################################################################################################
#
# case 选择分支,基本格式为 
#
# ====================
# case "变量名" in
# 第一个取值) 语句;;
# 第二个取值) 语句;;
# ...
# esac (把case倒过来写^_)^)
# ====================
#
#################################################################################################

cygwin=false
case "`uname`" in
CYGWIN*) cygwin=true;;
esac

###################################################################################################
#
# Linxu Shell 中的一些特殊变量
#
# ====================================================================================
# $0    shell脚本的名字
# $*    以一对双引号给出参数列表
# $@    将各个参数分别双引号返回
# $#    参数的个数,不包括shell脚本名本身
#         处理完一个参数之后,可以调用shift命令,将$#数字减1,并且剩余参数位置提前一位
#         shift命令也可以带一个参数,如shift9,表示前9个参数处理完毕。
# $_    上一个命令的最后一个参数
# $$    所在命令的PID
# $!    最后执行的后台命令的PID
# $?    上一条命令执行后的返回值(也称作 “退出码”)它是一个十进制数
#         多数Shell命令执行成功时,则返回值为0;如果执行失败,则返回非0值
# ====================================================================================

###################################################################################################

###################################################################################################
#
# while/until 循环
#
# ==================
# while
#   若干个命令行1
# do
#   若干个命令行2
# done
# ==================
#
# 只要while的“若干个命令行1”中最后一个命令的返回状态为真,while循环就继续执行do...done之间的“若干个命令行
# until 循环与 while 循环结构类似,区别在于:until是在条件为假时继续执行循环
#
###################################################################################################

###################################################################################################
#
# 关于引号的用法
#
# Linux shell 有 3 种引号,单引号,反引号(键盘左上角),双引号
#
# ================================================================================================
# 单引号:由单引号括起来的字符都作为普通字符出现
#
# 反引号:倒引号括起来的字符被shell解释为命令行
#         在执行时,Shell会先执行该命令行,并以它的标准输出结果取代整个倒引号部分
#
# 双引号:由双引号括起来的字符,除$、倒引号(`Esc键下面的那个键)和反斜线(\)仍保留其特殊功能外,
#         其余字符均作为普通字符对待
# ================================================================================================
#
###################################################################################################

######################################################################################################
#
# 正则表达式
#
# =================================
# 命令: expr 字符串 : 正则表达式
# =================================
#
# 语法
#
# =================================================================================================
# \      将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后向引用、或一个八进制转义符。
#        例如,'\n' 匹配一个换行符。'\\' 匹配 "\" 而 "\(" 则匹配 "("
#
# ^      匹配输入字符串的开始位置
#
# $      匹配输入字符串的结束位置
#
# *      匹配前面的子表达式零次或多次
#
# +      匹配前面的子表达式一次或多次
#
# ?      匹配前面的子表达式零次或一次
#
# {n}    n 是一个非负整数。匹配确定的 n 次
#
# {n,}   n 是一个非负整数。至少匹配n 次
#
# {n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。
#        注意在逗号和两个数之间不能有空格
#
# ?      当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。
#        非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。
#        例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'
#
# .      匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式
#
# (pattern)   匹配pattern 并获取这一匹配。要匹配圆括号字符,请使用 '\(' 或 '\)'
#
# (?:pattern) 匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。
#
# x|y    匹配 x 或 y
#
# [xyz] 字符集合。匹配所包含的任意一个字符
#
# [^xyz] 与[xyz]相反。匹配未包含的任意字符。
#
# [a-z] 字符范围。匹配指定范围内的任意字符。
#
# [^a-z] 与[a-z]相反。匹配任何不在指定范围内的任意字符
#
# \b     匹配一个单词边界,也就是指单词和空格间的位置。
#        例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
#
# \B     匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
#
# \cx    匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。
#
# \d     匹配一个数字字符。等价于 [0-9]
#
# \D     匹配一个非数字字符。等价于 [^0-9]
#
# \f     匹配一个换页符
#
# \n     匹配一个换行符
#
# \r     匹配一个回车符
#
# \s     匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]
#
# \S     匹配任何非空白字符。等价于 [^ \f\n\r\t\v]
#
# \t     匹配一个制表符
#
# \v     匹配一个垂直制表符
#
# \w     匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]
#
# \W     匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'
#
# \xn    匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长
#
# \num   匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。
#        例如,'(.)\1' 匹配两个连续的相同字符
#
# =================================================================================================
#
################################################################################################

# resolve links - $0 may be a softlink
THIS="$0"
while [ -h "$THIS" ]; do
ls=`ls -ld "$THIS"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '.*/.*' > /dev/null; then
    THIS="$link"
else
    THIS=`dirname "$THIS"`/"$link"
fi
done

# if no args specified, show usage
if [ $# = 0 ]; then
echo "Usage: nutch [-core] COMMAND"
echo "where COMMAND is one of:"
echo " crawl             one-step crawler for intranets"
echo " readdb            read / dump crawl db"
echo " convdb            convert crawl db from pre-0.9 format"
echo " mergedb           merge crawldb-s, with optional filtering"
echo " readlinkdb        read / dump link db"
echo " inject            inject new urls into the database"
echo " generate          generate new segments to fetch from crawl db"
echo " freegen           generate new segments to fetch from text files"
echo " fetch             fetch a segment's pages"
echo " parse             parse a segment's pages"
echo " readseg           read / dump segment data"
echo " mergesegs         merge several segments, with optional filtering and slicing"
echo " updatedb          update crawl db from segments after fetching"
echo " invertlinks       create a linkdb from parsed segments"
echo " mergelinkdb       merge linkdb-s, with optional filtering"
echo " index             run the indexer on parsed segments and linkdb"
echo " solrindex         run the solr indexer on parsed segments and linkdb"
echo " merge             merge several segment indexes"
echo " dedup             remove duplicates from a set of segment indexes"
echo " solrdedup         remove duplicates from solr"
echo " plugin            load a plugin and run one of its classes main()"
echo " server            run a search server"
echo " or"
echo " CLASSNAME         run the class named CLASSNAME"
echo "Most commands print help when invoked w/o parameters."
echo ""
echo "Expert: -core option is for developers only. It avoids building the job jar, "
echo "        instead it simply includes classes compiled with ant compile-core. "
echo "        NOTE: this works only for jobs executed in 'local' mode"
exit 1
fi

IS_CORE=0
#check for -core option
if [ "$1" == "-core" ] ; then
IS_CORE=1
shift
fi

# get arguments
COMMAND=$1
shift

# some directories
THIS_DIR=`dirname "$THIS"`
NUTCH_HOME=`cd "$THIS_DIR/.." ; pwd`

# some Java parameters
if [ "$NUTCH_JAVA_HOME" != "" ]; then
#echo "run java in $NUTCH_JAVA_HOME"
JAVA_HOME=$NUTCH_JAVA_HOME
fi

if [ "$JAVA_HOME" = "" ]; then
echo "Error: JAVA_HOME is not set."
exit 1
fi

JAVA=$JAVA_HOME/bin/java
JAVA_HEAP_MAX=-Xmx1000m 

# check envvars which might override default args
if [ "$NUTCH_HEAPSIZE" != "" ]; then
#echo "run with heapsize $NUTCH_HEAPSIZE"
JAVA_HEAP_MAX="-Xmx""$NUTCH_HEAPSIZE""m"
#echo $JAVA_HEAP_MAX
fi

# CLASSPATH initially contains $NUTCH_CONF_DIR, or defaults to $NUTCH_HOME/conf
CLASSPATH=${NUTCH_CONF_DIR:=$NUTCH_HOME/conf}
CLASSPATH=${CLASSPATH}:$JAVA_HOME/lib/tools.jar

# so that filenames w/ spaces are handled correctly in loops below
IFS=

# for developers, add plugins, job & test code to CLASSPATH
if [ -d "$NUTCH_HOME/build/plugins" ]; then
CLASSPATH=${CLASSPATH}:$NUTCH_HOME/build
fi
if [ -d "$NUTCH_HOME/build/test/classes" ]; then
CLASSPATH=${CLASSPATH}:$NUTCH_HOME/build/test/classes
fi

if [ $IS_CORE == 0 ] 
then
for f in $NUTCH_HOME/build/nutch-*.job; do
    CLASSPATH=${CLASSPATH}:$f;
done

# for releases, add Nutch job to CLASSPATH
for f in $NUTCH_HOME/nutch-*.job; do
    CLASSPATH=${CLASSPATH}:$f;
done
else
CLASSPATH=${CLASSPATH}:$NUTCH_HOME/build/classes
fi

# add plugins to classpath
if [ -d "$NUTCH_HOME/plugins" ]; then
CLASSPATH=${NUTCH_HOME}:${CLASSPATH}
fi

###################################################################################################
#
# for 循环
#
# ===========================
# for变量名 in 数值列表; do
#   若干个命令行
# done
# ===========================
#
###################################################################################################

# add libs to CLASSPATH
for f in $NUTCH_HOME/lib/*.jar; do
CLASSPATH=${CLASSPATH}:$f;
done

for f in $NUTCH_HOME/lib/jetty-ext/*.jar; do
CLASSPATH=${CLASSPATH}:$f;
done

# cygwin path translation
if $cygwin; then
CLASSPATH=`cygpath -p -w "$CLASSPATH"`
fi

###################################################################################################
#
# 文件测试
#
# =================================================================================================
# -e文件名: 如果文件存在则为真
# -r文件名: 如果文件存在且可读则为真
# -w文件名: 如果文件存在且可写则为真
# -x文件名: 如果文件存在且可执行则为真
# -s文件名: 如果文件存在且至少有一个字符则为真
# -d文件名: 如果文件存在且为目录则为真
# -f文件名: 如果文件存在且为普通文件则为真
# -c文件名: 如果文件存在且为字符型特殊文件则为真
# -b文件名: 如果文件存在且为块特殊文件则为真

# 非(“!”)、或(“-o)、与(“-a”)三个逻辑操作符用于将测试条件连接起来,
# 其优先级为: 非“!”最高,与“-a”次之,或“-o”最低
# =================================================================================================
#
###################################################################################################

# setup 'java.library.path' for native-hadoop code if necessary
JAVA_LIBRARY_PATH=''
if [ -d "${NUTCH_HOME}/build/native" -o -d "${NUTCH_HOME}/lib/native" ]; then
JAVA_PLATFORM=`CLASSPATH=${CLASSPATH} ${JAVA} org.apache.hadoop.util.PlatformName | sed -e 's/ /_/g'`

if [ -d "$NUTCH_HOME/build/native" ]; then
    JAVA_LIBRARY_PATH=${HADOOP_HOME}/build/native/${JAVA_PLATFORM}/lib
fi

if [ -d "${NUTCH_HOME}/lib/native" ]; then
    if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
      JAVA_LIBRARY_PATH=${JAVA_LIBRARY_PATH}:${NUTCH_HOME}/lib/native/${JAVA_PLATFORM}
    else
      JAVA_LIBRARY_PATH=${NUTCH_HOME}/lib/native/${JAVA_PLATFORM}
    fi
fi
fi

if [ $cygwin = true -a "X${JAVA_LIBRARY_PATH}" != "X" ]; then
JAVA_LIBRARY_PATH=`cygpath -p -w "$JAVA_LIBRARY_PATH"`
fi

# restore ordinary behaviour
unset IFS

# default log directory & file
if [ "$NUTCH_LOG_DIR" = "" ]; then
NUTCH_LOG_DIR="$NUTCH_HOME/logs"
fi
if [ "$NUTCH_LOGFILE" = "" ]; then
NUTCH_LOGFILE='hadoop.log'
fi

#Fix log path under cygwin
if $cygwin; then
NUTCH_LOG_DIR=`cygpath -p -w "$NUTCH_LOG_DIR"`
fi

NUTCH_OPTS="$NUTCH_OPTS -Dhadoop.log.dir=$NUTCH_LOG_DIR"
NUTCH_OPTS="$NUTCH_OPTS -Dhadoop.log.file=$NUTCH_LOGFILE"

if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then
NUTCH_OPTS="$NUTCH_OPTS -Djava.library.path=$JAVA_LIBRARY_PATH"
fi

###################################################################################################
#
# 这里设置具体要运行哪个类

# 网络爬虫 org.apache.nutch.crawl.Crawl, 下一步就从这个类的主函数入手,分析之
#
###################################################################################################

# figure out which class to run
if [ "$COMMAND" = "crawl" ] ; then
CLASS=org.apache.nutch.crawl.Crawl
elif [ "$COMMAND" = "inject" ] ; then
CLASS=org.apache.nutch.crawl.Injector
elif [ "$COMMAND" = "generate" ] ; then
CLASS=org.apache.nutch.crawl.Generator
elif [ "$COMMAND" = "freegen" ] ; then
CLASS=org.apache.nutch.tools.FreeGenerator
elif [ "$COMMAND" = "fetch" ] ; then
CLASS=org.apache.nutch.fetcher.Fetcher
elif [ "$COMMAND" = "fetch2" ] ; then
CLASS=org.apache.nutch.fetcher.Fetcher2
elif [ "$COMMAND" = "parse" ] ; then
CLASS=org.apache.nutch.parse.ParseSegment
elif [ "$COMMAND" = "readdb" ] ; then
CLASS=org.apache.nutch.crawl.CrawlDbReader
elif [ "$COMMAND" = "convdb" ] ; then
CLASS=org.apache.nutch.tools.compat.CrawlDbConverter
elif [ "$COMMAND" = "mergedb" ] ; then
CLASS=org.apache.nutch.crawl.CrawlDbMerger
elif [ "$COMMAND" = "readlinkdb" ] ; then
CLASS=org.apache.nutch.crawl.LinkDbReader
elif [ "$COMMAND" = "readseg" ] ; then
CLASS=org.apache.nutch.segment.SegmentReader
elif [ "$COMMAND" = "segread" ] ; then
echo "[DEPRECATED] Command 'segread' is deprecated, use 'readseg' instead."
CLASS=org.apache.nutch.segment.SegmentReader
elif [ "$COMMAND" = "mergesegs" ] ; then
CLASS=org.apache.nutch.segment.SegmentMerger
elif [ "$COMMAND" = "updatedb" ] ; then
CLASS=org.apache.nutch.crawl.CrawlDb
elif [ "$COMMAND" = "invertlinks" ] ; then
CLASS=org.apache.nutch.crawl.LinkDb
elif [ "$COMMAND" = "mergelinkdb" ] ; then
CLASS=org.apache.nutch.crawl.LinkDbMerger
elif [ "$COMMAND" = "index" ] ; then
CLASS=org.apache.nutch.indexer.Indexer
elif [ "$COMMAND" = "solrindex" ] ; then
CLASS=org.apache.nutch.indexer.solr.SolrIndexer
elif [ "$COMMAND" = "dedup" ] ; then
CLASS=org.apache.nutch.indexer.DeleteDuplicates
elif [ "$COMMAND" = "solrdedup" ] ; then
CLASS=org.apache.nutch.indexer.solr.SolrDeleteDuplicates
elif [ "$COMMAND" = "merge" ] ; then
CLASS=org.apache.nutch.indexer.IndexMerger
elif [ "$COMMAND" = "plugin" ] ; then
CLASS=org.apache.nutch.plugin.PluginRepository
elif [ "$COMMAND" = "server" ] ; then
CLASS='org.apache.nutch.searcher.DistributedSearch$Server'
else
CLASS=$COMMAND
fi

# run it
exec "$JAVA" $JAVA_HEAP_MAX $NUTCH_OPTS -classpath "$CLASSPATH" $CLASS "$@"

你可能感兴趣的:(Nutch 的启动脚本分析 & Linux Shell)