Warum wurde `cp` entwickelt, um vorhandene Dateien stillschweigend zu überschreiben? [geschlossen]

30

Ich habe cpmit folgenden Befehlen getestet :

$ ls
first.html   second.html  third.html

$ cat first.html
first

$ cat second.html
second

$ cat third.html
third

Dann kopiere ich first.htmlnach second.html:

$ cp first.html second.html

$ cat second.html
first

Die Datei second.htmlwird unbemerkt ohne Fehler überschrieben. Wenn ich es jedoch in einer Desktop-Benutzeroberfläche durch Ziehen und Ablegen einer Datei mit demselben Namen mache, wird sie first1.htmlautomatisch mit einem Suffix versehen . Dadurch wird verhindert, dass eine vorhandene Datei versehentlich überschrieben wird.

Warum folgt cpman diesem Muster nicht, anstatt Dateien still zu überschreiben?

Algebra
quelle
10
Ich stelle mir vor, dass nur die Coreutils-Designer die Frage wirklich beantworten können, aber im Moment funktioniert es so. In der Regel werden die Apps unter der Annahme erstellt, dass der Benutzer wirklich das tut, was er tut, und um zusätzliche Eingabeaufforderungen zu minimieren. Wenn Sie das Verhalten ändern möchten, geben Sie als Alias ​​'cp' 'cp -i' oder 'cp -n' ein.
Kevinux
8
@kevlinux Die coreutils devs implementieren gerade den POSIX-Standard.
Kusalananda
17
Denn als es entworfen wurde, wollten die Leute so knapp wie möglich bei dem sein, was sie tun (also nicht kopieren) und wussten, was sie taten, und wenn sie Fehler machten, versuchten sie nicht, Werkzeuge zu beschuldigen. Es waren damals ganz andere Leute, die Computer machten. Es ist wie zu fragen, warum ein Skalpell für einen Herzchirurgen auch in Hände schneiden kann.
PlasmaHH
4
Unix wurde von und für Computer-Experten entwickelt, mit der Annahme, dass der Benutzer wusste, was er tat. Das Betriebssystem würde nach Möglichkeit genau das tun, was der Benutzer anordnete - ohne die Hand des Benutzers zu halten und ohne endlose Bestätigungen anzufordern. Wenn eine Operation etwas überschrieb, wurde angenommen, dass dies der Wunsch des Benutzers war. Denken Sie auch daran, dass dies Anfang der 1970er Jahre war - vor MS DOS, Windows und Heimcomputern -, die Hand des Benutzers bei jedem Schritt des Weges zu führen und zu halten, war noch nicht üblich. Außerdem wäre es bei teletype-bearbeiteten Terminals zu umständlich, immer nach Bestätigungen zu fragen.
Baard Kopperud
10
Nicht alias cpzu cp -ioder ähnlich , weil Sie ein Sicherheitsnetz mit gewöhnungs werden, so dass Systeme , bei denen es nicht möglich ist ( die meisten von ihnen), die viel riskanter. Es ist besser, sich routinemäßig cp -iusw. beizubringen, wenn Sie dies bevorzugen.
Reid

Antworten:

52

Das Standard-Überschreibverhalten von cpist in POSIX festgelegt.

  1. Wenn source_file vom Typ regular file ist, müssen die folgenden Schritte ausgeführt werden:

    3.a. Das Verhalten ist nicht spezifiziert, wenn dest_file existiert und von einem vorherigen Schritt geschrieben wurde. Andernfalls, wenn dest_file vorhanden ist, müssen die folgenden Schritte ausgeführt werden:

    3.ai Wenn die Option -i aktiviert ist, schreibt das Dienstprogramm cp eine Eingabeaufforderung für den Standardfehler und liest eine Zeile von der Standardeingabe. Wenn die Antwort nicht positiv ist, wird cp mit source_file nichts mehr tun und mit den verbleibenden Dateien fortfahren.

    3.a.ii. Ein Dateideskriptor für dest_file muss erhalten werden, indem Aktionen ausgeführt werden, die der Funktion open () entsprechen, die im Volume System Interfaces von POSIX.1-2017 definiert ist und mit dest_file als Pfadargument und dem bitweisen ODER von O_WRONLY und O_TRUNC als aufgerufen wird oflag argument.

    3.a.iii. Wenn der Versuch, einen Dateideskriptor abzurufen, fehlschlägt und die Option -f aktiviert ist, versucht cp, die Datei zu entfernen, indem Aktionen ausgeführt werden, die der Funktion unlink () entsprechen, die im Volume System Interfaces von POSIX.1-2017 definiert ist und mit dest_file aufgerufen wird als Pfadargument. Wenn dieser Versuch erfolgreich ist, fährt cp mit Schritt 3b fort.

