2011-08-15 15 views
15

Quiero recorrer las máquinas virtuales en ejecución y devolver solo lo que hay entre comillas.Obtenga una lista de máquinas virtuales en ejecución usando VBoxManage

Así que este comando:

VBoxManage list runningvms 

devuelve:

"UbuntuServer" {7ef01f8d-a7d5-4405-af42-94d85f999dff} 

Y yo sólo quiero que vuelva:

UbuntuServer 

Esto es lo que tengo hasta ahora (fallo):

#!/bin/bash 
for machine in `cat VBoxManage list runningvms`; do 
     echo "$machine" 
done 
exit 

Respuesta

16

Advertencia: todo esto es arriesgado si sus nombres de VM tienen caracteres glob de shell en ellos o si contienen espacios.


se puede hacer algo como esto si sólo hay una VM en ejecución:

read machine stuff <<< $(VBoxManage list runningvms) 
echo "$machine" 

alternativa con matrices de bash (mismas condiciones):

vbm=($(VBoxManage list runningvms)) 
echo "${vbm[0]}" 

Si ese programa devuelve más de una línea, un enfoque más clásico sería:

for machine in $(VBoxManage list runningvms|cut -d" " -f 1); do 
    echo "$machine" 
done 
+0

El "enfoque clásico" es una mala práctica, como lo es el enfoque 'array = ($ (...))'; ambos, por ejemplo, reemplazarán un solo token '*' en su entrada con una lista de archivos en el directorio actual. Consulte [No leer líneas con For] (http://mywiki.wooledge.org/DontReadLinesWithFor), [BashPitfalls # 50] (http://mywiki.wooledge.org/BashPitfalls#hosts.3D.28_.24.28aws_ .... 29_.29), y [BashFAQ # 1] (http://mywiki.wooledge.org/BashFAQ/001) –

+0

Necesita división de palabras para este ejemplo específico, y el nombre VM que coincide con un patrón global parece improbable. – Mat

+0

El peor evento de pérdida de datos en el que he estado presente sucedió porque alguien ignoró un evento "imposible" (un programa que crea archivos "posiblemente no podría" crear nada que no coincida [0-9a-f] {24}; un error en una biblioteca de terceros corrompió un puntero, volcando basura aleatoria que incluía un '' 'rodeado de espacios en blanco en el búfer utilizado para un nombre ... y un script de shell que iteraba sobre los nombres de archivo a la edad del sistema de respaldo y luego borraba *todo*). –

0
VBoxManage list runningvms | sed 's/"//g;s/ .*//' 

Para reproducir indefinidamente:

for machine in `VBoxManage list runningvms | sed 's/"//g;s/ .*//'` ; do 
    echo $machine 
done 

Esto romperá si su máquina tiene espacios en su nombre.

+0

Ver [No leer líneas con For] (http://mywiki.wooledge.org/DontReadLinesWithFor) –

15
VBoxManage list runningvms | cut -d '"' -f 2 | while read machine; do 
    echo "$machine" 
done 
+1

Eso es mejor que el mío - el mío fallará si el nombre de la imagen tiene espacios en él ... no había pensado en eso . – Mat

+1

¡La sintaxis 'while read ... do' es exactamente lo que estaba buscando! – Kyrstellaine

+1

Puede sacar el 'corte' escribiendo 'while IFS ='" 'leer _ máquina _; do'. –

2

para los fanáticos de una sola línea:

VBoxManage list runningvms | cut -d" " -f 1 | grep -oP "(?<=\").*(?=\")" 
1

Para validar cada línea como usted lo lee, la manera segura de hacer esto es escribir una expresión regular y utilizar BASH_REMATCH para extraer grupos de concordancia de ella .

Con el siguiente código:

re='^"(.*)" [{]([0-9a-f-]+)[}]$' 
while read -r line; do 
    if [[ $line =~ $re ]]; then 
    name=${BASH_REMATCH[1]}; uuid=${BASH_REMATCH[2]} 
    echo "Found VM with name $name and uuid $uuid" >&2 
    else 
    echo "ERROR: Could not parse line: $line" >&2 
    fi 
done < <(VBoxManage list runningvms) 

... y la siguiente aplicación simulada de VBoxManage (para permitir que la gente sin VirtualBox para reproducir la prueba):

VBoxManage() { printf '%s\n' '"UbuntuServer" {7ef01f8d-a7d5-4405-af42-94d85f999dff}'; } 

... de salida es de la siguiente manera:

Found VM with name UbuntuServer and uuid 7ef01f8d-a7d5-4405-af42-94d85f999dff 

Tenga en cuenta las ventajas de este enfoque:

  • No hace suposiciones infundadas, como excluir máquinas virtuales con espacios en blanco o citar literales en sus nombres de soporte.
  • Detecta cualquier línea que no coincida con el patrón esperado, en lugar de comportarse de una forma no anticipada en presencia de tales valores.
  • Todavía se comporta correctamente con los datos que hace coincide con el patrón, pero tiene valores imprevistos. (Por ejemplo, una máquina virtual llamada * no tendrá ese nombre reemplazado silenciosamente con el nombre de un archivo en el directorio actual).
  • que no implica herramientas exteriores al depósito tal como sed, cut, & c, sino que se basa exclusivamente en la funcionalidad shell-builtin -. Ver BashFAQ #1 documentar el uso de while read, y the bash-hackers' wiki on regular expression matching documentar [[ $string =~ $re ]].
Cuestiones relacionadas