Spark saveAsTextFile()导致Mkdirs无法为目录的一半创建

时间:2016-03-03 17:13:32

标签: java tomcat apache-spark spark-dataframe

我目前在tomcat中运行Java Spark Application并收到以下异常:

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

8 个答案:

答案 0 :(得分:8)

saveAsTextFile实际上是由Spark执行程序处理的。根据您的Spark设置,Spark执行程序可以作为不同的用户运行,而不是Spark应用程序驱动程序。我猜火花应用程序驱动程序准备好工作目录,但是作为不同用户运行的执行程序无权在该目录中写入。

更改为777无济于事,因为子目录不会继承权限,所以无论如何你都会得到755。

尝试以运行Spark的用户身份运行Spark应用程序。

答案 1 :(得分:2)

我建议暂时尝试更改为777。看看它是否有效。在本地文件系统上存在错误/问题权限。如果仍然无效,请告知我们是否有任何改变或完全相同的结果。

答案 2 :(得分:1)

可能selinux/apparmor会给你一招吗?请查看ls -Z和系统日志。

答案 3 :(得分:1)

所以,我一直遇到同样的问题,我的设置没有HDFS,Spark在独立模式下运行。我还没有能够使用本机Spark方法将spark数据帧保存到NFS共享。该进程作为本地用户运行,我尝试写入用户主文件夹。即使使用777创建子文件夹,我也无法写入该文件夹。

解决方法是将数据框转换为toPandas(),然后转换为to_csv()。这神奇地起作用。

答案 4 :(得分:1)

我也有同样的问题使用完整的hdfs路径解决了问题。

错误

Caused by: java.io.IOException: Mkdirs failed to create file:/QA/Gajendra/SparkAutomation/Source/_temporary/0/_temporary/attempt_20180616221100_0002_m_000000_0 (exists=false, cwd=file:/home/gajendra/LiClipse Workspace/SpakAggAutomation)

解决方案=: - 使用完整的hdfs路径和hdfs:// localhost:54310 /

hdfs://localhost:54310/QA/Gajendra/SparkAutomation 

答案 5 :(得分:0)

我和你有同样的问题。

我也不想写入hdfs,而是要写入本地内存共享。

经过研究,我发现我的原因是:有几个节点正在执行,但是,有些节点无法访问要写入数据的目录。

因此,解决方案是使目录可用于所有节点,然后起作用〜

答案 6 :(得分:0)

这很棘手,但是很容易解决。必须配置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()

答案 7 :(得分:0)

我们需要在本地模式下运行应用程序。

 val spark = SparkSession
      .builder()
      .config("spark.master", "local")
      .appName("applicationName")
      .getOrCreate()