2009-10-29 13 views
15

मैं एक प्रक्रिया मैं केवल कई परीक्षण पूरा करता है, तो सफलतापूर्वक आरंभ करना चाहते हैं पता लगाने के लिए एक अच्छा तरीका है।वहाँ एक बासी एनएफएस माउंट

एक परीक्षण की आवश्यकता है कि मेरे एनएफएस माउंट के सभी जीवित है और अच्छी तरह से कर रहे हैं।

मैं जानवर बल दृष्टिकोण की तुलना में बेहतर कर सकते हैं:


mount | sed -n "s/^.* on \(.*\) type nfs .*$/\1/p" | 
while read mount_point ; do 
    timeout 10 ls $mount_point >& /dev/null || echo "stale $mount_point" ; 
done 

यहाँ timeout एक उपयोगिता है कि पृष्ठभूमि में आदेश चला जाएगा, और एक निश्चित समय के बाद यह मार देंगे, अगर कोई SIGCHLD समय सीमा से पहले पकड़ा गया था, सफलता वापस लौटा/स्पष्ट तरीके से असफल रहा।


अंग्रेजी में: mount के उत्पादन में पार्स, चेक (एक टाइमआउट से घिरा) हर एनएफएस माउंट बिंदु। वैकल्पिक रूप से (ऊपर दिए गए कोड में नहीं) पहले स्टेल माउंट पर तोड़ना।

उत्तर

3

आप एक सी प्रोग्राम लिखने और ESTALE के लिए जाँच कर सकते हैं।

#include <sys/types.h> 
#include <sys/stat.h> 
#include <unistd.h> 
#include <iso646.h> 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 

int main(){ 
    struct stat st; 
    int ret; 
    ret = stat("/mnt/some_stale", &st); 
    if(ret == -1 and errno == ESTALE){ 
     printf("/mnt/some_stale is stale\n"); 
     return EXIT_SUCCESS; 
    } else { 
     return EXIT_FAILURE; 
    } 
} 
+0

से 'आदमी 3 errno': ESTALE सुरक्षित । क्या इसका मतलब है कि मुझे एक और समाधान की तलाश करनी चाहिए? –

+0

मुझे लगता है कि यह आपके कर्नेल पर निर्भर करता है। – Teddy

+0

हां, आप सही हैं: मेरे distro 'man 3 errno' के बाद के संस्करण में कहते हैं: "' ESTALE' स्टाइल फ़ाइल हैंडल (POSIX.1)) यह त्रुटि NFS और अन्य फ़ाइल सिस्टम के लिए हो सकती है "। और हालांकि मैं अपने प्रश्न में वर्णित क्रूर बल दृष्टिकोण के साथ गया, मैं इस जवाब को स्वीकार करूंगा। –

7

मेरा एक सहयोगी आपकी लिपि में भाग गया। यह एक "जानवर बल" दृष्टिकोण से बचने नहीं है, लेकिन अगर मैं बैश में कर सकते हैं:

while read _ _ mount _; do 
    read -t1 < <(stat -t "$mount") || echo "$mount timeout"; 
done < <(mount -t nfs) 

mount सूचीबद्ध कर सकते हैं एनएफएस सीधे mounts। read -t (एक खोल निर्मित) एक कमांड का समय निकाल सकता है। stat -t (terse output) अभी भी ls * की तरह लटकता है। ls अनावश्यक आउटपुट उत्पन्न करता है, विशाल/धीमी निर्देशिका सूचीओं पर झूठी सकारात्मक जोखिमों को जोखिम देता है, और पहुंच के लिए अनुमतियों की आवश्यकता होती है - जो उनके पास नहीं होने पर झूठी सकारात्मक ट्रिगर भी करेगा।

while read _ _ mount _; do 
    read -t1 < <(stat -t "$mount") || lsof -b 2>/dev/null|grep "$mount"; 
done < <(mount -t nfs) 

हम यह प्रयोग कर रहे हैं lsof -b साथ (गैर अवरुद्ध, तो यह भी लटका नहीं होगा) क्रम रुक जाता है के स्रोत का निर्धारण करने के लिए।

