Kod Elisp, aby sprawdzić połączenie z Internetem

13

Kiedy otwieram Emacsa, ocenia mój plik init, który obejmuje odświeżanie moich archiwów pakietów przez połączenie internetowe. Jest to problematyczne, gdy nie mam połączenia z Internetem, dlatego muszę uniemożliwić wykonanie tego kodu podczas uruchamiania Emacsa bez połączenia z Internetem. Aby rozwiązać ten problem, zastanawiam się, czy istnieje sposób, aby Emacs zignorował kod odświeżania pakietu, gdy nie mam połączenia z Internetem?

Oto kilka pierwszych moich linii 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)       

Wyobrażam sobie, że mogę dodać kod, aby załadować mój plik Emacs w następujący sposób:

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

Czy istnieje (connected-to-internet)funkcja lub podobne podejście do rozwiązania tego problemu?

modulitos
źródło
2
Istnieje pokrewna odpowiedź tutaj stackoverflow.com/a/21065704/3170376 .
Imię
2
Dlaczego chcesz odświeżyć archiwa pakietów po uruchomieniu Emacsa?
phils
@ Imię To więcej niż spokrewnione. To odpowiedź (zakładając, że działa).
Malabarba
1
Radzę, abyś nie uruchamiał odświeżania pakietów przy każdym uruchomieniu. Najprawdopodobniej będziesz musiał uruchomić go raz, gdy najpierw ściągasz konfigurację na nowej maszynie, a potem nie będziesz jej potrzebował przez wiele miesięcy. Robienie tego, gdy masz połączenie, jest złą odpowiedzią na ten problem, prawdziwym problemem jest to, że w ogóle go uruchamiasz, kiedy nie musisz.
Jordon Biondo

Odpowiedzi:

7

Cóż, jeśli nadal chcesz automatycznie odświeżać zawartość, jeśli to możliwe, możesz zrobić coś takiego jak poniższy kod:

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

Należnych jest kilka notatek:

  1. Jest to powolne i będzie powolne podczas normalnego uruchamiania, więc raczej robię to ręcznie.
  2. Ogólnie nie ma możliwości przetestowania połączenia z Internetem. Możesz odkryć, że nie jesteś w stanie połączyć się z określoną usługą po upływie określonego czasu. Jest to również jeden z powodów, dla których jest tak wolny.
  3. Kod jest raczej ilustracją tego, jak podejść do problemu. Mógłbyś łatwo zrobić (ignore-errors (package-refresh-contents)), gdybyś nie przejmował się, czy się to uda, czy nie.
wvxvw
źródło
To wyraźnie właściwy sposób, aby to zrobić. W dowolnym momencie niektóre części Internetu są dostępne, a niektóre nie, a właściwym sposobem radzenia sobie z nimi jest sprawdzenie łączności.
jch
1
Spowoduje to również utworzenie wielu dużych niewidzialnych buforów, najlepiej byłoby to zrobić (kill-buffer (url-ret ...))
Jordon Biondo
@JordonBiondo ok, punkt zajęty. Nie myślałem o tym.
wvxvw,
6

Proste rozwiązanie, które zaadaptowałem z moich skryptów powłoki to

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

Możesz to przetestować w *scratch*buforze:

(message (if (internet-up-p) "Up" "Down"))
"Up"
Tyler Earnest
źródło
Najbardziej podoba mi się to rozwiązanie, ponieważ jest proste, szybkie i testuje połączenie z Internetem.
miguelmorin
4

Jedną z rzeczy, których możesz spróbować, jest funkcja network-interface-list. Zwraca listę interfejsów sieciowych i ich adresów IP.

Dla mnie jest to, co zwraca, gdy jestem podłączony zarówno do Ethernetu, jak i Wi-Fi:

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

A kiedy wyłączam Wi-Fi, en0znika:

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

Eksperymentuj z tym i zobacz, co zyskujesz, gdy nie masz połączenia z Internetem. Na przykład, aby odświeżyć pakiety tylko, gdy en0jest włączony, wykonaj coś takiego:

(when (assoc "en0" (network-interface-list))
  (package-refresh-contents))
legoscia
źródło
To interesująca funkcja. Rozumiem, (("eth0" . [10 72 153 234 0]) ("lo" . [127 0 0 1 0]))bo jestem podłączony do sieci Ethernet.
Kaushal Modi
3

Aby rozwinąć odpowiedź Legoscii:

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

Zwróci listę aktywnych połączeń sieciowych ( lo.*jest to interfejs pętli zwrotnej, w niektórych przypadkach low innych lo#.

Jeśli test powróci non-nil, oznacza to, że połączenie sieciowe (wifi / ethernet, nie ma gwarancji, że faktycznie dotrze do zewnętrznego internetu. Musiałby jednak pingować gdzieś w celu przetestowania tego), jeśli powróci, nilnie będzie możliwości odzyskania pakietu lista.

Jonathan Leech-Pepin
źródło
2

Korzystam z poniższych, aby wykluczyć loopbackinterfejsy, a także interfejsy VirtualBox i Docker. Mam nadzieję, że to jest pomocne.

(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
źródło
2

W nowoczesnym systemie Linux z DBus i NetworkManager:

(defun nm-is-connected()
  (equal 70 (dbus-get-property
             :system "org.freedesktop.NetworkManager" "/org/freedesktop/NetworkManager"
             "org.freedesktop.NetworkManager" "State")))
db48x
źródło
1

Myślę, że patrzysz na to w niewłaściwy sposób. Jeśli naprawdę chcesz automatycznie zaktualizować swoje pakiety, nie rób tego synchronicznie podczas uruchamiania: zrób to z jakiegoś bezczynnego timera. Na przykład

(run-with-idle-timer 10 nil
  (lambda ()
    (package-refresh-contents)
    ..etc..))
Stefan
źródło