Ver Mensaje Individual
  #1  
Viejo 08/05/13, 11:02:23
Avatar de maid450
maid450 maid450 no está en línea
Miembro del foro
Mensajes: 450
 
Fecha de registro: sep 2009
Localización: Valencia
Mensajes: 450
Modelo de smartphone: Nexus 5 / Nexus 7
Versión de Radio: Cualquiera que ponga buen Rock
Tu operador: Yoigo
Mencionado: 15 comentarios
Tagged: 0 hilos
Introducción a los comandos de terminal en Tasker

Hola a todos!
En este tutorial voy a tratar de explicar un poco los conceptos básicos de los comandos de terminal en Android y como lanzarlos y aprovecharlos en Tasker.

Nota: los conceptos de este tutorial son bastante avanzados, aunque voy a tratar de explicarlo de forma sencilla.
En principio los comandos ejecutados como usuario normal no deberían ser capaces de causar un gran daño (el comando adecuado podría borrar todas tus fotos por ejemplo, pero no dañar al sistema) pero los comandos ejecutados como usuario root permiten hacer cualquier cosa, no ejecutar nada de esta forma si no se confía en la fuente o no se entiende más o menos lo que se está haciendo.


1. ¿Qué son?
Android está basado en linux, un sistema operativo que se caracteriza entre otras cosas por tener un terminal (llamado shell en inglés) muy potente que permite poder controlar casi por completo todo el sistema y obtener información mediante "ordenes" más o menos complejas, estas ordenes se conocen como comandos de terminal.
Los comandos en sí son programas (o ficheros con codigo ejecutable) que se guardan en /system/bin (ahí están los principales, aunque hay otros posibles sitios) así que pueden haber mods que dejen programas ahí y ya estarían disponibles para ejecutar.
Un ejemplo típico es "Busybox" que añade varios comandos comunes de linux y es más que recomendable instalarlo para todo usuario que tenga el telefono rooteado.

2. ¿Para qué sirven?
Como he dicho antes, mediante comandos se pueden hacer muchísimas cosas, aunque casi todo lo que nos pueda interesar puede hacerse mediante acciones normales de tasker.
Sin embargo hay cosas generalmente avanzadas que no se pueden hacer directamente y requieren hacer uso de comandos del terminal.
Como se hacen ciertas cosas y que se puede hacer ya es otra historia, en este aspecto linux es muy diferente a Mac OSX o a Windows, no hay una guia general de linux porque hay muchas variantes con pequeñas y no tan pequeñas diferencias entre si, Android es solo una de estas variantes especialmente adaptada para dispositivos mobiles.
Pero por otra parte la comunidad linuxera destaca por ser muy colaborativa y publicar mucha documentación de tutoriales, soluciones a problemas y demás, asi que no es dificil encontrar recursos si se busca "como hacer XXXXX en android", especialmente si sabes inglés.

3. Ejemplo práctico
Una limitación habitual en tasker es querer controlar si en un momento dado una aplicación está en marcha.

Esto es muy sencillo con aplicaciones "normales" ya que basta con hacer un perfil con el contexto "aplicación -> la aplicación a controlar" y una tarea de entrada que cree una variable %APPX a 1 y en la tarea de salida cambie el valor de la variable a 0.
Sin embargo, en aplicaciones que se puedan quedar en segundo plano esto no funciona, ya que en cuanto la aplicación deja de estar en primer plano, tasker piensa que se ha salido de la aplicación y la variable se pondría a 0.
Sin embargo el sistema operativo si que sabe que la aplicación sigue en marcha, ¡asi que vamos a preguntarle usando comandos!

Antes que nada, para poder lanzar estos comandos hay que tener un emulador de terminal instalado, el más conocido es este: https://play.google.com/store/apps/d...al.androidterm, pero cualquiera debería valer.

El comando completo a usar sería este:
Código:
cat /proc/$(pgrep %pname$)/oom_adj
¡No asustarse! Vamos a explicar por partes que hace este churro.

Primero que nada, Android no usa los nombres típicos por los que conocemos a las aplicaciones a nivel interno, sino lo que se llama el package name, y a nivel aún más interno (lo explicaré luego) el PID.
Para averiguar el package name de una aplicación lo más facil es buscar la aplicación en la web de google play y fijarse en la URL del navegador, el package name es lo que pone entre el "id=" y el primer "&" si lo hay, por ejemplo para el terminal emulator el package name es jackpal.androidterm.
Cuando Android lanza una aplicación le asigna un PID (Process ID) dinámico (si la aplicación muere y se vuelve a lanzar el nuevo PID que le asigne casi seguro que no será el mismo), que es un número que en adelante el sistema usará internamente para el manejo de memoria y más cosas.

