[SOLVED] Executing command through qm guest exec limitations?

devilkin

Member
May 11, 2020
26
3
23
Hi,

I'm currently trying to figure out what's going when executing the following command through qm guest exec:

Code:
qm guest exec 110 --timeout 0 -- /bin/bash -c 'docker exec mariadb mysqldump --all-databases -u root -pmyfancypw'

Executing the docker command directly on the guest works, but not via qm guest exec. In the end I get this error:
Code:
VM 110 qmp command 'guest-exec-status' failed - got timeout

I'm not entirely sure how the redirection of stdout of the docker exec through the qemu guest agent works. Executing other docker commands works fine.
 
Hi,

Does the other command work? e.g.:

Bash:
qm guest exec 110 --timeout 0 -- /bin/bash -c 'docker run hello-world'
 
Hi,

Does the other command work? e.g.:

Bash:
qm guest exec 110 --timeout 0 -- /bin/bash -c 'docker run hello-world'

Yep, without issue.

Bash:
# qm guest exec 110 --timeout 0 -- /bin/bash -c 'docker run hello-world'
{
   "err-data" : "Unable to find image 'hello-world:latest' locally\nlatest: Pulling from library/hello-world\n2db297
10123e: Pulling fs layer\n2db29710123e: Verifying Checksum\n2db29710123e: Download complete\n2db29710123e: Pull comp
lete\nDigest: sha256:2498fce14358aa50ead0cc6c19990fc6ff866ce72aeb5546e1d59caac3d0d60f\nStatus: Downloaded newer imag
e for hello-world:latest\n",
   "exitcode" : 0,
   "exited" : 1,
   "out-data" : "\nHello from Docker!\nThis message shows that your installation appears to be working correctly.\n\
nTo generate this message, Docker took the following steps:\n 1. The Docker client contacted the Docker daemon.\n 2.
 The Docker daemon pulled the \"hello-world\" image from the Docker Hub.\n    (amd64)\n 3. The Docker daemon created
 a new container from that image which runs the\n    executable that produces the output you are currently reading.\
n 4. The Docker daemon streamed that output to the Docker client, which sent it\n    to your terminal.\n\nTo try som
ething more ambitious, you can run an Ubuntu container with:\n $ docker run -it ubuntu bash\n\nShare images, automat
e workflows, and more with a free Docker ID:\n https://hub.docker.com/\n\nFor more examples and ideas, visit:\n http
s://docs.docker.com/get-started/\n\n"
}
 
I ended up with a different approach:
* Executing the command with output on the VM side, dumping to a local file
* Base64 encoded the file
* Downloaded it using pvesh file-read
* Decode the file

Bash:
#!/bin/bash

VM_ID=<VM_ID>
NODE_NAME=<node-name>
RETENTION=30
VM_DIR=/var/tmp
DIR=/backupdir

declare -A CONTAINERS

CONTAINERS[container-name]="root-pw"

for CONTAINER in "${!CONTAINERS[@]}"; do
  EXITED=0

  BACKUP_DIR="${DIR}/${CONTAINER}"
  BACKUP_FILE="mysql_${CONTAINER}_$(date '+%F').databases.sql.xz"
  VM_BACKUP_FILE="${BACKUP_FILE}.base64"

  if [ ! -d "${BACKUP_DIR}" ]; then
    mkdir -p "${BACKUP_DIR}"
  fi

  # Start backup to VM disk
  CMD_PID=$(qm guest exec ${VM_ID} --synchronous 0 -- /bin/sh -c "docker exec ${CONTAINER} mysqldump --all-databases -u root -p${CONTAINERS[${CONTAINER}]} | xz | base64 > ${VM_DIR}/${VM_BACKUP_FILE}" | jq -r .pid)

  # Wait for backup to finish
  while [ ${EXITED} -eq 0 ]; do
    read EXITED EXITCODE ERROR < <(qm guest exec-status ${VM_ID} ${CMD_PID} | jq -r '[.exited, .exitcode // 0, ."err-data" // "None"]|@sh')
    sleep 5
  done

  if [ ${EXITCODE} -ne 0 ]; then
    echo "error occurred taking backup: ${ERROR}"
    exit 1
  fi

  # Download backup
  set -o pipefail
  pvesh get /nodes/cube/${NODE_NAME}/${VM_ID}/agent/file-read --output-format json --file ${VM_DIR}/${VM_BACKUP_FILE} 2>/dev/null | jq -r .content | base64 -d > ${BACKUP_DIR}/${BACKUP_FILE}
  if [ ${?} -ne 0 ]; then
    echo "error occurred downloading backup!"
    exit 1
  fi

  # Test backup
  unxz -t ${BACKUP_DIR}/${BACKUP_FILE}
 
  # Delete temporary file 
  read EXITED EXITCODE ERROR < <(qm guest exec ${VM_ID} --timeout=0 -- rm ${VM_DIR}/${VM_BACKUP_FILE} | jq -r '[.exited, .exitcode // 0, ."err-data" // "None"]|@sh')
  if [ ${EXITCODE} -ne 0 ]; then
    echo "error occurred deleting temporary file: ${ERROR}"
    exit 1
  fi
  
  # Cleanup local backup dir
  find ${BACKUP_DIR} -ctime +${RETENTION} -exec rm {} \; 
done
 
Last edited:
  • Like
Reactions: Moayad

About

The Proxmox community has been around for many years and offers help and support for Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
We think our community is one of the best thanks to people like you!

Get your subscription!

The Proxmox team works very hard to make sure you are running the best software and getting stable updates and security enhancements, as well as quick enterprise support. Tens of thousands of happy customers have a Proxmox subscription. Get yours easily in our online shop.

Buy now!