Elisp代码以检查互联网连接


13

当我打开Emacs时,它将评估我的初始化文件,该文件包括通过Internet连接刷新我的软件包档案。当我没有互联网连接时,这是有问题的,因此在没有互联网连接的情况下启动Emacs时,我需要阻止执行该代码。为了解决此问题,我想知道当我没有互联网连接时是否有一种方法让Emacs忽略软件包刷新代码吗?

这是我的前几行init.el

;; Requisites: Emacs >= 24
(require 'package)
(package-initialize)

;; PACKAGE MANAGEMENT
(add-to-list 'package-archives 
  '("melpa" . "http://melpa.milkbox.net/packages/") t)

(package-refresh-contents)       

我想我可以添加代码来加载我的Emacs文件,如下所示:

;; Requisites: Emacs >= 24
(when (connected-to-internet-p)   ; I need this predicate function
  (require 'package)
  (package-initialize)
  (add-to-list 'package-archives 
               '("melpa" . "http://melpa.milkbox.net/packages/") t)
  (package-refresh-contents))

是否有(connected-to-internet)功能或类似方法来解决此问题?


2
这里有一个相关的答案stackoverflow.com/a/21065704/3170376
命名

2
为什么要在启动Emacs时刷新软件包归档文件?
phils 2015年

@Name不仅仅是相关的。它(假设它的作品)的答案。
马拉巴巴

1
我强烈建议您不要在每次启动时都运行package-refresh-contents。最有可能的是,当您首先在新计算机上拉下配置时,您将需要运行一次,然后再几个月都不需要它。有连接时执行此操作是解决此问题的错误答案,真正的问题是您根本不需要运行它。
Jordon Biondo

Answers:


7

好吧,如果您仍然希望自动刷新内容,则可以执行以下代码:

(defun can-retreive-packages ()
  (cl-loop for url in '("http://marmalade-repo.org/packages/"
                        "http://melpa.milkbox.net/packages/"
                        "http://elpa.gnu.org/packages/")
           do (condition-case e
                  (kill-buffer (url-retrieve-synchronously url))
                (error (cl-return)))
           finally (cl-return t)))

几乎没有应注意的事项:

  1. 这很慢,并且在正常启动时会很慢,所以我宁愿手动执行。
  2. 通常没有办法测试互联网连接。在尝试了一段时间后,您只能发现无法连接到特定服务。这也是它这么慢的原因之一。
  3. 该代码更多地说明了如何解决该问题。(ignore-errors (package-refresh-contents))如果您不在乎它是否成功,则可以轻松完成。

显然,这是正确的方法。在任何时候,Internet的某些部分都可以访问,而某些部分则不能访问,并且处理它的正确方法是探查连接性。
2015年

1
这也将创建一堆大的看不见的缓冲区,最好这样做(kill-buffer(url-ret ...))
Jordon Biondo

@JordonBiondo好的,要点了。还没想过
wvxvw

6

我从shell脚本中采用的一个简单解决方案是

(defun internet-up-p (&optional host)
    (= 0 (call-process "ping" nil nil nil "-c" "1" "-W" "1" 
                       (if host host "www.google.com"))))

您可以在*scratch*缓冲区中对此进行测试:

(message (if (internet-up-p) "Up" "Down"))
"Up"

我最喜欢此解决方案,因为它简单,快速,并且可以测试与更广泛的Internet的连接。
miguelmorin19年

4

您可以尝试的一件事就是功能network-interface-list。它返回网络接口及其IP地址的列表。

对我来说,这是当我同时连接到以太网和wifi时返回的内容:

(("en5" .
  [10 151 0 63 0])
 ("en0" .
  [10 151 2 76 0])
 ("lo0" .
  [127 0 0 1 0]))

当我关闭wifi时,en0消失了:

(("en5" .
  [10 151 0 63 0])
 ("lo0" .
  [127 0 0 1 0]))

尝试一下,看看没有Internet连接时会得到什么。例如,要仅在en0启动时刷新软件包,请执行以下操作:

(when (assoc "en0" (network-interface-list))
  (package-refresh-contents))

这是一个有趣的功能。我得到,(("eth0" . [10 72 153 234 0]) ("lo" . [127 0 0 1 0]))因为我已连接到以太网。
Kaushal Modi 2015年

3

扩大Legoscia的答案:

(defun test-internet ()
  (remove-if (lambda (el)
                   (string-match-p "lo.*" (car el)))
                 (network-interface-list)))

这将返回活动网络连接的列表(lo.*是回送接口,在某些情况下lo是其他情况)lo#

如果测试返回non-nil,则表明存在网络连接(wifi /以太网,但是不能保证它实际上可以到达外部互联网。为此,必须在某个地方执行ping操作),如果返回nil,则无法检索软件包清单。


2

我使用以下内容排除loopback接口以及VirtualBox和Docker接口。希望对您有所帮助。

(defun tzz-has-network ()
  (remove-if (lambda (i)
               (or (string-match-p "\\(vboxnet\\|docker\\).*" i)
                   (member 'loopback (nth 4 (network-interface-info i)))))
             (mapcar 'car (network-interface-list))))

2

在具有DBus和NetworkManager的现代Linux系统上:

(defun nm-is-connected()
  (equal 70 (dbus-get-property
             :system "org.freedesktop.NetworkManager" "/org/freedesktop/NetworkManager"
             "org.freedesktop.NetworkManager" "State")))

1

我认为您看错了方式。如果您确实要自动更新软件包,则不要在启动时同步进行更新:从某种形式的空闲计时器开始进行更新。例如

(run-with-idle-timer 10 nil
  (lambda ()
    (package-refresh-contents)
    ..etc..))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.