Código Elisp para verificar a conexão à Internet

13

Quando abro o Emacs, ele avalia meu arquivo init, que inclui a atualização dos meus arquivos de pacotes via conexão com a Internet. Isso é problemático quando não tenho uma conexão com a Internet, portanto, preciso impedir a execução desse código ao iniciar o Emacs sem uma conexão com a Internet. Para resolver esse problema, gostaria de saber se existe alguma maneira de o Emacs ignorar o código de atualização de pacotes quando não tenho uma conexão com a Internet?

Aqui estão as primeiras linhas do meu 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)       

Eu imagino que posso adicionar código para carregar meu arquivo Emacs da seguinte maneira:

;; 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))

Existe uma (connected-to-internet)função ou abordagem semelhante para resolver esse problema?

modulitos
fonte
2
Há uma resposta relacionada aqui stackoverflow.com/a/21065704/3170376 .
Nome
2
Por que você deseja atualizar os arquivos do pacote quando inicia o Emacs?
Phillip
@Name Isso é mais do que relacionado. É a resposta (supondo que funcione).
Malabarba 23/01
1
Eu recomendo fortemente que você não execute o pacote de atualização de conteúdo em cada inicialização. É mais provável que você precise executá-lo uma vez ao baixar sua configuração em uma nova máquina e depois não precisará dela novamente por meses. Fazê-lo quando você tem uma conexão é a resposta errada para esse problema, o verdadeiro problema é que você está executando tudo quando não precisa.
21415 Jordânia Biondo

Respostas:

7

Bem, se você ainda deseja atualizar o conteúdo automaticamente, sempre que possível, faça algo como o código abaixo:

(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)))

Poucas notas são devidas:

  1. Isso é lento e lento ao iniciar normalmente, então prefiro fazê-lo manualmente.
  2. Não há como testar a conexão à Internet em geral. Você só pode descobrir que não consegue se conectar a um serviço específico após um período de tempo que tentou. Essa também é uma das razões pelas quais é tão lento.
  3. O código é mais uma ilustração de como abordar o problema. Você poderia ter feito isso facilmente (ignore-errors (package-refresh-contents))se não se importasse se conseguiu ou não.
wvxvw
fonte
Essa é claramente a maneira certa de fazer isso. A qualquer momento, algumas partes da Internet são acessíveis e outras não, e a maneira correta de lidar com isso é investigar a conectividade.
jch 24/01
1
Isso também irá criar um grupo de grandes buffers invisíveis, seria melhor fazer (kill-tampão (url-ret ...))
Jordon Biondo
@JordonBiondo ok, ponto levado. Ainda não pensei nisso.
Wvxvw
6

Uma solução simples que eu adotei nos meus scripts de shell é

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

Você pode testar isso no *scratch*buffer:

(message (if (internet-up-p) "Up" "Down"))
"Up"
Tyler Earnest
fonte
Eu gosto mais desta solução porque é simples, rápida e testa a conexão com a Internet em geral.
miguelmorin 27/06/19
4

Uma coisa que você pode tentar é a função network-interface-list. Ele retorna uma lista de interfaces de rede e seus endereços IP.

Para mim, é isso que retorna quando estou conectado à Ethernet e ao wifi:

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

E quando desligo o wifi, en0desaparece:

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

Experimente e veja o que você ganha quando não tem uma conexão com a Internet. Por exemplo, para atualizar apenas os pacotes quando en0estiver pronto, faça algo como:

(when (assoc "en0" (network-interface-list))
  (package-refresh-contents))
legoscia
fonte
Essa é uma função interessante. Eu recebo (("eth0" . [10 72 153 234 0]) ("lo" . [127 0 0 1 0]))porque estou conectado à Ethernet.
precisa saber é o seguinte
3

Para expandir a resposta de Legoscia:

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

Isso retornará uma lista de conexões de rede ativas ( lo.*é a interface de loopback, em alguns casos loem outros lo#.

Se o teste retornar non-nil, haverá uma conexão de rede (wifi / ethernet, no entanto, não há garantia de que ele realmente atinja a Internet externa. Teria que executar ping em algum lugar como teste para isso); se ele retornar nil, não haverá como recuperar o pacote. Lista.

Jonathan Leech-Pepin
fonte
2

Eu uso o seguinte para excluir loopbackinterfaces e também interfaces VirtualBox e Docker. Espero que seja útil.

(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))))
Ted Zlatanov
fonte
2

Em um sistema Linux moderno com DBus e NetworkManager:

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

Eu acho que você está olhando da maneira errada. Se você realmente deseja atualizar automaticamente seus pacotes, não faça isso de forma síncrona na inicialização: faça isso de um temporizador ocioso de algum tipo. Por exemplo

(run-with-idle-timer 10 nil
  (lambda ()
    (package-refresh-contents)
    ..etc..))
Stefan
fonte