当我的计算机进入睡眠状态时,我正在浏览器中下载一个大文件。
下载丢失。
有什么办法可以防止这种情况发生吗?
答案1
是的,我也遇到过这个问题。解决它的唯一方法是不要让电脑进入睡眠状态(即使屏幕关闭,我记不清怎么做了,抱歉),或者使用支持暂停下载的浏览器。上次 Vivaldi 对我有用。
答案2
当计算机进入睡眠状态时,计算机将进入低功耗状态,只允许足够的电量流向 RAM 以保持其内容正常运行。不幸的是,在大多数情况下,这也意味着网卡的电源被切断,导致系统进入睡眠状态。
此时,您唯一的选择是停止系统睡眠。一种方法是在电源设置中将“黑屏”更改为“永不”。
您可以随时使用下载管理器恢复下载,但仍然会遇到系统离线时下载暂停的问题。
答案3
睡眠会中断几乎所有操作系统的下载。下载期间,您需要让计算机保持唤醒状态。
您可以手动执行此操作,但我自己编写了一个小脚本,可以自动防止我的笔记本电脑在下载期间进入睡眠状态。我不是专家,所以我会在适用的地方发布我的所有来源/参考资料。我希望这个答案会是一个有用的资源 :D
这个问题启发了我的回答:
我将在下面的链接中解释如何设置我的脚本版本:
TODO DONE:我意识到通过检查下载文件夹的大小来感知下载比使用 更好ifstat
。这是因为如果您从浏览器(例如 Youtube)观看视频,程序会认为您正在下载文件,但实际上您并没有下载。
这是新命令:
du -ks ~/Downloads
该程序仍可工作,但在“下载”(/观看 YouTube 视频)后,直到 SLEEP_TIME 过去,您都无法手动触发睡眠。然后,如果在 Ubuntu 设置中配置了睡眠,您的计算机将在之后进入睡眠状态。
Python 代码已更新,您不再需要它ifstat
。您可以安全地卸载它:
sudo apt remove ifstat
如何设置仅在下载期间防止睡眠的脚本:
步骤 0:(可选)
创建一个文件夹,用于保存此答案中的所有脚本。总共有 4 个脚本。
步骤 1:创建可以自动调用的 bash 文件来启用和禁用睡眠
- 创建一个名为的文件
enable-sleep.sh
,并输入以下代码:
sudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target
- 创建另一个用于禁用睡眠的文件,文件名为
disable-sleep.sh
:
sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
- 现在对这两个文件执行此答案中的步骤,以允许这两个文件都以 sudo 权限安全执行: 如何在脚本中执行 sudo 命令而不要求输入密码?
步骤 2:创建一个名为disable-sleep-during-downloads.py
- 确保您已安装
python
并acpi
拥有:
sudo apt update && sudo apt install python3 && sudo apt install acpi
创建一个名为的文件
disable-sleep-during-downloads.py
并使其可执行。将以下代码粘贴到其中,并填写[[GAPS]]:
#!/usr/bin/env python3
import subprocess
import time
# Get the output of a bash command
def get(cmd):
return subprocess.check_output(["/bin/bash", "-c", cmd]).decode("utf-8")
# Set a minimum speed (KiB/sec) to be considered a download activity.
# Would leave as 0 unless you're downloads folder increases in size when your not downloading something from the
# internet (extremely unlikely for most users)
# NOTE: This means that if you move a file into the downloads folder that is large enough, then sleep will be disabled, but
# it will get re-enabled after (LOOP_TIME * NO_OF_ITERATIONS_FOR_CONCLUSION) seconds has elapsed.
SPEED_LIMIT = 0
# The amount of time this script does nothing for, before checking if there's another download, in seconds.
# We want to make sure this script is not intensive on the CPU, so we make it sleep for several seconds.
# (This script has next to no impact on the processor if we sleep for several seconds).
# NOTE: If you work in the downloads folder often, then editing and saving files in the Downloads folder can trigger this
# script to disable sleep, and make it disable sleep for LOOP_TIME seconds, so just be wary, not really a problem for most users.
# This script will still work for you if you don't mind this either. It'll enable sleep after (LOOP_TIME * NO_OF_ITERATIONS_FOR_CONCLUSION) has elapsed
LOOP_TIME = 20
# The number of iterations we wait before we conclude no download is happening in a folder.
# Checking twice should be good enough, I can't see why it wouldn't be, but this is a configurable constant
# so I will leave it here just in case
NO_OF_ITERATIONS_FOR_CONCLUSION = 2
# All the folders you want to sense if there's a download going into it
# For most users, "~/Downloads" is sufficient, but sometimes applications download into different folders,
# You can add any other folders into this list below:
# DOWNLOAD_FOLDERS_PATHS = ["~/Downloads", "any/other", "path/'add it'/on"]
DOWNLOAD_FOLDERS_PATHS = ["~/Downloads"]
# The command to get the size of the downloads folder
size_of_downloads_cmd = "du -ks "
# The command to enable sleep
enable_sleep_cmd = (
r"sudo [[/PATH/TO]]/enable-sleep.sh"
)
# The command to disable sleep
disable_sleep_cmd = (
r"sudo [[/PATH/TO]]/disable-sleep.sh"
)
# The command to check if the ac-power is connected to the laptop
check_ac_power_is_connected = r"acpi -a | cut -d' ' -f3 | cut -d- -f1"
print(f"### DISABLE SLEEP ONLY DURING DOWNLOADS SCRIPT STARTED ###")
# The number of checks before we're certain no downloads are happening
# Why we don't keep track of no_of_checks per folder? TL;DR we don't need to
# If any single folder has a download, then we don't need to check the rest
# so we don't need to keep track of no_of_checks for every folder,
# just a single folder which has a download happening (doesn't even need to be the same one)
# This initial value will ensure sleep is enabled on first iteration if no downloads
# are happening
no_of_checks = NO_OF_ITERATIONS_FOR_CONCLUSION
try:
# Get our initial folder sizes
checks = [
int(get(size_of_downloads_cmd + path + "982heiu2qh&&&*TGI^$%E").split()[0])
for path in DOWNLOAD_FOLDERS_PATHS
]
print("~~ Enabling Sleep ~~")
print(get(enable_sleep_cmd))
is_sleep_enabled = True
print(f"### SETUP COMPLETE, STARTING INFINITE LOOP ###")
while True:
time.sleep(LOOP_TIME)
try:
print("\n###-###-###-###-###")
is_ac_connected = get(check_ac_power_is_connected).strip() == "on"
# To ensure sleep is not enabled mid-download (the case of NO_OF_ITERATIONS_FOR_CONCLUSION = 1)
any_downloads = False
for idx, path in enumerate(DOWNLOAD_FOLDERS_PATHS):
# Get the new folder size
check_next = int(get(size_of_downloads_cmd + path).split()[0])
# I used integer divide because we're I doubt we need to sense downloads of speeds smaller than 1KiB/s
# In case you ever need to, replace // with / below
current_download_speed_in_kib_s = (
check_next - checks[idx]
) // LOOP_TIME
# For testing purposes. Doesn't matter if you leave them uncommented or not
print(f"\nChecking path: {path}")
print(f"LOOP_TIME = {LOOP_TIME}")
print(f"is_ac_connected = {is_ac_connected}")
print(f"check_1 = {checks[idx]}")
# Now we have our download speed, we need to remember the previous download folder's size, to sense downloads
# This should always update, regardless of if there is a download or not
# because a download is a rate of increase in a folder, not is the folder bigger
# eg. I removed a large file from downloads during a download:
# - The folder is not bigger anymore, and may never be bigger than before
# the large file was removed. NO_OF_ITERATIONS_FOR_CONCLUSION prevents enabling sleep in such unexpected cases
# - But soon it will sense a rate of increase again from the download, and disable
# sleep again
checks[idx] = check_next
print(f"check_2 = {check_next}")
print(f"SPEED_LIMIT = {SPEED_LIMIT}KiB/s")
print(
f"current_download_speed_in_kb_s = {current_download_speed_in_kib_s}KiB/s"
)
# If the ac-power is connected, and the current download speed is above the speed limit
if is_ac_connected and current_download_speed_in_kib_s > SPEED_LIMIT:
if is_sleep_enabled:
print("!! Disabling Sleep !!")
print(get(disable_sleep_cmd))
is_sleep_enabled = False
# Get ready to start checking, or reset if a download is still happening
# (A check will be completed before making a conclusion, That's why its 1 not 0)
no_of_checks = 1
any_downloads = True
# There's no need to check other folders once we found a download is happening
break
# We increment after the for loop, since each folder has only been checked once during the for loop, or enable sleep again
# Sleep won't enable unless no_of_checks is not reset and there's no downloads and we've checked enough times
print(
"\n"
+ (
"All checks complete."
if no_of_checks >= NO_OF_ITERATIONS_FOR_CONCLUSION
else f"Check {no_of_checks} complete."
)
)
if (
(not is_sleep_enabled)
and (not any_downloads)
and no_of_checks >= NO_OF_ITERATIONS_FOR_CONCLUSION
):
print("~~ Enabling Sleep ~~")
print(get(enable_sleep_cmd))
is_sleep_enabled = True
elif no_of_checks < NO_OF_ITERATIONS_FOR_CONCLUSION:
no_of_checks += 1
except subprocess.CalledProcessError:
print("?? There was a CalledProcessError ??")
print(f"Sleep is {('en' if is_sleep_enabled else 'dis')}abled")
except Exception as e:
print(
f"There was an error. This script attempts to enable sleep again in the case of failure.\n{e}"
)
print("~~ Enabling Sleep ~~")
print(get(enable_sleep_cmd))
步骤 3:创建 bash 文件来运行并测试它
- 创建一个名为的文件
disable-sleep-during-downloads.sh
并粘贴以下命令(此文件不需要 sudo 权限):
flock --verbose -n /var/lock/disable-sleep-during-downloads.lock python3 [[PATH/TO]]/disable-sleep-during-downloads.py
flock
确保任何时候都只有一个此脚本实例在运行。使此文件可执行。(来源:https://www.tutorialspoint.com/ensure-only-one-instance-of-a-bash-script-is-running-on-linux)
- 现在您可以通过运行此文件来测试此脚本(您可能希望
SLEEP_TIME = 60
出于测试目的进行设置)
[[PATH/TO]]/disable-sleep-during-downloads.py
然后尝试运行下载,或者您可以使用互联网速度测试,看看在下载测试期间将交流电源插入笔记本电脑时它是否会禁用睡眠,并在测试后启用睡眠。(使用 Ctrl+C 停止脚本)
- 一旦您满意,请设置
SLEEP_TIME
笔记本电脑在交流电源下进入睡眠状态的时间。
步骤 4:将此脚本添加到登录时自动启动,然后重新启动。
- 转到系统设置,并在设置中添加此脚本以在自动启动时运行。
- 如果可以,请确保可以在交流电源断开或电池电量不足时启用睡眠模式,方法是
enable-sleep.sh
在交流电源断开后立即运行脚本:
然后重新启动系统。
步骤 5:测试脚本是否已成功自动启动
尝试再次运行脚本:
[[PATH/TO]]/disable-sleep-during-downloads.py
如果失败并说无法获取锁,则表示脚本已成功运行,因为这意味着已经有一个正在运行的实例。
步骤 6:转到 Ubuntu 设置并正常设置睡眠选项
现在您可以进入常规系统设置,并像平常一样设置所需的睡眠设置。此脚本不会干扰这些设置,您的计算机将像平常一样进入睡眠状态,但不会在下载期间进入睡眠状态。
希望这对你有帮助:D
故障排除
来源:https://unix.stackexchange.com/questions/174028/killing-a-shell-script-running-in-background
如果您需要在该脚本自动启动后将其关闭,请运行此命令,然后再次启用睡眠功能:
killall disable-sleep-during-downloads.sh
sudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target
然后进入设置并停止该脚本自动启动。
答案4
是的,将您的计算机配置为不进入睡眠状态(在电源选项中的某处)。
应用程序能够防止睡眠,因此您可以找到具有此功能的下载客户端。对于 FTP,Filezilla 具有此功能,但我不知道有哪个 HTTP 下载客户端具有此功能。但由于您使用的是 Ubuntu,也许保持清醒可以帮助。