Ahora, volviendo al comando, en realidad se trata de un comando dentro de otro, primero que nada habría que reemplazar %pname por el package name de la aplicación que queramos comprobar (para el ejemplo usaremos el propio terminal, recordemos: jackpal.androidterm) y si ejecutamos el comando interno que es

Código:
pgrep jackpal.androidterm
nos devolverá el PID de la aplicación (en mi caso da 25419, pero a cada uno le puede dar un valor diferente).

Y ahora por fin la explicación del comando completo: se da el caso de que android crea una carpeta por cada proceso en /proc (de ahí su nombre) y dentro de la carpeta de cada proceso entre otras cosas hay un archivo llamado "oom_adj" que solo contiene un numero con el estado de ejecución del mismo.

El comando "cat" simplemente muestra el contenido del archivo que le digas, de modo que cuando ejecutamos
Código:
cat /proc/$(pgrep jackpal.androidterm$)/oom_adj
primero resuelve el PID del proceso (recordemos en mi caso 25419), con lo que sería equivalente a ejecutar
Código:
cat /proc/25419/oom_adj
que devolvería el estado de ejecución de ese proceso.

Para el caso que nos interesa, un "0" significa que está en primer plano y un "2" en segundo plano, cualquier otro valor es que está en otro estado que podemos considerar como inactivo.

Espero no haberos perdido por el camino soy consciente que no es el ejemplo más sencillo, pero como digo, para hacer cosas sencillas no suele ser necesario usar el terminal, y he tratado de explicarlo lo mejor posible y no limitarme a soltar el comando y que penseis que hace magia...

4. Usar comandos con Tasker
Tasker tiene predefinida una acción en "Script -> Ejecutar consola" (o "Script -> Run shell" en inglés) que permite ejecutar comandos.
No confundir con las otras acciones en esta categoría:
- "Javascript" y "Javascriptlet" Son casi identicos y sirven para ejecutar código javascript dentro de tasker, no comandos de terminal. Lo cubriré en un proximo tutorial.
- "Ejecutar Script" Sirven para ejecutar código en otros lenguajes (como python o php) hay que instalaer los interpretes con SL4A. Lo cubriré en un proximo tutorial.

En la acción se puede definir el comando a ejecutar (permite usar variables), la cuenta atrás o "timeout" (tiempo máximo de ejecución, si se sobrepasa se cancela la orden, 0 es para infinito), y unas variables para almacenar la "salida" o "output" (lo que devuelve el comando), los "Errores" (posibles mensajes de error si algo va mal) y el "Resultado" (no confundir con la salida, esto es un codigo numérico que indica si la ejecución ha ido bien (devolvería 0) o no (devolvería cualquier otra cosa, depende del comando y el error), este valor no se ve al ejecutar comandos a mano desde el terminal) y tambien se puede marcar si se quiere ejecutar el comando como usuario root o no (hay comandos que necesitan ser ejecutados como root, mantenerlo desactivado siempre que sea posible).
Lo de "continuar tarea en caso de error" es conveniente marcarlo, ya que hay comandos que es normal que no devuelvan un resultado 0: en el ejemplo de antes por ejemplo, si el proceso que buscamos no tiene PID en el momento de ejecutar el comando, el fallará porque intenta mostrar un archivo que en ese momento no existe y si no marcamos esta opción la tarea se pararía y no haría nada más.

5. Comandos habituales / utiles

