如何等待 snapd 自动刷新完成?

如何等待 snapd 自动刷新完成?

gsutil在 Google Compute Engine 上,我有一个使用和的启动脚本gcloud,它们是google-cloud-sdk预安装在ubuntu-minimal-1804-lts 公众形象,这是我正在使用的图像的基础图像。但是当我今天运行启动脚本时,它失败了 8 次中的 4 次,因为它决定在运行的snapd同时自动刷新。startup-script

在启动脚本中,我如何等到 snap 的自动刷新完成?

以下是我运行的命令,用来确定是否snapd与启动脚本同时更新:

$ snap changes --abs-time
ID   Status  Spawn                 Ready                 Summary
3    Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Auto-refresh snaps "core", "google-cloud-sdk"

$ snap tasks 3 --abs-time
Status  Spawn                 Ready                 Summary
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:45Z  Ensure prerequisites for "google-cloud-sdk" are available
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:46Z  Download snap "google-cloud-sdk" (82) from channel "stable/ubuntu-18.04"
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:47Z  Fetch and check assertions for snap "google-cloud-sdk" (82)
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:48Z  Mount snap "google-cloud-sdk" (82)
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:48Z  Run pre-refresh hook of "google-cloud-sdk" snap if present
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:48Z  Stop snap "google-cloud-sdk" services
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:48Z  Remove aliases for snap "google-cloud-sdk"
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:48Z  Make current revision for snap "google-cloud-sdk" unavailable
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Copy snap "google-cloud-sdk" data
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Setup snap "google-cloud-sdk" (82) security profiles
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Make snap "google-cloud-sdk" (82) available to the system
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Automatically connect eligible plugs and slots of snap "google-cloud-sdk"
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Set automatic aliases for snap "google-cloud-sdk"
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Setup snap "google-cloud-sdk" aliases
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Run post-refresh hook of "google-cloud-sdk" snap if present
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Start snap "google-cloud-sdk" (82) services
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Clean up "google-cloud-sdk" (82) install
Done    2019-05-16T18:08:34Z  2019-05-16T18:08:49Z  Run configure hook of "google-cloud-sdk" snap if present

$ journalctl -u google-startup-scripts
May 16 18:08:39 my-instance startup-script[1469]: INFO startup-script-url: + gsutil cp gs://my-bucket/app.tar.gz /opt/my-bucket/app.tar.gz
May 16 18:08:41 my-instance startup-script[1469]: INFO startup-script-url: /snap/google-cloud-sdk/41/usr/bin/python2: relocation error: /lib/x86_64-linux-gnu/libnss_dns.so.2: symbol 
__resolv_context_get, version GLIBC_PRIVATE not defined in file libc.so.6 with link time reference

在另一个例子中,gsutil失败并显示不同的消息:

ERROR: (gsutil) /snap/google-cloud-sdk/41/usr/bin/python2: command not found

答案1

我一直在尝试重现您的问题,通过使用您所述的“ubuntu-minimal-1804-lts”图像创建一个实例

gcloud compute instances create \
--image-family ubuntu-minimal-1804-lts \
--image-project ubuntu-os-cloud \
--machine-type n1-standard-1 \
--boot-disk-size=15 \
--boot-disk-type=pd-ssd \
--zone=europe-west1-c \
--tags=allow-incoming-ssh \
--metadata=startup-script-url="gs://testinggrounds/startup.sh" \
ubuntu-test

然后重启几次

for i in {1..7}; \
do \
gcloud compute instances reset ubuntu-test --zone europe-west1-c; \
sleep 120s; \
done

但我没有解决您所说的这个问题。

四处寻找你得到的错误,我发现报告该问题的用户在帖子中提出了一个非常相似的问题,可能与您发现的相同。该问题应该已得到修复,正如其背后的团队所报告的那样。您能否检查一下你的 Ubuntu 18.04 镜像的日期在我分享的这个帖子的开始日期之前?也许通过使用更新图片你的问题就解决了。