Als die POSIX-Spezifikation geschrieben wurde, gab es bereits eine große Anzahl von Skripten mit einer integrierten Annahme für das Standardüberschreibverhalten. Viele dieser Skripte wurden entwickelt, um ohne direkte Benutzerpräsenz ausgeführt zu werden, z. B. als Cron-Jobs oder andere Hintergrundaufgaben. Eine Änderung des Verhaltens hätte sie kaputt gemacht. Sie alle zu überprüfen und zu ändern, um eine Option hinzuzufügen, mit der das Überschreiben erzwungen werden kann, wo immer dies erforderlich war, wurde wahrscheinlich als große Aufgabe mit minimalen Vorteilen angesehen.

Außerdem wurde die Unix-Befehlszeile immer so gestaltet, dass erfahrene Benutzer effizient arbeiten können, auch auf Kosten einer schwierigen Lernkurve für Anfänger. Wenn der Benutzer einen Befehl eingibt, muss der Computer davon ausgehen, dass der Benutzer ihn wirklich meint, ohne dass er etwas anderes erraten muss. Es liegt in der Verantwortung des Benutzers, mit potenziell zerstörerischen Befehlen vorsichtig umzugehen.

Als das ursprüngliche Unix entwickelt wurde, hatten die Systeme im Vergleich zu modernen Computern so wenig Speicher und Massenspeicher, dass das Überschreiben von Warnungen und Eingabeaufforderungen wahrscheinlich als verschwenderischer und unnötiger Luxus angesehen wurde.

Als der POSIX-Standard geschrieben wurde, war der Präzedenzfall fest verankert, und die Verfasser des Standards waren sich der Tugenden bewusst, die Abwärtskompatibilität nicht zu brechen .

Außerdem kann, wie andere beschrieben haben, jeder Benutzer diese Funktionen für sich selbst hinzufügen / aktivieren, indem er Shell-Aliase verwendet oder sogar einen Ersetzungsbefehl erstellt cpund diesen modifiziert $PATH, um die Ersetzung vor dem Standardsystembefehl zu finden, und das Sicherheitsnetz auf diese Weise abrufen, wenn erwünscht.

Aber wenn Sie dies tun, werden Sie feststellen, dass Sie eine Gefahr für sich selbst schaffen. Wenn sich der cpBefehl bei interaktiver Verwendung auf eine andere Art und Weise verhält, als wenn er von einem Skript aus aufgerufen wird, können Sie sich möglicherweise nicht daran erinnern, dass der Unterschied besteht. Auf einem anderen System könnten Sie leichtsinnig werden, weil Sie sich an die Warnungen und Eingabeaufforderungen auf Ihrem eigenen System gewöhnt haben.

Wenn das Verhalten in Skripten weiterhin dem POSIX-Standard entspricht, werden Sie sich wahrscheinlich an die Eingabeaufforderungen im interaktiven Gebrauch gewöhnen. Schreiben Sie dann ein Skript, das Massenkopien ausführt, und stellen Sie dann fest, dass Sie versehentlich etwas überschrieben haben.

Was kann der Befehl tun, wenn Sie die Eingabeaufforderung auch in Skripten erzwingen, wenn er in einem Kontext ausgeführt wird, in dem sich kein Benutzer befindet, z. B. Hintergrundprozesse oder Cron-Jobs? Wird das Skript hängen bleiben, abgebrochen oder überschrieben?