सूचक के लिए धन्यवाद!

  • test -d (एक खोल में निर्मित) stat के बजाय काम करेगा (एक मानक बाहरी) के रूप में अच्छी तरह से है, लेकिन read -t रिटर्न सफलता तभी जब उसका समय नहीं है और इनपुट की एक पंक्ति पढ़ता है। चूंकि test -d stdout का उपयोग नहीं करता है, (($? > 128)) त्रुटि पर जांच की आवश्यकता होगी - लीगिलिटी हिट, आईएमओ के लायक नहीं।
+0

जबकि बाद वाला उदाहरण कमांड को अनुमति देता है (बिना फांसी के स्टेटस पर) lsof -b 2 बस सभी स्टेट टेस्ट छोड़ने और कुछ भी वापस करने के लिए प्रतीत होता है। –

+0

जैसा कि आप जानते हैं, '<(...) 'को उप-खोल में निष्पादित किया गया है, और यदि' एनएसएफ 'के कारण' stat (1)' लटका है, तो सब-शैल शानदार ढंग से समाप्त नहीं होगा। इसके लिए सुधार के लिए [check-nfs.sh] (https://gist.github.com/cinsk/840ed553905cb6e8f0ae) देखें। – cinsk

5

मुझे कुछ समय लिया, लेकिन यहाँ मैं क्या मिला जो अजगर में काम करता है:

import signal, os, subprocess 
class Alarm(Exception): 
    pass 

def alarm_handler(signum, frame): 
    raise Alarm 

pathToNFSMount = '/mnt/server1/' # or you can implement some function 
           # to find all the mounts... 

signal.signal(signal.SIGALRM, alarm_handler) 
signal.alarm(3) # 3 seconds 
try: 
    proc = subprocess.call('stat '+pathToNFSMount, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 
    stdoutdata, stderrdata = proc.communicate() 
    signal.alarm(0) # reset the alarm 
except Alarm: 
    print "Oops, taking too long!" 

टिप्पणी:

  1. answer here को ऋण।
  2. तुम भी वैकल्पिक योजना इस्तेमाल कर सकते हैं: अगर कांटा समाप्त

    os.fork() और os.stat()

जांच, अगर यह समय समाप्त हो गया आप इसे मार सकता है। आपको time.time() और इसी तरह से काम करने की आवश्यकता होगी।

3

ईएसटीएएल के लिए जांचने वाला एक सी प्रोग्राम लिखना एक अच्छा विकल्प है यदि आपको स्टाइल फ़ाइल सिस्टम की वजह से कमांड को समाप्त करने का इंतजार नहीं है। यदि आप "टाइमआउट" विकल्प को कार्यान्वित करना चाहते हैं तो इसे लागू करने के लिए सबसे अच्छा तरीका है (सी प्रोग्राम में) एक बच्चे की प्रक्रिया को फोर्क करना है जो फ़ाइल खोलने का प्रयास करता है। फिर आप जांचते हैं कि क्या बाल प्रक्रिया ने आवंटित समय के भीतर फाइल सिस्टम में सफलतापूर्वक फ़ाइल को पढ़ना समाप्त कर दिया है या नहीं।

#include <stdlib.h> 
#include <stdio.h> 
#include <stdint.h> 
#include <unistd.h> 
#include <errno.h> 
#include <fcntl.h> 
#include <sys/wait.h> 


void readFile(); 
void waitForChild(int pid); 


int main(int argc, char *argv[]) 
{ 
    int pid; 

    pid = fork(); 

    if(pid == 0) { 
    // Child process. 
    readFile(); 
    } 
    else if(pid > 0) { 
    // Parent process. 
    waitForChild(pid); 
    } 
    else { 
    // Error 
    perror("Fork"); 
    exit(1); 
    } 

    return 0; 
} 

void waitForChild(int child_pid) 
{ 
    int timeout = 2; // 2 seconds timeout. 
    int status; 
    int pid; 

    while(timeout != 0) { 
    pid = waitpid(child_pid, &status, WNOHANG); 
    if(pid == 0) { 
     // Still waiting for a child. 
     sleep(1); 
     timeout--; 
    } 
    else if(pid == -1) { 
     // Error 
     perror("waitpid()"); 
     exit(1); 
    } 
    else { 
     // The child exited. 
     if(WIFEXITED(status)) { 
     // Child was able to call exit(). 
     if(WEXITSTATUS(status) == 0) { 
      printf("File read successfully!\n"); 
      return; 
     } 
     } 
     printf("File NOT read successfully.\n"); 
     return; 
    } 
    } 

    // The child did not finish and the timeout was hit. 
    kill(child_pid, 9); 
    printf("Timeout reading the file!\n"); 
} 

void readFile() 
{ 
    int fd; 

    fd = open("/path/to/a/file", O_RDWR); 
    if(fd == -1) { 
    // Error 
    perror("open()"); 
    exit(1); 
    } 
    else { 
    close(fd); 
    exit(0); 
    } 
} 
1

एक और तरीका है, खोल स्क्रिप्ट का उपयोग कर:

यहाँ यह करने के लिए अवधारणा सी कार्यक्रम का एक छोटा सा सबूत है। मेरे लिए अच्छा काम करता है:

#!/bin/bash 
# Purpose: 
# Detect Stale File handle and remove it 
# Script created: July 29, 2015 by Birgit Ducarroz 
# Last modification: -- 
# 

# Detect Stale file handle and write output into a variable and then into a file 
mounts=`df 2>&1 | grep 'Stale file handle' |awk '{print ""$2"" }' > NFS_stales.txt` 
# Remove : ‘ and ’ characters from the output 
sed -r -i 's/://' NFS_stales.txt && sed -r -i 's/‘//' NFS_stales.txt && sed -r -i 's/’//' NFS_stales.txt 

# Not used: replace space by a new line 
# stales=`cat NFS_stales.txt && sed -r -i ':a;N;$!ba;s/ /\n /g' NFS_stales.txt` 

# read NFS_stales.txt output file line by line then unmount stale by stale. 
# IFS='' (or IFS=) prevents leading/trailing whitespace from being trimmed. 
# -r prevents backslash escapes from being interpreted. 
# || [[ -n $line ]] prevents the last line from being ignored if it doesn't end with a \n (since read returns a non-zero exit code when it encounters EOF). 

while IFS='' read -r line || [[ -n "$line" ]]; do 
    echo "Unmounting due to NFS Stale file handle: $line" 
    umount -fl $line 
done < "NFS_stales.txt" 
#EOF 
3

मैं https://github.com/acdha/mountstatus जो UndeadKernel क्या उल्लेख किया है के लिए इसी तरह एक दृष्टिकोण है, जो मैं सबसे मजबूत दृष्टिकोण होना पाया गया है का उपयोग करता है लिखा है: यह एक डेमॉन जो समय समय पर एक बच्चे forking द्वारा सभी घुड़सवार फ़ाइल सिस्टम को स्कैन करता है है प्रक्रिया जो उच्च स्तरीय निर्देशिका और SIGKILL को सूचीबद्ध करने का प्रयास करती है, यदि यह किसी निश्चित टाइमआउट में प्रतिक्रिया देने में विफल रहता है, तो दोनों सफलता और syslog में विफलताओं के साथ विफल रहता है। इससे कुछ क्लाइंट कार्यान्वयन (जैसे पुराने लिनक्स) के साथ समस्याएं टालती हैं जो त्रुटि के कुछ वर्गों के लिए टाइमआउट नहीं ट्रिगर करती हैं, एनएफएस सर्वर जो आंशिक रूप से उत्तरदायी होते हैं लेकिन उदा। आदि listdir की तरह वास्तविक कॉल का जवाब नहीं होगा,

मैं उन्हें प्रकाशित नहीं है, लेकिन शामिल Makefile fpm का उपयोग करता है एक नवोदय स्क्रिप्ट के साथ आरपीएम और देब संकुल का निर्माण।

+0

जंग को परियोजना को पोर्ट करने और कुछ अन्य सुविधाओं को जोड़ने के साथ-साथ अब डेब और आरपीएम पैकेज भी हैं: https://github.com/acdha/mountstatus/releases –

1

पिछले जवाब के अलावा, जो कुछ परिस्थितियों में लटका हुआ है में, यह टुकड़ा चेकों सभी उपयुक्त माउंट, संकेत KILL साथ मारता है, और CIFS साथ भी परीक्षण किया जाता है

grep -v tracefs /proc/mounts | cut -d' ' -f2 | \ 
    while read m; do \ 
    timeout --signal=KILL 1 ls -d $m > /dev/null || echo "$m"; \ 
    done 
संबंधित मुद्दे