O Bash tem cache de executáveis?

5

Eu estava apenas escrevendo um programa C ++ no meu computador Ubuntu 14.10. Como é um programa cliente / servidor, eu tenho três emuladores de terminal abertos: um para escrever código e compilação, um para teste de cliente e o último para teste de servidor. Depois de um tempo, achei que tinha um bug no meu código. Eu perdi mais de uma hora rastreando, e descobriu-se que sair do diretório e entrar nele novamente resolveu todo o problema. Para ser preciso, esses foram os comandos que executei:

some_directory$ ./client
some_directory$ cd ..
$ cd some_directory
some_directory$ ./client

Sem alterar nada - e sem recompilação - as duas execuções deram resultados diferentes. A única coisa em que consigo pensar é em algum tipo de cache que armazena versões antigas de arquivos, mas nunca ouvi falar de tal recurso. Existe uma explicação e como resolvê-lo (atualizá-lo automaticamente, sem sair do diretório)?

    
por akrasuski1 31.01.2015 / 04:36

2 respostas

3

Eu não acho que o bash faça algo tão chique (ele faz cache de caminhos para executáveis especificados sem caminhos, mas isso não se aplica aqui, já que você está especificando o caminho)

Parece que o diretório em que você estava foi movido ou montado. No caso de construir software, o movimento do diretório é mais provável.

Caso de movimentação de diretório

Um exemplo de recriar o comportamento de um movimento de diretório, no terminal 1

cd /tmp
mkdir dir1
cd dir1
touch exampleFile

Em seguida, no terminal 2:

cd /tmp
mv dir1 dir2
mkdir dir1
cd dir1

Ambos os shells aparecem como estando em um diretório chamado 'dir1', mas uma listagem mostrará conteúdos diferentes. Se o terminal2 criar um arquivo chamado 'exampleFile', ambos os shells mostrarão 'exampleFile' em 'dir1', mas eles são arquivos diferentes. Isso ocorre porque o shell no terminal 1 está de fato em dir2 agora, ele simplesmente não o conhece. O shell no terminal 1 pode chegar ao verdadeiro 'dir1' via cd:

cd .

Isso parece estranho, mas resolve novamente o caminho.

Sobre o caso de montagem

Isso ocorre quando um shell (ou qualquer programa) está em um diretório e, em seguida, um sistema de arquivos é montado sobre ele. Por exemplo, no terminal 1:

mkdir /tmp/dir1
cd /tmp/dir1

terminal 2:

mount /dev/whateverdev /tmp/dir1
cd /tmp/dir1

O terminal 1 vê os arquivos do sistema de arquivos original nesse diretório. O terminal 2 vê os arquivos de / dev / whateverdev.

Como evitar

No caso de montagem excessiva, isso é principalmente apenas estar ciente do que você está fazendo ou de como a sua máquina está configurada (por exemplo, se um automounter estiver sendo executado quando uma unidade USB estiver conectada).

No caso de movimentações de diretório, isso depende um pouco mais do sistema de compilação. Se houver uma regra que faça um backup do diretório de saída antigo, movendo-o e, em seguida, crie um novo diretório para a nova compilação, você se deparará com essa situação com bastante frequência. Verifique suas regras de criação para truques.

Claro, isso também poderia ter sido um acidente não intencional de uma única vez (semelhante ao que foi mostrado no primeiro exemplo acima). Nesse caso, a consciência de que isso pode acontecer ajudará você.

    
por 31.01.2015 / 05:28
2

Em geral hash e sync

hash - construído no comando bash

Para acelerar a operação quando você executa um comando, o bash shell armazena seu caminho em uma tabela hash . Cada shell instance tem seu próprio hash table . Para mais informações, leia este excerto de man bash :

If the name is neither a shell function nor a builtin, and contains no slashes, bash searches each element of the PATH for a directory containing an executable file by that name.
Bash uses a hash table to remember the full pathnames of executable files (see hash under SHELL BUILTIN COMMANDS below). A full search of the directories in PATH is performed only if the command is not found in the hash table.

Você pode substituir uma entrada na lista (por exemplo, o comando client ) por hash client ; você pode apagar esta entrada da lista com hash -d client ; você pode redefinir a lista completamente com hash -r .

Sync - Sincroniza dados no disco com memória

O comando sync garante que tudo na memória seja gravado no disco.

Para acelerar a operação, muitas vezes o Linux pode armazenar alguns dados nos buffers do sistema de arquivos do kernel, isto é, dados que foram programados para gravação via chamadas de sistema de E / S de baixo nível [1] .

Por outro lado, "Discos rígidos podem usar como padrão o uso de seu próprio cache de gravação volátil para gravações de buffer, o que melhora bastante o desempenho e, ao mesmo tempo, introduz um potencial para gravações perdidas" [2]

sync writes any data buffered in memory out to disk. This can include (but is not limited to) modified superblocks, modified inodes, and delayed reads and writes. This must be implemented by the kernel; The sync program does nothing but exercise the 'sync' system call. The kernel keeps data in memory to avoid doing (relatively slow) disk reads and writes. This improves performance, but ...

[se estiver interessado, continue a ler aqui ou com info coreutils sync ].

Específico para o seu problema

Se o seu problema depender de um dos aspectos acima, você pode tentar escrever em apenas uma linha mais de um comando e, depois, recuperá-los rapidamente com a tecla de seta para cima, por exemplo:

  • hash -d ./client; ./client ,
  • sync ; ./client ,
  • hash -d ./client ; sync ; ./client
  • (cd .. ; cd - ; ./client ) , sua própria solução. Aqui você executa o cliente em um subshell que coleta a herança que você fez em seu shell (como variáveis ...) mas que não retornará as mudanças para o atual < em> shell .

Sem um entendimento completo das operações envolvidas nas etapas de compilação e na operação de discagem entre cliente e servidor, pode ser difícil encontrar a causa (pode até ser um link simbólico ou uma alta latência em um NFS sistema de arquivos ...). Nesse caso, você precisa pesquisar a origem por tentativas e erros.

    
por 31.01.2015 / 11:54