Forum: PC-Programmierung Linux atomarer Dateizugriff


von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

Hallo,

Ich möchte mit einem Raspberry Pi und einer USB-Webcam regelmäßig ein 
Foto machen (Cronjob). Dieses wird in einem Verzeichnis gespeichert, 
welches über den Webserver zugänglich ist, der ebenfalls auf dem Pi 
läuft. Nun soll eine Internetseite das jeweils aktuelle jpg-Foto 
einbinden (immer der gleiche, statische Dateiname). Das Problem ist nun, 
dass ich nicht weiß, wie ich verhindere, dass man das Foto über den 
Webserver holt während die das Skript gerade ein neues Foto in das 
Verzeichnis schreibt. Das heißt ich möchte, dass das neue Foto erst ab 
dem Zeitpunkt zugreifbar ist, wenn es vollständig gespeichert ist. Wie 
kann ich das machen? Gibt es da eine Art Mutex, die den Webserver ein 
paar Millisekunden hinhalten kann, wenn gerade noch gespeichert wird? 
Oer wie würdet ihr das Problem lösen?

Ich weiß, dass dieses Forum thematisch nicht 100%ig auf die Thematik 
meiner Frage ausgelegt ist. Ich habe hier aber schon oft kompetente 
Foristen mit pragmatischen Lösungsansätzen gelesen und hoffe daher, dass 
mir hier jemand helfen kann.

Vielen Dank schon mal im Voraus!

Freiherr Isidor von Dornheim-Rottenburg

von Gustav (Gast)


Lesenswert?

move ist üblicherweisse atomar. Man schreibt in eine temporäre Datei und 
movet dann an den eigentlichen Zielort.

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

Oh, dafür liebe ich dieses Forum! funktioniert das auch, wenn am Zielort 
zuvor eine Datei mit gleichem Namen ist, die ersetzt wird? Weil die 
Internetseite ja immer auf den gleichen Dateinamen zugreift.
Danke!

von Kai S. (zigzeg)


Lesenswert?

Gustav schrieb:
> move

Das Kommando heisst "mv", als Betriebssystemaufruf heisst das rename() !
Natuerlich muss man die alte Datei vor dem rename() loeschen mit 
"unlink()", oder ? Und dann ist es leider nicht mehr atomar. Wird aber 
wahrscheinlich trotzdem klappen.

Update: Ups, nicht vorher loeschen, denn rename() macht das schon wenn 
die Zeildatei existiert ! Haette vorher mal die manpage anschauen sollen 
...

Es gibt sogar eine weitreichende Garantie:

The rename() system call guarantees that an instance of new will always
     exist, even if the system should crash in the middle of the 
operation.

Nett, oder ?

: Bearbeitet durch User
von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

Ja, das ist echt nett von Linux! Aber auch von euch für die schnelle 
Hilfe! Danke nochmals!

von Peter II (Gast)


Lesenswert?

Kai S. schrieb:
> The rename() system call guarantees that an instance of new will always
>      exist, even if the system should crash in the middle of the
> operation.
>
> Nett, oder ?

nein, denn es garantiert nur das die Datei immer Vorhanden ist. Entweder 
über den neuen oder den alten Namen.

Es garantiert nicht, das die Zieldatei immer verfügbar ist. Das das 
Problem bekannt ist, wurde im einer der letzter Kernel Version eine 
neuer Syscall eingebaut, der 2 Dateien atomar tauscht.

@Freiherr Isidor von Dornheim
Es sind nicht sehr sinnvoll ständig auf der Festplatte rumzuschreiben, 
dafür sie die SD-Karten nicht gedacht.

Ich würde das Image einfach im Ram speichern, für Webserver bietet sich 
z.b. memcache an.

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

Und wie schreibe ich eine Datei in den Ram? Ist memcache ein Mountpoint, 
über den das RAM im Dateisystem zugängig ist? Eigentlich wollte ich alle 
Bilder auch archivieren. Dafür müsste ich ohnehin auf die SD-Karte (oder 
ein USB-Medium) schreiben.

