作为Upstart服务启动时,无法读取UTF-8文件名

我的Java程序recursion读取目录的内容。 这是一个示例树(注意非ASCII字符):

./sviluppo ./sviluppo/ciaò ./sviluppo/ciaò/subdir ./sviluppo/pippo ./sviluppo/pippo/prova2.txt <-file ./sviluppo/così 

该程序以Upstart服务启动,configuration文件名为/init/myservice.conf

 description "Private Service" author "AD" start on runlevel [2345] stop on runlevel [! 2345] exec java -jar /home/mainFind.jar >> /tmp/log.txt 

当我启动服务时:

 root@mdr:/tmp# service myservice start myservice start/running, process 15344 

它不logging名称中包含非ASCII字符的文件名:

 root@mdr:/tmp# cat /tmp/log.txt Found dir: /mnt/sviluppo/pippo 

相反,当我运行该命令(以root身份来模仿它作为服务启动时会发生什么情况),它可以正常工作,不pipe是否使用exec

 root@mdr:/tmp# java -jar /home/mainFind.jar >> /tmp/log.txt root@mdr:/tmp# exec java -jar /home/mainFind.jar >> /tmp/log.txt root@mdr:/tmp# cat /tmp/log.txt Found dir: /mnt/sviluppo/ciaò Found dir: /mnt/sviluppo/ciaò/subdir Found dir: /mnt/sviluppo/pippo Found dir: /mnt/sviluppo/così 

为什么由同一个用户运行的同一个程序在Upstart服务中不起作用,但是从命令行运行时正确处理了所有的文件名? 这是Java代码

 public static void aggiungiFileDir(File f){ File[] lista= f.listFiles(); for(int i=0;i<lista.length;i++){ if(lista[i].isDirectory()){ System.out.println("Found dir: "+lista[i]); } } } 

其中forms参数f是根目录。 该函数将在每个子目录上recursion调用。

编辑2:发布ls

 root@mdr:/tmp# ls -al /mnt/sviluppo totale 20 drwx------ 5 root root 4096 nov 15 15:10 . drwxr-xr-x 7 root root 4096 nov 9 10:43 .. drwxr-xr-x 2 root root 4096 nov 15 15:10 ciaò drwxr-xr-x 2 root root 4096 nov 15 11:23 così drwxr-xr-x 2 root root 4096 nov 15 17:57 pippo 

Java使用本地调用来列出目录的内容。 底层的C运行时依赖于语言环境的概念,从文件系统存储的字节blob构建Java String作为文件名。

当你从一个shell执行一个Java程序(作为一个特权用户或一个非特权用户)时,它将携带一个由变量组成的环境 。 读取变量LANG以将字节流转码为Java字符串,默认情况下在Ubuntu上与UTF-8编码关联。

请注意,一个进程不需要从任何shell运行,但看看代码看起来,Upstart是聪明的,足以理解配置文件中的命令是否打算从shell执行。 所以,假设JVM是通过一个shell来调用的,问题是变量LANG没有被设置,所以C运行时假设一个默认的字符集,而不是 UTF-8。 解决方案是在Upstart节:

 description "List UTF-8 encoded filenames" author "Raffaele Sgarro" env LANG=en_US.UTF-8 script cd /workspace java -jar list.jar test > log.txt end script 

我使用en_US.UTF-8作为语言环境,但是任何支持UTF-8的语言都可以。 测试list.jar的来源

 public static void main(String[] args) { for (File file : new File(args[0]).listFiles()) { System.out.println(file.getName()); } } 

目录/workspace/test包含像àààèèè等文件名。 现在你可以移动到数据库部分;)