我在工作流中的oozie和sample.sh文件的ambari视图ui中创建工作流运行后,我有一个错误。当我将shell的主体更改为简单命令(例如echo 1
(时,没有出现此错误请通知我
2:34,752 WARN ShellActionExecutor:523 - SERVER[dlmaster02.sic] USER[root] GROUP[-] TOKEN[] APP[shell-wf] JOB[0000043-180630152627142-oozie-oozi-W] ACTION[0000043-180630152627142-oozie-oozi-W@shell-node] Launcher ERROR, reason: Main class [org.apache.oozie.action.hadoop.ShellMain], main() threw exception, Cannot run program "sample.sh" (in directory "/hadoop/yarn/local/usercache/root/appcache/application_1531029096800_0022/container_e18_1531029096800_0022_01_000002"): error=2, No such file or directory
2018-07-21 16:42:34,753 WARN ShellActionExecutor:523 - SERVER[dlmaster02.sic] USER[root] GROUP[-] TOKEN[] APP[shell-wf] JOB[0000043-180630152627142-oozie-oozi-W] ACTION[0000043-180630152627142-oozie-oozi-W@shell-node] Launcher exception: Cannot run program "sample.sh" (in directory "/hadoop/yarn/local/usercache/root/appcache/application_1531029096800_0022/container_e18_1531029096800_0022_01_000002"): error=2, No such file or directory
java.io.IOException: Cannot run program "sample.sh" (in directory "/hadoop/yarn/local/usercache/root/appcache/application_1531029096800_0022/container_e18_1531029096800_0022_01_000002"): error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at org.apache.oozie.action.hadoop.ShellMain.execute(ShellMain.java:110)
at org.apache.oozie.action.hadoop.ShellMain.run(ShellMain.java:69)
at org.apache.oozie.action.hadoop.LauncherMain.run(LauncherMain.java:75)
at org.apache.oozie.action.hadoop.ShellMain.main(ShellMain.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.oozie.action.hadoop.LauncherMapper.map(LauncherMapper.java:231)
at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:54)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:453)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:343)
at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:170)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1869)
at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:164)
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 17 more
我的工作流程的xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<workflow-app xmlns="uri:oozie:workflow:0.5" name="test">
<start to="shell_1"/>
<action name="shell_1">
<shell xmlns="uri:oozie:shell-action:0.3">
<job-tracker>${resourceManager}</job-tracker>
<name-node>${nameNode}</name-node>
<configuration>
<property>
<name>Group</name>
<value>hadoop</value>
</property>
</configuration>
<exec>/user/ambari-qa/sample.sh</exec>
<file>/user/ambari-qa/sample.sh</file>
</shell>
<ok to="end"/>
<error to="kill"/>
</action>
<kill name="kill">
<message>${wf:errorMessage(wf:lastErrorNode())}</message>
</kill>
<end name="end"/>
</workflow-app>
我也遇到了同样的问题,但在我的情况下,根本原因是shell脚本的CRLF行分隔符(rn
(。
当我将shell脚本的行分隔符更改为LF(n
(时,这个问题得到了解决。
注意:在默认设置的Windows中使用IntelliJ时,CRLF(rn
(将是默认的行分隔符
当您通过Ambari工作流管理工具(Ambari View(执行此操作时,您应该编辑shell操作,向下滚动到"高级属性",并添加一个要运行的"文件",如"/user/admin/hello.sh",该文件必须是hdfs中的文件。如果不这样做,则文件不会复制到yarn容器的文件缓存中,因此您将得到"找不到文件"。
如果你这样做,那么"提交"作业,转到仪表板,然后打开作业,然后单击"定义"选项卡,你应该会看到图形工具在工作流中添加了一个<file>
节点:
<?xml version="1.0" encoding="UTF-8" standalone="no"?><workflow-app xmlns="uri:oozie:workflow:0.5" name="helloworldshell">
<start to="shell_1"/>
<action name="shell_1">
<shell xmlns="uri:oozie:shell-action:0.3">
<job-tracker>${resourceManager}</job-tracker>
<name-node>${nameNode}</name-node>
<exec>hello.sh</exec>
<file>/user/admin/hello.sh</file>
<capture-output/>
</shell>
<ok to="end"/>
<error to="kill"/>
</action>
<kill name="kill">
<message>${wf:errorMessage(wf:lastErrorNode())}</message>
</kill>
<end name="end"/>
</workflow-app>
重要的线路是:
<exec>hello.sh</exec>
<file>/user/admin/hello.sh</file>
像<file>/x/y/z</file>
这样的节点会将hdfs文件从hdfs上的路径复制到远程数据节点服务器上正在运行的shell操作的当前工作目录中,该操作在yarn容器中运行。然后<exec>z</exec>
元素可以使用它,它将在最终JVM的$PWD
中查找它。$PWD
设置为工作运行的最终主机上生成的临时位置。对于工作流作业的每次运行,这可能是不同的服务器和不同的文件夹。
请注意,运行任何oozie工作流的"纱线容器"都是nothing,类似于docker容器。它是一个JVM,具有一个托管类路径和一个安全管理器集,用于防止您读取任意linux文件。在大型集群上,任何操作都可以在任何节点上运行,因此文件必须通过HDFS分发。有一种缓存机制可以确保文件在主机上本地缓存。由yarn设置的安全管理器只允许您访问由XML中的一个或多个<file>
节点定义的文件缓存中正确设置的文件。
虽然如果您不了解底层技术,工作流GUI似乎非常有用,但在调试时,手册就没有太大帮助。在边缘节点的命令行上执行一些"helloworld"作业是一个好主意,首先将示例xml放入hdfs文件夹,然后使用命令行工具启动作业。工作流web UI只是在顶部添加了一个图形使用界面。
一般来说,您所做的是将文件放入您保存的工作流下面的子文件夹中:
$ tree shdemo
shdemo
├── bin
│ ├── hello.sh
└── workflow.xml
在工作流程中,使用文件的相对路径而不是绝对路径:
<file>bin/hello.sh#hello.sh</file>
#
表示要将文件符号链接到$PWD,这是可选的,但可能会有所帮助。对于复杂的工作流,您可以为不同的文件类型(例如,"bin"、"config"、"data"(创建不同的子文件夹。然后,您可以将许多<file?
条目添加到工作流XML中。最后,您将所有这些文件夹从运行它的地方复制到hdfs中:
# copy up the workflow files and subfolders into hdfs
hdfs dfs -copyFromLocal -f shdemo /user/$(whoami)/my_workflows
# launch it from that location within hdfs
oozie job -oozie $OOZIE_URL -config shdemo-job.properties -run
您会注意到,当您使用工作流GUI时,当您想要提交作业时,您必须将工作流"保存"到HDFS文件夹中。这是一个hdfs文件夹,您将在其中添加一个bin/hello.sh
,您将如上所述引用它。再一次,web UI只是命令行技术之上的皮肤。一旦您在命令行上有了一个简单的命令行,您就可以将其导入工作流GUI,编辑它,并将其保存回相同的hdfs位置。
请尝试以下操作并告诉我您的结果。
<exec>sample.sh</exec>
<file>${nameNode}/user/ambari-qa/sample.sh</file>
它需要一个带有Namenode的完整路径才能访问,否则它将寻找默认路径,这里的错误表明脚本在默认路径中不可用。