Почему ruby, кроме случаев записи в std :: error или std :: out, когда сеанс пропал? - PullRequest
1 голос
/ 14 ноября 2011

Я написал программу, которая может работать в течение 16 или 20 часов на Linux-коробке с некоторой разновидностью RedHat OS. Он работает нормально, если я запускаю его с nohup или перенаправляю вывод в файл, но когда пользователь запускает его, отправляет в фоновый режим и выходит из системы, произойдет сбой при попытке отправить простое сообщение о состоянии (сообщив номер файлов, которые привели к файлу). Выдает исключение, предположительно, потому что поток больше не действителен.

Как только мы поняли, почему это работает для меня, а не для него, я провел несколько тестов и обнаружил, что ruby ​​уникален в этом поведении по сравнению с Python, Bash и perl.

Есть ли веская причина, по которой ruby ​​ведет себя не так, как другие языки сценариев в этой ситуации? Есть ли способ изменить его, чтобы он вел себя как остальные?

Я почти уверен, что C ++ (и C) не волнует, увидит ли конечный пользователь вывод своих сообщений, но я не написал тест для этих языков. Я был удивлен, узнав, что задания, отправленные на задний план, не исчезли, как только вы вышли из системы! Так что я, конечно, никогда не проверял это поведение в прошлом.

Ответы [ 2 ]

0 голосов
/ 14 ноября 2011

Когда вы выходите из системы, процесс, который является получателем ваших $ stderr и $ stdout, прерывается.Ваши дескрипторы файлов $ stderr и $ stdout теперь подключены к сломанному каналу.Когда вы пишете им, вы должны получить SIGPIPE из операционной системы.

Вы ошибаетесь в том, что C ++ и C не заботятся.Это не имеет никакого отношения к языку реализации или к тому, может ли «пользователь» «видеть» вывод.Речь идет о том, действителен ли дескриптор файла.Поскольку другой конец закрыт, его уже нет.

Взгляните на демона, написанного на C или C ++.Обратите внимание, как он закрывает stderr и stdout в дочернем процессе после fork и перед exec.Таким образом он защищает себя от записи в сломанный канал и отправки ОС SIGPIPE операционной системой.

0 голосов
/ 14 ноября 2011

Если вы перейдете в фоновый режим, я считаю, что каждая программа на любом языке, пытающаяся записать в stdout, должна получить код ошибки. В случае C вы получите некоторое возвращаемое значение, которое вы можете игнорировать. На других языках я бы очень удивился, если бы на самом деле только бросил исключение рубин. В конце концов, как это сделано, проблема заключается в ядре. Я написал один демон на Perl, и я уверен, что мне пришлось реализовать закрытие stdout, stderr и stdin и двойное разветвление, чтобы не быть убитым без nohup. Вы не должны полагаться на недокументированные функции и либо зависеть от nohup, чтобы сделать это за вас, либо от правильного закрытия дескрипторов ввода и вывода. Или снова откройте их в лог-файл, используя низкоуровневый открытый вызов.

Вы пробовали всегда с перенаправлением на скрипт или с него на другие языки? Сломанный канал обычно является ошибкой, когда program1 | У анонимного канала program2 один конец закрывается, а другой просит прочитать / записать его.

...