Pergunta

Atualizar: Acontece que eu estava sendo muito estúpida. Eu estava verificando o tempo de modificação quando deveria estar verificando o tempo de acesso. A razão pela qual não era reproduzível foi que os arquivos de teste foram feitos com dd if=/dev/urandom of="$target" bs='1K' count=1 || exit 1, que na maioria das vezes era rápido demais para o tempo de modificação (fim de dd) dos novos arquivos para serem diferentes do tempo de acesso (tempo de início de dd). Outra coisa a ser observada.

Estou trabalhando em um script para aplicar o tempo de acesso de um arquivo mais dois anos a outro arquivo. Isso usa stat -c %x, date --rfc-3339=ns e touch -a --date="$result". stat e date ambas as seqüências de data de saída com nanossegundos, como

2012-11-17 10:22:15.390351800+01:00

, e info coreutils 'touch invocation' diz que suporta nanossegundos. Mas, às vezes, ao aplicar o toque, há uma pequena diferença entre o registro de data e hora aplicado e o retorno posteriormente por Stat. Aqui estão os dados de uma execução real:

$ for i in {1..100}; do ./t_timecopy.sh 2>/dev/null| grep ASSERT; done
ASSERT:Expecting same access time expected:<2012-11-17 10:58:40.719320935+01:00> but was:<2012-11-17 10:58:40.723322203+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:00:04.342346275+01:00> but was:<2012-11-17 11:00:04.346358718+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:00:39.343348183+01:00> but was:<2012-11-17 11:00:39.347351686+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:01:08.655348312+01:00> but was:<2012-11-17 11:01:08.659347625+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:01:37.930346876+01:00> but was:<2012-11-17 11:01:37.934347311+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:02:16.939319832+01:00> but was:<2012-11-17 11:02:16.943323061+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:02:46.456443149+01:00> but was:<2012-11-17 11:02:46.458379114+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:03:15.487339595+01:00> but was:<2012-11-17 11:03:15.491341426+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:04.646335863+01:00> but was:<2012-11-17 11:04:04.650346634+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:14.410326608+01:00> but was:<2012-11-17 11:04:14.414331233+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:24.159367348+01:00> but was:<2012-11-17 11:04:24.163352418+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:04:33.931387953+01:00> but was:<2012-11-17 11:04:33.935350115+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:05:03.394361030+01:00> but was:<2012-11-17 11:05:03.398320957+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:05:42.054317430+01:00> but was:<2012-11-17 11:05:42.059106497+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:06:40.346320820+01:00> but was:<2012-11-17 11:06:40.350346956+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:08:17.194346778+01:00> but was:<2012-11-17 11:08:17.198338832+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:08:27.102347603+01:00> but was:<2012-11-17 11:08:27.106320380+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:09:16.247322948+01:00> but was:<2012-11-17 11:09:16.251347966+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:09:55.191325266+01:00> but was:<2012-11-17 11:09:55.195320672+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:12:09.915318301+01:00> but was:<2012-11-17 11:12:09.919334099+01:00>
ASSERT:Expecting same access time expected:<2012-11-17 11:12:28.906346914+01:00> but was:<2012-11-17 11:12:28.910348186+01:00>

Portanto, 21 em cada 100 testes falharam, com uma média de 3,938ms e uma mediana de 4,001 ms. Alguma ideia do que poderia causar isto?

$ uname -a
Linux user 2.6.32-22-generic #33-Ubuntu SMP Wed Apr 28 13:27:30 UTC 2010 i686 GNU/Linux
Foi útil?

Solução

Eu usei esse monte de OneLiners (reconhecidamente rápidos e sujos) para testar seu problema no meu sistema - um Mandriva Linux 2010.1 (x86-64):

seq 1 1000 | while read f; do sleep 0.01; touch test-$f-0; done

seq 1 1000 | while read f; do touch -a -d "$(stat -c %x test-$f-0 | sed 's|^2010|2012|')" test-$f-1; done

seq 1 1000 | while read f; do A="$(stat -c %x test-$f-0)"; B="$(stat -c %x test-$f-1)"; if [[ ! "${A#2010}" = "${B#2012}" ]]; then echo test-$f; fi; done

Não consegui reproduzir seu problema mesmo uma vez. Parece que o toque não é alimentado com o carimbo de data e hora esperado no parâmetro -d, mas algo calculado de outra forma.

Obviamente, o problema pode ser específico do sistema; nesse caso, precisaríamos de mais informações sobre o seu sistema (CPU, são as versões OS 32 ou 64 bits, kernel/glibc/coreUtils etc).

ATUALIZAR:

Eu tentei o mesmo com versões de 32 bits de Stat e Touch. Nenhum problema surgiu. O kernel ainda era de 64 bits.

Update2:

Eu também tentei esse conjunto de OneLiners, que se concentram mais no ATIME:

$ seq 1 1000 | while read f; do sleep 0.01; touch test-$f-0; done
$ seq 1 1000 | while read f; do sleep 0.01; touch test-$f-1; done
$ seq 1 1000 | while read f; do sleep 0.01; cat test-$f-0; done
$ seq 1 1000 | while read f; do touch -a -d "$(stat -c %x test-$f-0 | sed 's|^2010|2012|')" test-$f-1; done
$ seq 1 1000 | while read f; do A="$(stat -c %x test-$f-0)"; B="$(stat -c %x test-$f-1)"; if [[ ! "${A#2010}" = "${B#2012}" ]]; then echo test-$f; fi; done

Novamente nenhum problema detectado. Eu tentei isso com as opções de montagem de relatime e estatatime.

Atualização3:

Acabei de realizar os testes acima no meu laptop Mandriva i686. Parece que não tenho problemas com a precisão de nanossegundos lá também. Também verifiquei em outro sistema de 32 bits que, se a precisão de nanossegundos não for suportada (por exemplo, ext3), o campo de nanossegundos na saída STAT se tornará zero.

Outras dicas

Toque no Windows 7 de 64 bits traz problemas semelhantes. Este é o meu código de exploração:

touch a && touch b && ls --full-time a b
touch -r a b && ls --full-time a b

E a saída:

-rw-rw-rw-  1 Jarek 0 0 2012-05-09 12:05:27.851839700 +0200 a
-rw-rw-rw-  1 Jarek 0 0 2012-05-09 12:05:27.874841000 +0200 b

-rw-rw-rw-  1 Jarek 0 0 2012-05-09 12:05:27.851839700 +0200 a
-rw-rw-rw-  1 Jarek 0 0 2012-05-09 12:05:27.851839000 +0200 b

ls e touch vem de gnuwin32. Nas 2 primeiras linhas de saída, há uma diferença de registro de data e hora de 20 ms. Bom. Mas na segunda corrida, eles devem ser iguais (b tirou o selo de a). Sem sorte. Há uma diferença de 0,7 nós :).

svn status vê a diferença e, portanto, é difícil enganá -la touch.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top