{"id":1362,"date":"2014-06-16T20:16:14","date_gmt":"2014-06-16T18:16:14","guid":{"rendered":"http:\/\/blog.rastersoft.com\/?p=1362"},"modified":"2014-06-16T20:16:14","modified_gmt":"2014-06-16T18:16:14","slug":"reemplazando-android","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=1362","title":{"rendered":"Reemplazando Android"},"content":{"rendered":"<p>(La segunda parte de este art\u00edculo est\u00e1 en <a href=\"https:\/\/blog.rastersoft.com\/?p=1386\" target=\"_blank\">https:\/\/blog.rastersoft.com\/?p=1386<\/a>)<\/p>\n<p>Hace unas semanas me compr\u00e9 un cacharro de tipo AndroidTV (<a href=\"http:\/\/www.dx.com\/p\/at-818-1080p-fhd-android-4-1-1-dual-core-google-tv-player-w-1gb-ram-8gb-rom-hdmi-rj45-wi-fi-222600\" target=\"_blank\">este en concreto<\/a>). Sin embargo ya ten\u00eda claro que no quer\u00eda tener Android, sino un linux como $DEITY manda. Por eso busqu\u00e9 uno con el <a href=\"https:\/\/blog.rastersoft.com\/?p=1253\" target=\"_blank\">mismo chip que mi tablet<\/a>. Por desgracia esta vez no consegu\u00ed que arrancase desde una tarjeta externa (parece que han cambiado algo en el cargador). Pero como a cabezota no me gana nadie, decid\u00ed buscar alguna alternativa.<\/p>\n<p>Por supuesto no quer\u00eda eliminar el Android que ya trae, m\u00e1s que nada por si me lo cargo y acabo con un bonito pisapapeles. Por eso decid\u00ed intentar una ruta intermedia: una vez arrancado el sistema, lanzar\u00eda un programa que matar\u00eda todos los procesos de Android y lanzar\u00eda una Debian almacenada en un disco externo, desde un entorno chroot, con su entorno gr\u00e1fico y todo. De esta manera, si no enchufo el disco el sistema arrancar\u00eda Android normalmente, y si lo enchufo, arrancar\u00eda Linux.<\/p>\n<p>Obviamente la cosa no es tan sencilla. Para empezar, los diversos procesos de Android se vuelven a lanzar autom\u00e1ticamente si mueren, por lo que no podemos utilizar un simple <em>kill pid<\/em>. Afortunadamente existen los comandos <em>start<\/em> y <em>stop<\/em> que lanzan y detienen todo el entorno gr\u00e1fico. Para probarlos utilic\u00e9 <a href=\"http:\/\/developer.android.com\/tools\/help\/adb.html\" target=\"_blank\"><em>adb<\/em><\/a>, disponible en el entorno de desarrollo de Android. Para ello primero lanc\u00e9 el servidor con<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">sudo .\/adb start server<\/pre>\n<\/div>\n<p>Y luego cada vez que necesitaba una consola en el dispositivo, lo conectaba con el cable USB y lanzaba:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">.\/adb shell<\/pre>\n<\/div>\n<p>Y efectivamente, si ejecutaba <em>stop<\/em> el entorno de Android desaparec\u00eda, quedando la pantalla congelada. Ejecutando <em>start<\/em> volv\u00eda a arrancar todo. Afortunadamente, aunque mi dispositivo no est\u00e1 completamente <em>rooteado<\/em>, si es lo suficientemente <em>libre<\/em> como para que, por defecto, entre como <em>root<\/em> desde esta shell, adem\u00e1s de incluir un <em>busybox<\/em> con <em>chroot<\/em>. Con esto ya tengo resuelto el primer gran problema. Es cierto que todav\u00eda quedan varios servicios en marcha, como el gestor de red, pero es un problema secundario que ya resolveremos luego.<\/p>\n<p>OJO: el servicio <em>adb<\/em> en el dispositivo Android tarda un poco en ser lanzado. Si acab\u00e1is de arrancarlo, sed pacientes. Por otro lado, a veces la lista de dispositivos USB con Android no est\u00e1 actualizada en Linux, as\u00ed que es posible que haya que tocar un poco en <em>udev<\/em> para que reconozca el nuestro.<\/p>\n<h3>Autoarranque<\/h3>\n<p>Si s\u00f3lo quisiese lanzar manualmente el nuevo entorno ya tendr\u00eda el problema resuelto; pero yo quiero un dispositivo que arranque Debian incluso si no estoy (por ejemplo si se va la luz y luego vuelve), por lo que no queda m\u00e1s remedio que meter las narices en el proceso de arranque de Android.<\/p>\n<p>Alguno puede pensar que ir a tan bajo nivel es exagerado, pero hay un motivo: la primera idea que se me ocurri\u00f3 fue buscar alg\u00fan programa nativo de Android que en el arranque lance autom\u00e1ticamente un <em>script<\/em> que yo le pase. Encontr\u00e9 varios, pero fue entonces cuando descubr\u00ed que mi cacharro no est\u00e1 <em>rooteado<\/em> del todo, por lo que ese <em>script<\/em> no pod\u00eda lanzar un <em>chroot<\/em> ni nada por el estilo. As\u00ed pues, no queda m\u00e1s remedio que meter las narices m\u00e1s abajo.<\/p>\n<p>Como en cualquier sistema Linux, una vez arrancado el n\u00facleo se ejecuta el proceso <em>init<\/em>. Pero aqu\u00ed acaban los paralelismos, porque en Android este proceso es muy diferente del <em>SysV Init<\/em>: aqu\u00ed hay un conjunto de ficheros <em>.rc<\/em> con una serie de indicaciones de qu\u00e9 procesos hay que lanzar, en qu\u00e9 orden, con qu\u00e9 permisos, de qu\u00e9 dependen, y, sobre todo, si es necesario volver a lanzarlos si mueren. Estos ficheros <em>.rc<\/em> se encuentran en el ra\u00edz del sistema de ficheros, y ese es primer problema serio con el que nos encontramos: en general, el sistema ra\u00edz es de tipo <em>rootfs<\/em>. Este sistema de ficheros es un tipo de <em>ramfs,<\/em> que se inicializa durante el arranque con unos valores predeterminados, y adem\u00e1s est\u00e1 montado como s\u00f3lo lectura. Aunque en principio podemos hacer <em>mount -o remount,rw \/<\/em> para permitir escritura, cualquier cambio que hagamos desaparecer\u00e1 al reiniciar. La \u00fanica manera de modificar el sistema de archivos es recompilarlo y grabar la partici\u00f3n entera, y eso es algo que no quiero hacer por el riesgo de cascar el sistema. Sin embargo, en <em>\/system<\/em> tenemos una partici\u00f3n que s\u00ed es modificable, porque es de tipo <em>ext4<\/em>, as\u00ed que intentaremos meter nuestro autoarranque ah\u00ed. En caso de que, por defecto, dicha partici\u00f3n est\u00e9 montada como s\u00f3lo lectura, podemos volverla de lectura\/escritura con:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">mount -o remount,rw \/system<\/pre>\n<\/div>\n<p>y devolverla a s\u00f3lo lectura con<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">mount -o remount,ro \/system<\/pre>\n<\/div>\n<p><a href=\"https:\/\/android.googlesource.com\/platform\/system\/core\/+\/master\/init\/readme.txt\" target=\"_blank\">El formato de los ficheros <em>.rc<\/em> es relativamente sencillo<\/a>: si una l\u00ednea comienza por <strong><em>on XXXXX<\/em><\/strong>, las l\u00edneas siguientes definen los comandos a realizar cuando ocurra el evento <em>XXXXX<\/em>. Pero si empieza por <strong><em>service XXXXX<\/em><\/strong>, entonces las siguientes l\u00edneas definen a dicho servicio <em>XXXXX<\/em>, que se debe lanzar al inicio. Un ejemplo de servicio ser\u00eda este:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">service console \/system\/bin\/sh\n    class core\n    console\n    disabled\n    user shell\n    group log<\/pre>\n<\/div>\n<p>Estas l\u00edneas definen el servicio <em>console<\/em>, que se lanza ejecutando el binario <em>\/system\/bin\/sh<\/em>. Adem\u00e1s, debe lanzarse como usuario <em>shell<\/em> y grupo <em>log<\/em>. Si estos dos par\u00e1metros no se incluyen se lanza como <em>root<\/em>.<\/p>\n<p>Una l\u00ednea especial, que nos interesa especialmente, es <em>oneshot<\/em>. Cuando un servicio la incluye significa que debe lanzarse una \u00fanica vez durante el arranque, y si se muere no debe lanzarse de nuevo. En cambio, aquellos servicios que no incluyen <em>oneshot<\/em> se vuelven a lanzar si mueren. El motivo de explicar esto es que lo que vamos a hacer es buscar un servicio de tipo <em>oneshot<\/em>, y reemplazar su binario por un <em>script<\/em> que primero llame al binario original, y luego haga lo que a nosotros nos interese. En mi caso tuve m\u00e1s suerte, y encontr\u00e9 este servicio:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">service flash_recovery \/system\/etc\/install-recovery.sh\n    class main\n    oneshot<\/pre>\n<\/div>\n<p>Por el nombre, tiene pinta de ser lo que se lanza cuando se borran las preferencias y se quiere dejar el sistema como reci\u00e9n comprado. Si vamos a <em>\/system\/etc<\/em>, vemos que no existe el fichero <em>install-recovery.sh<\/em>, supongo que porque s\u00f3lo se crear\u00e1 cuando se quieran borrar los datos; pero eso significa que nosotros podemos meter en su lugar un ejecutable o un <em>script<\/em> y \u00e9ste se ejecutar\u00e1 como <em>root<\/em> cada vez que arranque el sistema. Y adem\u00e1s, al estar en <em>\/system<\/em> podemos editarlo a nuestro antojo \u00a1Justo lo que est\u00e1bamos buscando!<\/p>\n<h3>Lanzamiento condicional<\/h3>\n<p>Ahora que ya tenemos donde meter nuestro c\u00f3digo, la primera idea que se nos viene a la cabeza es montar un sistema <em>Debian<\/em> en, por ejemplo, <em>\/system\/debian<\/em>, escribir un <em>script<\/em> que monte una copia de\u00a0<em>proc, sys <\/em>y<em>\u00a0<\/em><em>dev<\/em>, y meterlo directamente en <em>\/system\/etc\/install-recovery.sh<\/em>. Esto tiene varios problemas:<\/p>\n<ul>\n<li>Las unidades en formato Ext2\/3\/4 no se montan autom\u00e1ticamente desde Android, por lo que tendr\u00edamos que hacerlo <em>a mano<\/em>.<\/li>\n<li>Adem\u00e1s, si hay varias unidades USB, tendr\u00edamos que ver cual es la correcta de todas ellas<\/li>\n<li>Seg\u00fan como lo hagamos podemos perder por completo el acceso a Android.<\/li>\n<li>Tendremos el sistema <em>hardcoded<\/em>, grabado en piedra, y para cambiar cualquier cosa tendremos que volver a entrar en la flash de nuestro dispositivo.<\/li>\n<\/ul>\n<p>La opci\u00f3n por la que me he decantado es la de disponer de un disco duro externo con el sistema Debian, e incluir en \u00e9l un peque\u00f1o fichero ejecutable con un nombre espec\u00edfico. De esa manera el \u00fanico cambio que hay que hacer en nuestro sistema Android es a\u00f1adir un peque\u00f1o programa que se lance durante el inicio y que compruebe todas las unidades USB en busca de dicho ejecutable, y si lo encuentra, que lo lance. De esa manera podemos meter ah\u00ed toda la magia y reducir al m\u00ednimo los cambios a realizar en nuestro dispositivo Android.<\/p>\n<p>Lo primero que hice fue crear un peque\u00f1o programa que comprobase constantemente si aparec\u00eda un nuevo dispositivo USB; en caso de que as\u00ed fuese, intentar\u00eda montarlo como una partici\u00f3n EXT4 en un punto concreto y ejecutar un fichero <em>runlinux.sh<\/em> en \u00e9l. Al principio lo hice todo con comandos <em>shell<\/em>, pero el resultado era bastante chapucero porque lo que hac\u00eda era comprobar de manera peri\u00f3dica (cada cinco segundos) si hab\u00eda dispositivos. Adem\u00e1s, cada comprobaci\u00f3n implicaba ejecutar varios <em>grep, sed<\/em> y otros comandos, lo que aumentaba el consumo de CPU. Aunque una vez lanzado el sistema Debian esta comprobaci\u00f3n se deten\u00eda, s\u00ed segu\u00eda en marcha mientras se estuviese trabajando en Android. Por eso al final lo reescrib\u00ed en C y utilizando <a href=\"http:\/\/en.wikipedia.org\/wiki\/Inotify\" target=\"_blank\"><em>inotify<\/em><\/a>, de manera que no hace falta realizar una espera activa, sino que el programa s\u00f3lo se despierta cuando se inserta un nuevo dispositivo. El <a href=\"http:\/\/www.rastersoft.com\/blogpic\/launch_debian.tar.bz2\">c\u00f3digo de este programa se puede bajar desde aqu\u00ed<\/a>. Para compilarlo basta con utilizar el comando<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">arm-linux-androideabi-gcc launch_debian.c -o launch_debian<\/pre>\n<\/div>\n<p>El compilador <em>arm-linux-androideabi<\/em> est\u00e1 disponible en Debian y derivadas en el paquete <em>gcc-arm-linux-androideabi<\/em>. A continuaci\u00f3n hay que copiar el binario a <em>\/system\/bin<\/em> en nuestro dispositivo Android, y a\u00f1adir el siguiente <em>script<\/em> en <em>\/system\/etc\/install-recovery.sh<\/em>:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">#!\/system\/bin\/sh\n\n\/system\/bin\/launch_debian &amp;<\/pre>\n<\/div>\n<p>Este script lo que hace es lanzar <em>launch_debian<\/em> en segundo plano, y \u00e9ste se quedar\u00e1 esperando a que se conecte un nuevo dispositivo USB con alguna partici\u00f3n EXT4. En caso de que eso ocurra, montar\u00e1 dicha partici\u00f3n (con las opciones <em>noatime<\/em> y <em>nodiratime<\/em>; para discos duros normales no es necesario, pero es interesante para unidades <em>flash<\/em>) e intentar\u00e1 ejecutar el fichero <em>runlinux.sh<\/em>, pas\u00e1ndole como primer par\u00e1metro la ruta donde est\u00e1 montada la partici\u00f3n (por defecto <em>\/system\/debian<\/em>), y como segundo par\u00e1metro el dispositivo que se ha montado (por ejemplo, <em>sdb2<\/em>). Una vez que termine de ejecutarse correctamente dicho fichero, <em>launch<\/em><em>_debian<\/em> morir\u00e1. Pero si falla la ejecuci\u00f3n o no existe dicho fichero, el programa seguir\u00e1 probando con el resto de dispositivos.<\/p>\n<p>El motivo de poner un <em>script<\/em> intermedio en lugar de meter el ejecutable directamente en <em>\/system\/etc\/install-recovery.sh<\/em> es porque as\u00ed, si por cualquier motivo el sistema Android sobreescribe dicho fichero, puedo recuperarlo f\u00e1cilmente desde una consola, en lugar de necesitar transferir un binario.<\/p>\n<h3>Generando el sistema de ficheros<\/h3>\n<p>Ahora que ya tenemos todo listo en el sistema Android queda generar el entorno Debian, que ser\u00e1 el que ejecutemos, as\u00ed como un <em>script<\/em> que lo lance mediante una llamada a <em>chroot<\/em>.<\/p>\n<p>Vamos a empezar con el entorno Debian. Para ello formatearemos un disco en EXT3 o en EXT4 y, desde un sistema Debian o derivado (Ubuntu, por ejemplo) bajamos el paquete <em>debootstrap<\/em>. A continuaci\u00f3n montamos manualmente el disco donde queremos generar el sistema (porque, por defecto, los escritorios lo montan con las opciones <em>nodev<\/em> y <em>noexec<\/em>, y <em>debootstrap<\/em> se niega a trabajar en esas condiciones), y desde una l\u00ednea de comandos teclearemos (asumiendo que el disco donde queremos instalar el sistema base est\u00e1 en <em>\/mnt<\/em>):<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">sudo debootstrap --arch=armhf --foreign --variant=minbase wheezy \/mnt http:\/\/ftp.us.debian.org\/debian<\/pre>\n<\/div>\n<p>En este caso estamos instalando Debian <em>wheezy<\/em>, que es la rama <em>testing<\/em> a la hora de escribir este art\u00edculo. En el futuro puede ser necesario cambiar a otra rama, seg\u00fan se desee.<\/p>\n<p>Una vez ha terminado de instalarse, editamos el fichero\u00a0<em>etc\/resolv.conf <\/em>para a\u00f1adir un\u00a0<em>DNS<\/em> por defecto. En mi caso he utilizado los de google, pero se puede utilizar cualquiera. Mi fichero qued\u00f3 as\u00ed:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\"># Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)\n#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN\n#nameserver 127.0.1.1\nnameserver 8.8.8.8\nnameserver 8.8.4.4<\/pre>\n<\/div>\n<p>Ahora desmontamos el disco y lo conectamos a nuestro sistema Android. Luego ejecutamos <em>.\/adb shell<\/em> para entrar en \u00e9l, y procederemos a montar la unidad donde instalamos el sistema en, por ejemplo, <em>\/mnt\/usb_storage<\/em>. Una vez hecho esto, y tras asegurarnos de que tenemos conexi\u00f3n a internet desde nuestro dispositivo Android, ejecutamos los siguientes comandos (tambi\u00e9n en nuestro dispositivo Android mediante <em>adb shell<\/em>) para entrar en el entorno <em>chroot<\/em> y terminar la instalaci\u00f3n del sistema base:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">export PATH=\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin:\/sbin:\/bin:$PATH\nexport HOME=\/root\nexport LD_LIBRARY_PATH=\nmount -o bind \/proc \/mnt\/usb_storage\/proc\nmount -o bind \/sys \/mnt\/usb_storage\/sys\nmount -o bind \/dev \/mnt\/usb_storage\/dev\nmount -o bind \/dev\/pts \/mnt\/usb_storage\/dev\/pts\nbusybox chroot \/mnt\/usb_storage \/bin\/bash -l\ndebootstrap\/debootstrap --second-stage<\/pre>\n<\/div>\n<p>Con esto terminamos la instalaci\u00f3n del sistema base, pero ahora toca configurarlo. En primer lugar vamos a configurar <a href=\"http:\/\/en.wikipedia.org\/wiki\/Advanced_Packaging_Tool\" target=\"_blank\">APT<\/a> para poder bajar paquetes y dem\u00e1s. Para ello salimos del entorno <em>chroot,<\/em> desmontamos el disco, lo montamos en nuestro ordenador y editamos el fichero <em>\/etc\/apt\/sources.list<\/em> para a\u00f1adir las siguientes l\u00edneas:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">deb http:\/\/ftp.de.debian.org\/debian wheezy main contrib non-free\ndeb http:\/\/ftp.de.debian.org\/debian wheezy-updates main contrib non-free\ndeb http:\/\/security.debian.org\/ wheezy\/updates main contrib non-free<\/pre>\n<\/div>\n<p>Ahora podemos volver a montar el disco en nuestro sistema Android y volver a lanzar el entorno <em>chroot<\/em>. Vamos a instalar ahora las herramientas b\u00e1sicas que nos faltan para terminar de configurar el sistema con autoarranque y poder dedicarnos a jugar con \u00e9l. Para ello vamos a instalar el servicio de gesti\u00f3n de redes, para tener acceso a internet completo, el servidor SSH para poder gestionar todo de manera remota, ifconfig, ping, el cliente DHCP y un editor de textos (normalmente uso nano pero da problemas desde\u00a0<em>adb<\/em>; por eso uso\u00a0<em>vim<\/em> de manera temporal) para editar los \u00faltimos ficheros necesarios para que todo funcione autom\u00e1ticamente. Para ello, una vez que estamos de nuevo dentro de la jaula <em>chroot <\/em>(\u00a1\u00a1\u00a1no olvidarse de los <em>exports!!!)<\/em>, ejecutamos los siguientes comandos:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">apt-get update\napt-get dist-upgrade -y\napt-get install ifupdown openssh-server net-tools vim iputils-ping isc-dhcp-client<\/pre>\n<\/div>\n<p>El siguiente paso es crear el fichero <em>runlinux.sh<\/em>, que ser\u00e1 ejecutado desde nuestro entorno Android por <em>launch_debian<\/em>. Este\u00a0<em>script<\/em> preparar\u00e1 el entorno para lanzar una sesi\u00f3n <em>chroot<\/em>, y debe contener las siguientes l\u00edneas:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">#!\/system\/bin\/sh\n\n# stop the Android system\nstop\nsleep 1\n# stop the daemons to ensure that\n# they don't disturb the debian system\n# (can't kill them because INIT would\n#  relaunch them)\n# Also allows to send them to SWAP\nbusybox killall -SIGSTOP netd\nbusybox killall -SIGSTOP vold\nbusybox killall -SIGSTOP displayd\nbusybox killall -SIGSTOP ueventd\nbusybox killall -SIGSTOP debuggerd\nbusybox killall -SIGSTOP rild\nbusybox killall -SIGSTOP drmserver\nbusybox killall -SIGSTOP mediaserver\nbusybox killall -SIGSTOP installd\nbusybox killall -SIGSTOP servicemanager\n# mount proc, sys, dev and dev\/pts\nmount -o bind \/proc $1\/proc\nmount -o bind \/sys $1\/sys\nmount -o bind \/dev $1\/dev\nmount -o bind \/dev\/pts $1\/dev\/pts\nexport HOME=\/\nexport LD_LIBRARY_PATH=\nexport PATH=\/sbin:\/bin:\/usr\/local\/sbin:\/usr\/local\/bin:\/usr\/sbin:\/usr\/bin\n# set the Framebuffer devices where standard apps expect them\ncp -a \/dev\/graphics\/* \/dev\n# launch our Debian system\n\/system\/bin\/busybox chroot $1 \/bin\/system.sh<\/pre>\n<\/div>\n<p>Lo primero que hace este <em>script <\/em>es detener el entorno Android, de manera que liberamos la memoria consumida por \u00e9ste. A continuaci\u00f3n env\u00eda una se\u00f1al SIGSTOP a diversos procesos de Android que siguen en marcha, como el gestor de red. Esto es necesario porque, si no, interferir\u00eda con las herramientas de Debian. Por otro lado, como ya expliqu\u00e9 antes, no podemos matarlos porque el sistema <em>init<\/em> los lanzar\u00eda de nuevo.<\/p>\n<p>El siguiente paso consiste en montar <em>proc<\/em>, <em>sys, dev<\/em> y <em>dev\/pts<\/em> en el sistema Debian. Vemos que utiliza el primer par\u00e1metro, pues <em>launch_debian<\/em> pasa ah\u00ed la ruta donde se mont\u00f3 la partici\u00f3n.<\/p>\n<p>A continuaci\u00f3n inicializamos las variables de entorno. Vemos que borramos <em>LD_LIBRARY_PATH<\/em>. Esto es as\u00ed porque algunos Android la utilizan para a\u00f1adir otras rutas con bibliotecas, pero en nuestro caso nos interferir\u00eda.<\/p>\n<p>Luego se copian todos los ficheros de dispositivo situados en <em>\/dev\/graphics<\/em> a <em>\/dev<\/em>. Esto es as\u00ed porque en Android los dispositivos framebuffer est\u00e1n en esa ruta alternativa, por lo que tenemos que copiarlos a donde las aplicaciones de Linux esperan encontrarlos.<\/p>\n<p>Por \u00faltimo ejecutamos nuestro <em>chroot<\/em>. Cabe indicar que es necesario poner la ruta completa de <em>busybox<\/em> porque hemos sobreescrito la variable de entorno <em>PATH<\/em>. Vemos que lanzamos el <em>script \/bin\/system.sh<\/em>. Este <em>script<\/em> ser\u00e1 quien lance todo lo que queramos lanzar en nuestro sistema Debian (servidor X, demonios&#8230;). En el caso actual lo que hice fue poner en \u00e9l las siguientes l\u00edneas:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">#!\/bin\/bash\n\nservice networking restart\nservice ssh restart<\/pre>\n<\/div>\n<p>Con esto inicializo la red (necesario si el disco estaba enchufado al encender el dispositivo Android, porque <em>launch_debian<\/em> lo detectar\u00e1 tan r\u00e1pido que no dar\u00e1 tiempo a que arranque Android y configure la red), y lanzo el servidor <em>ssh<\/em>, que me permitir\u00e1 entrar de manera remota. Para que estos dos comandos funcionen, sin embargo, es imprescindible configurar algunas cosas primero:<\/p>\n<ul>\n<li>Para el servicio <em>networking<\/em> es necesario editar el fichero <em>\/etc\/network\/interfaces<\/em> y configurar ah\u00ed nuestros dispositivos de red. <a href=\"https:\/\/wiki.debian.org\/NetworkConfiguration#Setting_up_an_Ethernet_Interface\" target=\"_blank\">Teniendo en cuenta la gran cantidad de tutoriales que hay al respecto, no voy a a\u00f1adir mucho m\u00e1s<\/a>.<\/li>\n<\/ul>\n<ul>\n<li>Para que <em>ssh<\/em> funcione, lo primero que es necesario es ponerle clave al usuario <em>root. <\/em>Para ello utilizamos el comando <em>passwd<\/em>. Una vez hecho esto editamos <a href=\"http:\/\/www.faqs.org\/docs\/securing\/chap15sec122.html\" target=\"_blank\"><em>\/etc\/ssh\/sshd_config <\/em><\/a>para ajustar la configuraci\u00f3n.<\/li>\n<\/ul>\n<p>Con todo esto ya tenemos el sistema base configurado y listo. Salimos de nuestra jaula <em>chroot<\/em>, ejecutamos <em>sync<\/em> por si acaso, y reiniciamos nuestro dispositivo Android. Si todo va bien, el entorno Android no deber\u00eda ni siquiera arrancar, y deber\u00edamos poder entrar mediante ssh.<\/p>\n<p>El siguiente paso ser\u00e1 a\u00f1adir BitTorrent, servidor FTP y alg\u00fan cliente multimedia para utilizarlo como equipo de sal\u00f3n, pero eso lo dejo para futuras entradas.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>(La segunda parte de este art\u00edculo est\u00e1 en https:\/\/blog.rastersoft.com\/?p=1386) Hace unas semanas me compr\u00e9 un cacharro de tipo AndroidTV (este en concreto). Sin embargo ya ten\u00eda claro que no quer\u00eda tener Android, sino un linux como $DEITY manda. Por eso busqu\u00e9 uno con el mismo chip que mi tablet. Por desgracia esta vez no consegu\u00ed &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=1362\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Reemplazando Android<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,7],"tags":[],"class_list":["post-1362","post","type-post","status-publish","format-standard","hentry","category-cacharreo","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/1362","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1362"}],"version-history":[{"count":0,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/1362\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1362"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1362"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1362"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}