Minha primeira ideia é:
# deploy into public_html_new, and then:
rsync -vaH --delete public_html_new/ public_html/
Uma boa solução foi usar o rsync. Ele mudou apenas os arquivos realmente alterados. Cuidado, as barras no final dos caminhos são importantes aqui.
Normalmente, o apache não precisa ser reiniciado, não é o mundo java. Ele verifica a alteração de todos os arquivos php a pedido e relê (e re-tokeniza) automaticamente.
O Git pull foi semelhante eficiente, embora tenha sido um pouco mais difícil de script. É claro que permitiu um amplo espectro de diferentes possibilidades de detecção de fusão / alteração.
Essa solução funcionará perfeitamente apenas se não houver mudanças realmente importantes - se houver grandes alterações na implantação, um pouco de risco não poderá ser encerrado, porque há um intervalo de tempo não desprezível, quando o código será parcialmente alterado e particularmente não.
Se houver grandes mudanças, minha sugestão foi sua solução inicial (duas renomear).
Aqui está uma solução um pouco incondicional, mas 100% atômica:
(1) monte uma parte alternativa do seu sistema de arquivos, onde o seu magento ocorre:
mount /dev/sdXY /mnt/tmp
(2) --bind
monte seu public_html_new em public_html:
mount --bind /path/to/public_html_new /path/to/public_html
A partir deste ponto, o apache verá sua nova implantação. Qualquer alteração de um 404 é impossível.
(3) faça a sincronização com o rsync, mas no ponto de montagem alternativo):
rsync -vaH --delete /mnt/tmp/path/to/public_html_new/ /mnt/tmp/path/to/public_html/
(4) remova o suporte de ligação
umount /path/to/public_html