Spark saveAsTextFile() 导致 Mkdirs 无法为一半目录创建
Posted
技术标签:
【中文标题】Spark saveAsTextFile() 导致 Mkdirs 无法为一半目录创建【英文标题】:Spark saveAsTextFile() results in Mkdirs failed to create for half of the directory 【发布时间】:2016-03-03 17:13:32 【问题描述】:我目前在 tomcat 中运行 Java Spark 应用程序并收到以下异常:
Caused by: java.io.IOException: Mkdirs failed to create file:/opt/folder/tmp/file.json/_temporary/0/_temporary/attempt_201603031703_0001_m_000000_5
上线
text.saveAsTextFile("/opt/folder/tmp/file.json") //where text is a JavaRDD<String>
问题是 /opt/folder/tmp/ 已经存在并成功创建到 /opt/folder/tmp/file.json/_temporary/0/ 然后它遇到了看起来像剩下的权限问题路径 _temporary/attempt_201603031703_0001_m_000000_5
本身的一部分,但我将 tomcat 用户权限(chown -R tomcat:tomcat tmp/
和 chmod -R 755 tmp/
)授予 tmp/ 目录。有谁知道会发生什么?
谢谢
编辑@javadba:
[root@ip tmp]# ls -lrta
total 12
drwxr-xr-x 4 tomcat tomcat 4096 Mar 3 16:44 ..
drwxr-xr-x 3 tomcat tomcat 4096 Mar 7 20:01 file.json
drwxrwxrwx 3 tomcat tomcat 4096 Mar 7 20:01 .
[root@ip tmp]# cd file.json/
[root@ip file.json]# ls -lrta
total 12
drwxr-xr-x 3 tomcat tomcat 4096 Mar 7 20:01 _temporary
drwxrwxrwx 3 tomcat tomcat 4096 Mar 7 20:01 ..
drwxr-xr-x 3 tomcat tomcat 4096 Mar 7 20:01 .
[root@ip file.json]# cd _temporary/
[root@ip _temporary]# ls -lrta
total 12
drwxr-xr-x 2 tomcat tomcat 4096 Mar 7 20:01 0
drwxr-xr-x 3 tomcat tomcat 4096 Mar 7 20:01 ..
drwxr-xr-x 3 tomcat tomcat 4096 Mar 7 20:01 .
[root@ip _temporary]# cd 0/
[root@ip 0]# ls -lrta
total 8
drwxr-xr-x 3 tomcat tomcat 4096 Mar 7 20:01 ..
drwxr-xr-x 2 tomcat tomcat 4096 Mar 7 20:01 .
catalina.out 中的异常
Caused by: java.io.IOException: Mkdirs failed to create file:/opt/folder/tmp/file.json/_temporary/0/_temporary/attempt_201603072001_0001_m_000000_5
at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:438)
at org.apache.hadoop.fs.ChecksumFileSystem.create(ChecksumFileSystem.java:424)
at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:906)
at org.apache.hadoop.fs.FileSystem.create(FileSystem.java:799)
at org.apache.hadoop.mapred.TextOutputFormat.getRecordWriter(TextOutputFormat.java:123)
at org.apache.spark.SparkHadoopWriter.open(SparkHadoopWriter.scala:91)
at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1$$anonfun$13.apply(PairRDDFunctions.scala:1193)
at org.apache.spark.rdd.PairRDDFunctions$$anonfun$saveAsHadoopDataset$1$$anonfun$13.apply(PairRDDFunctions.scala:1185)
at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:66)
at org.apache.spark.scheduler.Task.run(Task.scala:89)
at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:213)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
... 1 more
【问题讨论】:
你能公布你是如何提交申请的吗?什么师傅?你有没有机会使用猜测? 【参考方案1】:saveAsTextFile
真正由 Spark 执行器处理。根据您的 Spark 设置,Spark 执行程序可能以不同于您的 Spark 应用程序驱动程序的用户身份运行。我猜火花应用程序驱动程序为作业准备好目录,但是作为不同用户运行的执行程序无权在该目录中写入。
更改为 777 无济于事,因为权限不会被子目录继承,所以无论如何你都会得到 755。
尝试以运行 Spark 的同一用户身份运行 Spark 应用程序。
【讨论】:
最可能的响应。我刚刚将我的应用程序设置为使用 HDFS/S3 作为解决方法。没有遇到权限问题,如果我有机会我会回溯并确认这一点。 如何在同一个用户下运行 spark executors?【参考方案2】:我建议暂时改成777
。看看它在那个时候是否有效。本地文件系统上存在错误/问题 wrt 权限。如果这仍然不起作用,请告诉我们是否有任何变化或完全相同的结果。
【讨论】:
不幸的是,在 755 之前尝试过,结果是一样的。 请告诉我们ls -lrta /opt/folder/tmp/file.json/_temporary/0/_temporary
的输出
抱歉耽搁了。添加了更新。就这样吧。它不能 mkdir 过去 0/
它似乎【参考方案3】:
我也遇到了同样的问题,我的问题已经通过使用完整的 HDFS 路径解决了:
错误
原因:java.io.IOException:Mkdirs 未能创建文件:/QA/Gajendra/SparkAutomation/Source/_temporary/0/_temporary/attempt_20180616221100_0002_m_000000_0 (exists=false, cwd=file:/home/gajendra/LiClipse Workspace /SpakAggAutomation)
解决方案
使用带有hdfs://localhost:54310/<filePath>
的完整HDFS路径
hdfs://localhost:54310/QA/Gajendra/SparkAutomation
【讨论】:
【参考方案4】:会不会是 selinux/apparmor
在耍你?检查ls -Z
和系统日志。
【讨论】:
【参考方案5】:所以,我遇到了同样的问题,我的设置没有 HDFS 并且 Spark 以独立模式运行。我无法使用本机 Spark 方法将 Spark 数据帧保存到 NFS 共享。该过程以本地用户身份运行,我尝试写入用户主文件夹。即使使用 777 创建子文件夹,我也无法写入该文件夹。
解决方法是使用toPandas()
转换数据帧,然后使用to_csv()
。这很神奇。
【讨论】:
【参考方案6】:我和你有同样的问题。
我也不想写入 hdfs,而是写入本地内存共享。
经过一番研究,我发现对于我的情况,原因是:有几个节点在执行,但是有些节点无法访问您要写入数据的目录。
所以解决办法是让目录对所有节点都可用,然后就可以了~
【讨论】:
你是怎么做到的【参考方案7】:我们需要在本地模式下运行应用程序。
val spark = SparkSession
.builder()
.config("spark.master", "local")
.appName("applicationName")
.getOrCreate()
【讨论】:
【参考方案8】:这是一个棘手的问题,但很容易解决。必须配置 job.local.dir 变量指向工作目录。以下代码适用于编写 CSV 文件:
def xmlConvert(spark):
etl_time = time.time()
df = spark.read.format('com.databricks.spark.xml').options(rowTag='HistoricalTextData').load(
'/home/zangetsu/proj/prometheus-core/demo/demo-1-iot-predictive-maintainance/dataset/train/')
df = df.withColumn("TimeStamp", df["TimeStamp"].cast("timestamp")).groupBy("TimeStamp").pivot("TagName").sum(
"TagValue").na.fill(0)
df.repartition(1).write.csv(
path="/home/zangetsu/proj/prometheus-core/demo/demo-1-iot-predictive-maintainance/result/",
mode="overwrite",
header=True,
sep=",")
print("Time taken to do xml transformation: --- %s seconds ---" % (time.time() - etl_time))
if __name__ == '__main__':
spark = SparkSession \
.builder \
.appName('XML ETL') \
.master("local[*]") \
.config('job.local.dir', '/home/zangetsu/proj/prometheus-core/demo/demo-1-iot-predictive-maintainance') \
.config('spark.driver.memory','64g') \
.config('spark.debug.maxToStringFields','200') \
.config('spark.jars.packages', 'com.databricks:spark-xml_2.11:0.5.0') \
.getOrCreate()
print('Session created')
try:
xmlConvert(spark)
finally:
spark.stop()
【讨论】:
以上是关于Spark saveAsTextFile() 导致 Mkdirs 无法为一半目录创建的主要内容,如果未能解决你的问题,请参考以下文章
Spark&Scala:saveAsTextFile()异常
Spark saveAsTextFile写入空文件 - _ $ folder $到S3