如何在每次启动时循环浏览grub背景图像

最终答案已经公布

在阅读整个问题之前,请注意以下答案。

问题的简短版本

在Bash中如何找到此文件中的下一个项目?

  • … / 640×480,A.JPG
  • … / 640×480,B.JPG
  • … / 640×480,C.JPG

当前项目嵌入此字符串中?

GRUB_BACKGROUND="/home/rick/Pictures/Wallpaper/640x480-a.jpg" 

如果当前项是最后一个文件条目,则需要选择第一个文件条目。 需要在grub中更新新条目以进行下一次引导。

到目前为止做了什么

我有Grub的多个背景图片。 手动编辑/etc/default/grub来更改背景图像,然后运行sudo update-grub非常耗时,我可能会忘记这样做。 我希望每次启动/重启都会自动完成。

我已经设置了一个名为/etc/cron.d/cycle-grub-background的cron作业,其中包含:

 SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin @reboot root /usr/local/bin/cron-reboot-cycle-grub-background 

我相信这项工作将在每次重启时运行,而不是每天运行,因为有时笔记本电脑很多天没有重启,我不想跳过可用的grub背景图像。

忽略下面充满假设和危险错误的代码

以下代码仅供历史参考。 请不要使用它,因为它严重破坏和设计不佳。

文件/usr/local/bin/cron-reboot-cycle-grub-background包含:

 #!/bin/bash # NAME: cron-reboot-cycle-grub-background # DATE: February 18, 2017 # PATH: /usr/local/bin/ # DESC: Cycle through available 640x480 wallpaper for grub background # Get list of all grub images when 1920x1080 monitor has been downgraded # to more readable 640x480 pixel format ls /home/rick/Pictures/Wallpaper/640x480* > /tmp/grub-backgrounds # Find this boot grub background image name cat /etc/default/grub | grep BACKGROUND > /tmp/grub-background # case? to find current background in backgrounds? # Can we run systemd inhibit lock to prevent shutdown or reboot now? # sed? to change to next background in /etc/default/grub # Copy /etc/default/grub to /boot/grub/grub.cfg is the same as # running sudo update-grub with out the 12 second delay cp /boot/grub/grub.cfg /boot/grub/grub.cfg~ cp /etc/default/grub /boot/grub/grub.cfg # Can we release systemd inhibitor now? # Now next reboot will have new background image exit 0 

假设文件/tmp/grub-backgrounds包含:

 640x480-a.jpg 640x480-b.jpg 640x480-c.jpg 

假设文件/tmp/grub-background包含:

 GRUB_BACKGROUND="/home/rick/Pictures/Wallpaper/640x480-a.jpg" 

然后列表中的下一张图片将是...640x480-b.jpg

但是如果当前的图片是...c.jpg那么下一张图片会重置到列表的开头,应该是...a.jpg

我需要将这个圆圈照原样。 我认为某种file case后跟sed是有序的(你可以通过代码注释看到),但我无法完全理解它。

一如既往,我很感激所有的想法。

简答

 #!/bin/bash CURR_FILE=$(cat /etc/default/grub | grep BACKGROUND) # Get grub current line CURR_FILE=$(cut -d "=" -f 2 <<< "$CURR_FILE") # File name only CURR_FILE=$(echo "$CURR_FILE" | tr -d '"') # Remove double quotes for ALL_FILES in /home/rick/Pictures/Wallpaper/640x480*; do # Loop through every file if [[ "$FIRST_FILE" == "" ]]; then FIRST_FILE="$ALL_FILES" elif [[ "$MATCH_FILE" != "" ]]; then NEXT_FILE="$ALL_FILES" break # We've got it! fi if [[ "$CURR_FILE" == "$ALL_FILES" ]]; then MATCH_FILE="$ALL_FILES" # We found our current file entry fi done # If $NEXT_FILE empty we hit end of list so use First file name if [[ "$NEXT_FILE" == "" ]]; then NEXT_FILE="$FIRST_FILE" fi # replace background file name in grub source file sed -i "s|$CURR_FILE|$NEXT_FILE|g" /etc/default/grub # replace background file name in grub configuration file # Backup... just in case :) cp /boot/grub/grub.cfg /boot/grub/grub.cfg~ # Short cut so we don't have to run `sudo update-grub` sed -i "s|$CURR_FILE|$NEXT_FILE|g" /boot/grub/grub.cfg 

