Tym razem nieco bardziej pokręcony przykład pobierania pliku. W powstałym skrypcie są wady, dlatego jest to dobry materiał do krytyki. Zapraszam!
W wypadku kolejnych wydań dystrybucji SystemRescue nie ma analogicznych aliasów, by wskazywać na plik z ostatnim wydaniem tak, jak ma to miejsce w przypadku tumbleweed. Jednak SourceForge, na którym projekt *SystemRescue *jest utrzymywany, udostępnia łącze przekierowujące do najnowszego wydania (pliku iso), a link do docelowego serwera lustrzanego jest rozwiązywany dynamicznie.
Za pomocą curla*, *plik iso z najnowszym wydaniem można pobrać w ten sposób:
curl -kL https://sourceforge.net/projects/systemrescuecd/files/latest/download -o systemrescue-latest-amd64.iso
Jaki mam cel
Co kilka miesięcy, a czasem częściej, pojawia się nowe wydanie SystemRescue. Chcę mieć to wydanie dostępne lokalnie i chcę je pobrać tylko raz, gdy będzie ono już dostępne.
Jakie mam ograniczenia
Ponownie piszę w Ash. Docelowy skrypt również będzie działał na routerze z alternatywnym firmware. Również ponownie nie mogę sprawdzać sum sha256, bo nie mam na routerze dostępnej stosownej binarki. Do kompletu nie chcę męczyć procesora routera liczeniem sum kontrolnych większych plików.
Dlaczego nie wget
Posługując się curlem mogę spróbować przechwycić komunikaty przy przekierowaniach i w miarę prosty sposób zdecydować: czy iso z najnowszym wydaniem już istnieje lokalnie, czy też należy pobrać nowe.
Rozwiązywanie URL
Wymyśliłem coś takiego:
REDIRECT0="https://sourceforge.net/projects/systemrescuecd/files/latest/download"
REDIRECT1="$(curl -ks ${REDIRECT0} | grep https | sed -e 's/.*<a href="//' -e 's/">.*//')"
REDIRECT2="$(curl -ks ${REDIRECT1} | grep https | sed -e 's/.*<a href="//' -e 's/">.*//')"
Wadą tego rozwiązania jest to, że dość niezgrabnie można tutaj przechycić kod wyjścia, więc ostatecznie tego nie robię. Dodatkowo zbyt częste testowanie skryptu powoduje, że link przekierowujący nie będzie od czasu do czasu prawidłowo rozwiązywany (i bardzo dobrze!), a sam skrypt nie obsługuje takiego przypadku.
Logikę skryptu buduję wokół zawartości pliku sumy kontrolnej dla najnowszego udostępnianego obrazu iso, więc moim początkowym celem jest pobranie właśnie tegoż pliku z sumą kontrolną.
Położenie pliku z sumą kontrolną udało mi się odtworzyć, a plik pobrać w ten sposób - zwracam uwagę, że w tym wypadku curl wymaga przekierowania -L.
curl -kLs ${REDIRECT2}.sha256 -o ${TMPDIR}/${FILENAME}.sha256
***case *i inne zastrzeżenia
**Dla przypadków takich jak poniższy zalecane jest polecenie *case. *Zostawiam ten kawałek skryptu dokładnie w takiej postaci po to, być mieć pod ręką inny punkt odniesienia dla analogicznych przypadków.
SOURCESHA256="$(cat ${TMPDIR}/${FILENAME}.sha256 | cut -f1 -d' ')"
grep -q ${SOURCESHA256} ${TARGETDIR}/*.sha256
RET=$?
${RET} -eq 0 ] && _log "SHA256 checksum was found in ${TARGETDIR}. ${FILENAME} should be already in place." && exit 0
${RET} -eq 2 ] && _log "SHA256 checksum files not found. ${TARGETDIR} appears to be empty. Continuing."
${RET} -eq 1 ] && _log "SHA256 checksum not found. Continuing."
Dodatkowo nie potrafię z jednej strony zachować możliwie krótkiego i prostego kodu skryptu, a z drugiej obsłużyć wszystkich możliwch zwrotek z curla. Do kompletu nie przechwytuję też kodu wyjścia przy tworzeniu zmiennych REDIRECT.
Mimo tych wad poniższe rozwiązanie jest póki co wystarczające.
**
Całość skryptu
**
#!/bin/sh
# a script get the latest the release of SystemRescue distribution
# v0.1; 01/14/2022
SCRIPTNAME=$0
TMPDIR="/tmp/mnt/sda1/tmp"
TARGETDIR="/tmp/mnt/sda1/ftp/pub/linux/sysrescd/iso"
LOG="/tmp/mnt/sda1/var/log/$(echo ${SCRIPTNAME} | sed 's/.*\///').log"
REDIRECT0="https://sourceforge.net/projects/systemrescuecd/files/latest/download"
_log () {
echo "$(date +"%Y%m%d.%H%M%S") :: ${SCRIPTNAME} :: $*" >> ${LOG}
}
REDIRECT1="$(curl -ks ${REDIRECT0} | grep https | sed -e 's/.*<a href="//' -e 's/">.*//')"
REDIRECT2="$(curl -ks ${REDIRECT1} | grep https | sed -e 's/.*<a href="//' -e 's/">.*//')"
FILENAME="$(echo ${REDIRECT2} | sed 's/.*\///')"
_log "${FILENAME} to be checked."
rm -f ${TMPDIR}/${FILENAME}*
curl -kLs ${REDIRECT2}.sha256 -o ${TMPDIR}/${FILENAME}.sha256 && _log "${FILENAME}.sha256 downloaded to ${TMPDIR}."
! -f ${TMPDIR}/${FILENAME}.sha256 ] && _log "Error when downloading ${FILENAME}.sha256. Exit 1." && exit 1
SOURCESHA256="$(cat ${TMPDIR}/${FILENAME}.sha256 | cut -f1 -d' ')"
grep -q ${SOURCESHA256} ${TARGETDIR}/*.sha256
RET=$?
${RET} -eq 0 ] && _log "SHA256 checksum was found in ${TARGETDIR}. ${FILENAME} should be already in place." && exit 0
${RET} -eq 2 ] && _log "SHA256 checksum files not found. ${TARGETDIR} appears to be empty. Continuing."
${RET} -eq 1 ] && _log "SHA256 checksum not found. Continuing."
curl -ks ${REDIRECT2} -o ${TMPDIR}/${FILENAME} && _log "${FILENAME} downloaded to ${TMPDIR}."
mv ${TMPDIR}/${FILENAME}.sha256 ${TARGETDIR}/${FILENAME}.sha256
mv ${TMPDIR}/${FILENAME} ${TARGETDIR}/${FILENAME}
$? -eq 0 ] && _log "${FILENAME} is available locally." && exit 0
_log "End of the script reached. Exit 1" && exit 1