我看到您说这个问题是前不久突然出现的,所以可能不是版本问题,但检查一下也无妨。

如果不是这样,那么我建议延迟启动脚本的执行或尝试使其在其他 snapd 服务之后运行

[Unit]
Description=Google Compute Engine Startup Scripts
After=local-fs.target network-online.target network.target rsyslog.service
After=google-instance-setup.service google-network-daemon.service
After=cloud-final.service multi-user.target
After=snapd.seeded.service
After=snapd.service
Wants=local-fs.target network-online.target network.target cloud-final.service
Wants=snapd.seeded.service

[Service]
ExecStartPre=/bin/sleep 20
ExecStart=/usr/bin/google_metadata_script_runner --script-type startup
KillMode=process
Type=oneshot
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/snap/bin

[Install]
WantedBy=multi-user.target

此文件位于/lib/systemd/system/google-startup-scripts.service。我添加了After=snapd.serviceExecStartPre=/bin/sleep 20以尝试延迟服务的执行。您的文件应该与上面的文件完全一样,没有我的添加。

如果仍然不起作用,您可以尝试使用该After=指令添加其他 snap 服务,因为 systemd 服务文件夹中还有一些其他服务:

$ ls /lib/systemd/system/ | grep snap

snapd.autoimport.service
snapd.core-fixup.service
snapd.failure.service
snapd.seeded.service
snapd.service
snapd.snap-repair.service
snapd.snap-repair.timer
snapd.socket
snapd.system-shutdown.service

希望能帮助到你!

答案2

我把它放在启动脚本的顶部,snap changes直到一切都运行完毕:Done

# Returns 0 if snapd is not updating google-cloud-sdk
# (nothing has happened, or all changes are Done, Hold, Error)
# Returns 1 if snapd is updating google-cloud-sdk
# (there is at least one chnage that is Doing, Abort, Undo, or Undoing)
# Echos the offending line
# https://serverfault.com/questions/967674/how-to-wait-for-snapd-auto-refresh-to-complete
function isSnapIdle {
  # For the format of snap changes, see:
  # see https://github.com/snapcore/snapd/blob/8ae45c207f3c488f0ab0dc3615661df9b0854b20/overlord/state/change.go
  # and https://github.com/snapcore/snapd/blob/8ae45c207f3c488f0ab0dc3615661df9b0854b20/cmd/snap/cmd_changes.go#L124
  local line
  local changes
  if changes=$(snap changes google-cloud-sdk); then
    :
  else
    # When snap is upgrading itself, snap changes can fail
    echo "snap changes gave error $? $changes"
    return 2
  fi
  while read line; do
    local state=$(echo "$line" | awk '{print $2}')
    if [ "$state" = Do ] || [ "$state" = Doing ] || [ "$state" = Abort ] || [ "$state" = Undo ] || [ "$state" = Undoing ]; then
      echo "$line"
      return 1
    fi
  done < <(echo "$changes" | tail -n +2)
  return 0
}
function waitUntilSnapIdle {
  local lastSnapChange=
  local snapChange
  while ! snapChange=$(isSnapIdle); do
    if [ "$snapChange" != "$lastSnapChange" ]; then
      echo >&2 "Waiting for snapd to finish installing: $snapChange"
    fi
    lastSnapChange="$snapChange"
    sleep 1
  done
  echo >&2 "Snapd does not appear to be installing google-cloud-sdk"
}

waitUntilSnapIdle

答案3

我遇到了同样的问题,并将原因归咎于 snap 的自动更新!就我而言,等待snap refresh花费了太多时间,而且一个人仍然可以管理作业数量,所以我只是减少了允许的刷新窗口到工作周中较为平静的部分。

例如尝试:

# Allows snap refreshes on Monday at 10AM and also on Friday at 3PM
sudo snap set system refresh.timer=mon,10:00,,fri,15:00

相关内容