Nota: los comandos van entre comillas, pero hay que ejecutarlos sin ellas, para los parametros que hay que pasarles (las rutas de directorios, ficheros, etc...) si contienen espacios hay que rodearlos con comillas para que no piense que son varios parametros, por ejemplo cat /sdcard/mi archivo.txt habría que ejecutarlo como cat "/sdcard/mi archivo.txt" y cp /sdcard mi archivo.txt /sdcard/mi otro archivo.txt sería cp "/sdcard mi archivo.txt" "/sdcard/mi otro archivo.txt"

  • cd: cambia al directorio especificado, por ejemplo "cd /sdcard" situa el directorio actual a la raíz de la tarjeta sd (todos los que hayais vivido la epoca MS-DOS os sonará este )
  • pwd: devuelve la ruta del directorio actual
  • ls: devuelve una lista de los ficheros y carpetas del directorio actual, si se le pasa un directorio (por ejemplo "ls /sdcard" devuelve una lista con los directorios y ficheros dentro de esa carpeta)
  • cp: copia un archivo, hay que pasarle la ruta del archivo origen y el destino, por ejemplo: "cp /sdcard/hola.txt /sdcard/hola2.txt" crea una copia de "hola.txt" y la llama "hola2.txt"
  • rm: borra un archivo (con este hay que ir con cuidado ;-)) por ejemplo "rm /sdcard/hola.txt"
  • cat:devuelve el contenido del fichero especificado, por ejemplo si tienes un fichero "hola.txt" en la raiz de la tarjeta SD "cat sdcard/hola.txt"mostrará el contenido del fichero
  • grep: filtra una entrada y devuelve solo las lineas que contenga el texto pasado (ver en apartado 6)
Aquí hay una lista de algunos comandos disponibles en Android.

Este tutorial pretende ser una introducción, los detalles concretos sobre el uso de todos estos comandos se pueden encontrar facilmente por internet

6. Obtener ayuda
Todos los comandos suelen tener una ayuda con una descripción de lo que hace el comando y las distintas opciones si las tiene.
Normalmente para ver esta ayuda se hace escribiendo en un terminal "comando -h" o "comando --help" (un guión cuando es una letra y 2 para la palabra completa).
Si no funciona ninguna de las dos formas (devolverán un error del tipo "no existe la opción" o algo así) algunos comandos muestran la ayuda al escribir el comando a secas, sin ninguna opción ni parametro, ojo no probar esto si un comando, por su nombre, podría tener sentido si se ejecuta sin parametros, ya que podría ejecutarse si hacemos esto.

7. Conceptos avanzados
Redirigir entrada y salida de comandos


- Entrada
Antes hemos visto por ejemplo el comando "cat" que muestra el contenido de un fichero, en el caso del ejemplo era un fichero que solo tiene un numero, pero podría ser un fichero de texto con muchas lineas y te interese solo una linea concreta o solo algunas cosas, para eso hay un comando muy util llamado "grep" que ilustra muy bien como redirigir la salida de un comando a la entrada de otro.


Pongamos un fichero de texto en /sdcard/fechahora.txt con este contenido:
Código:
Fecha: 08/05/2013
Hora: 10:00
Si hacemos
Código:
cat /sdcard/fechahora.txt
nos devolverá todo este texto, pero si hacemos
Código:
cat /sdcard/fechahora.txt | grep Hora
lo que pasará es que al poner el "|" entre ambos comandos, hará que el resultado del "cat" (todo el texto) sea la entrada del "grep" y al pasarle a este como parametro "Hora" solo dejará pasar las lineas que contengan la palabra "Hora" y la orden completa nos devolverá
Código:
Hora: 10:00
De esta forma podemos encadenar comandos haciendo que un comando utilice el resultado de otro como entrada

-Salida
Aunque Tasker nos permite con la acción de ejecutar un comando guardarnos su resultado en una variable para hacer con él lo que queramos, a veces nos podrá interesar guardar lo que devuelva un comando en un fichero, esto se puede hacer redirigiendo la salida del comando en vez de a la pantalla a un fichero, y esto se consigue poniendo "> ruta_fichero_destino.txt" despues del comando, por ejemplo, si ejecutamos
Código:
ls / > /sdcard/ls.txt
no mostrará nada por pantalla, pero lo que se hubiese mostrado (una lista de los directorios y ficheros contenidos en el directorio raíz /) se escribira en un fichero "ls.txt" que se creará en /sdcard.


Si se volviese a ejecutar lo mismo el fichero destino se sobreescribiría con el nuevo contenido, mientras que si ponemos ">>" en vez de ">" hace lo mismo pero en vez de sobreescribir el fichero, añade al final de este el resultado de la nueva ejecución (la primera vez lo crearía si no existiese igualmente)

Es mi primer tutorial (pretendo hacer alguno más con el tiempo si este tiene buena acogida ) así que acepto críticas constructivas sobre si pensais que debo explicar mejor o ahondar en alguna cosa

Última edición por maid450 Día 06/02/14 a las 08:57:18
Responder Con Cita
Los siguientes 17 usuarios han agradecido a maid450 su comentario:
[ Mostrar/Ocultar listado de agradecimientos ]