So finden Sie alle fehlenden Bilder?

Sicher. Hier ist der raw-Text:

"Es sieht so aus, als ob \"Fung-Wong\", \"Mario\" oder schlicht \"Taifun #16\" am [Donnerstag in Japan an Land gehen](http://www.jma.go.jp/jp/typh/1416l.html):\n\n![Taifun 16](/uploads/default/35/4608d96d1b27846f.png)"

Und hier ist der cooked-Text:

"<p>Es sieht so aus, als ob „Fung-Wong“, „Mario“ oder schlicht „Taifun <span class=\"hashtag\">#16</span>“ am <a href=\"http://www.jma.go.jp/jp/typh/1416l.html\" rel=\"nofollow noopener\">Donnerstag in Japan an Land gehen</a>:</p>\n<p><div class=\"lightbox-wrapper\"><a class=\"lightbox\" href=\"/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png\" title=\"4608d96d1b27846f.png\"><img src=\"/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png\" alt=\"Taifun 16\" width=\"602\" height=\"500\"><div class=\"meta\">\n<svg class=\"fa d-icon d-icon-far-image svg-icon\" aria-hidden=\"true\"><use xlink:href=\"#far-image\"></use></svg><span class=\"filename\">4608d96d1b27846f.png</span><span class=\"informations\">800×664</span><svg class=\"fa d-icon d-icon-discourse-expand svg-icon\" aria-hidden=\"true\"><use xlink:href=\"#discourse-expand\"></use></svg>\n</div></a></div></p>"

Diese sind etwas schwer zu lesen, wenn sie auf einer einzigen Zeile komprimiert sind. Hier ist der formatierte raw-Text:

