Unix Shell Guide

Apache Hadoop的大部分功能是通过shell控制的。有几种方法可以修改这些命令执行的默认行为。

重要的终端用户环境变量

Apache Hadoop拥有许多环境变量,用于控制软件的各个方面。(参见hadoop-env.sh及相关文件。)其中部分环境变量专门用于帮助终端用户管理运行时环境。

HADOOP_CLIENT_OPTS

该环境变量用于所有终端用户非守护进程操作。它可以通过系统属性定义来设置任何Java选项以及任何Apache Hadoop选项。例如:

HADOOP_CLIENT_OPTS="-Xmx1g -Dhadoop.socks.server=localhost:4000" hadoop fs -ls /tmp

将增加内存并通过SOCKS代理服务器发送此命令。

注意:如果定义了'YARN_CLIENT_OPTS',当使用'yarn'运行命令时,它将替换'HADOOP_CLIENT_OPTS'。

(command)_(subcommand)_OPTS

还可以在每个子命令的基础上设置选项。这允许为特定情况创建特殊选项。模式的第一部分是正在使用的命令,但全部大写。命令的第二部分是正在使用的子命令。最后以字符串_OPT结尾。

例如,要配置mapred distcp使用2GB堆内存,可以使用:

MAPRED_DISTCP_OPTS="-Xmx2g"

这些选项将在执行过程中出现在HADOOP_CLIENT_OPTS之后,通常具有优先权。

HADOOP_CLASSPATH

注意:全局设置应通过shell配置文件条目进行配置,而永久性的用户级设置应使用hadoop_add_classpath函数在${HOME}/.hadooprc文件中配置。更多信息请参阅下文。

Apache Hadoop脚本能够通过设置此环境变量,向正在运行的命令的类路径中注入更多内容。它应该是一个以冒号分隔的目录、文件或通配符位置列表。

