Codice Elisp per verificare la connessione a Internet


13

Quando apro Emacs, valuta il mio file init, che include l'aggiornamento dei miei archivi di pacchetti tramite connessione internet. Ciò è problematico quando non ho una connessione a Internet, quindi devo impedire l'esecuzione di quel codice quando avvio Emacs senza una connessione a Internet. Per risolvere questo problema, mi chiedo se c'è un modo per far sì che Emacs ignori il codice di aggiornamento del pacchetto quando non ho una connessione Internet?

Ecco le prime righe del mio 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)       

Immagino di poter aggiungere il codice per caricare il mio file Emacs come segue:

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

Esiste una (connected-to-internet)funzione o un approccio simile per risolvere questo problema?


2
C'è una risposta correlata qui stackoverflow.com/a/21065704/3170376 .
Nome

2
Perché vuoi aggiornare gli archivi dei pacchetti quando avvii Emacs?
phils,

@Name Questo è più che correlato. È la risposta (supponendo che funzioni).
Malabarba,

1
Consiglio vivamente di non eseguire package-refresh-contents ad ogni avvio. È molto probabile che sia necessario eseguirlo una volta quando si abbassa la configurazione su una nuova macchina e non sarà più necessario per mesi. Farlo quando si dispone di una connessione è la risposta sbagliata a questo problema, il vero problema è che lo si esegue affatto quando non è necessario.
Jordon Biondo,

Risposte:


7

Bene, se volessi ancora aggiornare automaticamente i contenuti, quando possibile, potresti fare qualcosa come il codice qui sotto:

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

Sono necessarie poche note:

  1. Questo è lento e sarà lento quando si avvia normalmente, quindi preferisco farlo manualmente.
  2. Non è possibile verificare la connessione a Internet in generale. Puoi scoprire che non riesci a connetterti a un determinato servizio dopo un certo periodo di tempo che hai provato. Questo è anche uno dei motivi per cui è così lento.
  3. Il codice è più un esempio di come affrontare il problema. Avresti potuto facilmente farlo (ignore-errors (package-refresh-contents))se non ti importasse se ci fosse riuscito o no.

Questo è chiaramente il modo giusto per farlo. In qualsiasi momento, alcune parti di Internet sono accessibili e altre no, e il modo corretto di gestirlo è sondare la connettività.
dal

1
Questo creerà anche un sacco di grandi buffer invisibili, sarebbe meglio farlo (kill-buffer (url-ret ...))
Jordon Biondo

@JordonBiondo ok, punto preso. Non ci ho pensato.
wvxvw,

6

Una semplice soluzione che ho adottato dai miei script di shell è

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

Puoi verificarlo nel *scratch*buffer:

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

Mi piace di più questa soluzione perché è semplice, veloce e mette alla prova la connessione a Internet più ampia.
miguelmorin,

4

Una cosa che potresti provare è la funzione network-interface-list. Restituisce un elenco di interfacce di rete e i loro indirizzi IP.

Per me, questo è ciò che ritorna quando sono connesso sia a Ethernet che a wifi:

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

E quando spengo il wifi, en0scompare:

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

Sperimenta con quello e vedi cosa ottieni quando non hai una connessione Internet. Ad esempio, per aggiornare i pacchetti solo quando en0è attivo, fare qualcosa del tipo:

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

Questa è una funzione interessante. Ottengo (("eth0" . [10 72 153 234 0]) ("lo" . [127 0 0 1 0]))perché sono connesso a Ethernet.
Kaushal Modi,

3

Per espandere la risposta di Legoscia:

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

Questo restituirà un elenco di connessioni di rete attive ( lo.*è l'interfaccia di loopback, in alcuni casi loin altri lo#.

Se il test ritorna non-nil, allora c'è una connessione di rete (wifi / ethernet, nessuna garanzia che in realtà raggiunga Internet esterno comunque. Dovrebbe eseguire il ping da qualche parte come test per quello), se ritorna nilallora non c'è modo di recuperare il pacchetto elenco.


2

Uso quanto segue per escludere le loopbackinterfacce e anche le interfacce VirtualBox e Docker. Spero sia utile

(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

Su un moderno sistema Linux con DBus e NetworkManager:

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

1

Penso che tu lo stia guardando nel modo sbagliato. Se vuoi davvero aggiornare automaticamente i tuoi pacchetti, allora non farlo in modo sincrono all'avvio: fallo da un timer inattivo di qualche tipo. Per esempio

(run-with-idle-timer 10 nil
  (lambda ()
    (package-refresh-contents)
    ..etc..))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.