von Peter II (Gast)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> Und wie schreibe ich eine Datei in den Ram? Ist memcache ein Mountpoint,
> über den das RAM im Dateisystem zugängig ist? Eigentlich wollte ich alle
> Bilder auch archivieren. Dafür müsste ich ohnehin auf die SD-Karte (oder
> ein USB-Medium) schreiben.

memcache ist keine Ramdisk sondern ein Programm.

http://de.wikipedia.org/wiki/Memcached

> Eigentlich wollte ich alle
> Bilder auch archivieren. Dafür müsste ich ohnehin auf die SD-Karte (oder
> ein USB-Medium) schreiben.
davon war aber vorher keine rede.

von Praktiker (Gast)


Lesenswert?

oft werden Dateien unter unix auch mit Namen ".name" geschrieben 
(unsichtbare Datei) und wenn sie fertig geschrieben sind nach "name" via 
mv verschoben ...

von Peter II (Gast)


Lesenswert?

Praktiker schrieb:
> oft werden Dateien unter unix auch mit Namen ".name" geschrieben
> (unsichtbare Datei) und wenn sie fertig geschrieben sind nach "name" via
> mv verschoben ...

und schon haben wir wieder das atomar Problem.

von Gustav (Gast)


Lesenswert?

Peter II schrieb:
> und schon haben wir wieder das atomar Problem.

Nein.

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

@Peter II: Ok, aber eine Ramdisk könnte mir auch helfen um zu 
verhindern, dass die SD-Karte so schnell "abgenutzt" wird. Dort könnte 
ich immer das aktuelle Foto ablegen. Zum Archivieren könnte ich auf ein 
externes Laufwerk (usb-Festplatte) ausweichen.
Dass ich das mit dem Archivieren zuerst nicht geschrieben habe, war weil 
ich nicht dachte, dass das relevant für mein Problem wäre, Sorry

Gruß
Freiherr Isidor von Dornheim-Rottenburg

von atom (Gast)


Lesenswert?

Ihr Vollpfosten solltet mal nachlesen was "atomar" bedeutet.
Bei Speichermedien mit FS ist gar kein Zugriff atomar.

Man kann höchstens die Zeitspanne verkürzen, in der die
Bilddatei geschrieben wird, in der Hoffnung, dass es
dann seltener vorkommt, dass der Webserver während
der Speicherung das Bild lädt und darstellt.
Scheinbar ist das Programm, welches das Bild macht und
abspeichert, langsamer als move.

von Peter II (Gast)


Lesenswert?

Gustav schrieb:
> Peter II schrieb:
>> und schon haben wir wieder das atomar Problem.
>
> Nein.

doch. Die Datei wird kurzzeitig nicht verfügbar sein.

von Schaulus Tiger (Gast)


Lesenswert?

wenn du alle Bilder aufheben willst, kannst du sie unter einem 
eindeutigen Namen (2014-08-22-1050 oder so) auf die SD-Karte schreiben 
und dann die gerade geschriebene Datei nach /tmp kopieren. Anschließend 
wird sie mit mv umbenannt, damit der Name für den Webserver immer gleich 
bleibt.

Auf die Art wird genau so viel wie nötig und so wenig wie möglich auf 
die SD-Karte geschrieben. Für /tmp verwendet man heutzutage "tmpfs"; 
normal sollte das sowieso so eingerichtet sein.

von Schaulus Tiger (Gast)


Lesenswert?

Peter II schrieb:
> Gustav schrieb:
>> Peter II schrieb:
>>> und schon haben wir wieder das atomar Problem.
>>
>> Nein.
>
> doch. Die Datei wird kurzzeitig nicht verfügbar sein.

