Невозможно прочитать имена файлов UTF-8 при запуске в качестве службы Upstart
Моя программа Java считывает содержимое каталога рекурсивно. Это образец дерева (обратите внимание на символы, отличные от ASCII):
./sviluppo
./sviluppo/ciaò
./sviluppo/ciaò/subdir
./sviluppo/pippo
./sviluppo/pippo/prova2.txt <-file
./sviluppo/così
Программа запускается как служба Upstart с конфигурационным файлом с именем /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
Когда я запускаю службу:
[email protected]:/tmp# service myservice start
myservice start/running, process 15344
он не записывает имена файлов с не-ASCII-символами в имени:
[email protected]:/tmp# cat /tmp/log.txt
Found dir: /mnt/sviluppo/pippo
Вместо этого, когда я запускаю команду (как root, чтобы имитировать то, что происходит, когда она запускается как служба), она отлично работает с и без exec
:
[email protected]:/tmp# java -jar /home/mainFind.jar >> /tmp/log.txt
[email protected]:/tmp# exec java -jar /home/mainFind.jar >> /tmp/log.txt
[email protected]:/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]);
}
}
}
Если формальный параметр f
является корнем dir. Функция будет называться рекурсивно на каждом поддире.
EDIT 2: Post ls
[email protected]:/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
Ответы
Ответ 1
Java использует собственный вызов для отображения содержимого каталога. В основе C-сценария лежит концепция языка для создания Java String
из байтовой памяти, хранящейся в файловой системе в качестве имени файла.
При выполнении Java-программы из оболочки (либо как привилегированный пользователь, либо непривилегированный) она содержит среду, состоящую из переменных. Переменная LANG
считывается для перекодирования потока байтов в строку Java, а по умолчанию Ubuntu связана с кодировкой UTF-8.
Обратите внимание, что процесс не должен запускаться из любой оболочки, но, глядя на код, кажется, что Upstart достаточно умен, чтобы понять, когда команда в файле конфигурации предназначена для запуска из оболочки. Итак, если предположить, что JVM вызывается через оболочку, проблема в том, что переменная 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
содержит имена файлов, такие как ààà
, èèè
и т.д. Теперь вы можете перейти к части базы данных;)