Hängen oder Abbrechen bedeutet, dass eine Aufgabe, die automatisch erledigt werden sollte, nicht erledigt wird. Das Nicht-Überschreiben kann manchmal auch selbst zu Problemen führen: Beispielsweise werden alte Daten möglicherweise zweimal von einem anderen System verarbeitet, anstatt durch aktuelle Daten ersetzt zu werden.

Ein großer Teil der Leistungsfähigkeit der Befehlszeile beruht auf der Tatsache, dass Sie , sobald Sie wissen, wie etwas in der Befehlszeile zu tun ist, implizit auch wissen, wie dies durch Skripterstellung automatisch geschehen kann . Dies gilt jedoch nur, wenn die Befehle, die Sie interaktiv verwenden, auch in einem Skript-Kontext genauso funktionieren. Jegliche signifikanten Unterschiede im Verhalten zwischen der interaktiven Verwendung und der Verwendung von Skripten führen zu einer Art kognitiver Dissonanz, die für einen Power-User ärgerlich ist.

telcoM
quelle
54
"Warum funktioniert das so?" "Weil es der Standard sagt." "Warum sagt der Standard das?" "Weil es so schon geklappt hat."
Baptiste Candellier
16
Der letzte Absatz ist der wahre Grund. Bestätigungsdialoge und " Wollen Sie das wirklich tun? "
Eingabeaufforderungen
@BaptisteCandellier - Einverstanden. Es ist wie der ultimative Grund da draußen, aber verheerend, gerade außerhalb der Reichweite dieser Antwort.
TED
2
Der letzte Absatz ist der Grund, warum er rm -rfso effektiv ist, auch wenn Sie ihn nicht in Ihrem Home-Verzeichnis ausführen wollten ...
Max Vernon
2
@TED Lustig , wie niemand jemals erwähnt , wie die unlink (2) SYSCALL auch ‚versagt‘ zu fragen : „Mutter, darf ich?“ Zur Bestätigung , wenn diese sempiternal Diskussionen wieder hinten ihre zierlichen Köpfe. :)
tchrist
20

cpkommt von Anfang an von Unix. Es war dort, lange bevor der Posix-Standard geschrieben wurde. In der Tat: Posix hat gerade das bestehende Verhalten cpin dieser Hinsicht formalisiert .

Wir reden über Epoche (1970-01-01), als Männer echte Männer waren, Frauen echte Frauen und pelzige kleine Kreaturen ... (ich schweife ab). In jenen Tagen vergrößerte das Hinzufügen von zusätzlichem Code ein Programm. Das war damals ein Problem, denn der erste Computer, auf dem Unix lief, war ein PDP-7 (aufrüstbar auf 144 KB RAM!). Die Dinge waren also klein, effizient und ohne Sicherheitsmerkmale.

In jenen Tagen musste man also wissen, was man tat, weil der Computer einfach nicht in der Lage war, Sie daran zu hindern, etwas zu tun, was Sie später bereuten.

