eKsiążki
https://forum.eksiazki.org/

Aktualizacja calibre przez crona
https://forum.eksiazki.org/calibre-f164/aktualizacja-calibre-przez-crona-t11018.html
Strona 1 z 1

Autor:  Zefiryn [ 13 lut 2012 0:19:12 ]
Tytuł:  Aktualizacja calibre przez crona

Kwestia w zasadzie dotyczy chyba linuksa i pythona jako takiego, ale, że to do calibre, to pytam tutaj.
Stworzyłem sobie prosty skrypt w bashu do aktualizacji calibre (wedle przepisu na stronie calibre)
Kod:
#!/bin/bash
/usr/bin/python -c "import sys; py3 = sys.version_info[0] > 2; u = __import__('urllib.request' if py3 else 'urllib', fromlist=1); exec(u.urlopen('http://status.calibre-ebook.com/linux_installer').read()); main(install_dir='/opt')"


Wrzuciłem plik sh do /usr/bin, dodałem +x i przy uruchomieniu z konsoli ładnie działa, calibre się pobiera, a następnie instaluje.
Kiedy próbowałem dorzucić do crona zadanie by automatycznie w piątki mi aktualizował napotkałem dziwny problem.
Zadanie (dla roota) jest zdefiniowane następująco
Kod:
0 22 * * 5 /usr/bin/calibre_update.sh


Na potrzeby testów zmieniłem czas wywołania na */8 i mam poniższe efekty:
w logach:
Kod:
Feb 11 16:48:01 localhost CROND[6369]: (root) CMD (/usr/bin/calibre_update.sh)

Oznaca to, że zadanie zostało poprawnie zdefiniowane i odpalone. Jednak calibre nie zostało zaktualizowane, a na maila przyszła wiadomość:
Kod:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 270, in main
File "<string>", line 182, in prints
TypeError: encode() argument 1 must be string, not None


Próbowałem znaleźć problem i zauważyłem, że ten sam komunikat dosataję kiedy ubiję program zanim ściągnie paczkę z najnowszą wersją. Doszedłem do wniosku, że cron ubija mój skrypt zanim w pełni się wykona. Dorzuciłem na końcu zadania w cronie znaczek et (&) aby skrypt uruchomił się jako wydzielony proces i nie był zamknięty przez crona. Niestety nic to nie dało. Informacji o zadaniu w ogóle na maila nie otrzymałem (co nie dziwi, wszak zrobiłem fork, więc cron go nie kontrolował), ale nie było żadnego ruchu sieci (specjalnie wszystko powyłączałem i patrzyłem w iptraf).

Mam zatem pytanie do kogoś kto się zna na pythone, czy trzeba czegoś szczególnego żeby ten calibrowy skrypt instalacyjny zmusić do działania?