Nein.
1
Foto.jpeg ---> altes_bild
2
3
Foto.jpeg ---> altes_bild
4
201408221050 ---> halbes_neues_bild
5
6
Foto.jpeg ---> altes_bild
7
201408221050 ---> neues_bild
8
9
mv 201408221050 Foto.jpeg
10
11
Foto.jpeg ---> neues_bild
oder wie sonst läuft das ab?

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

liegt /tmp dann auf dem ram? Oder auf der SD-Karte? Andernfalls könnte 
ich das auch mit einer RAMdisk realisieren

von Peter II (Gast)


Lesenswert?

Schaulus Tiger schrieb:
> mv 201408221050 Foto.jpeg

das ist das Problem.

Wenn im Hintergrund ein Programm ständig auf Foto.jpeg zugreifst, wirst 
du merken das es kurzeitig nicht das ist.

Du bekommst du Datei für einen kurzen Moment nicht geöffnet, weil sie 
nicht da ist.

Für eine Webcam mag das ok sein, sauber ist es so auf jeden fall nicht.

von Peter II (Gast)


Lesenswert?

so hier noch das Problem:

http://www.heise.de/open/artikel/Kernel-Log-Was-3-15-bringt-1-Dateisysteme-und-Storage-2183256.html

Atomar umbenennen

Über den neuen Syscall "renameat2()" kann Software den Kernel anweisen, 
zwei Dateien atomar auszutauschen. Userspace-Programme sehen so entweder 
den alten oder neuen Zustand, nie aber einen der Zustände im 
Umbenennungsprozess. Das ist unter anderem zur sauberen Implementierung 
von Dateisystemen wichtig, die per "Union Mounting" mehrere Dateisysteme 
zu einem verbinden; das nutzen beispielsweise Live-Linuxe, um den Inhalt 
einer schreibgeschützten DVD mit dem Inhalt eines beschreibbaren 
USB-Sticks zu einem einzelnen Dateisystem zu verknüpfen, das alle neu 
geschriebenen Daten auf dem USB-Stick ablegt. Der neue Syscall ist damit 
ein wichtiger Schritt zur Union-Mount-Unterstützung im Kernel, auf die 
wechselnde Entwickler seit über fünfzehn Jahren hinarbeiten.

von Klaus W. (mfgkw)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> Und wie schreibe ich eine Datei in den Ram? Ist memcache ein Mountpoint,
> über den das RAM im Dateisystem zugängig ist?

Wenn du nichtsa auf der SDCard speichern willst, bietet sich auch ein 
tmpfs an.
Auf einem Olimex A20 mit Debian sieht es z.B. so aus:
<pre>
klaus@A20:~ > df
Filesystem     1K-blocks     Used Available Use% Mounted on
rootfs          30667212 19767816   9341952  68% /
/dev/root       30667212 19767816   9341952  68% /
devtmpfs          415368        0    415368   0% /dev
tmpfs              83096      180     82916   1% /run
tmpfs               5120        0      5120   0% /run/lock
tmpfs             166180       92    166088   1% /run/shm
</pre>
In die run/-Verzeichnisse kann man munter schreiben, owohl die effektiv 
nur im RAM sind.
Weitere könnte man sich schaffen...


> Eigentlich wollte ich alle
> Bilder auch archivieren. Dafür müsste ich ohnehin auf die SD-Karte (oder
> ein USB-Medium) schreiben.

Dann brauchst du auch kein RAM zum Speichern.

Idee: mit fortlaufenden Namen auf der SDCard speichern, und anschließend 
jeweils einen symbolischen Link mit festem Namen auf die letzte Datei 
richten.
Über den Link greift dann dein Webserver zu.
Damit das wiederum nicht kollidiert, könnte man jeweils den neuen Link 
mit einem temprären Namen anlegen (z.B. in einem tmpfs-Verzeichnis) und 
anschließend in den richtigen Namen umbenennen.
So hats du alles, was archiviert bleiben soll, auf der Karte und alles 
dynamische im RAM.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Damit das wiederum nicht kollidiert, könnte man jeweils den neuen Link
> mit einem temprären Namen anlegen (z.B. in einem tmpfs-Verzeichnis) und
> anschließend in den richtigen Namen umbenennen.