(Es gibt einen schönen Cartoon von Zevar; suchen Sie nach "zevar cerveaux assiste par ordinateur", um die Entwicklung des Computers zu ermitteln. Oder versuchen Sie es unter http://perinet.blogspirit.com/archive/2012/02/12/zevar-et- cointe.html solange es existiert)

Für diejenigen, die wirklich interessiert sind (ich habe einige Spekulationen in den Kommentaren gesehen): Das Original cpauf dem ersten Unix enthielt ungefähr zwei Seiten Assembler-Code (C kam später). Der relevante Teil war:

sys open; name1: 0; 0   " Open the input file
spa
  jmp error         " File open error
lac o17         " Why load 15 (017) into AC?
sys creat; name2: 0     " Create the output file
spa
  jmp error         " File create error

(Also ein harter sys creat)

Und wenn wir schon dabei sind: Version 2 von Unix verwendet (Code-Sniplet)

mode = buf[2] & 037;
if((fnew = creat(argv[2],mode)) < 0){
    stat(argv[2], buf);

das ist auch ein hartes creatohne tests oder absicherungen. Beachten Sie, dass der C-Code für V2 Unix cpweniger als 55 Zeilen enthält!

Ljm Dullaart
quelle
5
Fast richtig, außer es ist " kleines Fell " (Kreaturen von Alpha Centauri) und nicht " kleines Fell "!
TripeHound
1
@TED: Es ist durchaus möglich , frühe Versionen von cpnur opened das Ziel mit O_CREAT | O_TRUNCund führte eine read/ writeSchleife; Sicher, mit modern cpgibt es so viele Knöpfe, dass es im Grunde genommen statvorher versuchen muss, das Ziel zu erreichen, und es könnte leicht zuerst auf Existenz überprüft werden (und tut dies mit cp -i/ cp -n), aber wenn die Erwartungen von originalen, nackten cpWerkzeugen erfüllt würden , würde sich dieses Verhalten ändern würde bestehende Skripte unnötig brechen. Es ist nicht so, als aliaskönnten moderne Shells nicht einfach cp -iden Standard für die interaktive Verwendung festlegen.
ShadowRanger
@ShadowRanger - Hmmm. Sie haben völlig Recht, dass ich wirklich keine Ahnung habe, ob es einfach oder schwierig war. Kommentar gelöscht.
TED
1
@ShadowRanger Ja, aber das ist nur eine harte Lektion, bis es auf einem Produktionssystem läuft ...
chrylis -on strike-
1
@sourcejedi: Spaß! Ändert nichts an meiner Grundtheorie (dass es einfacher war, nur bedingungslos mit Trunkierung zu öffnen und creatzufällig mit open+ gleichzusetzen O_CREAT | O_TRUNC), aber das Fehlen von O_EXCLdoes erklärt, warum es nicht so einfach gewesen wäre, mit vorhandenen Dateien umzugehen; so wäre von Natur aus rassig zu tun versuchen (Sie würden im Grunde müssen open/ statExistenz zu überprüfen, dann verwenden creat, aber auf große verteilten Systemen, ist es immer möglich , durch die Zeit , die du bekommen creat, jemand anderes die Datei gemacht und jetzt haben Sie geblasen es sowieso weg). Kann auch nur bedingungslos überschreiben.
ShadowRanger
19

Weil diese Befehle auch in Skripten verwendet werden sollen, die möglicherweise ohne menschliche Aufsicht ablaufen, und weil es in vielen Fällen tatsächlich Fälle gibt, in denen Sie das Ziel überschreiben möchten (die Philosophie der Linux-Shells ist, dass der Mensch weiß, was Sie macht)

Es gibt noch ein paar Sicherheitsvorkehrungen:

  • GNU cphat eine -n| --no-clobberMöglichkeit
  • Wenn Sie mehrere Dateien in eine einzige kopieren, cpwird beanstandet, dass die letzte kein Verzeichnis ist.
Magnet
quelle
Dies gilt nur für eine herstellerspezifische Implementierung, und die Frage betraf nicht diese herstellerspezifische Implementierung.
Schily
10

Ist es "eine Sache auf einmal tun"?

Dieser Kommentar klingt wie eine Frage nach einem allgemeinen Konstruktionsprinzip. Oft sind Fragen dazu sehr subjektiv, und wir können keine richtige Antwort schreiben. Seien Sie gewarnt, dass wir in diesem Fall Fragen schließen können.

Manchmal haben wir eine Erklärung für die ursprüngliche Designauswahl, weil die Entwickler darüber geschrieben haben. Aber ich habe keine so schöne Antwort auf diese Frage.

Warum cpist das so?

Das Problem ist, dass Unix über 40 Jahre alt ist.

Wenn Sie jetzt ein neues System erstellen, treffen Sie möglicherweise andere Entwurfsentscheidungen. Aber das Ändern von Unix würde bestehende Skripte beschädigen, wie in anderen Antworten erwähnt.

Warum wurde cp entwickelt, um vorhandene Dateien stillschweigend zu überschreiben?

Die kurze Antwort lautet "Ich weiß nicht" :-).

Verstehe, dass dies cpnur ein Problem ist. Ich denke, dass keines der ursprünglichen Befehlsprogramme gegen das Überschreiben oder Löschen von Dateien geschützt ist. Die Shell hat ein ähnliches Problem beim Umleiten der Ausgabe:

$ cat first.html > second.html

Dieser Befehl überschreibt auch unbemerkt second.html.

Ich bin gespannt, wie all diese Programme umgestaltet werden könnten. Dies erfordert möglicherweise zusätzliche Komplexität.

Ich denke, das ist ein Teil der Erklärung: Frühes Unix betonte einfache Implementierungen . Eine ausführlichere Erklärung finden Sie unter "Schlechter ist besser" am Ende dieser Antwort.

Sie können es ändern, > second.htmlsodass es mit einem Fehler beendet wird, falls es second.htmlbereits vorhanden ist. Aber wie bereits erwähnt, manchmal der Benutzer nicht will , eine vorhandene Datei ersetzen. Zum Beispiel kann sie ein komplexes Kommando aufbauen und es mehrmals versuchen, bis es das tut, was sie will.

Der Benutzer kann rm second.htmlzuerst ausgeführt werden, wenn dies erforderlich ist. Dies könnte ein guter Kompromiss sein! Es hat einige mögliche eigene Nachteile.

  1. Der Benutzer muss den Dateinamen zweimal eingeben.
  2. Die Leute bekommen auch viel Ärger mit rm. Deshalb möchte ich auch rmsicherer machen . Aber wie? Wenn wir rmjeden Dateinamen anzeigen lassen und den Benutzer zur Bestätigung auffordern, muss er nun drei Befehlszeilen anstatt einer schreiben . Wenn sie dies zu oft tun muss, wird sie es sich zur Gewohnheit machen und "y" eingeben, um es zu bestätigen, ohne nachzudenken. Es könnte also sehr nervig und trotzdem gefährlich sein.

Auf einem modernen System empfehle ich , den trashBefehl zu installieren und stattdessen zu verwenden, rmwo dies möglich ist. Die Einführung von Trash Storage war eine großartige Idee, z. B. für einen grafischen Einzelbenutzer-PC .

Ich denke, es ist auch wichtig, die Einschränkungen der ursprünglichen Unix-Hardware zu kennen - begrenzter RAM- und Festplattenspeicher, Ausgabe auf langsamen Druckern sowie System- und Entwicklungssoftware.

Beachten Sie, dass das ursprüngliche Unix keine Tab-Vervollständigung hatte , um schnell einen Dateinamen für einen rmBefehl einzugeben . (Außerdem verfügt die ursprüngliche Bourne-Shell nicht über einen Befehlsverlauf, z. B. wenn Sie die Aufwärtspfeiltaste verwenden bash).

Bei der Druckerausgabe würden Sie den zeilenbasierten Editor verwenden ed. Dies ist schwerer zu lernen als ein visueller Texteditor. Sie müssen einige aktuelle Zeilen drucken, entscheiden, wie Sie sie ändern möchten, und einen Bearbeitungsbefehl eingeben.

Using > second.htmlähnelt der Verwendung eines Befehls in einem Zeileneditor. Die Auswirkung hängt vom aktuellen Status ab. (Wenn second.htmlbereits vorhanden, wird der Inhalt verworfen.) Wenn der Benutzer sich über den aktuellen Status nicht sicher ist, wird erwartet, dass er ausgeführt wird lsoder ls second.htmlzuerst.

"Einfache Implementierung" als Gestaltungsprinzip

Es gibt eine populäre Interpretation von Unix-Design, die beginnt:

Das Design muss sowohl in der Implementierung als auch in der Benutzeroberfläche einfach sein. Es ist wichtiger, dass die Implementierung einfach ist als die Schnittstelle. Einfachheit ist die wichtigste Überlegung in einem Design.

...

Gabriel argumentierte, dass "Schlimmer ist besser" erfolgreichere Software hervorbringe als der MIT-Ansatz: Solange das anfängliche Programm im Grunde genommen gut ist, wird es viel weniger Zeit und Mühe kosten, es anfangs zu implementieren, und es wird einfacher sein, sich an neue Situationen anzupassen. So wird beispielsweise die Portierung von Software auf neue Maschinen wesentlich einfacher. Daher wird sich seine Verwendung schnell verbreiten, lange bevor ein [besseres] Programm entwickelt und bereitgestellt werden kann (First-Mover-Vorteil).

https://en.wikipedia.org/wiki/Worse_is_better

sourcejedi
quelle
Warum wird das Ziel mit cpeinem "Problem" überschrieben ? Wenn es interaktiv um Erlaubnis bittet oder fehlschlägt, kann dies ein ebenso großes "Problem" sein.
Kusalananda
wow Danke. Ergänzen Sie die Richtlinie: 1) Schreiben Sie Programme, die eines können und es gut machen. 2) Vertrauen Sie dem Programmierer.
Algebra
2
@ Kusalananda Datenverlust ist ein Problem. Ich persönlich bin daran interessiert, das Risiko zu verringern, dass ich Daten verliere. Hierfür gibt es verschiedene Ansätze. Zu sagen, dass es sich um ein Problem handelt, bedeutet nicht, dass die Alternativen auch keine Probleme haben.
sourcejedi
1
@riderdragon In der C-Sprache geschriebene Programme können oft auf sehr überraschende Weise fehlschlagen, da C dem Programmierer vertraut. Aber Programmierer sind einfach nicht so zuverlässig. Wir müssen sehr fortschrittliche Tools wie Valgrind schreiben , die benötigt werden, um die Fehler zu finden, die Programmierer machen. Ich denke, es ist wichtig, Programmiersprachen wie Rust oder Python oder C # zu haben, die versuchen, "Speichersicherheit" zu erzwingen, ohne dem Programmierer zu vertrauen. (Die C-Sprache wurde von einem der Autoren von UNIX erstellt, um UNIX in einer portablen Sprache zu schreiben.)
Sourcejedi
1
Noch besser ist cat first.html second.html > first.htmles, first.htmlwenn second.htmlnur der Inhalt von überschrieben wird . Der ursprüngliche Inhalt geht für immer verloren.
doneal24
9

