Kode Elisp untuk memeriksa koneksi internet

13

Ketika saya membuka Emacs, itu mengevaluasi file init saya, yang termasuk menyegarkan arsip paket saya melalui koneksi internet. Ini bermasalah ketika saya tidak memiliki koneksi internet, jadi saya perlu mencegah eksekusi kode itu ketika memulai Emacs tanpa koneksi internet. Untuk mengatasi masalah ini, saya ingin tahu apakah ada cara agar Emacs mengabaikan kode penyegaran paket ketika saya tidak memiliki koneksi internet?

Inilah beberapa baris pertama dari saya 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)       

Saya membayangkan bahwa saya dapat menambahkan kode untuk memuat file Emacs saya sebagai berikut:

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

Apakah ada (connected-to-internet)fungsi, atau pendekatan serupa, untuk menyelesaikan masalah ini?

modulitos
sumber
2
Ada jawaban terkait di sini stackoverflow.com/a/21065704/3170376 .
Nama
2
Mengapa Anda ingin menyegarkan arsip paket saat Anda memulai Emacs?
phils
@Nama Itu lebih dari sekadar terkait. Ini yang jawabannya (dengan asumsi bekerja).
Malabarba
1
Saya sangat menyarankan agar Anda tidak menjalankan paket-refresh-konten pada setiap startup. Kemungkinan besar Anda harus menjalankannya sekali ketika pertama kali menarik konfigurasi Anda pada mesin baru dan kemudian Anda tidak akan membutuhkannya lagi selama berbulan-bulan. Melakukannya ketika Anda memiliki koneksi adalah jawaban yang salah untuk masalah ini, masalah sebenarnya adalah Anda menjalankannya sama sekali saat Anda tidak perlu melakukannya.
Jordon Biondo

Jawaban:

7

Nah, jika Anda masih ingin me-refresh konten secara otomatis, jika memungkinkan, Anda dapat melakukan sesuatu seperti kode di bawah ini:

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

Beberapa catatan jatuh tempo:

  1. Ini lambat, dan akan lambat ketika memulai secara normal, jadi saya lebih suka melakukannya secara manual.
  2. Tidak ada cara untuk menguji koneksi internet secara umum. Anda hanya dapat menemukan bahwa Anda tidak dapat terhubung ke layanan tertentu setelah beberapa waktu Anda mencoba. Ini juga salah satu alasan mengapa sangat lambat.
  3. Kode lebih merupakan ilustrasi tentang cara mendekati masalah. Anda bisa dengan mudah dilakukan (ignore-errors (package-refresh-contents))jika Anda tidak peduli apakah itu berhasil atau tidak.
wvxvw
sumber
Itu jelas cara yang tepat untuk melakukannya. Pada suatu saat, beberapa bagian Internet dapat diakses dan beberapa tidak, dan cara yang tepat untuk mengatasinya adalah menyelidiki konektivitas.
jch
1
Ini juga akan membuat banyak buffer besar yang tak terlihat, sebaiknya dilakukan (kill-buffer (url-ret ...))
Jordon Biondo
@JordonBiondo ok, poin sudah diambil. Belum memikirkannya.
wvxvw
6

Solusi sederhana yang saya adopsi dari skrip shell saya adalah

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

Anda dapat menguji ini di *scratch*buffer:

(message (if (internet-up-p) "Up" "Down"))
"Up"
Tyler Earnest
sumber
Saya paling suka solusi ini karena sederhana, cepat, dan menguji koneksi ke internet yang lebih luas.
miguelmorinin
4

Satu hal yang bisa Anda coba adalah fungsinya network-interface-list. Ini mengembalikan daftar antarmuka jaringan dan alamat IP mereka.

Bagi saya, inilah yang dikembalikan ketika saya terhubung ke Ethernet dan wifi:

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

Dan ketika saya mematikan wifi, en0menghilang:

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

Percobaan dengan itu dan lihat apa yang Anda dapatkan ketika Anda tidak memiliki koneksi Internet. Misalnya, untuk hanya menyegarkan paket saat en0habis, lakukan sesuatu seperti:

(when (assoc "en0" (network-interface-list))
  (package-refresh-contents))
legoscia
sumber
Itu fungsi yang menarik. Saya dapatkan (("eth0" . [10 72 153 234 0]) ("lo" . [127 0 0 1 0]))karena saya terhubung ke ethernet.
Kaushal Modi
3

Untuk memperluas jawaban Legoscia:

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

Ini akan mengembalikan daftar koneksi jaringan aktif ( lo.*adalah antarmuka loopback, dalam beberapa kasus lodi yang lain lo#.

Jika tes kembali non-nil, maka ada koneksi jaringan (wifi / ethernet, tidak ada jaminan itu benar-benar mencapai internet luar. Namun harus melakukan ping di suatu tempat sebagai tes untuk itu), jika itu kembali nilmaka tidak ada cara untuk mengambil paket daftar.

Jonathan Leech-Pepin
sumber
2

Saya menggunakan berikut ini untuk mengecualikan loopbackantarmuka dan juga antarmuka VirtualBox dan Docker. Saya harap ini membantu.

(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
sumber
2

Pada sistem Linux modern dengan DBus dan NetworkManager:

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

Saya pikir Anda melihatnya dengan cara yang salah. Jika Anda benar-benar ingin memperbarui paket-paket Anda secara otomatis, maka jangan lakukan itu secara serempak pada saat startup: lakukan dari semacam pengatur waktu. Misalnya

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