und das ist schon wieder nicht Atomar. Beim umbenennen gibt es 
kurzzeitig da Ziel nicht mehr.

von Nürnberger (Gast)


Lesenswert?

>Es sind nicht sehr sinnvoll ständig auf der Festplatte rumzuschreiben,
>dafür sie die SD-Karten nicht gedacht.

Cronjobs habe normalerweise in minimale Auflösung von 1 Minute.
Das wird für die SD-Karten wohl nicht so kritisch sein??!
Das System schreibt sowieso viel auf der SD-Platte "rum".

von Thorsten (Gast)


Lesenswert?

Ein mv(1) auf dem selben Dateisystem bzw. rename(2) ist unter Linux und 
jedem anständigen Unix atomar und garantiert auch, dass die Datei zu 
jedem Zeitpunkt mit open(2) geöffnet werden kann.

von Peter II (Gast)


Lesenswert?

Thorsten schrieb:
> Ein mv(1) auf dem selben Dateisystem bzw. rename(2) ist unter Linux und
> jedem anständigen Unix atomar und garantiert auch, dass die Datei zu
> jedem Zeitpunkt mit open(2) geöffnet werden kann.

wo steht das genau?

wenn ich Datei X nach Y umbenenne, dann heist das das X immer lesbar 
ist, zu Y erfolgt keine Aussage.

Wir haben zumindest und Linux das Problem gehabt, das beim umbenennen 
genau zu diesen Problem kommt.

von Peter II (Gast)


Lesenswert?

Nürnberger schrieb:
> Cronjobs habe normalerweise in minimale Auflösung von 1 Minute.
> Das wird für die SD-Karten wohl nicht so kritisch sein??!
> Das System schreibt sowieso viel auf der SD-Platte "rum".

warum sollte es da tun? Festplatten schaltet sich sogar bei einem 
timeout von 10min ab, weil nichts zu schreiben ist.

von Gustav (Gast)


Lesenswert?

Peter II schrieb:
> Wenn im Hintergrund ein Programm ständig auf Foto.jpeg zugreifst, wirst
> du merken das es kurzeitig nicht das ist.

Das kannst du noch so oft behaupten, es wird dadurch aber nicht richtig.

von Peter II (Gast)


Lesenswert?

Gustav schrieb:
> Das kannst du noch so oft behaupten, es wird dadurch aber nicht richtig.

und warum wird dann extra eine neue Kernel Funktion geschrieben?

http://lwn.net/Articles/569134/

von Peter II (Gast)


Lesenswert?

Gustav schrieb:
> Das kannst du noch so oft behaupten, es wird dadurch aber nicht richtig.

ok geben micht geschlagen:

http://man7.org/linux/man-pages/man2/rename.2.html
 If newpath already exists, it will be atomically replaced (subject to
       a few conditions; see ERRORS below), so that there is no point at
       which another process attempting to access newpath will find it
       missing.

aber wir hatte zumindest Probleme damit, er verlasse mich nicht darauf.

von Thorsten (Gast)


Lesenswert?

Peter II schrieb:
> wenn ich Datei X nach Y umbenenne, dann heist das das X immer lesbar
> ist, zu Y erfolgt keine Aussage.

Bei einem
  rename("old", "new");
bei existentem "new" ist garantiert dass "new" während des Umbennenens 
immer existiert und gelesen werden kann. Ohne diese Semantik würden 
etliche Programme nicht korrekt funktionieren.

Nachlesen kann man das unter anderem in POSIX 1998. Zitat:

If the link named by the new argument exists, it shall be removed and 
old renamed to new. In this case, a link named new shall remain visible 
to other processes throughout the renaming operation and refer either to 
the file referred to by new or old before the operation began.