Das Design von "cp" geht auf das ursprüngliche Design von Unix zurück. Es gab tatsächlich eine kohärente Philosophie hinter dem Unix-Design, die etwas weniger war, als halb im Scherz Worse-is-Better * genannt wurde .

Die Grundidee ist, dass die Vereinfachung des Codes eine wichtigere Überlegung im Hinblick auf das Design ist, als eine perfekte Benutzeroberfläche zu haben oder "das Richtige zu tun".

  • Einfachheit - Das Design muss sowohl in der Implementierung als auch in der Benutzeroberfläche einfach sein. Es ist wichtiger, dass die Implementierung einfach ist als die Schnittstelle . Einfachheit ist die wichtigste Überlegung in einem Design.

  • Korrektheit - Das Design muss in allen beobachtbaren Aspekten korrekt sein. Es ist etwas besser, einfach als richtig zu sein.

  • Konsistenz - Das Design darf nicht zu inkonsistent sein. In einigen Fällen kann die Konsistenz der Einfachheit halber geopfert werden, aber Es ist jedoch besser, diejenigen Teile des Entwurfs zu löschen, die mit weniger häufigen Umständen zu tun haben, als entweder Komplexität der Implementierung oder Inkonsistenz einzuführen.

  • Vollständigkeit - Das Design muss so viele wichtige Situationen abdecken, wie es praktisch ist. Alle vernünftigerweise erwarteten Fälle sollten abgedeckt werden. Die Vollständigkeit kann zugunsten einer anderen Qualität geopfert werden. Tatsächlich muss die Vollständigkeit geopfert werden, wenn die Einfachheit der Implementierung gefährdet wird. Konsistenz kann geopfert werden, um Vollständigkeit zu erreichen, wenn die Einfachheit beibehalten wird; Besonders wertlos ist die Konsistenz der Schnittstelle.

