Обычно, tr
не должен мочь записать, что сообщение об ошибке, потому что оно должно было быть уничтожено сигналом SIGPIPE при попытке записать что-то после другого конца канала, было закрыто после завершения head
.
Вы получаете то сообщение об ошибке потому что так или иначе, выполнение процесса tr
был настроен для игнорирования SIGPIPEs. Я подозреваю, что это могло бы быть сделано popen()
реализация на Вашем языке там.
Можно воспроизвести его путем выполнения:
sh -c 'trap "" PIPE; tr -dc "[:alpha:]" < /dev/urandom | head -c 8'
Можно подтвердить, что это - то, что происходит путем выполнения:
strace -fe signal sh your-program
(или эквивалент в Вашей системе, не используя Linux). Вы будете затем видеть что-то как:
rt_sigaction(SIGPIPE, {SIG_IGN, ~[RTMIN RT_1], SA_RESTORER, 0x37cfc324f0}, NULL, 8) = 0
или
signal(SIGPIPE, SIG_IGN)
сделанный в одном процессе перед тем же самым процессом или одним из его потомков выполняется /bin/sh
это интерпретирует ту командную строку и запускается tr
и head
.
Если Вы делаете a strace -fe write
, Вы будете видеть что-то как:
write(1, "AJiYTlFFjjVIzkhCAhccuZddwcydwIIw"..., 4096) = -1 EPIPE (Broken pipe)
write
системный вызов перестал работать с ошибкой EPIPE вместо того, чтобы инициировать SIGPIPE.
В любом случае tr
выйдет. При игнорировании SIGPIPE, из-за той ошибки (но это также инициировало сообщение об ошибке). Если не это выходит после получения SIGPIPE. Вы действительно хотите, чтобы это вышло, так как Вы не хотите это продолжающий чтение /dev/urandom
после того, как те 8 байтов были read
head
.
Чтобы избежать, чтобы сообщение об ошибке, можно было восстановить обработчик по умолчанию для SIGPIPE с:
trap - PIPE
До вызова tr
:
popen("trap - PIPE; { tr ... | head -c 8; } 2>&1", ...)
можно использовать perl
:
$ perl -le 'print((stat shift)[9])' test.txt
1402577190
или GNU дата
:
$ date -r test.txt +%s
можно установить GNU дата
на AIX
, см. ссылку на это соединение .