von Nürnberger (Gast)


Lesenswert?

Peter II schrieb:
> Nürnberger schrieb:
>> Cronjobs habe normalerweise in minimale Auflösung von 1 Minute.
>> Das wird für die SD-Karten wohl nicht so kritisch sein??!
>> Das System schreibt sowieso viel auf der SD-Platte "rum".
>
> warum sollte es da tun? Festplatten schaltet sich sogar bei einem
> timeout von 10min ab, weil nichts zu schreiben ist.

Naja, ein aktiver webserver loggt ja alles mögliche.
(ok, das könnte man sicherlich deaktivieren)
Üblicherweise wird für log-Daten kein tmp-Verzeichnis gewählt,
denn dann wären diesen Daten nach einem System-Absturz weg.

von c.m. (Gast)


Lesenswert?

bevor du eine neue datei schreibst löschst du die alte (mit dem selben 
namen). falls die alte grade geöffnet war kann das programm immernoch 
den inhalt lesen (und reinschreiben). eine alte unix hacktechnik um 
unsichtbar daten wegschreiben zu können - die datei taucht als name im 
FS nicht auf, aber das handle ist noch geöffnet und es kann ganz normal 
darauf zugegriffen werden.

für den fall das deine websoftware genau dann ein bild laden will wenn 
die alte datei eben gelöscht, aber nie neue noch nicht angelegt wurde, 
machst du zwei zugriffe mit einem timeout(<erstellungsintervall) 
dazwischen.


es gibt übrigens noch die möglichkeit video direkt zu streamen (weiß 
aber nicht ob der raspi das eventuelle transcoden schafft) - falls du es 
ganz hardcore haben willst ;)

von Michael R. (Firma: Brainit GmbH) (fisa)


Lesenswert?

Peter II schrieb:
> und warum wird dann extra eine neue Kernel Funktion geschrieben?

Ihr verwechselts da was:

rename() ist per Definition atomar

was nciht atomar ist, ist das Vertauschen zweier Dateien,

also a.txt  und b.txt austauschen
weil das nur als drei einzelne rename() calls abgebildet werden kann
rename a.txt x.txt
rename b.txt a.txt
rename x.txt b.txt

jeder der einzelnen rename() ist zwar für sich atomar, aber nicht die 
drei operationen zusammen.

Deshalb (und nur deshalb) gibts den neuen SysCall (der auch nur für 
einen speziellen Zweck eingebaut wurde, nämlich union-filesystems)

: Bearbeitet durch User
von tmomas (Gast)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> @Peter II: Ok, aber eine Ramdisk könnte mir auch helfen um zu
> verhindern, dass die SD-Karte so schnell "abgenutzt" wird.

Vergiss das mit der schnellen Abnutzung.

Ich habe hier einen 32GB USB Stick (Sandisk Cruzer Blade), auf den 
werden täglich (24/7/365) 12960 jpgs von 5 Kameras geschrieben, ca. 
50..100kB pro jpg je nach cam.

Zusätzlich noch 1x täglich je ein Zeitraffervideo von 50...175MB pro 
cam.

Auslastung des Sticks schwankt zwischen 50%...80%, d.h. ich habe immer 
mindestens 20% des Speicherplatzes frei.

Der Stick ist seit mehr als einem Jahr im Einsatz, ohne 
Ausfallerscheinungen.

Wenn USB Sticks kaputtgehen, dann nicht durch "Abnutzung" durch häufiges 
Schreiben, sondern durch mechanische Belastung.

von tmomas (Gast)


Lesenswert?

Schaulus Tiger schrieb:
> Foto.jpeg ---> altes_bild
>
> Foto.jpeg ---> altes_bild
> 201408221050 ---> halbes_neues_bild
>
> Foto.jpeg ---> altes_bild
> 201408221050 ---> neues_bild
>
> mv 201408221050 Foto.jpeg
>
> Foto.jpeg ---> neues_bild