( Hervorhebung von mir )

Denken Sie daran, dass dies 1970 war, der Anwendungsfall von "Ich möchte diese Datei kopieren Wenn man nur wenn sie noch nicht existiert" für jemanden, der eine Kopie durchführt, ein ziemlich seltener Anwendungsfall gewesen. Wenn Sie das möchten, können Sie dies durchaus vor der Kopie überprüfen, und das kann sogar per Skript erfolgen.

Der Autor des Aufsatzes hatte auch eine Theorie dazu, warum ein Betriebssystem mit diesem Entwurfsansatz dasjenige war, das sich gegen alle anderen damals gebauten Betriebssysteme durchgesetzt hat.

Ein weiterer Vorteil der Schlimmer-Ist-Besser-Philosophie besteht darin, dass der Programmierer auf ein gewisses Maß an Sicherheit, Bequemlichkeit und Aufwand angewiesen ist, um eine gute Leistung und einen geringen Ressourcenverbrauch zu erzielen. Programme, die mit dem New Jersey-Ansatz geschrieben wurden, funktionieren sowohl auf kleinen als auch auf großen Computern, und der Code ist portabel, da er auf einem Virus geschrieben ist.

Es ist wichtig zu bedenken, dass das ursprüngliche Virus grundsätzlich gut sein muss. In diesem Fall ist die Ausbreitung des Virus so lange gewährleistet, wie es tragbar ist. Sobald sich das Virus verbreitet hat, wird es unter Druck stehen, es zu verbessern, möglicherweise indem seine Funktionalität um mehr als 90% erhöht wird. Die Benutzer sind jedoch bereits darauf vorbereitet, schlechteres als das Richtige zu akzeptieren. Daher wird die schlechtere Software erstens akzeptiert, zweitens wird von den Benutzern erwartet, dass sie weniger erwarten, und drittens wird sie bis zu einem Punkt verbessert, der beinahe das Richtige ist.