Autor:  t3d [ 13 lut 2012 12:23:38 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Nieco oftopicznie zapytam, ale co to za dystrybucja i dlaczego nie chcesz, żeby zajmował się tym manager pakietów?

Autor:  Zefiryn [ 13 lut 2012 20:21:58 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Dystrybucja to Mandriva 2010.2. Dla mojej wersji paczka calibre ma numerek 0.6.48. Dla najnowszego wydania 0.8.13. Generalnie paczki są przygotowywane rzadziej niż raz na tydzień, a po drugie w nie lubię automatycznych aktualizacji (najnowsze wydanie hplip rozwaliło mi drukowanie w trybie draft na mojej drukarce).

Próbowałem dodać do skryptu
Kod:
wait{$}
ale nie to nie dało.

Autor:  fenuks [ 13 lut 2012 20:25:10 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Przy założeniu, że wyłączasz regularnie komputer (ja zazwyczaj usypiam/hibernuję), dodaj do skryptu sprawdzanie dnia tygodnia i ustaw żeby się uruchamiał wraz ze startem systemy, ale nie przez crona, tylko 'normalnie', przez autostart.

Autor:  MerlinEk [ 14 lut 2012 20:43:53 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Twoje problemy wynikają najpewniej z faktu, iż z poziomu crona przy odpaleniu skryptu zmienne środowiskowe są inaczej ustawiane niż przy odpalaniu tegoż samego bezpośrednio z powłoki. Może jakieś ścieżki do includowania są wówczas niepoustawiane i stąd błąd.

Autor:  Zefiryn [ 15 lut 2012 1:25:35 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Spróbowałem i niewiele to pomogło, poustawiłem większość rzeczy ze zmiennych konta roota, PATH, PYTHONPATH, SHLVL i parę innych.

Zacząłem także eksperymentować z kodem samego pythona odpalanego z crona. Przepisałem najpierw skrypt do pythona
Kod:
#!/usr/bin/env python

import sys
import urllib
code = (urllib.urlopen('http://status.calibre-ebook.com/linux_installer').read())
exec(code)
main(install_dir='/opt')


Do momentu pobrania kodu wszystko się ładnie wykonuje. Zrzciłem sobie to do pliku i kod jest pobierany i jest wykonywany. Zacząłem więc testować ten kod. Wydzieliłem go sobie do pliku i odpaliłem. Kompilacja przebiegła pomyślnie. Dodałem do niego wywołanie main jak powyżej i wówczas w konsoli dostałem błąd taki, jak w cronie.

Okazuje się, że problem pojawia się w funkcji wyświetlającej dane na ekranie
Kod:
def prints(*args, **kwargs):
    f = kwargs.get('file', sys.stdout.buffer if py3 else sys.stdout)
    end = kwargs.get('end', b'\n')
    enc = getattr(f, 'encoding', 'utf-8')
    if isinstance(end, unicode):
        end = end.encode(enc)
    for x in args:
        if isinstance(x, unicode):
            x = x.encode(enc)
        f.write(x)
        f.write(b' ')
    f.write(end)
    if py3 and f is sys.stdout.buffer:
        f.flush()

Przy normalnym wywołaniu stdout jest terminalem i wszystko jest pięknie. Kiedy ustaliłem standardowe wyjście na plik poprzez
Kod:
sys.stdout = open("/home/zefiryn/out.txt","w")

linia
Kod:
x = x.encode(enc)

Pokazała błąd, enc była ustawiona na NONE. Wygląda na to, że
Kod:
enc = getattr(f, 'encoding', 'utf-8')
nie działa prawidłowo kiedy wyjściem jest plik. Wnioskuję stąd, że kiedy na sztywno ustawiłem enc na utf8 wszystko poszło gładko, informacje zamiast na ekran zapisywały się do pliku i widziałem ruch na łączach.

Ponieważ ten skrypt jest pobierany z serwera nie jestem w stanie tego zmienić w locie. Zastanawiam się, czy mogę jakoś wymusić na nim by ta linijka działała jeżeli wyjściem jest plik. Jest jakaś zmienna, która dla stdout potrafi ustawić encoding.
Przy ustawieniu stdout jak powyżej dostaję następujące wyniki:
Kod:
f = kwargs.get('file', sys.stdout.buffer if py3 else sys.stdout) > <open file u'/home/zefiryn/out.txt', mode 'w' at 0xb7516f98>
enc = getattr(f, 'encoding', 'utf-8') > None


Wydaje mi się, że w ten sposób nie da się pobrać kodowania dla wyjścia. Czy jest ktoś, kto zna pythona na tyle, by pomóc mi tak ustawić wyjście by getattr działał lub tak ustawić poprawnie jego kodowanie?

Autor:  Zefiryn [ 15 lut 2012 1:47:53 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Udało mi się znaleźć rozwiązanie. Stworzyłem własną fukncję getattr. Kod odpalany przez crona wygląda teraz tak:

Kod:
#!/usr/bin/env python

import sys
import urllib
code = (urllib.urlopen('http://status.calibre-ebook.com/linux_installer').read())
sys.stdout = open("/root/out.txt","w")

def getattr(obj, attr, defVal):
  try:
    return obj.__dict__[attr]
  except:
    return defVal

exec(code)
main(install_dir='/opt')

Autor:  fenuks [ 15 lut 2012 23:26:17 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Przy przekierowaniu wyjścia na /dev/null skrypt z pierwszego postu wydaje się działać, w logu nie dojrzałem się błędów, ale poczekam do piątku z ostatecznym werdyktem.

Autor:  tofik [ 15 lut 2012 23:52:54 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Ja korzystam z minta i żałuję, że nie ma go w repozytoriach :(

Autor:  t3d [ 16 lut 2012 11:41:41 ]
Tytuł:  Re: Aktualizacja calibre przez crona

tofik napisał(a):
Ja korzystam z minta i żałuję, że nie ma go w repozytoriach :(

Dodaj sobie to PPA: https://launchpad.net/~n-muench/+archive/calibre

Autor:  Zefiryn [ 18 lut 2012 0:47:50 ]
Tytuł:  Re: Aktualizacja calibre przez crona

Mnie dzisiaj skrypt zadziałał, calibre został zaktualizowany do wersji 0.8.40

Strona 1 z 1 Wszystkie czasy w strefie UTC + 1 [czas letni (DST)]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group
http://www.phpbb.com/