"Es sieht so aus, als ob \"Fung-Wong\", \"Mario\" oder schlicht
\"Taifun #16\" am
[Donnerstag in Japan an Land gehen]
(http://www.jma.go.jp/jp/typh/1416l.html):\n\n
![Taifun 16](/uploads/default/35/4608d96d1b27846f.png)"

Und hier ist der formatierte cooked-Text:

"<p>
  Es sieht so aus, als ob „Fung-Wong“, „Mario“ oder schlicht
  „Taifun <span class=\"hashtag\">#16</span>“ am
  <a href=\"http://www.jma.go.jp/jp/typh/1416l.html\" rel=\"nofollow noopener\">
    Donnerstag in Japan an Land gehen
  </a>:
 </p>\n
 <p>
   <div class=\"lightbox-wrapper\">
     <a class=\"lightbox\" href=\"/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png\" title=\"4608d96d1b27846f.png\">
       <img src=\"/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png\" alt=\"Taifun 16\" width=\"602\" height=\"500\">
       <div class=\"meta\">\n
         <svg class=\"fa d-icon d-icon-far-image svg-icon\" aria-hidden=\"true\">
           <use xlink:href=\"#far-image\"></use>
         </svg>
         <span class=\"filename\">4608d96d1b27846f.png</span>
         <span class=\"informations\">800×664</span>
         <svg class=\"fa d-icon d-icon-discourse-expand svg-icon\" aria-hidden=\"true\">
           <use xlink:href=\"#discourse-expand\"></use>
         </svg>\n
       </div>
     </a>
   </div>
 </p>"

Übrigens gibt es auf meiner Seite quite eine Anzahl (weit über hundert) solcher Beiträge:

[1] pry(main)> Post.where("raw ~* :regex AND cooked !~* :regex", regex: '/uploads/default/[0-9]+/').count
=> 135

Du solltest in rohen und verarbeiteten Inhalten keine unterschiedlichen URL-Formate verwenden. Könntest du bitte den oben genannten Beitrag neu aufbereiten? Das kannst du über das Menü des Beitrags mit HTML neu aufbauen oder mit dem Befehl post.rebake! tun. Gibt es in diesem Beitrag benutzerdefinierte Felder, die mit „uploads

Hier sind alle anderen benutzerdefinierten Felder für diesen bestimmten Beitrag (vor dem Ausführen des Befehls HTML neu aufbauen):

  id: 43,
  user_id: 1,
  topic_id: 36,
  post_number: 3,
  created_at: Mon, 22 Sep 2014 05:05:16 UTC +00:00,
  updated_at: Mon, 22 Sep 2014 05:11:22 UTC +00:00,
  reply_to_post_number: nil,
  reply_count: 0,
  quote_count: 0,
  deleted_at: nil,
  off_topic_count: 0,
  like_count: 0,
  incoming_link_count: 0,
  bookmark_count: 0,
  avg_time: 58,
  score: 1.2,
  reads: 6,
  post_type: 1,
  sort_order: 3,
  last_editor_id: -1,
  hidden: false,
  hidden_reason_id: nil,
  notify_moderators_count: 0,
  spam_count: 0,
  illegal_count: 0,
  inappropriate_count: 0,
  last_version_at: Mon, 22 Sep 2014 05:11:22 UTC +00:00,
  user_deleted: false,
  reply_to_user_id: nil,
  percent_rank: 0.585365853658537,
  notify_user_count: 0,
  like_score: 0,
  deleted_by_id: nil,
  edit_reason: "downloaded local copies of images",
  word_count: 34,
  version: 2,
  cook_method: 1,
  wiki: false,
  baked_at: Sun, 14 Apr 2019 09:28:00 UTC +00:00,
  baked_version: 2,
  hidden_at: nil,
  self_edits: 2,
  reply_quoted: false,
  via_email: false,
  raw_email: nil,
  public_version: 2,
  action_code: nil,
  image_url: "/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png",
  locked_by_id: nil

Ich sehe kein Feld uploads, aber vielleicht ist image_url das, wonach du suchst? Sein Wert – vor dem Ausführen des Befehls HTML neu aufbauen – war:

/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png

Das Ausführen des Befehls HTML neu aufbauen scheint den Wert des Feldes image_url geändert zu haben in:

https://{{SITE FQDN}}/uploads/default/35/4608d96d1b27846f.png

Alle URLs im bearbeiteten Text scheinen ebenfalls aktualisiert worden zu sein:

"<p>
  It looks like “Fung-Wong”, “Mario”, or simply
  “Typhoon <span class=\"hashtag\">#16</span>” will be
  <a href=\"http://www.jma.go.jp/jp/typh/1416l.html\" rel=\"nofollow noopener\">
    making landfall in Japan on Thursday
  </a>:
 </p>\n
 <p>
   <div class=\"lightbox-wrapper\">
     <a class=\"lightbox\" href=\"https://{{SITE FQDN}}/uploads/default/35/4608d96d1b27846f.png\">
       <img src=\"https://{{SITE FQDN}}/uploads/default/35/4608d96d1b27846f.png\" alt=\"Typhoon 16\" width=\"602\" height=\"500\">
       <div class=\"meta\">\n
         <svg class=\"fa d-icon d-icon-far-image svg-icon\" aria-hidden=\"true\">
           <use xlink:href=\"#far-image\"></use>
         </svg>
         <span class=\"filename\">4608d96d1b27846f.png</span>
         <span class=\"informations\">800×664</span>
         <svg class=\"fa d-icon d-icon-discourse-expand svg-icon\" aria-hidden=\"true\">
           <use xlink:href=\"#discourse-expand\"></use>
         </svg>\n
       </div>
     </a>
   </div>
 </p>"

Was ist die Beziehung zwischen 4608d96d1b27846f.png und 01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png? Sie haben dieselben Abmessungen und sehen auf den ersten Blick identisch aus, sind aber eindeutig verschiedene Dateien:

$ diff /var/discourse/shared/standalone/uploads/default/35/4608d96d1b27846f.png /var/discourse/shared/standalone/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png
Binary files /var/discourse/shared/standalone/uploads/default/35/4608d96d1b27846f.png and /var/discourse/shared/standalone/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png differ

$ ls -l /var/discourse/shared/standalone/uploads/default/35/4608d96d1b27846f.png
-rw-r--r-- 1 chris www-data 150319 Jan 19 01:14 /var/discourse/shared/standalone/uploads/default/35/4608d96d1b27846f.png

$ ls -l /var/discourse/shared/standalone/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png
-rw-r--r-- 1 chris chris 95005 Jul  3 15:25 /var/discourse/shared/standalone/uploads/default/original/2X/0/01bb9fb7e29c2b65fd663cdc58705d1720f8fea7.png

Und natürlich bleibt die Frage mit dem Millionen-Dollar-Preis: Wie gehe ich vor, um /uploads/default/35/4608d96d1b27846f.png in das neue Upload-Schema zu migrieren?

Es scheint, dass deine Uploads nicht ordnungsgemäß auf das neue Schema migriert wurden. Die Änderung SiteSetting.migrate_to_new_scheme = true sollte diese Situation eigentlich beheben. Ich bin mir nicht sicher, warum dies in deinem Fall nicht passiert. Bitte überprüfe die Anzahl der Uploads, die noch nicht auf das neue Schema migriert wurden. Führe die folgenden Befehle aus, um die Ergebnisse zu ermitteln.

Upload.by_users.where("url NOT LIKE '%/original/_X/%' AND url LIKE '%/uploads/default%'").count
SiteSetting.migrate_to_new_scheme = true
Jobs::MigrateUploadScheme.new.execute(nil)
Upload.by_users.where("url NOT LIKE '%/original/_X/%' AND url LIKE '%/uploads/default%'").count

Nein, das sind keine benutzerdefinierten Felder. Du solltest die Werte für benutzerdefinierte Felder über den Befehl post.custom_fields abrufen.

Oh, sorry! Ich habe völlig missverstanden, was du mit benutzerdefinierten Feldern meintest.

Ich könnte mich irren, aber dieser bestimmte Beitrag scheint keine zu haben:

[1] pry(main)> Post.find_by(:id => 43).custom_fields
=> {}

Nun, das ist interessant …

[2] pry(main)> Upload.by_users.where("url NOT LIKE '%/original/_X/%' AND url LIKE '%/uploads/default%'").count
=> 0
[3] pry(main)> Post.find_by(:id => 43).image_url
=> "https://{{SITE FQDN}}/uploads/default/35/4608d96d1b27846f.png"

Es scheint, als gäbe es keine Ergebnisse, die deiner Abfrage entsprechen. Ist dieses Verhalten zu erwarten?

Außerdem:

Hast du eine Idee, was die Antwort auf diese Frage sein könnte?

Es sieht so aus, als wären deine Uploads bereits auf das neue Schema migriert worden. Die Beiträge wurden jedoch nicht korrekt auf die neuen Schema-URLs umgemapped. Diese Beiträge befinden sich jetzt in einem fehlerhaften Zustand. Kannst du mir die Zugangsdaten deiner Seite in einer privaten Nachricht senden? Dann kann ich das Problem untersuchen, sobald ich Zeit habe.

Ah, das war genau das, wovor ich Angst hatte. Leider handelt es sich hierbei um eine private Installation, und ich bin mir nicht sicher, ob ich einer externen Partei Zugriff (root) auf den Server gewähren darf. Gibt es vielleicht noch etwas anderes, das ich zur Fehlersuche unternehmen kann?

Seit Ende April fehlen mir Bilder, doch ich habe mich erst heute Abend damit befasst.

rake posts:missing_uploads
26766 Post-Uploads fehlen.

22693 Uploads fehlen.
22683 von 22693 sind Uploads nach dem alten Schema.
9352 von 535188 Posts sind betroffen.

Wir nutzen die stabile Version. Angesichts der neuesten Beiträge in diesem Thread bin ich mir nicht sicher, wie es weitergehen soll.

Edit: Ich habe eine bestimmte GIF-Datei ausgewählt und festgestellt, dass sie im Upload-Verzeichnis des Live-Servers fehlt. Sie ist jedoch im Tombstone-Verzeichnis meines Backup-Servers vorhanden. Ich habe diese Datei per scp vom Backup-Server (discourse/shared/standalone/uploads/tombstone/default/39/ee8670816301d4c4.gif) in das entsprechende Tombstone-Verzeichnis des Live-Servers kopiert und anschließend die obige Rake-Aufgabe erneut als Test ausgeführt.

Das Bild wird nun im betreffenden Post angezeigt, und die Gesamtwerte haben sich wie folgt geändert:

26750 Post-Uploads fehlen.

22692 Uploads fehlen.
22682 von 22692 sind Uploads nach dem alten Schema.
9336 von 535190 Posts sind betroffen.

Es scheint, als sei das Tombstone-Verzeichnis auf dem Live-Server 138 MB groß, während es auf dem Backup-Server 9,5 GB beträgt. Daher werde ich ein rsync dieses Verzeichnisses durchführen und die Rake-Aufgabe erneut ausführen, in der Hoffnung, dass sich die gemeldeten Zahlen weiter verringern.

@kansaichris es sieht so aus, als hättest du nur 3 Beiträge mit fehlenden Datei-Uploads. In diesem Fall solltest du den Beitragshandtext manuell mit der korrekten Upload-URL bearbeiten.

@skl du hast viele Uploads im alten Schema. Nachdem du die Tombstone-Uploads vom Backup-Server kopiert hast, solltest du die folgenden Befehle ausführen, um sie auf das neue Schema zu migrieren.

rake posts:missing_uploads    # stelle sicher, dass `rsync` die Dateien kopiert hat
rake uploads:recover          # falls nach rsync noch fehlende Uploads vorhanden sind
SiteSetting.migrate_to_new_scheme = true
Jobs::MigrateUploadScheme.new.execute(nil)
Upload.by_users.where("url NOT LIKE '%/original/_X/%' AND url LIKE '%/uploads/default%'").count
# stelle sicher, dass die Anzahl 0 ist
rake posts:missing_uploads    # überprüfe den Status erneut

Vielen Dank für die Hilfe, @vinothkannans. Ich habe Ihren Anweisungen gefolgt (die Ausführung dauerte etwa 12 Stunden), und die Zahlen sind etwas gesunken:

22.614 Post-Uploads fehlen.
19.830 Uploads fehlen.
19.821 von 19.830 sind Uploads im alten Schema.
7.339 von 535.224 Beiträgen sind betroffen.

Da noch immer Uploads fehlen, habe ich mich außerhalb des Tombstone-Ordners umgesehen und festgestellt, dass auf dem Live-Server im Ordner uploads/default 22.885 leere Verzeichnisse angezeigt werden (auf dem Backup-Server sind es 10 leere Verzeichnisse). Zudem gibt es eine Größenabweichung von über 10 GB auf dem Backup, daher werde ich jetzt uploads/default vom Backup auf den Live-Server per rsync synchronisieren und Ihre Anweisungen erneut ausführen.

Edit: rake posts:missing_uploads scheint eine CPU-intensive, einstufige Aufgabe zu sein, die seit über 30 Stunden läuft. Daher habe ich den Server vorübergehend auf eine dedizierte CPU-Instanz umgestellt. Bilder scheinen vorerst wieder verfügbar zu sein, wenn auch im alten Schema. Vermutlich hat ein Discourse-Update ursprünglich zu der Löschung geführt.

Hmm… wenn es wirklich nur 3 Beiträge mit fehlenden Uploads gibt, warum scheinen dann 135 Beiträge zu existieren, deren Rohtext das alte Upload-Schema verwendet, obwohl der aufbereitete Text das neue Upload-Schema nutzt?

[1] pry(main)> Post.where("raw ~* :regex AND cooked !~* :regex", regex: '/uploads/default/[0-9]+/').count
=> 135

Aufgrund von Mismatches im Upload-URL-Schema in den Spalten raw und cooked. Der Rake-Task posts:missing_uploads prüft die Uploads ausschließlich anhand der Spalte cooked. Irgendwie musst du diese nicht übereinstimmenden Upload-URLs beheben. Ohne einen Blick in die Datenbank kann ich dir nicht weiterhelfen.

:crossed_fingers:

Ah, okay, mir war nicht bewusst, dass die Aufgabe posts:missing_uploads nur die Spalte cooked prüft – das würde die Diskrepanz definitiv erklären. :+1:

Ist es korrekt zu sagen, dass der Migrationsprozess, der durch das Setzen von SiteSetting.migrate_to_new_scheme auf true gestartet wird, ebenfalls nur den Wert der Spalte cooked prüft?

Die neue Schema-Migration wird URLs sowohl in raw als auch in cooked ersetzen. In deinem Fall ist dies jedoch nicht geschehen.

Das denke ich auch. Du kannst auch die Spalte last_updated_at der betroffenen Beiträge überprüfen.

Die Aufgabe wurde mit einem Fehler abgebrochen und zeigt bei jedem Versuch denselben Fehler an:

[2019-07-26T09:18:56.829375 #572]  WARN -- : Schlecht formatiertes IFD: undefinierte Methode `map' für nil:NilClass
....rake abgebrochen!
ArgumentError: negative Länge -2 angegeben
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/exifr-1.3.6/lib/exifr/jpeg.rb:89:in `readframe'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/exifr-1.3.6/lib/exifr/jpeg.rb:116:in `examine'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/exifr-1.3.6/lib/exifr/jpeg.rb:34:in `block in initialize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/exifr-1.3.6/lib/exifr/jpeg.rb:34:in `open'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/exifr-1.3.6/lib/exifr/jpeg.rb:34:in `initialize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim/worker/jhead.rb:40:in `new'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim/worker/jhead.rb:40:in `oriented?'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim/worker/jhead.rb:27:in `optimize'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim.rb:122:in `block (5 levels) in optimize_image'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim/handler.rb:41:in `process'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim.rb:122:in `block (4 levels) in optimize_image'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim.rb:120:in `each'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim.rb:120:in `block (3 levels) in optimize_image'
/var/www/discourse/vendor/bundle/ruby/2.6.0/gems/discourse_image_optim-0.26.2/lib/image_optim.rb:247:in `block in with_timeout'
Aufgaben: TOP => posts:missing_uploads

Bist du auf der neuesten Version oder einer älteren?

Neueste stabile Version „2.3.2 +4“

Sie werden höchstwahrscheinlich auf der neuesten Beta sein müssen.

Wenn du selbst hostest, gibt es kaum einen Grund, die stabile Version zu nutzen. Sie ist tatsächlich schwieriger zu unterstützen.

Der Kunde hat ausdrücklich gewünscht, bei der stabilen Version zu bleiben. Das war ihm beim Übergang des Projekts von mir gegenüber sehr wichtig.