รหัส Elisp เพื่อตรวจสอบการเชื่อมต่ออินเทอร์เน็ต


13

เมื่อฉันเปิด Emacs มันจะประเมินไฟล์ init ของฉันซึ่งรวมถึงการรีเฟรชคลังข้อมูลแพคเกจของฉันผ่านการเชื่อมต่ออินเทอร์เน็ต นี่เป็นปัญหาเมื่อฉันไม่มีการเชื่อมต่ออินเทอร์เน็ตดังนั้นฉันจำเป็นต้องป้องกันการเรียกใช้โค้ดนั้นเมื่อเริ่มต้น 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

@Name นั่นเป็นอะไรที่เกี่ยวข้องมากกว่ากัน มันคำตอบ (สมมติว่ามันใช้งานได้)
Malabarba

1
ฉันขอแนะนำอย่างยิ่งว่าคุณไม่ได้เรียกใช้ package-refresh-content ในการเริ่มต้นแต่ละครั้ง เป็นไปได้มากว่าคุณจะต้องเปิดใช้งานหนึ่งครั้งเมื่อดึงการตั้งค่าลงในเครื่องใหม่ก่อนจากนั้นคุณจะไม่ต้องการมันอีกเป็นเวลาหลายเดือน ทำเมื่อคุณมีการเชื่อมต่อเป็นคำตอบที่ไม่ถูกต้องสำหรับปัญหานี้ปัญหาที่แท้จริงคือว่าคุณกำลังใช้งานอยู่เมื่อคุณไม่จำเป็นต้องเป็น
Jordon Biondo

คำตอบ:


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))หากคุณไม่สนใจว่าจะประสบความสำเร็จหรือไม่

เห็นได้ชัดว่าเป็นวิธีที่เหมาะสมที่จะทำ ในบางครั้งบางส่วนของอินเทอร์เน็ตสามารถเข้าถึงได้และบางส่วนไม่ได้และวิธีที่เหมาะสมในการจัดการกับมันคือการสอบสวนการเชื่อมต่อ
jch

1
สิ่งนี้จะสร้างบัฟเฟอร์ขนาดใหญ่ที่มองไม่เห็นมันจะเป็นการดีที่สุด (kill-buffer (url-ret ... ))
Jordon Biondo

@JordonBiondo ตกลงเอาจุด ยังไม่ได้คิดเกี่ยวกับมัน
wvxvw

6

ทางออกง่ายๆที่ฉันได้นำมาใช้จากสคริปต์เปลือกของฉันคือ

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

ฉันชอบโซลูชันนี้มากที่สุดเพราะใช้งานง่ายรวดเร็วและทดสอบการเชื่อมต่อกับอินเทอร์เน็ตที่กว้างขึ้น
miguelmorin

4

network-interface-listสิ่งหนึ่งที่คุณอาจจะลองเป็นฟังก์ชั่น ส่งคืนอลิสต์ของเน็ตเวิร์กอินเตอร์เฟสและที่อยู่ IP ของมัน

สำหรับฉันนี่คือสิ่งที่จะได้รับเมื่อฉันเชื่อมต่อกับทั้ง Ethernet และ 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]))

ทดลองกับสิ่งนั้นและดูสิ่งที่คุณจะได้รับเมื่อคุณไม่มีการเชื่อมต่ออินเทอร์เน็ต ตัวอย่างเช่นหากต้องการรีเฟรชแพ็กเกจเมื่อen0เป็นไปได้ให้ทำดังนี้:

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

นั่นเป็นฟังก์ชั่นที่น่าสนใจ ฉันได้รับ(("eth0" . [10 72 153 234 0]) ("lo" . [127 0 0 1 0]))เพราะฉันเชื่อมต่อกับอีเธอร์เน็ต
Kaushal Modi

3

หากต้องการขยายคำตอบของ Legoscia:

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

นี้จะกลับรายการของการเชื่อมต่อเครือข่ายที่ใช้งาน ( lo.*คืออินเตอร์เฟซวนรอบในบางกรณีในผู้อื่นlolo#

หากการทดสอบกลับ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

บนระบบ Linux ที่ทันสมัยด้วย DBus และ NetworkManager:

(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..))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.