मैं विम को बाहरी रूप से कैसे बंद करूं?


23

मान लें कि मेरे पास एक X11 सर्वर है जो लटका हुआ है, मुझे XTerm Vim सेशन के काम को सहेजने से रोकता है जिसे X11 सर्वर नियंत्रित करता है। (जीवीएम नहीं, बस नियमित विम-इन-एक्सटर्म।)

वहाँ एक रास्ता है कि मैं (एक अलग टर्मिनल से) कमांड लाइन से "सभी को बचाने और बाहर निकलने" के लिए चल रही विम प्रक्रिया बता सकता है? सिग्नल भेजकर, या किसी और माध्यम से?

मुझे विम स्वैप फ़ाइलों के बारे में पता है, और मैं सिर्फ विम को मार सकता हूं और स्वैप से पुनर्प्राप्त कर सकता हूं। मैं पूछ रहा हूं कि क्या कोई "क्लीनर" रास्ता है।


6
यदि उन Vim सत्रों को सक्षम सर्वर (जैसे gvim डिफ़ॉल्ट रूप से करता है) के साथ शुरू किया गया था, तो आप ऐसा करने के लिए Vim के क्लाइंट-सर्वर कार्यक्षमता का उपयोग कर सकते हैं। TTYs का कहना है कि नए कार्यक्रमों को नए टर्मिनल में लाने के लिए रेप्टियर का उपयोग करने का एक और विकल्प हो सकता है, और फिर उन्हें बंद कर दें।
मूरू

जवाबों:


25

हाल ही में इस समस्या में चलने के बाद (दूसरे तरीके से: दूरस्थ सर्वर पर चल रहा है, और मैं स्क्रीन भूल गया), मैंने एक तरह से शिकार करने का फैसला किया।

पहला विचार विम द्वारा उपयोग किए गए फ़ाइल विवरणों को देखना और इसे लिखने का प्रयास करना था। टर्मिनल एमुलेटर द्वारा खोले गए साओडोटर्मिनल के लिए विम के संकेत स्वाभाविक रूप से पर्याप्त हैं:

$ ls -l /proc/$(pgrep -n vim)/fd/
total 0
lrwx------ 1 muru muru 64 Nov 17 01:25 0 -> /dev/pts/14
lrwx------ 1 muru muru 64 Nov 17 01:25 1 -> /dev/pts/14
lrwx------ 1 muru muru 64 Nov 17 01:25 2 -> /dev/pts/14
lrwx------ 1 muru muru 64 Nov 17 01:25 3 -> socket:[99564312]

हालाँकि, मेरे शुरुआती कुछ प्रयास विफल रहे:

echo '^[:wq^M' > /proc/$(pgrep -n vim)/fd/0
echo ':wq^M' > /proc/$(pgrep -n vim)/fd/0
echo ':wq^M' > /proc/$(pgrep -n vim)/fd/0
echo '^C' > /proc/$(pgrep -n vim)/fd/0
printf "%s" '^[:wqa!^M' > /proc/$(pgrep -n vim)/fd/0

