Esta respuesta contiene pasos detallados para las siguientes configuraciones:
- imagen en la nube amd64 y arm64
- debootstrap amd64 y arm64
- imagen de escritorio amd64
Todo fue probado en un host Ubuntu 18.04 dirigido a invitados 18.04.
Imagen de nube amd64
Las imágenes en la nube de Ubuntu son imágenes preinstaladas que le permiten arrancar directamente sin realizar la instalación habitual del sistema de escritorio. Ver también: /server/438611/what-are-ubuntu-cloud-images
#!/usr/bin/env bash
sudo apt-get install cloud-image-utils qemu
# This is already in qcow2 format.
img=ubuntu-18.04-server-cloudimg-amd64.img
if [ ! -f "$img" ]; then
wget "https://cloud-images.ubuntu.com/releases/18.04/release/${img}"
# sparse resize: does not use any extra space, just allows the resize to happen later on.
# /superuser/1022019/how-to-increase-size-of-an-ubuntu-cloud-image
qemu-img resize "$img" +128G
fi
user_data=user-data.img
if [ ! -f "$user_data" ]; then
# For the password.
# /programming/29137679/login-credentials-of-ubuntu-cloud-server-image/53373376#53373376
# /server/920117/how-do-i-set-a-password-on-an-ubuntu-cloud-image/940686#940686
# /ubuntu/507345/how-to-set-a-password-for-ubuntu-cloud-images-ie-not-use-ssh/1094189#1094189
cat >user-data <<EOF
#cloud-config
password: asdfqwer
chpasswd: { expire: False }
ssh_pwauth: True
EOF
cloud-localds "$user_data" user-data
fi
qemu-system-x86_64 \
-drive "file=${img},format=qcow2" \
-drive "file=${user_data},format=raw" \
-device rtl8139,netdev=net0 \
-enable-kvm \
-m 2G \
-netdev user,id=net0 \
-serial mon:stdio \
-smp 2 \
-vga virtio \
;
GitHub aguas arriba .
Después de que se inicie QEMU, es posible que deba presionar enter para que se muestre el menú de inicio. Selecciona Ubuntu
desde allí.
Entonces, el comienzo del arranque dice:
error: no such device: root.
Press any key to continue...
pero incluso si no presiona ninguna tecla, el arranque continúa después de un breve tiempo de espera. Vota a favor este informe de error: https://bugs.launchpad.net/cloud-images/+bug/1726476
Una vez que finalice el arranque, inicie sesión con:
- nombre de usuario:
ubuntu
- contraseña:
asdfqwer
Internet funciona normalmente.
Imagen de la nube arm64
TODO: Noté que a veces ocurre un error al usar esto: https://bugs.launchpad.net/cloud-images/+bug/1818197
Muy similar a amd64, pero necesitamos algo de magia negra UEFI para que arranque.
sudo apt-get install cloud-image-utils qemu-system-arm qemu-efi
# Get the image.
img=ubuntu-18.04-server-cloudimg-arm64.img
if [ ! -f "$img" ]; then
wget "https://cloud-images.ubuntu.com/releases/18.04/release/${img}"
qemu-img resize "$img" +128G
fi
# For the password.
user_data=user-data.img
if [ ! -f "$user_data" ]; then
cat >user-data <<EOF
#cloud-config
password: asdfqwer
chpasswd: { expire: False }
ssh_pwauth: True
EOF
cloud-localds "$user_data" user-data
# Use the EFI magic. Picked up from:
# https://wiki.ubuntu.com/ARM64/QEMU
dd if=/dev/zero of=flash0.img bs=1M count=64
dd if=/usr/share/qemu-efi/QEMU_EFI.fd of=flash0.img conv=notrunc
dd if=/dev/zero of=flash1.img bs=1M count=64
fi
qemu-system-aarch64 \
-M virt \
-cpu cortex-a57 \
-device rtl8139,netdev=net0 \
-m 4096 \
-netdev user,id=net0 \
-nographic \
-smp 4 \
-drive "if=none,file=${img},id=hd0" \
-device virtio-blk-device,drive=hd0 \
-drive "file=${user_data},format=raw" \
-pflash flash0.img \
-pflash flash1.img \
;
GitHub aguas arriba .
debootstrap
amd64
No es una imagen prefabricada, pero descarga todos los paquetes prefabricados, por lo que también es rápida, pero también mucho más configurable y útil.
#!/usr/bin/env bash
set -eux
debootstrap_dir=debootstrap
root_filesystem=debootstrap.ext2.qcow2
sudo apt-get install \
debootstrap \
libguestfs-tools \
qemu-system-x86 \
;
if [ ! -d "$debootstrap_dir" ]; then
# Create debootstrap directory.
# - linux-image-generic: downloads the kernel image we will use under /boot
# - network-manager: automatically starts the network at boot for us
sudo debootstrap \
--include linux-image-generic \
bionic \
"$debootstrap_dir" \
http://archive.ubuntu.com/ubuntu \
;
sudo rm -f "$root_filesystem"
fi
linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"
if [ ! -f "$root_filesystem" ]; then
# Set root password.
echo 'root:root' | sudo chroot "$debootstrap_dir" chpasswd
# Remount root filesystem as rw.
cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF
# Automaticaly start networking.
# Otherwise network commands fail with:
# Temporary failure in name resolution
# /ubuntu/1045278/ubuntu-server-18-04-temporary-failure-in-name-resolution/1080902#1080902
cat << EOF | sudo tee "$debootstrap_dir/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF
sudo ln -sf "$debootstrap_dir/etc/systemd/system/dhclient.service" \
"${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"
# Why Ubuntu, why.
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
sudo chmod +r "${linux_image}"
# Generate image file from debootstrap directory.
# Leave 1Gb extra empty space in the image.
sudo virt-make-fs \
--format qcow2 \
--size +1G \
--type ext2 \
"$debootstrap_dir" \
"$root_filesystem" \
;
sudo chmod 666 "$root_filesystem"
fi
qemu-system-x86_64 \
-append 'console=ttyS0 root=/dev/sda' \
-drive "file=${root_filesystem},format=qcow2" \
-enable-kvm \
-serial mon:stdio \
-m 2G \
-kernel "${linux_image}" \
-device rtl8139,netdev=net0 \
-netdev user,id=net0 \
;
GitHub aguas arriba .
Esto arranca sin ningún error o advertencia del sistema.
Ahora desde la terminal, inicie sesión con root
/ root
, y luego verifique que Internet funcione con los siguientes comandos:
printf 'GET / HTTP/1.1\r\nHost: example.com\r\n\r\n' | nc example.com 80
apt-get update
apt-get install hello
hello
Usamos nc
como se explica en /programming/32341518/how-to-make-an-http-get-request-manually-with-netcat/52662497#52662497 porque:
Versión de Debian análoga: /unix/275429/creating-bootable-debian-image-with-debootstrap/473256#473256
Construye tu propio núcleo
Ya que estamos aquí:
git clone git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git
cd ubuntu-bionic
# Tag matches the working kernel that debootstrap downloaded for us.
git checkout Ubuntu-4.15.0-20.21
fakeroot debian/rules clean
debian/rules updateconfigs
fakeroot debian/rules build-generic
linux_image="$(pwd)/debian/build/build-generic/arch/x86_64/boot/bzImage"
Esto produjo exactamente la misma configuración y creo que usó exactamente el mismo código fuente que el Ubuntu empaquetado que debootstrap
descargó como se explica en: ¿Dónde puedo obtener el archivo .config del kernel 11.04?
Luego lo parcheé con:
diff --git a/init/main.c b/init/main.c
index b8b121c17ff1..542229349efc 100644
--- a/init/main.c
+++ b/init/main.c
@@ -516,6 +516,8 @@ asmlinkage __visible void __init start_kernel(void)
char *command_line;
char *after_dashes;
+ pr_info("I'VE HACKED THE LINUX KERNEL!!!");
+
set_task_stack_end_magic(&init_task);
smp_setup_processor_id();
debug_objects_early_init();
y reconstruir:
fakeroot debian/rules build-generic
e imprimió mi mensaje durante el arranque:
I'VE HACKED THE LINUX KERNEL!!!
Sin embargo, la reconstrucción no fue muy rápida, así que ¿tal vez hay un mejor comando? Solo esperaba que dijera:
Kernel: arch/x86/boot/bzImage is ready (#3)
y siguió adelante con la carrera.
debootstrap arm64
El procedimiento fue similar al de amd64, pero con las siguientes diferencias:
1)
Debemos hacer dos etapas debootstrap
:
- primero con
--foreign
solo descargar los paquetes
- luego instalamos QEMU estática en el
chroot
- luego hacemos la instalación del paquete
--second-stage
usando la emulación de modo de usuario QEMU +binfmt_misc
Ver también: ¿Qué es debootstrap - segunda etapa para
2) el arranque del kernel predeterminado falla al final con:
[ 0.773665] Please append a correct "root=" boot option; here are the available partitions:
[ 0.774033] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
La lista de particiones vacía indica que hay un error grave con el controlador de disco, después de probar un poco la opción que falta es:
CONFIG_VIRTIO_BLK=y
Creo que funciona cuando uso el ISO porque los módulos deben cargarse desde el initrd.
Intenté usar otros tipos de discos, pero virtio es el único valor válido para -drive if=
cuándo -M virt
, que es el tipo de máquina más sano hoy en día.
Por lo tanto, debemos recompilar nuestro propio núcleo con esa opción habilitada, como se explica aquí: al compilar el núcleo de forma cruzada, ¿cómo puedo evitar que se limpie cada vez que solo quiero modificar un archivo?
¡Los desarrolladores de Ubuntu deberían activar esta CONFIG y
por defecto! ¡Es muy útil!
TODO: la red no funciona, el mensaje de error es:
root@ciro-p51:~# systemctl status dhclient.service
root@ciro-p51:~# cat f
● dhclient.service - DHCP Client
Loaded: loaded (/etc/systemd/system/dhclient.service; enabled; vendor preset: enabled)
Active: failed (Result: protocol) since Sun 2018-01-28 15:58:42 UTC; 2min 2s ago
Docs: man:dhclient(8)
Process: 171 ExecStart=/sbin/dhclient -4 -q (code=exited, status=0/SUCCESS)
Jan 28 15:58:40 ciro-p51 systemd[1]: Starting DHCP Client...
Jan 28 15:58:42 ciro-p51 dhclient[171]: No broadcast interfaces found - exiting.
Jan 28 15:58:42 ciro-p51 systemd[1]: dhclient.service: Can't open PID file /var/run/dhclient.pid (yet?) after start: No such file or directory
Jan 28 15:58:42 ciro-p51 systemd[1]: dhclient.service: Failed with result 'protocol'.
Jan 28 15:58:42 ciro-p51 systemd[1]: Failed to start DHCP Client.
Aquí está el script totalmente automatizado:
#!/usr/bin/env bash
# /ubuntu/281763/is-there-any-prebuilt-qemu-ubuntu-image32bit-online/1081171#1081171
set -eux
debootstrap_dir=debootstrap
root_filesystem=debootstrap.ext2.qcow2
sudo apt-get install \
gcc-aarch64-linux-gnu \
debootstrap \
libguestfs-tools \
qemu-system-aarch64 \
qemu-user-static \
;
if [ ! -d "$debootstrap_dir" ]; then
sudo debootstrap \
--arch arm64 \
--foreign \
bionic \
"$debootstrap_dir" \
http://ports.ubuntu.com/ubuntu-ports \
;
sudo mkdir -p "${debootstrap_dir}/usr/bin"
sudo cp "$(which qemu-aarch64-static)" "${debootstrap_dir}/usr/bin"
sudo chroot "$debootstrap_dir" /debootstrap/debootstrap --second-stage
sudo rm -f "$root_filesystem"
fi
linux_image="$(printf "${debootstrap_dir}/boot/vmlinuz-"*)"
if [ ! -f "$root_filesystem" ]; then
# Set root password.
echo 'root:root' | sudo chroot "$debootstrap_dir" chpasswd
# Remount root filesystem as rw.
cat << EOF | sudo tee "${debootstrap_dir}/etc/fstab"
/dev/sda / ext4 errors=remount-ro,acl 0 1
EOF
# Automaticaly start networking.
# Otherwise network commands fail with:
# Temporary failure in name resolution
# /ubuntu/1045278/ubuntu-server-18-04-temporary-failure-in-name-resolution/1080902#1080902
cat << EOF | sudo tee "${debootstrap_dir}/etc/systemd/system/dhclient.service"
[Unit]
Description=DHCP Client
Documentation=man:dhclient(8)
Wants=network.target
Before=network.target
[Service]
Type=forking
PIDFile=/var/run/dhclient.pid
ExecStart=/sbin/dhclient -4 -q
[Install]
WantedBy=multi-user.target
EOF
sudo ln -sf "${debootstrap_dir}/etc/systemd/system/dhclient.service" \
"${debootstrap_dir}/etc/systemd/system/multi-user.target.wants/dhclient.service"
# Why Ubuntu, why.
# https://bugs.launchpad.net/ubuntu/+source/linux/+bug/759725
sudo chmod +r "${linux_image}"
# Generate image file from debootstrap directory.
# Leave 1Gb extra empty space in the image.
sudo virt-make-fs \
--format qcow2 \
--size +1G \
--type ext2 \
"$debootstrap_dir" \
"$root_filesystem" \
;
sudo chmod 666 "$root_filesystem"
fi
# Build the Linux kernel.
linux_image="$(pwd)/linux/debian/build/build-generic/arch/arm64/boot/Image"
if [ ! -f "$linux_image" ]; then
git clone --branch Ubuntu-4.15.0-20.21 --depth 1 git://kernel.ubuntu.com/ubuntu/ubuntu-bionic.git linux
cd linux
patch -p1 << EOF
diff --git a/debian.master/config/config.common.ubuntu b/debian.master/config/config.common.ubuntu
index 5ff32cb997e9..8a190d3a0299 100644
--- a/debian.master/config/config.common.ubuntu
+++ b/debian.master/config/config.common.ubuntu
@@ -10153,7 +10153,7 @@ CONFIG_VIDEO_ZORAN_ZR36060=m
CONFIG_VIPERBOARD_ADC=m
CONFIG_VIRTIO=y
CONFIG_VIRTIO_BALLOON=y
-CONFIG_VIRTIO_BLK=m
+CONFIG_VIRTIO_BLK=y
CONFIG_VIRTIO_BLK_SCSI=y
CONFIG_VIRTIO_CONSOLE=y
CONFIG_VIRTIO_INPUT=m
EOF
export ARCH=arm64
export $(dpkg-architecture -aarm64)
export CROSS_COMPILE=aarch64-linux-gnu-
fakeroot debian/rules clean
debian/rules updateconfigs
fakeroot debian/rules DEB_BUILD_OPTIONS=parallel=`nproc` build-generic
cd -
fi
qemu-system-aarch64 \
-append 'console=ttyAMA0 root=/dev/vda rootfstype=ext2' \
-device rtl8139,netdev=net0 \
-drive "file=${root_filesystem},format=qcow2" \
-kernel "${linux_image}" \
-m 2G \
-netdev user,id=net0 \
-serial mon:stdio \
-M virt,highmem=off \
-cpu cortex-a57 \
-nographic \
;
GitHub Upstream .
Imagen de escritorio
Ver: ¿Cómo ejecutar el escritorio de Ubuntu en QEMU?
Requiere pasar por el instalador manualmente, pero es lo más estable que puede hacer, y está muy bien si solo desea obtener una VM para uso interactivo que se ejecute de vez en cuando.
Para aarch64, todavía no he conseguido que funcione el escritorio, tal vez esté atento: ¿Cómo ejecutar Ubuntu 16.04 ARM en QEMU?