Irgendwann muß man sich dem Thema ja mal stellen und so habe ich mal einen Versuch gestartet, einige der (FRITZ!Box-bezogenen) Skript-Dateien aus meinem GitHub-Repository mit der "bash"-Version aus Windows 10 zu testen.
Die erste Hürde, die mich dabei fast zur Aufgabe brachte, war das Mapping des "console beep" auf einen Windows-Sound. Da ich - aus reiner Faulheit - fast ausschließlich mit "TAB completion" arbeite, kriege ich praktisch ständig den mit der Ausgabe eines "beep" (also des "BEL"-Zeichens, 0x07) verbundenen Sound um die Ohren gehauen. Das ist in einem Terminal-Programm oder auf einer "richtigen" Linux-Konsole nicht weiter tragisch ... aber dank des Mappings dieser Ausgabe auf den Windows-Sound für "Critical Stop" (mein Windows "spricht" Englisch, bei deutschem Windows ist das sicherlich ähnlich benannt) und der beachtlichen Länge der dort schon im "Windows Default"-Schema hinterlegten Datei, singt mir diese Shell zunächst mal bei jedem zweimaligen Drücken auf TAB (das kennt sicherlich jeder nur zu gut, der häufig in einer Linux-Konsole arbeitet) für 2-3 Sekunden die Ohren voll mit zweimaliger Ausgabe dieses Sounds. Ich habe mir erst einmal einen Wolf gesucht (weil die Standard-Sounds da auch recht ähnlich sind bzw. sogar auf dieselben Files zugreifen), welches nun überhaupt der richtige Sound-Eintrag ist, den man hier ändern muß. Ich hoffe mal, daß es früher oder später dafür ein eigenes Mapping gibt (das ist Sache der Applikation) - bei wirklich "critical stops" unter Windows ist der eher kurze Piepton dann wieder etwas wenig, wenn man sich auf seine Ohren verläßt beim Scheduling der Aufmerksamkeit über mehrere Rechner.
Was kann denn diese Shell nun?
- Sie hat - im heute aktuellen Paket - selbst die Version:
Code:
peh@BRAGI:~$ bash --version
GNU bash, Version 4.3.11(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
Lizenz GPLv3+: GNU GPL Version 3 oder jünger <http://gnu.org/licenses/gpl.html>
This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
- Sie kann problemlos per "/dev/tcp" bzw. per "/dev/udp" auf Netzwerk-Ressourcen zugreifen.
Code:
peh@BRAGI:~$ exec 3<>/dev/tcp/fritz.box/80;printf "GET / HTTP/1.0\r\n\r\n" >&3;cat <&3;exec 3>&-
HTTP/1.0 200 OK
Cache-Control: no-cache
Connection: close
Content-type: text/html; charset=utf-8
Date: Wed, 22 Mar 2017 16:02:49 GMT
Expires: -1
Pragma: no-cache
<!DOCTYPE html>
<html lang="de">
<head>
<meta http-equiv=content-type content="text/html; charset=utf-8" />
<meta http-equiv="Cache-Control" content="private, no-transform" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="format-detection" content="telephone=no" />
<meta http-equiv="x-rim-auto-match" content="none" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes, minimal-ui" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta http-equiv="cleartype" content="on">
<link rel="shortcut icon" type="image/x-icon" href="/favicon.ico" />
<link rel="apple-touch-icon" href="/css/default/images/kopfbalken_links.png" />
<link rel="apple-touch-startup-image" href="/css/default/images/kopfbalken_links.png">
<style>
@font-face {
font-family: 'Source Sans Pro';
src: url('/css/rd/fonts/sourcesanspro.woff');
}
@font-face {
font-family: 'Source Sans Pro';
src: url('/css/rd/fonts/sourcesansproBold.woff');
font-weight: bold;
}
@font-face {
font-family: 'AVM';
src: url('/css/rd/fonts/metaWebProBold.woff');
font-weight: bold;
}
html, input, textarea, keygen, select, button {
font-family: 'Source Sans Pro', Arial, sans-serif;
font-size: 100%;
}
.blue_bar_title,
.logoArea {
font-family: 'AVM', 'Source Sans Pro', Arial, sans-serif;
}
</style>
<link rel='stylesheet' type='text/css' href="/css/rd/login.css"/>
<title>
FRITZ!Box
</title>
</head>
<body>
<script>
var gNbc = false,
config = {"gu_type":"release","isDebug":false,"GUI_IS_REPEATER":false};
</script>
<script src="/js/avmcore.js?lang=de"></script>
<!--<script src="/js/browser.js"></script>-->
<!--<script src="/js/jsl.js"></script>-->
<!--<script src="/js/md5.js"></script>-->
<!--<script src="/js/html.js"></script>-->
<!--<script src="/js/func.js"></script>-->
<!--<script type="text/javascript" src="/myfritz/js/focuschanger.js?lang=de"></script>-->
<!--<script src="/js/html2.js?lang=de"></script>-->
<!--<script src="/js/http.js"></script>-->
<script type="text/javascript" src="/js/login.js"></script>
<script type="text/javascript">
[...]
}
function localInit() {
"use strict";
window.history.replaceState({}, '', '/');
html.blueBarHead({
"type": "login",
title: data.bluBarTitle,
parent: document.body
});
login.init(data);
}
localInit();
</script>
</body>
</html>
bzw. per UDP:
Code:
peh@BRAGI:~$ cat sip_request;exec 3<>/dev/udp/192.168.178.1/5060;cat <&3 &cat sip_request >&3;sleep 2;exec 3>&-
REGISTER sip:192.168.178.1 SIP/2.0
Via: SIP/2.0/UDP 192.168.178.1:5060;rport;branch=z9hG4bK060944C1C4F78B0F
From: <sip:620@192.168.178.2>;tag=1810144752
To: <sip:620@192.168.178.1>
Call-ID: 74A22606C03B63E7@192.168.178.2
CSeq: 1 REGISTER
Max-Forwards: 3
User-Agent: Not a FRITZ!Box
Content-Length: 0
Supported: 100rel
Accept: application/sdp, multipart/mixed
Accept-Encoding: identity
Allow-Events: telephone-event,refer,reg
Allow: INVITE,ACK,OPTIONS,CANCEL,BYE,UPDATE,PRACK,INFO,SUBSCRIBE,NOTIFY,REFER,MESSAGE,PUBLISH
[4] 858
SIP/2.0 404 Not Found
Via: SIP/2.0/UDP 192.168.178.1:5060;rport=50982;branch=z9hG4bK060944C1C4F78B0F;received=192.168.178.2
From: <sip:620@192.168.178.1>;tag=1810144752
To: <sip:620@192.168.178.1>;tag=28FC9E6700CEC7F7
Call-ID: 74A22606C03B63E7@192.168.178.1
CSeq: 1 REGISTER
User-Agent: FRITZ!OS
Content-Length: 0
(das Starten im Hintergrund (über &) ist genauso gut wie die Trennung zweier Kommandos über ein Semikolon)
- Auch FIFOs machen der Shell nichts aus ... das klappt ebenfalls:
Code:
peh@BRAGI:/tmp$ mknod -m 666 /tmp/my_fifo p;ls -l /tmp/my_fifo;ls -l;printf "\nread from FIFO: %s\n" "$(cat /tmp/my_fifo)" &echo "written into FIFO" >/tmp/my_fifo;sleep 3;rm /tmp/my_fifo
ls: /tmp/my_fifo: Invalid argument
prw-rw-rw- 1 peh peh 0 Mar 22 19:17 /tmp/my_fifo
ls: my_fifo: Invalid argument
total 0
prw-rw-rw- 1 peh peh 0 Mar 22 19:17 my_fifo
[1] 1012
read from FIFO: written into FIFO
[1]+ Done printf "\nread from FIFO: %s\n" "$(cat /tmp/my_fifo)"
peh@BRAGI:/tmp$
Wobei hier eine Merkwürdigkeit zutage tritt, die ggf. untersucht werden müßte ... das "ls"-Kommando mag das "lange Format" (Option "-l") offenbar nicht klaglos anzeigen (keine Ahnung bisher, welche Eigenschaft die Fehlermeldung verursacht), wenn es sich um ein "special file" (zumindest für Pipes und Sockets) handelt:
Code:
peh@BRAGI:/tmp$ touch my_file;mknod my_fifo p;ls -la
ls: git@github.com:22: Invalid argument
total 8
drwxrwxrwt 2 root root 0 Mar 22 19:23 .
drwxr-xr-x 2 root root 0 Jan 1 1970 ..
srw------- 1 peh peh 0 Mar 22 19:23 git@github.com:22
prw-rw-rw- 1 peh peh 0 Mar 22 19:24 my_fifo
-rw-rw-rw- 1 peh peh 0 Mar 22 19:24 my_file
Wenn man den Socket für das Sharen der SSH-Connection zu github.com löscht, mault das Kommando an der "my_fifo" herum:
Code:
peh@BRAGI:/tmp$ rm git@github.com\:22;ls -la
ls: my_fifo: Invalid argument
total 8
drwxrwxrwt 2 root root 0 Mar 22 19:26 .
drwxr-xr-x 2 root root 0 Jan 1 1970 ..
prw-rw-rw- 1 peh peh 0 Mar 22 19:24 my_fifo
-rw-rw-rw- 1 peh peh 0 Mar 22 19:24 my_file
Es liegt also nicht an Sonderzeichen im Dateinamen oder ähnlichem, sondern offenbar am "Dateityp" und irgendeiner noch fehlenden Emulation für diese speziellen Dateien. - Was hingegen nur sehr rudimentär vorhanden ist, wären die Angaben zum Netzwerk im procFS:
Code:
peh@BRAGI:~$ sudo ls -la /proc/net/
total 0
dr-xr-xr-x 1 root root 0 Mar 22 21:24 .
dr-xr-xr-x 1 root root 0 Mar 22 21:24 ..
-r--r--r-- 1 root root 0 Mar 22 21:24 if_inet6
-r--r--r-- 1 root root 0 Mar 22 21:24 netlink
-r--r--r-- 1 root root 0 Mar 22 21:24 tcp
-r--r--r-- 1 root root 0 Mar 22 21:24 tcp6
-r--r--r-- 1 root root 0 Mar 22 21:24 udp
-r--r--r-- 1 root root 0 Mar 22 21:24 udp6
dr-xr-xr-x 1 root root 0 Mar 22 21:24 xt_qtaguid
Vergleicht man das mit einem "richtigen Linux":
Code:
# ls -la /proc/net/
total 0
dr-xr-xr-x 8 root root 0 Mar 22 21:23 .
dr-xr-xr-x 9 root root 0 Mar 22 21:23 ..
-r--r--r-- 1 root root 0 Mar 22 21:23 anycast6
-r--r--r-- 1 root root 0 Mar 22 21:23 arp
-r--r--r-- 1 root root 0 Mar 22 21:23 bnep
-r--r--r-- 1 root root 0 Mar 22 21:23 connector
-r--r--r-- 1 root root 0 Mar 22 21:23 dev
-r--r--r-- 1 root root 0 Mar 22 21:23 dev_mcast
dr-xr-xr-x 2 root root 0 Mar 22 21:23 dev_snmp6
-r--r--r-- 1 root root 0 Mar 22 21:23 fib_trie
-r--r--r-- 1 root root 0 Mar 22 21:23 fib_triestat
-r--r--r-- 1 root root 0 Mar 22 21:23 hci
-r--r--r-- 1 root root 0 Mar 22 21:23 icmp
-r--r--r-- 1 root root 0 Mar 22 21:23 icmp6
-r--r--r-- 1 root root 0 Mar 22 21:23 if_inet6
-r--r--r-- 1 root root 0 Mar 22 21:23 igmp
-r--r--r-- 1 root root 0 Mar 22 21:23 igmp6
-r--r--r-- 1 root root 0 Mar 22 21:23 ip6_flowlabel
-r--r----- 1 root root 0 Mar 22 21:23 ip6_tables_matches
-r--r----- 1 root root 0 Mar 22 21:23 ip6_tables_names
-r--r----- 1 root root 0 Mar 22 21:23 ip6_tables_targets
-r--r--r-- 1 root root 0 Mar 22 21:23 ip_mr_cache
-r--r--r-- 1 root root 0 Mar 22 21:23 ip_mr_vif
-r--r----- 1 root root 0 Mar 22 21:23 ip_tables_matches
-r--r----- 1 root root 0 Mar 22 21:23 ip_tables_names
-r--r----- 1 root root 0 Mar 22 21:23 ip_tables_targets
-r--r--r-- 1 root root 0 Mar 22 21:23 ipv6_route
-r--r--r-- 1 root root 0 Mar 22 21:23 l2cap
-r--r--r-- 1 root root 0 Mar 22 21:23 mcfilter
-r--r--r-- 1 root root 0 Mar 22 21:23 mcfilter6
dr-xr-xr-x 2 root root 0 Mar 22 21:23 netfilter
-r--r--r-- 1 root root 0 Mar 22 21:23 netlink
-r--r--r-- 1 root root 0 Mar 22 21:23 netstat
-r--r----- 1 root root 0 Mar 22 21:23 nf_conntrack
-r--r----- 1 root root 0 Mar 22 21:23 nf_conntrack_expect
-r--r--r-- 1 root root 0 Mar 22 21:23 packet
-r--r--r-- 1 root root 0 Mar 22 21:23 pnp
-r--r--r-- 1 root root 0 Mar 22 21:23 protocols
-r--r--r-- 1 root root 0 Mar 22 21:23 psched
-r--r--r-- 1 root root 0 Mar 22 21:23 ptype
-r--r--r-- 1 root root 0 Mar 22 21:23 raw
-r--r--r-- 1 root root 0 Mar 22 21:23 raw6
-r--r--r-- 1 root root 0 Mar 22 21:23 route
dr-xr-xr-x 10 root root 0 Mar 22 21:23 rpc
-r--r--r-- 1 root root 0 Mar 22 21:23 rt6_stats
-r--r--r-- 1 root root 0 Mar 22 21:23 rt_acct
-r--r--r-- 1 root root 0 Mar 22 21:23 rt_cache
-r--r--r-- 1 root root 0 Mar 22 21:23 sco
-r--r--r-- 1 root root 0 Mar 22 21:23 snmp
-r--r--r-- 1 root root 0 Mar 22 21:23 snmp6
-r--r--r-- 1 root root 0 Mar 22 21:23 sockstat
-r--r--r-- 1 root root 0 Mar 22 21:23 sockstat6
-r--r--r-- 1 root root 0 Mar 22 21:23 softnet_stat
dr-xr-xr-x 2 root root 0 Mar 22 21:23 stat
-r--r--r-- 1 root root 0 Mar 22 21:23 tcp
-r--r--r-- 1 root root 0 Mar 22 21:23 tcp6
-r--r--r-- 1 root root 0 Mar 22 21:23 udp
-r--r--r-- 1 root root 0 Mar 22 21:23 udp6
-r--r--r-- 1 root root 0 Mar 22 21:23 udplite
-r--r--r-- 1 root root 0 Mar 22 21:23 udplite6
-r--r--r-- 1 root root 0 Mar 22 21:23 unix
dr-xr-xr-x 2 root root 0 Mar 22 21:23 vlan
-r--r--r-- 1 root root 0 Mar 22 21:23 wireless
dr-xr-xr-x 2 root root 0 Mar 22 21:23 xt_recent
ist das praktisch nichts und damit entfallen eben auch viele Möglichkeiten, Informationen über die verwendete Netzwerk-Konfiguration zu sammeln, wie das z.B. "eva_discover" machen will. Das kann man also schon mal komplett vergessen unter der Windows-"bash" und da waren wir noch gar nicht bei der Frage, ob und wie ein "socat" mit Broadcasts da funktionieren würde. - Auch andere Netzwerk-Zugriffe scheitern bei mir grandios ... schon ein einfaches "ping", was unter einem originalen Ubuntu auch als normaler Benutzer noch klappt, scheitert unter Windows mit "ping: icmp open socket: Permission denied" - und zwar selbst dann, wenn man es mit "sudo" aufruft.
Weitere Besonderheiten, die von den (unter Windows ggf. auch sinnvollen) Skript-Dateien im YourFritz-Repository benötigt werden könnten, fallen mir aus dem Stand jetzt nicht ein.
Daß es sich bei dem gesamten Subsystem eben nicht nur um eine "schnöde 'bash'" handelt, merkt man u.a. auch daran, daß hier der Symlink "/bin/sh" gar nicht auf diese "bash" zeigt, sondern (wie fast immer bei Canonical) auf eine "dash":
Code:
peh@BRAGI:~$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 Feb 19 2014 /bin/sh -> dash
peh@BRAGI:~$ which dash
/bin/dash
peh@BRAGI:~$ ls -l /bin/dash
-rwxr-xr-x 1 root root 121272 Feb 19 2014 /bin/dash
peh@BRAGI:~$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1021112 Okt 7 2014 /bin/bash
Das führt in der Konsequenz dann allerdings dazu, daß man am besten alle nicht POSIX-kompatiblen Skriptdateien (was dann auch "nicht dash-kompatibel" heißt) nicht einfach nur mit ihrem Namen aufruft. In aller Regel wird man ohnehin den Pfad mit den Skriptdateien und auch das lokale Verzeichnis (.) nicht in seiner PATH-Variablen haben, so daß man ohnehin am besten in das jeweilige Zielverzeichnis wechselt und dort die entsprechende Datei über die Angabe "./<script_name>" aufrufen sollte. Wenn man aber das bereits macht, dann kann man ja auch noch problemlos dort ein "bash" voranstellen, damit ist dann die Angabe im SheBang uninteressant.
Einige dieser Skript-Dateien benötigen den Zugriff auf ein paar "Hilfsfunktionen", mit denen ich einige häufig benötigte Operationen in Shell-Code (hier allerdings POSIX-kompatibel, das sollte also auch mit "dash" arbeiten) nachimplementiert habe, wenn einige Kommandos fehlen bzw. um im Shell-Code etwas schwieriger zu realisierende Aktionen (z.B. die Behandlung von Hexadezimal-Werten) nachnutzbar umzusetzen. Diese Dateien müssen halt auch auffindbar sein und so sollte man vor der Verwendung der Skript-Dateien dann noch die Variable "YF_SCRIPT_DIR" auf das Verzeichnis setzen, wo diese Dateien zu finden wären. Das sähe dann in etwa so aus (bei mir wurde das YourFritz-Repository in den Pfad "~/GitHub/YourFritz" geklont):
Code:
peh@BRAGI:~$ ls -l GitHub/YourFritz/helpers/
total 56
-rw-rw-rw- 1 peh peh 29229 Dec 2 14:35 E99-custom
drwxrwxrwx 2 peh peh 0 Mar 22 20:31 functions
-rwxrwxrwx 1 peh peh 6378 Dec 2 14:35 rc.template
-rwxrwxrwx 1 peh peh 333 Dec 2 14:35 sync_lib.sh
-rw-rw-rw- 1 peh peh 3857 Dec 2 14:35 yf_helpers
lrwxrwxrwx 1 peh peh 10 Dec 2 14:35 yourfritz_helpers -> yf_helpers
peh@BRAGI:~$ export YF_SCRIPT_DIR=~/GitHub/YourFritz/helpers <=== hier wird der Pfad zu den Hilfsfunktionen gesetzt
peh@BRAGI:~$ GitHub/YourFritz/eva_tools/eva_get_environment
GitHub/YourFritz/eva_tools/eva_get_environment: 36: read: Illegal option -u
GitHub/YourFritz/eva_tools/eva_get_environment: 208: GitHub/YourFritz/eva_tools/eva_get_environment: Bad substitution
peh@BRAGI:~$ bash GitHub/YourFritz/eva_tools/eva_get_environment <=== hier macht dann der oben erwähnte Aufruf mit "bash" davor den entscheidenden Unterschied
Login failed.
Ansonsten funktionieren definitiv die Skript-Dateien "
tools/juis_check" (vorausgesetzt, es gibt ein passendes "nc"-Kommando, dafür reicht aber schon das aus der BusyBox ohne spezielle Optionen) und "
tools/juischeckupdate" (das braucht dann noch die Installation des Pakets "libxml2-utils", damit "xmllint" verfügbar ist).
Im Unterverzeichnis "eva_tools" funktioniert "eva_discover" definitiv nicht, weil notwendige Strukturen fehlen. Da bleibt unter Windows dann ggf. der Griff zum "EVA-Discover.ps1", was ja dieselbe Funktionalität bietet. Wie das aufgerufen wird und was man ggf. vorher noch einstellen muß in seinem Windows-System, schreibe ich vermutlich im nächsten Beitrag mal auf.
Hingegen funktioniert "eva_get_environment" (bei passendem Aufruf) auch unter der Windows-"bash" (getestet mit einer 7580). Da die anderen Skripte zum Zugriff auf den FTP-Server im Bootloader alle auf derselben Vorgehensweise aufbauen, dürften die Dateien "eva_store_tffs" (damit kann man ja auch andere Partitionen schreiben, der Name stammt nur aus der ersten "Bestimmung"), "eva_switch_system", "eva_to_memory" und "image2ram" (das braucht gar kein Netz) ebenso funktionieren. Allerdings gibt es (bis auf "image2ram") in "EVA-FTP-Client.ps1" diese Funktionen auch in der "Darreichungsform" oder "Geschmacksrichtung" PowerShell - die würde ich wieder präferieren, wenn ich ein passendes Windows-System habe (und ein Windows 10 mit der "bash" paßt definitiv, umgekehrt ist das nicht notwendigerweise so).
Die Skripte zum Zusammenbau eines eigenen TFFS-Images funktionieren ebenfalls problemlos (YF_SCRIPT_DIR und das davorgesetzte "bash" nicht vergessen), allerdings ist die Emulation eines Linux-Dateisystems offenbar sehr, sehr langsam.
Da diese Skript-Dateien ununterbrochen irgendwelche Dateien fortschreiben wollen und es offenbar dabei heftige Performance-Probleme gibt, dauert ein Aufruf von
Code:
# time bash ~/GitHub/YourFritz/tffs/build_tffs_image ~/GitHub/YourFritz/tffs/tffs_name_table /tmp/environment.txt /tmp/count.txt >/tmp/tffs.image
real 2m24.078s
user 0m43.760s
sys 0m51.244s
auf einem eher schwachen Intel-Prozessor (Celeron 857@1.20 GHz) mit rotierender HDD mit einem nativen Linux keine 2,5 Minuten -> das braucht auf einem Asus-Laptop mit Core2Duo (T9300@2.50 GHz mit SSD statt rotierende HDD) unter Windows 10 dann satte 11:21 Minuten. Da bleibt eigentlich nur noch das Dateisystem als Flaschenhals übrig (es handelt sich um genau dieselben Daten, die da zusammengesetzt werden ... und es gab definitiv ein "base64", daran scheiterte das also nicht, daß auch dieses noch emuliert werden mußte). Sogar das "tffs_add_file", was auf dem ersten System (mit denselben Daten wieder) gerade mal knapp 21 Sekunden braucht, benötigt unter Windows 10 dann 5:28 Minuten, wobei der Löwenanteil davon (5:25 min) tatsächlich auf "sys"-Aktivitäten (also Dateisystemzugriffe in diesem Fall) entfällt.
Fazit: Einiges geht tatsächlich mit der Canonical-"bash" unter Windows 10 ... aber man muß schon einige Besonderheiten berücksichtigen. Vermutlich würden einige dieser Skript-Dateien wesentlich flotter laufen, wenn man einfach auf den Hauptspeicherverbrauch pfeift und anstelle vieler kleiner Dateisystemzugriffe (was bei einem "nativen" Dateisystem als "append mode" offenbar schneller läuft als unter der Windows-Emulation) die Dateien erst einmal als ellenlange Zeichenketten im Speicher zusammenbaut und dann mit so wenigen Dateisystemzugriffen wie möglich schreibt. Das ist dann genau der entgegengesetzte Ansatz, wenn man es mit einem "embedded system" vergleicht, wo man sicherlich eher Rücksicht auf den Hauptspeicherbedarf nehmen wird, wenn man nicht überreich damit gesegnet ist auf dem Gerät.