调试Hadoop map-reduce作业很痛苦。我可以打印到stdout,但这些日志显示在运行MR作业的所有不同机器上。我可以去找工作跟踪器,找到我的工作,然后点击每个单独的映射器来访问它的任务日志,但是当你有20多个mapper / reducer时,这非常麻烦。
我原本以为我可能要编写一个脚本来查看作业跟踪器,找出每个映射器/缩减器运行的机器,然后将日志记录回一个可能是猫的中心位置一起来。在我浪费时间做这件事之前,是否有人知道更好的方法来获得一个,整合stdout日志以获得作业的映射器和缩减器?
答案 0 :(得分:1)
我这样做的方式如下:
对于一般调试(即测试作业是否有效),我在本地计算机上以独立模式运行hadoop,并使用少量数据样本。这种方式hadoop可以像任何其他Java应用程序一样工作,并在控制台中显示映射器或缩减器的标准输出。
对于特定的错误(即作业在我的本地机器上正常运行,但在生产中死机)我只是调整代码以作为作业的输出,我通常在调试时发送到stdout。这样,您可以检查作业的结果以调试见解。这不是很好,但它工作正常。
另一种选择是检查jobtracker中的节点日志。他们有stdout和stderr。但是,由于几个原因,我发现上述解决方案要复杂得多(一段时间后删除日志,要查找几个节点等)
答案 1 :(得分:1)
所以我最后只是创建了一个Python脚本来执行此操作。这并不可怕。这是脚本,以防其他人想要使用它。显然它需要更多的错误检查,而不是硬编码的网址等,但你明白了。请注意,您需要下载Beautiful Soup
#!/usr/bin/python
import sys
from bs4 import BeautifulSoup as BS
from urllib2 import urlopen
import re
TRACKER_BASE_URL = 'http://my.tracker.com:50030/'
trackerURLformat = TRACKER_BASE_URL + 'jobtasks.jsp?jobid=%s&type=%s&pagenum=1' # use map or reduce for the type
def findLogs(url):
finalLog = ""
print "Looking for Job: " + url
html = urlopen(url).read()
trackerSoup = BS(html)
taskURLs = [h.get('href') for h in trackerSoup.find_all(href=re.compile('taskdetails'))]
# Now that we know where all the tasks are, go find their logs
logURLs = []
for taskURL in taskURLs:
taskHTML = urlopen(TRACKER_BASE_URL + taskURL).read()
taskSoup = BS(taskHTML)
allLogURL = taskSoup.find(href=re.compile('all=true')).get('href')
logURLs.append(allLogURL)
# Now fetch the stdout log from each
for logURL in logURLs:
logHTML = urlopen(logURL).read()
logSoup = BS(logHTML)
stdoutText = logSoup.body.pre.text.lstrip()
finalLog += stdoutText
return finalLog
def main(argv):
with open(argv[1] + "-map-stdout.log", "w") as f:
f.write(findLogs(trackerURLformat % (argv[1], "map")))
print "Wrote mapers stdouts to " + f.name
with open(argv[1] + "-reduce-stdout.log", "w") as f:
f.write(findLogs(trackerURLformat % (argv[1], "reduce")))
print "Wrote reducer stdouts to " + f.name
if __name__ == "__main__":
main(sys.argv)
答案 2 :(得分:0)
我的经验是,当您确切知道哪些地图/减少尝试导致您要通过日志检查问题时,您不需要点击20多个地图/减少输出链接。这就是为什么我总是使用Context.setStatus("在这里发出警告消息")当我抛出异常或增加计数器以引起怀疑时。
有关setStatus的更多信息:http://hadoop.apache.org/docs/r1.1.1/api/org/apache/hadoop/mapreduce/TaskInputOutputContext.html#setStatus(java.lang.String)
https://www.inkling.com/read/hadoop-definitive-guide-tom-white-3rd/chapter-5/running-on-a-cluster(调试作业部分)