TL;DR — Перейдите к ОБНОВЛЕНИЮ для игрушечного примера. Ниже был мой первоначальный вопрос, прежде чем я смог воспроизвести проблему в небольшом примере, отредактированном для ясности.
Я не понимаю, что здесь происходит. Я рвал на себе волосы, пытаясь понять, почему тест, который я написал на Perl, продолжает терпеть неудачу.
Я тестировал функцию, которая отключает ведение журнала при сбое открытия выходного файла журнала, чтобы вывод в STDERR не подавлялся. Чтобы проверить, работает ли это, я создал файл на лету и сделал его недоступным для записи с помощью chmod. Результирующий запуск кода должен вывести ошибку открытия вместе со всеми остальными STDERR в вывод STDERR. Я делал chmod в обратных кавычках перед запуском теста.
Однако то, что происходило, заключалось в том, что файл журнала продолжал записываться без ошибок, поэтому тест не прошел. Я начал проверять работоспособность, распечатывая вывод ls -halF
в разных местах, чтобы увидеть, где происходит изменение разрешений. Первоначальный chmod, казалось, работал:
`echo > file.log;chmod 444 file.log;ls -halF file.log`
Последующий ls -halF file.log
после некоторых других настроек подтвердил предполагаемые разрешения, но очень ранняя строка кода в моем запуске фактического тестового кода говорила, что у владельца есть разрешение на запись!
В конце концов я нашел решение проблемы — используя метод perl chmod()
вместо chmod в обратных кавычках, что заставляет меня думать, что происходит что-то асинхронное — и это не имело для меня никакого смысла.
В конце концов я попробовал это, потому что в моих многочисленных тестах я иногда видел, что тест случайно завершается успешно. Поэтому я написал быстрый цикл для выполнения одного и того же теста снова и снова — и обнаружил, что он случайно завершается успешно, возможно, в 30% случаев! Вот что заставило меня подумать, что в этой проблеме может быть какая-то асинхронность, которую я не мог объяснить, потому что я думал, что обратные кавычки, по сути, ждали завершения процесса, поскольку он возвращает вывод - так что здесь происходит? Я этого не понимаю.
Для полноты фактическая тестовая команда также выполняется в обратных кавычках — она запускает независимый скрипт.
В моем обновлении ниже я показываю другой случай, но он демонстрирует случайность состояний разрешений...
ОБНОВИТЬ
ХОРОШО. Это небольшой автономный пример, демонстрирующий проблему. Обратите внимание на разные выходные данные второй строки в каждом случае...
удалитьme1.pl
#!/usr/bin/perl
print(`echo '' > deleteme.log;chmod 444 deleteme.log`);
print("1: ",`ls -l deleteme.log`);
`chmod 777 deleteme.log;rm -f deleteme.log`;
удалитьme2.pl
#!/usr/bin/perl
print(`echo '' > deleteme.log;chmod 444 deleteme.log`);
print("2: ",`ls -l deleteme.log`);
chmod 0777, "deleteme.log";
unlink("deleteme.log");
Теперь посмотрите на результат этого повторяющегося цикла:
tcsh> foreach f ( `seq 1 30` )
perl deleteme1.pl
perl deleteme2.pl
end
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -rw-r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -rw-r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -rw-r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r--@ 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
1: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
2: -r--r--r-- 1 robleach staff 1 May 31 21:01 deleteme.log
Обратите внимание, что различия в правах владельца всегда связаны с deleteme1.pl. Я думаю, что @
указывает на расширенные атрибуты в macOS. Это может иметь какое-то отношение к этому, но бывают случаи, когда xattr есть, но нет различий в разрешениях...
И я также подозреваю, что проблема может быть как-то связана с этим:
>ls -1 t | wc -l
46391
Значит, что-то происходит асинхронно — какого черта?! Может ли это быть как-то связано с SIP или csr(util)?
ОБНОВЛЕНИЕ 2
Вот пример, более верный для моего конкретного случая.
удалитьme3.pl
Это представляет мое исправление:
#!/usr/bin/perl
open(TLG,">deleteme.log");
print TLG '';
close(TLG);
chmod 0444, "deleteme.log";
if(open(TEST,">deleteme.log"))
{print "3 opened\n"}
else
{print "3 unable to open\n"}
chmod 0777, "deleteme.log";
unlink("deleteme.log");
удалитьme4.pl
Это демонстрирует исходную проблему.
#!/usr/bin/perl
`echo '' > deleteme.log;chmod 444 deleteme.log`;
if(open(TEST,">deleteme.log"))
{print "4 opened\n"}
else
{print "4 unable to open\n"}
chmod 0777, "deleteme.log";
unlink("deleteme.log");
Я зациклился на этих 2, как указано выше:
tcsh>foreach f ( `seq 1 1000` )
perl deleteme3.pl
perl deleteme4.pl
end
Из 1000 попыток вместо deleteme3.pl
всегда выводилось 3 unable to open
. deleteme4.pl
выводит 4 opened
4 раза, а остальные 4 unable to open
.
Очевидно, это не демонстрирует частоту, которую я видел, когда большую часть времени мои разрешения были доступны для записи владельцем, но я предполагаю, что я попал в какую-то золотую середину, где что-то испортилось с моими правами доступа к файлам.
Мне бы очень хотелось посмотреть, сможет ли кто-нибудь воспроизвести эти результаты на любой платформе, но я использую macOS Sierra (10.12.6) с системой perl версии 5.18.2.
/bin/sh
с аргументами/bin/sh
,-c
иecho > file.log;chmod 444 file.log;ls -halF file.log
. Он ожидает возвратаsh
, прежде чем продолжить. Как вы сказали, это необходимо, так как он собирает вывод ребенка. Это отвечает на ваш вопрос? Если нет, то я не знаю, что это такое. - person ikegami   schedule 31.05.2020ls -l
в строке над вызовом этого скрипта написано r--. Я делаюls -l
в инициализации первого используемого модуля в запущенном скрипте, и он говоритrw-
. Так что я даже не уверен, как бы я воспроизвел это. Модуль большой. Позвольте мне посмотреть, смогу ли я воспроизвести его в уменьшенной версии, но я не уверен, как это сделать. - person hepcat72   schedule 01.06.2020