Подтвердить что ты не робот

Невозможно прочитать имена файлов 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
4b9b3361

Ответ 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 содержит имена файлов, такие как ààà, èèè и т.д. Теперь вы можете перейти к части базы данных;)