Exakt so mache ich das auch (anderer Rechner als der vorhin beschriebene 
mit 5 cams) und konnte bisher keine "kurzfristige" Nicht-Verfügbarkeit 
feststellen.

Für den angedachten Anwendungszweck funktioniert das hervorragend.

Und btw: Kann bitte mal jemand das schon so oft genannte "kurzfristig" 
näher quantifizieren? Ich behaupte, das "kurzfristig" ist so kurz, daß 
es keine praktische Relevanz hat.

von Peter II (Gast)


Lesenswert?

tmomas schrieb:
> Vergiss das mit der schnellen Abnutzung.

ich habe schon 2 stick mit 2GB damit geschrotet. Hatte ein normales 
Linux drauf und /var nicht auf ein tmpfs gelegt.

Nach jeweils 1Jahr hatte der Stick Schreibfehler.

von Gustav (Gast)


Lesenswert?

Peter II schrieb:
> und warum wird dann extra eine neue Kernel Funktion geschrieben?

Weil ein atomic swap etwas anderes ist. Da wird dir auch über die Datei 
"old" eine Garantie gegeben.

von Gustav (Gast)


Lesenswert?

Peter II schrieb:
> aber wir hatte zumindest Probleme damit, er verlasse mich nicht darauf.

Bei MacOS X ist das angeblich kaputt, weil nicht-atomar.

von tmomas (Gast)


Lesenswert?

Peter II schrieb:
> tmomas schrieb:
>> Vergiss das mit der schnellen Abnutzung.
>
> ich habe schon 2 stick mit 2GB damit geschrotet. Hatte ein normales
> Linux drauf und /var nicht auf ein tmpfs gelegt.
>
> Nach jeweils 1Jahr hatte der Stick Schreibfehler.

Welche Marke?
Wieviele Dateien bzw. MB/Tag hast du draufgeschrieben?


- Nimm einen Markenstick (Sandisk Cruzer Blade / Sandisk Cruzer fit sind 
meine Lieblinge)
- Nimm einen "großen" Stick. 8 oder 16GB kosten ja heute nichts mehr.
- Sorge dafür, daß immer ca. 20% frei sind. Betonung auf immer.
- Die jpgs und videos werden bei mir regelmäßig gelöscht, d.h. alle 
Speicherzellen werden mehr oder weniger gleichmäßig belastet. Es gibt 
nicht die Situation, daß von den 32GB 30GB dauerhaft belegt sind, und 
nur auf den restlichen 2GB rumgeschrieben wird.

Anmerkung: /var liegt bei mir auf einem tmpfs.

von Klaus W. (mfgkw)


Lesenswert?

Gerade nach /var kommen aber Sachen, die man meistens behalten möchte 
(und die sich ändern).

Pauschal würde ich /var nicht als RAM-fs empfehlen, auch wenn es sicher 
Fälle gibt, wo es gewünscht ist.

von Schaulus Tiger (Gast)


Lesenswert?

tmomas schrieb:
> Und btw: Kann bitte mal jemand das schon so oft genannte "kurzfristig"
> näher quantifizieren? Ich behaupte, das "kurzfristig" ist so kurz, daß
> es keine praktische Relevanz hat.

Null, jedenfalls in diesem Anwendungsfall mit "mv"; ich glaube, soweit 
waren wir uns inzwischen einig.

Man kann natürlich gemein sein: Das "mv" braucht eine gewisse 
Ausführungszeit, gerade auf SD-Karten (im Extremfall wohl über 1 
Sekunde). Und gerade weil es atomar ist, ist während der Zeit kein 
Zugriff möglich. Es gibt zwar keinen Fehler oder falsche Daten, aber 
wenn diese Verzögerung stört...

