Chrome, Raspberry-PI, Streaming, Absturz, Zattoo
TS
- betriebssystem
- browser
- raspberry
Hello,
ich habe leider immer noch nicht näher ermittelbare Abstürze meinerRaspberry-Pi 4, wenn ich mittels Chrome das Zattoo-Streaming benutzte. Manchmal läuft es stundenlang störungsfrei, dann stürzt die Raspberry aber auch wieder unvorhersehbar ab.
Wenn ich gleichzeitig ein htop auf einem zusätzichen SSH-Device laufen lasse, zeigt miŕ das immer den Absturz in einem einzigen Thread (von vier laufenden) Chrome-Thread an. Leider steht dann das gesamte System.
Glück Auf
Tom vom Berg
Hm. Raspi4 stürzt also ab.
Wenn ich gleichzeitig ein htop auf einem zusätzlichen SSH-Device laufen lasse, zeigt miŕ das immer dann Absturz in einem einzigen Thread (von vier laufenden) an. Leider steht dann das gesamte System.
Du meinst mit „das gesamte System“ die grafische Oberfläche? Der SSH-Server und htop scheinen ja Deiner Äußerung nach noch zu laufen…
Nie vergessen:
Hello,
Hm. Raspi4 stürzt also ab.
- Wie sieht es denn mit der Temperatur aus?
Alles m Rahmen
- Und mit Speicher(RAM)?
Laut htop maximal 50% genutzt
- Verwendest Du eine Speicherkarte, USB-Stick oder eine SSD?
Speicherkarte
- Gibt es zram, swap?
SWAP ja
- Verwendest Du ramlog (log2ram)?
nö, nicht dass ich wüsste
- Wie wird der Raspi gekühlt?
Dickes Alu-Gehäuse. Die Temperaturabfrage des Kernels ist auch nicht bedenklich.
- Ist er getunt?
Womit? Ich habe keine Parameter verstellt.
- Sagen die Logs etwas? (sylog, kern.log, dmesg)
Muss ich nochmal prüfen. Das könnte noch Erkenntnisse bringen.
Das Problem kam auch erst mit der Umstellung der Streaming-Kanäle auf HD auf. Am Anfang gab es das nur bei Zattoo-Alpha.
Da war die Lastanzeige (htop) dann kontinuierlich im Limit.
Nach einem Upgrade wurde es etwas besser, nach weiteren sogar erheblich. Die Last sank von über 4 (theoretisches Maximum) auf ca. 1,9 bis 2,5.
Aber manche Tage stürzt das Ding dann trotzdem noch ins Nirwana und einer der Threads ist dann über alle Limits.
Glück Auf
Tom vom Berg
Starte den „Chrome“ mal manuell im Terminal und logge die Ausgaben.
Bei mir (sic: bei MIR!) ist das /usr/bin/chromium-browser
.
Starte den dann wie folgt:
$DeinStartBefehl 1> ~/chromium.log 2> ~/chromium.log
und zeige uns nach dem Absturz die letzten (ungefähr) 20 Zeilen:
tail -n20 ~/chromium.log
(Die kannst Du mit tail -f ~/chromium.log
auch in einer ssh-Sitzung holen...)
Hallo,
$DeinStartBefehl 1> ~/chromium.log 2> ~/chromium.log
kann das gutgehen? Mit zwei Handles konkurrierend in dieselbe Logdatei schreiben? Ich würde sicherheitshalber zwei verschiedene nehmen.
Einen schönen Tag noch
Martin
kann das gutgehen?
Du hast Recht. Tut es nicht.
Korrektur des Startbefehls:
$DeinStartBefehl 1> ~/chromium.log 2> ~/chromium.err
Korrektur des „Fernsehens“:
tail -n20 ~/chromium.log ~/chromium.err
Getestet mit:
#/usr/bin/bash
echo "1: Teste Fehlerkanal" 1>&2;
echo "2: Teste Standardoutput";
echo "3: Teste Fehlerkanal" 1>&2;
echo "4: Teste Standardoutput";
und
./test.sh 1> test.log 2> test.err; cat test.log test.err
Hello,
kann das gutgehen?
Du hast Recht. Tut es nicht.
Muss es aber!
Wenn da nicht proprietär mit dem Dateizeiger herumgewerkelt wird, ist sogar bei Windows sichergstellt, dass der Append-Mode beim Beschreiben von Logdateien vom OS kontrolliert wird und Schreibzugriffe auf dieselbe Datei streng serialisiert werden.
Diese "Fossil-Funktion" ist bis heute am Leben erhalten worden, aus gutem Grund!
Glück Auf
Tom vom Berg
Hello,
kann das gutgehen?
Du hast Recht. Tut es nicht.
Muss es aber!
Tut es aber nicht. Hatte ich, wie gezeigt, getestet. Da ist der Wunsch irrelevant.
Willst Du alle Ausgaben in einem Logfile, welches bei einem neuen Start auch neu geschrieben wird,dann bleibt Dir (wie Robert auch schon schrieb):
$DeinStartBefehl 2> $DeinLogFile 1>&2
Hierbei sorgt das nachgestellte (hinten stehende!) 1>&2
dafür, dass die Standardausgabe zur Fehlerkonsole umgeleitet wird und das 2> $DeinLogFile
, dass die Fehlerkonsole sodann in eine Datei umgeleitet oder zu einem Gerät geschickt wird.
Willst Du alle Ausgaben an ein Logfile anhängen, dann möge
$DeinStartBefehl 2>> $DeinLogFile 1>&2
genügen.
Tipp:
Ich hab nachgesehen, was Du wohl mit „streamen“ meinst. Das ist wohl das Streamen zu solchen Chromcast-Dingern. Das verursacht durchaus eine hohe Prozessor-Last, die gleichberechtigt ist und die vergleichbar geringe Rechenkapazität eines Raspi „stark bindet“.
Daraus ergibt sich folgender Ansatz:
Ich starte den chromium-browser wie folgt:
#!/bin/sh
if [ -f /usr/bin/chromium ]; then
p="/usr/bin/chromium";
elif [ -f /usr/bin/chromium-browser ]; then
p="/usr/bin/chromium-browser";
fi
wmctrl -R 'chromium' || $p --start-maximized $*
exit
(Das Programm wmctrl kannst Du mit sudo apt install wmctrl
nachinstallieren.)
Das Skript prüft zunächst, ob chromium oder chromium-browser installiert ist.
Dann schaut es nach, ob sich ein Fenster mit 'chromium' im Titel wieder herstellen (in den Vordergrund holen) lässt. Wenn nicht wird der Browser gestartet. Das mag nicht perfekt sein, weil es auch ein Fenster mit dem Titel "chromium-browser.sh - /home/foo/bin/ - geany" in den Vordergrund holt, genügt aber in meinem Alltag - das verhindert bei mir, dass ich notlos und Ressourcen verschwendend etliche Chromium-Fenster aufmache, ich habe alle Vorkommen im Menü oder sonstigen Icons (Schnellstart, Desktop) angepasst... und verfahre mit einem ganzen Rudel anderer Programme genau so.)
Was Dir das bringt:
Du kannst versuchen, die Zeile
wmctrl -R 'chromium' || $p --start-maximized $*
anzupassen:
wmctrl -R 'chromium' || nice -10 $p --start-maximized $*
Danach startet der chromium als ziemlich freundlicher Mitbürger - auch dessen Kinder sind plötzlich auffallend nett und lassen im Fall des Falles andere Prozesse vor. Ich vermute, dann bleibt Dein Desktop steuerbar - auch wenn der Prozess, der gerade das Fenster des Chromium als Video in die Gegend schickt, stark ausgelastet ist.
Hello Martin,
$DeinStartBefehl 1> ~/chromium.log 2> ~/chromium.log
kann das gutgehen? Mit zwei Handles konkurrierend in dieselbe Logdatei schreiben? Ich würde sicherheitshalber zwei verschiedene nehmen.
In Logdateien schreiben findet üblicherweise im Append-Mode statt und da kümmert sich das Betriebssystem selber um Kollisionsfreiheit. Append-Schreiboperationen (auch über mehrere Threads hinweg) auf dieselbe Datei werden vom OS serialisiert.
Und welch Wunder: das funktioniert sogar bei WINDoofs ;-P
Glück Auf
Tom vom Berg
n'Abend Tom,
$DeinStartBefehl 1> ~/chromium.log 2> ~/chromium.log
kann das gutgehen? Mit zwei Handles konkurrierend in dieselbe Logdatei schreiben? Ich würde sicherheitshalber zwei verschiedene nehmen.
In Logdateien schreiben findet üblicherweise im Append-Mode statt
ja, das mag wohl sein. Hier haben wir aber den Fall, dass erst eine Datei zum Schreiben geöffnet wird (nicht append, sondern create!) und das stdout-Handle dann auf diese Datei gelenkt wird; dann wird dieselbe Datei mit einem zweiten Handle nochmal neu erzeugt und diesmal stderr auf dieses neue Handle gelenkt.[1] Das ist wtwas anderes als das koordinierte Schreiben mehrerer Prozesse in eine gemeinsame Log-Datei, das ja in der Regel über einen weiteren Prozess koordiniert wird, der die Schreibzugriffe serialisiert und geordnet umsetzt.
und da kümmert sich das Betriebssystem selber um Kollisionsfreiheit. Append-Schreiboperationen (auch über mehrere Threads hinweg) auf dieselbe Datei werden vom OS serialisiert.
Ja. Aber dann müsste man mindestens das stderr-Handle auch im Append-Modus umleiten, also mit 2>>, vielleicht sogar beide, damit's nicht knallt.
Und welch Wunder: das funktioniert sogar bei WINDoofs ;-P
Das ist nun wirklich erstaunlich.
Einen schönen Tag noch
Martin
Das zweite Öffnen derselben Datei im create-Modus müsste schon fehlschlagen (File Locking). ↩︎
Moin,
$DeinStartBefehl 1> ~/chromium.log 2> ~/chromium.log
kann das gutgehen? Mit zwei Handles konkurrierend in dieselbe Logdatei schreiben? Ich würde sicherheitshalber zwei verschiedene nehmen.
Ich kenne daher die Variante
$DeinStartBefehl > ~/chromium.log 2>&1
also logge jede Ausgabe in die Datei und leite die Fehlerausgabe nach stdout
um.
Viele Grüße
Robert
Mir fällt es gerade wie Schuppen von den Augen... Streamen erzeugt womöglich eine ziemlich hohe Last, welche den Prozessor vollständig beschäftigt. Der vermeintliche „Absturz“ könnte also eine „Schwester“ des bei mir aufgefallenen Problems mit der Auslastung sein.
Dann wäre das folgende eine mögliche Lösung:
Starte den „Chrome“ mal manuell im Terminal und logge die Ausgaben.
Den Befehl hierzu kannst Du via des, zum Bearbeiten des Startmenüs bestimmten Programms Deiner Installation ermitteln.
(Bis hier her entspricht das Antwort Nr. 2)
Starte den Chrome dann wie folgt:
nice -n 19 $DeinStartBefehl
#! /usr/bin/python3
from pathlib import Path
import math
class cpufreq:
def __init__( self ):
self._governor = ''
self._minfreq = ''
self._curfreq = ''
self._maxfreq = ''
self._calcstates = ''
self._sysruntime = ''
self._cpuTimefactor = 100
self._hmFactor = 1000000
self._hmString = 'GHz'
self._tempFile ='/sys/devices/virtual/thermal/thermal_zone0/temp'
self._tempFaktor = 0.001
self._tempFormat = '′C'
if ( Path( '/sys/devices/system/cpu/cpu0/cpufreq/' ).is_dir() ) :
self._path = '/sys/devices/system/cpu/cpu0/cpufreq/'
elif ( Path( '/sys/devices/system/cpu/cpufreq/' ).is_dir() ):
self._path = '/sys/devices/system/cpu/cpufreq/'
self.read_from_system( );
def read_the_line( self, fileName ):
f = open( fileName, 'r' )
l = f.read().strip()
f.close()
return l
def human_readble( self, z ):
z = z / self.hmFactor
return '%0.3f %s'%( z, self._hmString )
def Seconds2Human( self, s:int, daystring = 'd' ):
s = int(s)
# Days
if ( s > 86400 ):
d = math.floor( s / 86400 )
s = s - d * 86400
else:
d = 0
# Houres
if ( s > 3600 ):
h = math.floor( s / 3600 )
s = s - h * 3600
else:
h = 0
# Minutes
if ( s > 60 ):
m = math.floor( s / 60 )
s = s - m * 60
else:
m = 0
return '%d%s %02d:%02d:%02d'%( d, daystring, h, m, s )
def read_from_system( self ):
if ( Path( self._path + 'scaling_governor' ).exists() ):
self._governor = self.read_the_line( self._path + 'scaling_governor' )
self._minfreq = self.read_the_line( self._path + 'scaling_min_freq' )
self._curfreq = self.read_the_line( self._path + 'scaling_cur_freq' )
self._maxfreq = self.read_the_line( self._path + 'scaling_max_freq' )
elif( Path( self._path + 'cpuinfo_min_freq' ).exists() ):
self._governor = false
self._minfreq = self.read_the_line( self._path + 'cpuinfo_min_freq' )
self._maxfreq = self.read_the_line( self._path + 'cpuinfo_max_freq' )
if ( Path( self._path + 'cpuinfo_curr_freq' ).exists() ):
self.curfreq = self.read_the_line( self._path + 'cpuinfo_cur_freq' )
elif ( self._maxfreq == self._minfreq ):
self._curfreq = self._minfreq
else:
self._curfreq = 0
else:
self._governor = false
self._minfreq = 0
self._curfreq = 0
self._maxfreq = self.read_the_line( self._path + 'cpuinfo_max_freq' )
if ( Path( self._path + 'stats/time_in_state' ).exists() ):
# self._calcstates = self.read_the_line( self._path + 'stats/time_in_state' )
self._calcstates = self.readTimestates()
else:
self._calcstates = false
def human_readble ( self, z ):
z = int(z) / self._hmFactor
return '%0.3f %s' % ( z, self._hmString )
def getFreq ( self, v, hm ):
if ( hm ):
return self.human_readble( v )
else:
return v
def readTimestates( self ):
f = open( self._path + 'stats/time_in_state' , 'r' )
lines = f.readlines()
f.close
summe = 0
arr = {}
for line in lines:
line = line.strip()
if ( line ):
f, t = line.split(' ')
t = math.floor( int(t) / self._cpuTimefactor )
d = {};
if ( t != 0 ):
summe += t
f = self.human_readble( f )
d['t_abs'] = t
d['t_hum'] = self.Seconds2Human( t )
arr[f] = d
self._sysruntime = summe;
for f in arr.keys():
arr[f]['t_rel'] = '%1.4f'%(round( arr[f]['t_abs'] / summe, 4 ) )
arr[f]['t_100'] = '%5.1f%%' %( round( arr[f]['t_abs'] / summe * 100 , 1 ) )
return arr
def getMinFreq( self, hm = False ):
return self.getFreq ( self._minfreq, hm )
def getCurFreq( self, hm = False ):
return self.getFreq ( self._curfreq, hm )
def getMaxFreq( self, hm = False ):
return self.getFreq ( self._maxfreq, hm );
def getSysRunTime( self, hm = False ):
if ( hm ):
return self.Seconds2Human( self._sysruntime );
else:
return self._sysruntime;
def getCpuTemp ( self, hm = False ):
t = float( self.read_the_line( self._tempFile ).strip() )
t = t * self._tempFaktor;
if ( hm ):
return '%4.1f%s'%(round( t, 1 ), self._tempFormat);
else:
return t;
def getCalcstates ( self ):
return self._calcstates;
def getGovernor ( self ):
return self._governor;
### main ###
import os
if not os.environ.get('SHELL'):
print ( 'Content-Type: text/plain; charset=utf-8' )
print ( 'Refresh: 1' )
print ()
cf = cpufreq()
CurFreq = cf.getCurFreq( True )
print ('Governor: ' , cf.getGovernor() )
print ('Geringste Frequenz: ' , cf.getMinFreq( True ) )
print ('Gegenwärtige Frequenz: ' , CurFreq , ' <' )
print ('Maximale Frequenz: ' , cf.getMaxFreq( True ) )
print ('System läuft seit: ' , cf.getSysRunTime( True ) )
a = cf.getCalcstates()
if ( a ):
print ( 'Zeitliche Frequenznutzung:' )
for freq in a.keys() :
if ( freq == CurFreq ):
LE = ' <'
else:
LE = ''
print ( freq + ': ' , a[freq]['t_100'] , LE )
print ('Temperatur:' , cf.getCpuTemp( True ) )
print()
als cpufreq.py speichern, chmod 755 ...
in der ssh-shell mit watch -n1 -t cpufreq.py
starten und überwachen.
Sieht dann ETWA so aus:
Governor: ondemand
Geringste Frequenz: 1.500 GHz
Gegenwärtige Frequenz: 2.300 GHz <
Maximale Frequenz: 2.300 GHz
System läuft seit: 1d 17:48:23
Zeitliche Frequenznutzung:
0.600 GHz: 0.0%
0.700 GHz: 0.0%
0.800 GHz: 0.0%
0.900 GHz: 0.0%
1.500 GHz: 18.3%
1.800 GHz: 0.0%
2.300 GHz: 81.7% <
Temperatur: 57.5′C
Damit kannst Du nachsehen, ob der Raspi eventuell zu heiss wird und welche Frequenzen er fährt. (Meiner ist „schwer getunt“.)