有没有一种好的方法来检测过时的NFS挂载

我有一个程序,我想要启动只有几个testing成功完成。

我需要的一个testing是,我所有的NFS装载都很好。

我能比powershell方法做得更好吗:


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 ,那么会在一段时间后SIGCHLD ,以明显的方式返回成功/失败。


英文:parsingmount的输出,检查每个NFS挂载点(超时限制)。 可选地(不在上面的代码中)破坏第一个陈旧的安装。

Solutions Collecting From Web of "有没有一种好的方法来检测过时的NFS挂载"

你可以写一个C程序并检查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; } } 

我的一个同事碰到了你的剧本。 这不能避免“暴力”的方法,但如果我可能在Bash:

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

mount可以直接列出NFS挂载。 read -t (shell内建)可以超时一个命令。 stat -t (terse输出)仍然像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 (一个shell内置)将工作,而不是stat (一个标准的外部),但read -t返回成功只有当它不超时,并读取一行输入。 由于test -d不使用标准输出, (( $? > 128 ))级别检查将是必要的 – 不值得的易读性,国际海事组织。

花了我一些时间,但这里是我发现哪些工作在Python中:

 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. 在这里得到答案 。
  2. 你也可以使用替代方案:

    os.fork()os.stat()

检查叉子是否完成,如果超时,可以杀死它。 您需要使用time.time()等。

编写一个检查ESTALE的C程序是一个很好的选择,如果你不介意由于陈旧的文件系统等待命令完成。 如果你想实现一个“超时”选项,我发现实现它的最好方法(在C程序中)是分叉一个试图打开文件的子进程。 然后检查子进程是否已经在分配的时间内在文件系统中成功读取了一个文件。

这里是一个小概念C程序的证明:

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

另一种方法是使用shell脚本。 对我有好处:

 #!/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 

我写了https://github.com/acdha/mountstatus ,它使用了类似于Undeadcoreel提到的方法,我发现它是最稳健的方法:它是一个守护进程,通过分派子进程周期性地扫描所有已挂载的文件系统尝试列出顶级目录和SIGKILL它,如果它在特定的超时时间内没有响应,成功和失败记录到syslog。 这可以避免某些客户端实现(例如,较老的Linux)的问题,这些实现永远不会触发某些错误类别的超时,NFS服务器部分响应但不会响应像listdir这样的实际调用等。

我不发布它们,但是包含的Makefile使用fpm使用Upstart脚本来构建rpm和deb包。