^[और ^Mद्वारा प्राप्त किया गया CtrlVEscऔर CtrlVEnter, क्रमशः।

वे सभी टर्मिनल पर दिखाई देने वाले पात्रों में परिणत हुए (मैं इसे दूरस्थ रूप से लागू करने से पहले स्थानीय स्तर पर इसका परीक्षण कर रहा था)। चारों ओर से गुगली करते हुए, मुझे यह SO पोस्ट मिला , पायथन को pseudoterminal डिवाइस पर लिखने के लिए:

#!/usr/bin/python

import sys,os,fcntl,termios
if len(sys.argv) != 3:
   sys.stderr.write("usage: ttyexec.py tty command\n")
   sys.exit(1)
fd = os.open("/dev/" + sys.argv[1], os.O_RDWR)
cmd=sys.argv[2]
for i in range(len(cmd)):
   fcntl.ioctl(fd, termios.TIOCSTI, cmd[i])
fcntl.ioctl(fd, termios.TIOCSTI, '\n')
os.close(fd)

और एक इंटरैक्टिव अजगर खोल पर बाहर काम करने की कोशिश की:

$ sudo python3
Python 3.5.0 (default, Sep 20 2015, 11:28:25) 
[GCC 5.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, fcntl, termios
>>> fd = os.open('/dev/pts/14', os.O_RDWR)
>>> a = '\033:wqa!\n'
>>> for i in a: fcntl.ioctl(fd, termios.TIOCSTI, i);
... 
b'\x1b'
b':'
b'w'
b'q'
b'a'
b'!'
b'\n'
>>> 

किया हुआ!


1
ध्यान दें कि टर्मिनल तक पहुंचने के लिए अजगर स्क्रिप्ट को रूट अनुमति की आवश्यकता होती है।
Martinkunev

6

यदि आप चला रहे हैं, तो आप बाह्य रूप से आदेश भेज सकते हैं ...

विम सर्वर

उदाहरण के लिए, करना:

vim --servername vim

"vim" नाम के साथ एक सर्वर लॉन्च करने के लिए vim का कारण होगा। इसे दो बार कॉल करें और नए सर्वर को "vim1" कहा जाएगा, इसे तीन बार कॉल करें और यह "vim2" होगा, आदि। आप उस आदेश का एक उपनाम बनाना चाहते हैं।

विंडो टाइटल को देखकर आप जान सकते हैं कि किसी विशेष इंस्टेंस को किस सर्वर से नाम दिया गया है। जब आप देखते है:

[कोई नाम नहीं] + - VIM3

सर्वर नाम केस-असंवेदनशील है "VIM3" ("vim3" उसी के लिए संदर्भित होगा))। ध्यान दें कि यदि आप देखते हैं:

[नाम नहीं] + - वीआईएम

यह जरूरी नहीं कि इसका मतलब है कि इसे "VIM" नाम का एक सर्वर मिला है। आप यह सुनिश्चित कर सकते हैं कि सर्वर सर्वर नामों को सूचीबद्ध करके मौजूद है:

vim --serverlist

फिर भी, सवाल केवल "वीआईएम" के लिए उठता है, विशेष रूप से। यदि आप "GVIM" या किसी अन्य नाम को एक नंबर से जोड़कर देखते हैं, तो इसका मतलब है कि यह एक सर्वर है।

क्लाइंट का उपयोग कैसे करें

अब, अपने प्रश्न पर, आप सभी को बचा सकते हैं और किसी भी उदाहरण को देखते हुए छोड़ सकते हैं, जैसे:

vim --servername vim2 --remote-send $'\e:wqa\n'

यदि आप सम्मिलित या कमांड मोड में हैं, तो हम सामान्य मोड पर लौटने के लिए पलायन का उपयोग करते हैं। आप इसके अलावा कुछ भी कर सकते हैं :wqa, लेकिन यह मेरे लिए सबसे उपयुक्त लगता है क्योंकि यह बफ़र्स के स्वैपफिल को छोड़ देगा जिसे बचाया नहीं जा सकता था (क्योंकि वे नए हैं और फ़ाइल नाम नहीं है, आदि)।

यदि आप अपने मामले में सभी उदाहरणों के लिए ऐसा करना चाहते हैं, तो आप बस सर्वर सूची के माध्यम से लूप कर सकते हैं:

for instance in $(vim --serverlist); do
  vim --servername $instance --remote-send $'\e:wqa\n'
done

यदि किसी कारण से आप पसंद नहीं करते हैं --remote-send, तो आप इसके बजाय इसका उपयोग कर सकते हैं --remote-exprजिससे यह लाभ होता है कि यह ग्राहक को परिणाम या त्रुटि के कारण उत्पन्न करेगा, जैसे कि:

$ vim --servername vim2 --remote-expr 'execute("wqa")'

E141: No file name for buffer 1

ध्यान दें कि विम की सर्वर कार्यक्षमता का उपयोग करने के लिए यह आवश्यक है कि विम +clientserverविकल्प के साथ बनाया गया था ।


5

reptyrसिस्टम के पैकेज प्रबंधक का उपयोग करके कमांड स्थापित करें , जैसे:

sudo apt install reptyr
pacman -Sy reptyr

फिर reptyrरिमोट टीटीई को स्थानीय (नए) ट्टी पर स्विच करने के लिए कमांड का उपयोग करें , इस प्रकार है:

ssh user@remote-hostname
ps auxw | grep -i vim
reptyr PID

कमांड आउटपुट PIDसे प्रोसेस आईडी कहां है ps

त्रुटि होने पर:

12345 को संलग्न करने में असमर्थ: अनुमति से इनकार किया

"Ptrace स्कोप" को 0 में बदलें:

sudo su -
echo 0 > /proc/sys/kernel/yama/ptrace_scope

एक बार पुराने सत्र से नए सत्र में विम सत्र की अदला-बदली कर ली जाती है, हमेशा की तरह बचत करें और छोड़ें। ध्यान दें कि Enterकंसोल को ताज़ा करने के लिए आपको प्रेस करना पड़ सकता है ।


0

क्या होगा अगर तुम इनायत से विम को मारोगे?

kill -s 15 -p [PID for Vim]

किल-एस (सिग्नल) 15 को SIGTERM कहा जाता है, जो उस प्रक्रिया को इनायत से खुद को बंद करने के लिए कहता है।

विम उपयोग की पीआईडी ​​(प्रक्रिया आईडी) प्राप्त करने के लिए:
ps ax | grep vim


1
विम स्वचालित रूप से सहेजे नहीं गए परिवर्तनों को नहीं लिखते हैं, कोई फर्क नहीं पड़ता कि कौन से संकेत भेजे गए थे।
मुरु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.