"Christmas - the time to fix the computers of your loved ones" « Lord Wyrm

Device nodes (/dev/sdX) löschen um versehentlichen Zugriff zu verhindern

fogerl 23.12.2013 - 23:17 3898 15 Thread rating
Posts

fogerl

Little Overclocker
Registered: Jan 2005
Location: Wien
Posts: 98
Hallo zusammen,

ich bin gerade dabei haufenweise Daten zwischen verschiedenen Festplatten mit dd herumzuschaufeln. Ich suche nun einen Weg jene Festplatten, die von der ganzen Herumkopiererei verschont bleiben sollen (/dev/sda und /dev/sdb) zu schützen.

Ihr wisst schon -- ein Tippfehler genügt, und die Daten sind dahin.

Ich hatte die Idee, einfach den zugehörigen Device Node der Festplatte zu löschen. (rm /dev/sda)

Meine Fragen dazu:
* Ist dieser Schutz wirkungsvoll?
* Wie bekomme ich /dev/sda ohne Reboot zurück?
** partprobe hat nichts gebracht, und für "udevadm trigger" kenne ich die zugehörigen Argumente nicht.


/dev/sda zu befüllen ist eine sehr schlechte Idee, aber die Datei zu entfernen sollte angeblich keine Auswirkungen auf die darauf gespeicherten Daten haben.

Danke!
Bearbeitet von fogerl am 23.12.2013, 23:46

issue

Rock and Stone, brother!
Avatar
Registered: Feb 2003
Location: Linz
Posts: 3599
Keine Antwort auf deine Frage, aber: setz fuer deine zu bearbeitenden Devices Umgebungsvariablen und verwende die.
Also zb BACKUPHDD=/dev/sdX und operiere dann mit dd auf $BACKUPHDD

fogerl

Little Overclocker
Registered: Jan 2005
Location: Wien
Posts: 98
Danke für den Tipp!

Leider habe ich mit Umgebungsvariablen keine Erfahrung. Sind sie nur in jenem Terminalfenster gültig in dem Sie gesetzt wurden, oder systemweit?

COLOSSUS

Administrator
Frickler
Avatar
Registered: Dec 2000
Location: ~
Posts: 11890
Zitat von fogerl
Danke für den Tipp!

Leider habe ich mit Umgebungsvariablen keine Erfahrung. Sind sie nur in jenem Terminalfenster gültig in dem Sie gesetzt wurden, oder systemweit?

Umgebungsvariablen ("Environment Variables") sind immer nur im Kontext eines Prozesses gueltig. Kind-Prozesse erben das zum Zeitpunkt des Wegforkens bestehende Environment ihres Elternprozesses, haben danach aber sofort ihre eigene, eigenstaendige Kopie dieses Environments, das durch den Elternprozess (oder irgendeinen Prozess sonst, Debugger und Co. mal ausgenommen) nicht mehr beeinflussbar ist. Unter Linux kannst du dir den Inhalt des Environments (das infach nur ein durch NUL-Bytes organisierter Speicherbereich ist, der meist textaehnliche Daten enthaelt) in den Dateien unter /proc/<PID>/environ ansehen. Ein Beispiel:

Code:
root@htpc[ssh]:~ # tr \\0 \\n < /proc/$$/environ
USER=root
LOGNAME=root
HOME=/root
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/bin/X11
MAIL=/var/mail/root
SHELL=/bin/bash
SSH_CLIENT=192.168.0.1 4031 22
SSH_CONNECTION=192.168.0.1 4031 192.168.0.127 22
SSH_TTY=/dev/pts/0
TERM=xterm
LANG=en_US.UTF-8
LANGUAGE=en_US.UTF-8

("$$" ist eine Bourne-Shell-Variable, die zur PID der aktuellen Shell expandiert - das ist also das Environment meiner aktuellen Shell.)