* - oder was der Autor, aber sonst niemand, "The New Jersey Approach" nannte .

TED
quelle
1
Das ist die richtige Antwort.
Tchrist
+1, aber ich denke, es wäre hilfreich, ein konkretes Beispiel zu haben. Wenn Sie eine neue Version eines Programms installieren, das Sie bearbeitet und neu kompiliert (und möglicherweise getestet :-) haben, möchten Sie die alte Version des Programms absichtlich überschreiben. (Und wahrscheinlich ein ähnliches Verhalten von Ihrem Compiler wollen. So früh nur UNIX hat creat()vs open(). open()Konnte eine Datei erstellen , wenn es nicht existieren. Es dauert nur 0/1/2 für Lesen / Schreiben / beides. Es ist noch nicht nehmen O_CREAT, und es gibt keine O_EXCL).
Sourcejedi
@sourcejedi - Entschuldigung, aber als Softwareentwickler kann ich mir ehrlich gesagt kein anderes Szenario vorstellen als das, in dem ich eine Kopie machen würde. :-)
TED
@TED ​​Entschuldigung, ich meine, ich schlage dieses Beispiel als einen der nicht seltenen Fälle vor, in denen Sie definitiv ein Überschreiben wünschen, gegenüber dem Vergleich in der Frage, wo Sie es vielleicht nicht getan haben.
Sourcejedi
0

Der Hauptgrund ist, dass eine GUI per definitionem interaktiv ist, während eine binäre Oberfläche/bin/cp nur ein Programm ist, das von allen möglichen Stellen aus aufgerufen werden kann, zum Beispiel von Ihrer GUI aus ;-). Ich wette, dass auch heute die meisten Anrufe /bin/cpnicht von einem realen Terminal kommen, bei dem ein Benutzer einen Shell-Befehl eingibt, sondern von einem HTTP-Server, einem Mail-System oder einem NAS. Ein integrierter Schutz vor Benutzerfehlern ist in einer interaktiven Umgebung absolut sinnvoll. weniger in einer einfachen binären. Zum Beispiel wird Ihre GUI höchstwahrscheinlich /bin/cpden Hintergrund aufrufen , um die eigentlichen Vorgänge auszuführen, und müsste sich mit den Sicherheitsfragen zu Standard Out befassen, obwohl sie nur den Benutzer gefragt hat!

Beachten Sie, dass es vom ersten Tag an beinahe trivial war, auf /bin/cpWunsch einen sicheren Wrapper zu schreiben . Die * nix-Philosophie besteht darin, den Benutzern einfache Bausteine ​​zur Verfügung zu stellen /bin/cp.

Peter - Setzen Sie Monica wieder ein
quelle