HADOOP_CLASSPATH=${HOME}/lib/myjars/*.jar hadoop classpath

用户可以通过HADOOP_USER_CLASSPATH_FIRST变量提供路径位置的提示。将该变量设置为任意值将指示系统尝试将这些路径优先加载。

变量自动设置

如果用户有一组常用设置,可以将它们放入${HOME}/.hadoop-env文件中。该文件总是会被读取以初始化和覆盖用户可能想要自定义的任何变量。它使用bash语法,类似于.bashrc文件:

例如:

#
# my custom Apache Hadoop settings!
#

HADOOP_CLIENT_OPTS="-Xmx1g"
MAPRED_DISTCP_OPTS="-Xmx2g"
HADOOP_DISTCP_OPTS="-Xmx2g"

.hadoop-env 文件还可用于扩展功能并为 Apache Hadoop 添加新技巧。例如,要运行访问环境变量 ${HADOOP_SERVER} 中引用的服务器的 hadoop 命令,只需在 .hadoop-env 中添加以下内容即可:

if [[ -n ${HADOOP_SERVER} ]]; then
  HADOOP_CONF_DIR=/etc/hadoop.${HADOOP_SERVER}
fi

警告:并非所有的Unix Shell API例程在.hadoop-env中都可用或能正常工作。有关.hadooprc的更多信息,请参阅下文。

管理员环境

除了各种XML文件外,管理员在使用Unix Shell配置Apache Hadoop时还有两个关键功能:

  • 许多影响系统运行方式的环境变量。本指南仅重点介绍一些关键变量。通常在各*-env.sh文件中包含更多信息。

  • 对现有脚本进行补充或做一些平台特定的修改。Apache Hadoop提供了函数覆盖功能,因此可以在不进行大量工作的情况下直接修改现有代码库。替换函数的方法将在后续的Shell API文档中介绍。

(command)_(subcommand)_OPTS

到目前为止,最重要的是控制守护进程工作方式的_OPTS系列变量。这些变量应包含守护进程的所有相关设置。

与上述用户命令类似,所有守护进程都会遵循(command)_(subcommand)_OPTS模式。通常建议在hadoop-env.sh中设置这些选项,以确保系统在重启时知道应该使用哪些配置。与面向用户的子命令不同,守护进程不会遵循HADOOP_CLIENT_OPTS

此外,在额外安全模式下运行的守护进程还支持(command)_(subcommand)_SECURE_EXTRA_OPTS。这些选项是对通用*_OPTS补充,会出现在其后,因此通常具有更高优先级。

(command)_(subcommand)_USER

Apache Hadoop提供了一种按子命令执行用户检查的方法。虽然这种方法很容易被绕过,不应被视为安全功能,但它确实提供了一种防止意外操作的机制。例如,设置HDFS_NAMENODE_USER=hdfs将使hdfs namenodehdfs --daemon start namenode命令通过检查USER环境变量来验证运行命令的用户是否为hdfs用户。这同样适用于非守护进程。设置HADOOP_DISTCP_USER=jane将在允许执行hadoop distcp命令之前验证USER是否设置为jane

如果存在_USER环境变量且命令以特权运行(例如,以root身份;请参阅API文档中的hadoop_privilege_check),执行将首先切换到指定用户。对于出于安全原因支持用户账户切换并因此具有SECURE_USER变量的命令(详见下文),基础_USER变量需要是预期用于切换到SECURE_USER账户的用户。例如:

HDFS_DATANODE_USER=root
HDFS_DATANODE_SECURE_USER=hdfs

将强制以root身份执行'hdfs –daemon start datanode'命令,但在特权工作完成后最终会切换回hdfs用户。

请注意,如果使用了--workers标志,用户切换将在调用ssh之后进行。然而,sbin中的多守护进程启动和停止命令会在适当情况下提前切换,因此将使用指定_USER的密钥。

开发人员与高级管理员环境

Shell 配置文件

Apache Hadoop允许第三方通过多种可插拔接口轻松添加新功能。这包括一个shell代码子系统,可以方便地将必要内容注入基础安装中。

这一功能的核心是shell配置文件的概念。Shell配置文件是shell代码片段,可以执行诸如向类路径添加jar包、配置Java系统属性等操作。

Shell配置文件可以安装在${HADOOP_CONF_DIR}/shellprofile.d${HADOOP_HOME}/libexec/shellprofile.d目录中。位于libexec目录的Shell配置文件是基础安装的一部分,用户无法覆盖。如果最终用户在运行时更改了配置目录,则配置目录中的Shell配置文件可能会被忽略。

shell配置文件的示例位于libexec目录中。

Shell API

Apache Hadoop的shell代码拥有一个函数库,该库向管理员和开发者开放,用于辅助配置和高级功能管理。这些API遵循标准的Apache Hadoop接口分类规范,并新增了一个特性:可替换性。

shell代码允许覆盖核心功能。然而,并非所有功能都可以被替换或替换是安全的。如果某个功能不可安全替换,它将具有Replaceable: No属性。如果某个功能可以安全替换,它将具有Replaceable: Yes属性。

要替换某个函数,请在${HADOOP_CONF_DIR}目录下创建一个名为hadoop-user-functions.sh的文件。只需在该文件中定义新的替换函数,系统就会自动识别。该文件中可以包含任意数量的替换函数。函数替换的示例可参考hadoop-user-functions.sh.example文件。

标记为公开且稳定的函数可以直接在shell配置文件中安全使用。其他函数可能会在次要版本中发生变化。

用户级API访问

除了.hadoop-env允许单个用户覆盖hadoop-env.sh之外,用户还可以使用.hadooprc。该文件在Apache Hadoop shell环境配置完成后被调用,并允许使用完整的shell API函数调用集。

例如:

hadoop_add_classpath /some/path/custom.jar

将存入 .hadooprc

动态子命令

通过利用Shell API,第三方可以将自己的子命令添加到主要的Hadoop shell脚本(hadoop、hdfs、mapred、yarn)中。

在执行子命令之前,主脚本会检查是否存在(scriptname)_subcommand_(subcommand)函数。该函数将使用设置为所有剩余命令行参数的参数执行。例如,如果定义了以下函数:

function yarn_subcommand_hello
{
  echo "$@"
  exit $?
}

然后执行 yarn --debug hello world I see you 将激活脚本调试并调用 yarn_subcommand_hello 函数如下:

yarn_subcommand_hello world I see you

这将导致输出:

world I see you

还可以将新的子命令添加到使用说明输出中。hadoop_add_subcommand函数会将文本添加到使用说明输出。利用标准的HADOOP_SHELL_EXECNAME变量,我们可以限制哪些命令会使用我们的新功能。

if [[ "${HADOOP_SHELL_EXECNAME}" = "yarn" ]]; then
  hadoop_add_subcommand "hello" client "Print some text to the screen"
fi

我们将子命令类型设置为“client”,因为没有特殊限制、额外功能等。此功能也可用于覆盖内置命令。例如,定义:

function hdfs_subcommand_fetchdt
{
  ...
}

… 将用一个自定义的子命令替换现有的 hdfs fetchdt 子命令。

动态子命令的一些关键环境变量:

  • HADOOP_CLASSNAME

这是程序继续执行时要使用的Java类名称。

  • HADOOP_PRIV_CLASSNAME

这是在需要以特权模式运行守护进程时使用的Java类名称。(详见下文。)

  • HADOOP_SHELL_EXECNAME

这是正在执行的脚本名称。它可能是hadoop、hdfs、mapred或yarn其中之一。

  • HADOOP_SUBCMD

这是命令行中传递的子命令。

  • HADOOP_SUBCMD_ARGS

该数组包含经过Apache Hadoop通用参数处理后的参数列表,与传递给子命令函数作为参数的列表相同。例如,如果在命令行执行了hadoop --debug subcmd 1 2 3,那么${HADOOP_SUBCMD_ARGS[0]}将为1,且hadoop_subcommand_subcmd中的$1也将等于1。子命令函数可以修改此数组列表,以添加或删除参数列表中的值用于进一步处理。

  • HADOOP_SECURE_CLASSNAME

如果该子命令运行的服务支持安全模式,此变量应设置为安全版本的类名。

  • HADOOP_SUBCMD_SECURESERVICE

将此设置为true将强制子命令在安全模式下运行,无论hadoop_detect_priv_subcmd的设置如何。预期HADOOP_SECURE_USER将被设置为执行最终进程的用户。了解更多关于安全模式的信息。

  • HADOOP_SUBCMD_SUPPORTDAEMONIZATION

如果该命令可以作为守护进程执行,则设置为true。

  • HADOOP_USER_PARAMS

这是命令行的完整内容,未经任何解析处理。它将包含诸如--debug之类的标志。该内容不可被修改。

Apache Hadoop运行时设施要求在不需要进一步处理时函数应退出。例如,在上面的hello示例中,由于不需要Java和其他设施,简单的exit $?就足够了。然而,如果函数要使用HADOOP_CLASSNAME,则程序执行必须继续,以便针对给定的Java类启动带有Apache Hadoop特定参数的Java。另一个例子是在发生不可恢复错误的情况下。函数的职责是打印适当的消息(最好使用hadoop_error API调用)并正确退出。

以特权模式运行(安全模式)

某些守护进程,例如DataNode和NFS网关,可能以特权模式运行。这意味着它们需要以root身份启动,并(默认情况下)通过jsvc切换到另一个用户ID。这使得这些守护进程能够获取低编号的特权端口,然后在正常执行期间放弃超级用户权限。使用动态子命令的第三方也可以以特权方式运行。如果满足以下条件:

  • (command)_(subcommand)_SECURE_USER 环境变量已定义并指向有效的用户名
  • HADOOP_SECURE_CLASSNAME 已定义并指向一个有效的 Java 类

然后shell脚本将尝试以特权方式运行该类作为命令,就像处理内置命令一样。通常,用户需要定义_SECURE_USER变量,开发人员则在其shell脚本引导程序中定义_CLASSNAME。