Zur Loesung deines Problems wuerde ich dennoch etwas anderes vorschlagen: Auf "aktuellen" (das schreibe ich in dem Kontext jetzt seit 2006 oder so ;)) Distributionen mit udev gibt es nicht nur /dev/sd* als Device-Nodes fuer Blockgeraete an SATA, USB und Co., sondern auch nuetzliche Symlinks in /dev/disk/by-*/*. Brauchbar in Hinsicht auf deine Fragestellung ist meiner Ansicht nach vor allem /dev/disk/by-id/, da finden sich Symlinks zu Block Bevice Nodes mit deskriptiven Namen wie bswp.:

Code:
root@htpc[ssh]:~ # ls -l /dev/disk/by-id/ata-*
lrwxrwxrwx 1 root root  9 Dec 24 03:14 /dev/disk/by-id/ata-OCZ-ONYX_5AE0498XXXXXXXXXXXX -> ../../sda
lrwxrwxrwx 1 root root 10 Dec 24 03:14 /dev/disk/by-id/ata-OCZ-ONYX_5AE0498XXXXXXXXXXXX-part1 -> ../../sda1
lrwxrwxrwx 1 root root 10 Dec 24 03:14 /dev/disk/by-id/ata-OCZ-ONYX_5AE0498XXXXXXXXXXXX-part2 -> ../../sda2
lrwxrwxrwx 1 root root 10 Dec 24 03:14 /dev/disk/by-id/ata-OCZ-ONYX_5AE0498XXXXXXXXXXXX-part5 -> ../../sda5
lrwxrwxrwx 1 root root 10 Dec 24 03:14 /dev/disk/by-id/ata-OCZ-ONYX_5AE0498XXXXXXXXXXXX-part6 -> ../../sda6
lrwxrwxrwx 1 root root  9 Dec 24 03:14 /dev/disk/by-id/ata-WDC_WD20EARS-00S8B1_WD-WCAXXXXXXXX -> ../../sdb
lrwxrwxrwx 1 root root 10 Dec 24 03:14 /dev/disk/by-id/ata-WDC_WD20EARS-00S8B1_WD-WCAXXXXXXXX-part1 -> ../../sdb1

Hth!

bsox

Schwarze Socke
Avatar
Registered: Jun 2009
Location: Dschibuti
Posts: 1034
Es muss einfach mal gesagt werden, dass Colossus' posts immer wieder eine Freude sind zu lesen. Eine eigene Rubrik von ihm a la Karstiefels iyff wär ein Hammer auf oc.at!

issue

Rock and Stone, brother!
Avatar
Registered: Feb 2003
Location: Linz
Posts: 3599
Zitat von bsox
Es muss einfach mal gesagt werden, dass Colossus' posts immer wieder eine Freude sind zu lesen. Eine eigene Rubrik von ihm a la Karstiefels iyff wär ein Hammer auf oc.at!
Full ack!

Gabs mal, "Neues vom Pinguin" afair

COLOSSUS

Administrator
Frickler
Avatar
Registered: Dec 2000
Location: ~
Posts: 11890
Danke fuer das Lob/die Blumen :) Ja, IsSuE erinnert sich richtig, das gab es mal. Doch ist die gewissenhafte Recherche und die regelmaeszige Veroeffentlichung so einer Artikelreihe irrsinnig viel Aufwand, und seit ich Vollzeit arbeite, geht sich das leider nicht mehr aus.

t3mp

I Love Gasoline
Avatar
Registered: Mar 2003
Location: upstairs
Posts: 6252
Zitat von COLOSSUS
Doch ist die gewissenhafte Recherche und die regelmaeszige Veroeffentlichung so einer Artikelreihe irrsinnig viel Aufwand
Ich glaube ja, phoronix hat mehrere Bots laufen die diverse Git logs und lkml zu Artikeln verwurschten. ;)

COLOSSUS

Administrator
Frickler
Avatar
Registered: Dec 2000
Location: ~
Posts: 11890
Die durchschnittliche Qualitaet der Artikel, die dort veroeffentlicht werden, laesst das in meinen Augen durchaus plausibel scheinen. Meine "phoronix Premium"-Mitgliedschaft hab ich jedenfalls schon vor vielen Monden wieder gekuendigt, bezahlen tu ich nur noch fuer LWN.

fogerl

Little Overclocker
Registered: Jan 2005
Location: Wien
Posts: 98
Vielen Dank für die Tipps!

Das ich die Festplatten über /dev/disk/by-id/ anspreche sollte die Wahrscheinlichkeit auf die falschen Festplatten zuzugreifen tatsächlich minimieren. Für das letzte bisschen Rest-Unsicherheit würde ich aber trotzdem gerne die nicht-benötigten Festplatten gänzlich aus /dev verschwinden zu lassen. Könntet ihr dazu was sagen?


ad Umgebungsvariablen:
Da ich manchmal wohl in der Konsole, manchmal in der GUI in verschiedenen Terminalfenstern arbeite kann ich mich wohl nicht darauf verlassen, dass die Umgebungsvariablen so gesetzt sind wie ich sie brauche.

Ich hab mir also ein Shellskript geschrieben, dass dies erledigt.

Das sollte eh auch funktionieren, oder?

(Ich frage etwas blöd, da ich aktuell keinen Zugriff auf eine Linuxkiste habe auf der ich das austesten könnte.)

COLOSSUS

Administrator
Frickler
Avatar
Registered: Dec 2000
Location: ~
Posts: 11890
Die Device Nodes unter /dev/sd* sind nur eine Art Einstiegsluke fuer den Userspace in Blockgeraete, die ja der Kernel verwaltet. Der (Datei-)Name dieser Device Nodes ist dabei unerheblich, welcher Device Node zu welchem Geraet fuehrt, wird durch andere Metadaten dieser Inodes bestimmt: dem File Type (muss fuer ein Blockgeraet wie Festplatten, USB Mass Storage und dgl. "Block Special" sein), sowie der Major und Minor Number. Wie diese Metadaten fuer /dev/sda (beispielhaft) aussehen, kann man sich einfach ansehen:

Code:
root@htpc[ssh]:~ # ls -l /dev/sda
brw-rw---T 1 root disk 8, 0 Dec 25 00:15 /dev/sda

Der erste Buchstabe der Ausgabe von `ls`, das "b", charakterisiert ein "Block Special"-Device. Nach den Permissions ("rw-rw---T"), dem Link Count ("1"), dem Owner und Group-Owner ("root" und "disk") kommt im Falle eines Block- oder Character-Devices die Major Number, hier "8" - per Konvention ein SCSI-Subsystem-Blockdevice, und danach die Minor Number, die idR. einfach in aufsteigender Reihenfolge, hier per Partition auf der Disk, vergeben werden.

Die Metadaten eines Inodes kann man sich auch sehr uebersichtlich mit einem Programm namens `stat` ansehen (der syscall, der diese Informationen unter der Haube eruiert, heiszt genauso):

Code:
root@htpc[ssh]:~ # stat /dev/sda
  File: `/dev/sda'
  Size: 0               Blocks: 0          IO Block: 4096   block special file
Device: 5h/5d   Inode: 1319        Links: 1     Device type: 8,0
Access: (1660/brw-rw---T)  Uid: (    0/    root)   Gid: (    6/    disk)
Access: 2013-12-25 00:15:47.570406138 +0100
Modify: 2013-12-25 00:15:47.558406079 +0100
Change: 2013-12-25 00:15:47.558406079 +0100
 Birth: -

Device Nodes werden heute weitestgehend automatisch ueber udev verwaltet, in grauer Vorzeit musste man das aber noch manuell erledigen. Das Programm, mit dem man dies tat (und mit dem man heute noch z. B. Systeme mit kaputtem udev reparieren kann), ist `mknod`. Moechte ich z. B. einen Device Node namens "/dev/myfirstharddisk" erstellen, die den Kernel auf das selbe Device wie "/dev/sda" zeigen laesst, so mache ich das wie folgt:

Code:
root@htpc[ssh]:~ # mknod /dev/myfirsthharddisk b 8 0
root@htpc[ssh]:~ # ls -l /dev/myfirsthharddisk
brw-r--r-- 1 root root 8, 0 Dec 25 13:21 /dev/myfirsthharddisk

Obwohl dieser Device Node auf das selbe Device wie "/dev/sda" zeigt, ist er weder ein Soft- noch ein Hardlink auf diesen anderen Node. Zeigen kann man das z. B. durch eine Auflistung der Partitionen der Devices:

Code:
root@htpc[ssh]:~ # fdisk -l /dev/{sda,myfirsthharddisk} |grep ^/dev/
/dev/sda1   *        2048      499711      248832   83  Linux
/dev/sda2          501758    47374335    23436289    5  Extended
/dev/sda5          501760    23937023    11717632   83  Linux
/dev/sda6        23939072    47374335    11717632   83  Linux
/dev/myfirsthharddisk1   *        2048      499711      248832   83  Linux
/dev/myfirsthharddisk2          501758    47374335    23436289    5  Extended
/dev/myfirsthharddisk5          501760    23937023    11717632   83  Linux
/dev/myfirsthharddisk6        23939072    47374335    11717632   83  Linux

Device Nodes wie "/dev/myfirsthharddisk5" existieren dabei noch nicht (das ist in `fdisk` so hartkodiert); wuerde man ein "/dev/sda5" aequivalentes Device anlegen wollen, so wuerde man sich die Major und Minor Numbers dieses Inodes ansehen, und dann einen angepassten Aufruf von `mknod` folgen lassen:

Code:
root@htpc[ssh]:~ # ls -l /dev/sda5
brw-rw---T 1 root disk 8, 5 Dec 25 00:15 /dev/sda5
root@htpc[ssh]:~ # mknod /dev/myfirsthharddisk5 b 8 5
# Der Beweis, dass dies die selben Partitionen sind:
root@htpc[ssh]:~ # file -s /dev/myfirsthharddisk5 /dev/sda5
/dev/myfirsthharddisk5: Linux rev 1.0 ext4 filesystem data, UUID=17864597-e24f-4d97-9aa9-210fdc6f797d, volume name "ROOT" (needs journal recovery) (extents) (large files) (huge files)
/dev/sda5:              sticky Linux rev 1.0 ext4 filesystem data, UUID=17864597-e24f-4d97-9aa9-210fdc6f797d, volume name "ROOT" (needs journal recovery) (extents) (large files) (huge files)

(Whoops, vielleicht wieder mal Zeit fuer ein fsck hier... ;))


Warum ich das alles erklaere? Du ahnst es vermutlich schon: Wenn du /dev/sda loeschen willst, um dich vor Tippfehlern zu bewahren, einfach vorher die Major und Minor Numbers notieren, das "/dev/sda" Inode loeschen, und nach getaner Arbeit wieder mit `mknod` erstellen. Ist keine Hexerei, und so lange kein Programm versucht, "/dev/sda" direkt zu oeffnen, wird es keine Probleme im Betrieb geben - gemountete Dateisysteme z. B. bleiben davon voellig unberuehrt.

Ein bisschen geschwindelt habe ich vorhin uebrigens, denn "/dev/sda" ist nicht nur irgendein Name dieses Devices, es ist der sogenannte "Kernel Name" - der Name, den das Device vom Kernel per Policy/Konvention bekommt, wenn es im System erkannt wird, und bevor udev dann uebernimmt und seinen Regelsatz abarbeitet. Mann kann zwar in Folge auch ein anderes Blockgeraet "/dev/sda" nennen, nachdem man den Eintrag fuer das urspruenglich so benannte in /dev/ geloescht hat, sollte es aber nicht tun. Ist man jedenfalls mal in der misslichen Lage, die Mjaor und Minor Number des Devices Nodes, den man vorsorglich entfernt hat, vergessen zu haben, hilft sysfs weiter, das Major und Minor-Tupel fuer die Kernel Names vorhaelt:

Code:
root@htpc[ssh]:~ # cat /sys/block/sda/dev
8:0


Wenn du so oft mit Blockgeraeten arbeitest lohnt es sich aber ziemlich sicher, einen eigenen Satz udev-Regeln zu schreiben, die dir bestimmte Geraete mit fuer deinen User passenden Permissions (wenn du nicht als root arbeitest, kannst du auch nicht aus versehen einen wichtigen Datentraeger mit falschen Daten befuellen) in /dev/ einrichten.


Deine Frage mit dem Shellscript in Bezug auf Umgebungsvariablen verstehe ich leider nicht.

fogerl

Little Overclocker
Registered: Jan 2005
Location: Wien
Posts: 98
Servus,

danke für den ausführlichen Post! Ob ich es hinbekomme einen gelöschten Device Node wieder dann wieder zu erstellen werde ich dann testen müssen. Ich hoffe ich bekomme es hin -- ich würde wirklich gerne von der Möglichkeit gebrauch machen Partitionen -- um sie zu schützen -- gänzlich aus /dev/ verschwinden zu lassen. Das setzt jedoch vorraus, dass ich sie anschließend auch wieder zurück bekomme.


Meine Frage bzgl. Umgebungsvariablen war vlt. unvollständig gestellt, gemeint war: Kann ich das Setzen von Umgebungsvariablen genau so über ein Shellskript automatisieren wie alles andere auch?

Aber ich vermute fast, dass die Frage unnötig ist. Ich denke, die Antwort ist ja. :)

COLOSSUS

Administrator
Frickler
Avatar
Registered: Dec 2000
Location: ~
Posts: 11890
Zu deiner Shellscript-Frage: ja klar, ein Shellscript kann jedes (na gut, ein paar Ausnahmen gibt es, aber die werden dich in diesem Fall nicht behindern) Statement enthalten, das du auch interaktiv abarbeiten lassen kannst. Allerdings startet deine Shell beim Ausfuehren eines Shellscripts eine Subshell - also einen Kindprozess, der durch den Interpreter des Shellscripts (meist /bin/sh oder /bin/bash) bestimmt wird. Fuer diesen Kindprozess gilt das weiter oben gesagte: du kannst das Environment des Parent Process - also der Shell, die dein Shellscripts als Kindprozess ausfuehrt - aus dem Kindprozess heraus nicht beeinflussen. Wenn du in einem Shellscript also Umgebungsvariablen setzt und dieses ausfuehrst, hast du nichts von diesen Env-Variablen in deiner interaktiven Shell.

Abhilfe schafft man sich mit dem shell-Builtin `source` (das man auch ueber seine Kurzform, `.`, aufrufen kann), das ein Shellscript innerhalb eines Shell-Prozesses ausfuehrt, ohne einen Kindprozess zu forken. Hier eine Illustration:

Code:
colo@tpx200:/tmp $ ls -l env_demo 
-rwxr-xr-x 1 colo colo 53 Dec 29 17:08 env_demo
colo@tpx200:/tmp $ cat env_demo
#!/bin/sh
export my_first_envvar="1"
export my_second_envvar="two"
colo@tpx200:/tmp $ ./env_demo 
colo@tpx200:/tmp $ echo "${my_first_envvar}" "${my_second_envvar}"
 
colo@tpx200:/tmp $ source ./env_demo
colo@tpx200:/tmp $ echo "${my_first_envvar}" "${my_second_envvar}"
1 two

fogerl

Little Overclocker
Registered: Jan 2005
Location: Wien
Posts: 98
Perfekt! Dann baue ich mir einfach ein Skript, mit dem ich mir dann die Variablen setze die ich dann für dd als Argumente (ist das das richtige Wort?) verwende.

Zitat von IsSuE
Keine Antwort auf deine Frage, aber: setz fuer deine zu bearbeitenden Devices Umgebungsvariablen und verwende die.
Also zb BACKUPHDD=/dev/sdX und operiere dann mit dd auf $BACKUPHDD

COLOSSUS

Administrator
Frickler
Avatar
Registered: Dec 2000
Location: ~
Posts: 11890
Ja, genau. Kannst ja das Ergebnis nochmal hier posten und es "absegnen" lassen, um ganz sicher zu gehen ;)
Kontakt | Unser Forum | Über overclockers.at | Impressum | Datenschutz