von Daniel F. (df311)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> Das Problem ist nun,
> dass ich nicht weiß, wie ich verhindere, dass man das Foto über den
> Webserver holt während die das Skript gerade ein neues Foto in das
> Verzeichnis schreibt. Das heißt ich möchte, dass das neue Foto erst ab
> dem Zeitpunkt zugreifbar ist, wenn es vollständig gespeichert ist. Wie
> kann ich das machen?

schreib doch das neue Foto mit einem eindeutigen Namen in ein 
Verzeichnis (damit hast du gleichzeitig auch noch ein Archiv) und setz 
nach dem speichern einfach einen symlink (z.b. current) auf das 
aktuellste Bild.
Einen Symlink zu erstellen/ändern sollte (theoretisch) schneller sein 
als das Bild zu speichern

von Andreas D. (rackandboneman)


Lesenswert?

Ein ganz wichtiger Fakt zu unlink() und rename() wurde hier noch nicht 
erwähnt:

Wenn ein Prozess die Datei zu dem Zeitpunkt offen hatte zu dem unlink() 
oder rename() passierte bekommt besagter Prozess gar nichts davon mit, 
Änderungen werden in die umbenannte oder scheinbar gelöschte Datei 
geschrieben (die erst wirklich bei Prozessende gelöscht wird!).
Wer es nicht glaubt öffne mal eine MP3-Datei in irgendeinem Player auf 
einem Linux/Unix-System und verschiebe oder lösche sie während sie 
abgespielt wird...

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

Guten Morgen,
danke für eure Hilfe in dieser Sache. Hier kamen wirklich von allen 
Seiten sehr konstruktive Beiträge!

 @Andy D. : Ja, das finde ich ziemlich gut. Mir ist es wichtig, dass zu 
JEDER Zeit ein vollständiges, nicht korrumpiertes Foto zur Verfügung 
steht. Auch wenn gerade ein neues aufgenommen/abgespeichert wird.

@all:
Der Raspberry-Webcamserver soll über eine Dyn-DNS im Netz hängen. Ich 
möchte aber nicht, dass jeder Besucher meiner Seite gleich "zu mir nach 
Hause gehen kann" - ich möchte die Dyndns nicht im für Seitenbesucher 
sichtbaren Seitenquelltext stehen haben. Gibt es eine Möglichkeit, den 
Hauptwebserver mit php dazu zu bringen (regelmäßig) das neueste Foto vom 
Webcamwebserver zu holen und dann aus einem eigenen Verzeichnis zum 
Seitenbesucher zu bringen?

Ich hoffe ich konnte verständlich machen, was ich möchte. Wenn nicht, 
einfach nochmal nachhaken ;)

Vielen Dank schon mal im Voraus!

Freiherr Isidor von Dornheim-Rottenburg

von Daniel F. (df311)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> Gibt es eine Möglichkeit, den
> Hauptwebserver mit php dazu zu bringen (regelmäßig) das neueste Foto vom
> Webcamwebserver zu holen und dann aus einem eigenen Verzeichnis zum
> Seitenbesucher zu bringen?

z.B. curl
in verbindung mit einem blow- äh cronjob (regelmäßig) oder auch direkt 
bei einem seitenaufruf (on demand). welche variante die geschicktere ist 
hängt u.a. auch von der anzahl der seitenaufrufe ab.
dabei kannst du das foto auch noch gleich mit einem wasserzeichen 
versehen, verkleinern, drehen, was auch immer
1
function getImg() {
2
  $ch = curl_init('http://dein.raspberry.com/webcam/current.jpg');
3
4
  curl_setopt_array($ch, array(
5
    CURLOPT_RETURNTRANSFER => true,
6
  ));
7
8
  $img = curl_exec($ch);
9
  curl_close($ch);
10
11
  $fh = fopen('current.jpg', 'x+');
12
  fwrite($fh, $img);
13
  fclose($fh);
14
15
  echo '<img src="current.jpg" alt="xxx">';
16
}