积分

经过大量的谷歌搜索,连同反复试验,问题得到了90%的解决。 然后在Pilot6 , Terdon和Zanna的聊天室里给予了难以置信的帮助,对我来说最困难的部分(使用sed )已经解决了。

cl-netbox和Byte Commander也发布了一些评论性评论,让Ask Ubuntu的聊天室成为我在网上二十年来经常光顾的最友好最同质的技术聊天室。

使用cron每次启动时调用脚本

创建包含以下内容的文件/etc/cron.d/cycle-grub-background

 SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin @reboot root /usr/local/bin/cron-reboot-cycle-grub-background 

注意:使用sudo权限创建文件。 无需将其标记为可执行文件,但这样做也不会受到影响。

使用调试和变量声明的长答案

 #!/bin/bash # NAME: cron-reboot-cycle-grub-background # DATE: February 18, 2017. Modified April 9, 2017. # PATH: /usr/local/bin/ # DESC: Cycle through available wallpaper for grub background CURR_FILE=$(cat /etc/default/grub | grep BACKGROUND) # Get grub current line echo "Grub line: $CURR_FILE" CURR_FILE=$(cut -d "=" -f 2 <<< "$CURR_FILE") # File name only CURR_FILE=$(echo "$CURR_FILE" | tr -d '"') # Remove double quotes echo "Current file: $CURR_FILE" FIRST_FILE="" NEXT_FILE="" MATCH_FILE="" for ALL_FILES in /home/rick/Pictures/1600x900/*; do # Loop through every file if [[ "$FIRST_FILE" == "" ]]; then FIRST_FILE="$ALL_FILES" fi if [[ "$MATCH_FILE" != "" ]]; then NEXT_FILE="$ALL_FILES" break # We've got it! fi if [[ "$CURR_FILE" == "$ALL_FILES" ]]; then MATCH_FILE="$ALL_FILES" # We found our current file entry fi done # If $NEXT_FILE empty we hit end of list so use First file name if [[ "$NEXT_FILE" == "" ]]; then NEXT_FILE="$FIRST_FILE" fi echo "First file: $FIRST_FILE" echo "Match file: $MATCH_FILE" echo "Next file: $NEXT_FILE" # replace background file name in grub source file sed -i "s|$CURR_FILE|$NEXT_FILE|g" /etc/default/grub # replace background file name in grub control file # Backup... just in case :) cp /boot/grub/grub.cfg /boot/grub/grub.cfg~ # Short cut so we don't have to run `sudo update-grub` sed -i "s|$CURR_FILE|$NEXT_FILE|g" /boot/grub/grub.cfg # Now next reboot will have new background image exit 0 

几点说明

长版本答案使用与短版本不同的图片目录名称。 在任何一种情况下,您都需要更新到存储图像的目录。

sed通常使用/作为分隔符但是我们的路径/文件名包含/所以我们使用| 代替。

更改/etc/default/grub后的常规方法是运行sudo update-grub 。 但是,在我的机器上需要12秒才能在运行这个冗长的过程时重新启动机器。 鉴于必须使用systemd-inhibit

快捷方式使用sed/boot/grub/grub.cfg搜索和替换。 如果出现问题,将备份文件。 在此计算机上设置cron reboot的方式,但是在键入登录密码并打开终端窗口以检查更新时完成该过程。

从任何系统的启动脚本运行的简单脚本可以允许单步执行特定文件夹中的壁纸图像,每次重启一步。 它比使用update-grub和更简单的逻辑快得多,而且它永远不需要运行update-grub 。 缺点是,如果要将图像添加到列表中,则必须编辑脚本或编写稍微复杂的脚本以处理变量列表长度,并且无法从文件名中分辨出每个文件中的图像。

 mv wallpaper3.png wallpaperx.png mv wallpaper2.png wallpaper3.png mv wallpaper1.png wallpaper2.png mv wallpaperx.png wallpaper1.png 

即使有几十个文件的列表,这个脚本的更长,真实版本应该在SSD上的几分之一秒内执行,或者在盘片驱动器上几秒钟内执行。 它很简单,逻辑很明显,几个月或几年之后,你不会怀疑这个脚本所启动的脚本应该做什么。