bitte auf evtl. funktionsnamen, optionen, parameter, etc. nicht 100% 
festnageln - habs nur aus dem kopf geschrieben und nicht nachgeschaut. 
der code soll ja auch mehr das prinzip verdeutlichen

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

OK danke,
ich denke ich werde es wohl bei Seitenaufruf machen müssen, weil ich bei 
dem Hauptwebserver nur ftp-Zugriff und einen (eingeschränkten) 
Datenbank-Zugang habe. Ich kann also keinen Cron-Job installieren. Oder 
kann man das auch auf eine andere Art und Weise regelmäßig laufen 
lassen? Ich habe mit php leider noch keine Erfahrungen gemacht.

von Andreas D. (rackandboneman)


Lesenswert?

Dieses Verhalten könnte man noch besser ausnutzen in dem man einfach 
einen Hardlink pflegt der stets auf die Datei zeigt die der Webserver 
ausliefern soll.

von tmomas (Gast)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> Gibt es eine Möglichkeit, den
> Hauptwebserver mit php dazu zu bringen (regelmäßig) das neueste Foto vom
> Webcamwebserver zu holen und dann aus einem eigenen Verzeichnis zum
> Seitenbesucher zu bringen?

Wie schon erwähnt: cronjob + curl oder auch ein einfaches wget

Alternativ: Laß doch den Raspi das neue Bild auf den Hauptserver 
hochladen. Auf dem hast du doch alle Möglichkeiten, oder zumindest mehr 
Möglichkeiten, als auf dem Hauptserver, oder?

von Freiherr Isidor von Dornheim-Rottenburg (Gast)


Lesenswert?

Ja, auf dem Raspberry habe ich freie Hand. Ich kann also das Foto von da 
aus per ftp zum Webserver befördern. Dann stellt sich aber erneut die 
Frage, ob ich das jeweils aktuelle Foto zum Webserver laden kann (und 
dabei das vorherige überschreiben) und dabei zu JEDER Zeit ein nicht 
korrumpiertes Foto an den Website-Besucher ausliefern kann?

von Εrnst B. (ernst)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> zu JEDER Zeit ein nicht
> korrumpiertes Foto an den Website-Besucher ausliefern kann?

Machs mit zwei Dateien und drei Dateinamen:

RPi macht über FTP:
Upload TMPFILE
Delete IMAGE1.JPG
Rename TMPFILE IMAGE1.JPG
Upload TMPFILE
Delete IMAGE2.JPG
Rename TMPFILE IMAGE2.JPG
Goto 10;

Dein PHP macht:

IMAGE1handle = fopen IMAGE1.JPG
IMAGE2handle = fopen IMAGE2.JPG

fstat IMAGE1handle (wenn OK)
fstat IMAGE2handle (wenn OK)

neueres Auswählen (wenn beide OK)
ggfs: fclose auf unbenötigten (älteren) Handle

Bild rausstreamen. (while... fread ... )

fclose

Trick ist: kein file_exists-Check o.Ä. vorher machen, direkt fopen 
verwenden, Rückgabewert auswerten.
Das Filehandle bleibt gültig, auch wenn gleichzeitig der FTP-Server ein 
"unlink" ausführt.

Dein Problem verschiebt sich damit vom Atomaren Umbennenen zum Atomaren 
Löschen von Dateien. Und das ist m.W.n. gegeben.

: Bearbeitet durch User
von Blablubb (Gast)


Lesenswert?

Freiherr Isidor von Dornheim-Rottenburg schrieb:
> Oer wie würdet ihr das Problem lösen?

Mit einer Lockdatei in dem Verzeichnis, in dem die Bilder liegen. Das 
ist dann "so eine Art Mutex", wie Du Dir das wünschst.

Ich habe den Thread jetzt nur überflogen, aber ich glaube, dass das noch 
nicht vorgeschlagen wurde - was mich wundert :-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.