如何在启动时挂载sshfs?

使用NAS盒子作为24/7文件服务器,我想使用sshfs从Ubuntu 9.04桌面连接到它。 目前,我在桌面的fstab中有这样的一行:

sshfs#jldugger@storage:/mnt/HD_a2/ /mnt/storage fuse comment=sshfs,auto,users,exec,uid=1000,gid=1000,allow_other,reconnect,transform_symlinks,BatchMode=yes,fsname=sshfs#jldugger@storage/mnt/HD_a2/ 0 0 

我可以确认它适用于mount /mnt/storage 。 我需要的是在启动时安装它的一些方法,但在networking连接build立之后。

目前,Ubuntu中的Upstart不会生成networking事件。 相反,它调用传统的sysvinit。 默认NetworkManager已安装并正在运行; 而不是将networking事件发送给新手,它包含一个运行部件调度程序(/etc/NetworkManager/dispatcher.d/),它本身只依赖于ifupdown的运行部件调度程序(/etc/network/*.d/)。 尤其是你关心的是/etc/network/if-up.d/和/etc/network/if-down.d/

首先设置一个未encryption的ssh密钥对,这样你就可以在没有提示的情况下挂载这个点。 编写一个脚本,将其放在/etc/network/if-up.d/中并使其可执行。 以下是在UbuntuForums上发现的,对我来说是足够的:

 #!/bin/sh ## http://ubuntuforums.org/showthread.php?t=430312 ## The script will attempt to mount any fstab entry with an option ## "...,comment=$SELECTED_STRING,..." ## Use this to select specific sshfs mounts rather than all of them. SELECTED_STRING="sshfs" # Not for loopback [ "$IFACE" != "lo" ] || exit 0 ## define a number of useful functions ## returns true if input contains nothing but the digits 0-9, false otherwise ## so realy, more like isa_positive_integer isa_number () { ! echo $1 | egrep -q '[^0-9]' return $? } ## returns true if the given uid or username is that of the current user am_i () { [ "$1" = "`id -u`" ] || [ "$1" = "`id -un`" ] } ## takes a username or uid and finds it in /etc/passwd ## echoes the name and returns true on success ## echoes nothing and returns false on failure user_from_uid () { if isa_number "$1" then # look for the corresponding name in /etc/passwd local IFS=":" while read name x uid the_rest do if [ "$1" = "$uid" ] then echo "$name" return 0 fi done </etc/passwd else # look for the username in /etc/passwd if grep -q "^${1}:" /etc/passwd then echo "$1" return 0 fi fi # if nothing was found, return false return 1 } ## Parses a string of comma-separated fstab options and finds out the ## username/uid assigned within them. ## echoes the found username/uid and returns true if found ## echoes "root" and returns false if none found uid_from_fs_opts () { local uid=`echo $1 | egrep -o 'uid=[^,]+'` if [ -z "$uid" ]; then # no uid was specified, so default is root echo "root" return 1 else # delete the "uid=" at the beginning uid_length=`expr length $uid - 3` uid=`expr substr $uid 5 $uid_length` echo $uid return 0 fi } # unmount all shares first sh "/etc/network/if-down.d/umountsshfs" while read fs mp type opts dump pass extra do # check validity of line if [ -z "$pass" -o -n "$extra" -o "`expr substr ${fs}x 1 1`" = "#" ]; then # line is invalid or a comment, so skip it continue # check if the line is a selected line elif echo $opts | grep -q "comment=$SELECTED_STRING"; then # get the uid of the mount mp_uid=`uid_from_fs_opts $opts` if am_i "$mp_uid"; then # current user owns the mount, so mount it normally { sh -c "mount $mp" && echo "$mp mounted as current user (`id -un`)" || echo "$mp failed to mount as current user (`id -un`)"; } & elif am_i root; then # running as root, so sudo mount as user if isa_number "$mp_uid"; then # sudo wants a "#" sign icon front of a numeric uid mp_uid="#$mp_uid" fi { sudo -u "$mp_uid" sh -c "mount $mp" && echo "$mp mounted as $mp_uid" || echo "$mp failed to mount as $mp_uid"; } & else # otherwise, don't try to mount another user's mount point echo "Not attempting to mount $mp as other user $mp_uid" : echo "Not attempting to mount $mp as other user $mp_uid" fi fi # if not an sshfs line, do nothing done </etc/fstab wait 

如果您有无线或其他不可靠的连接,请将以下内容放在/etc/network/if-down.d/中:

 #!/bin/bash # Not for loopback! [ "$IFACE" != "lo" ] || exit 0 # comment this for testing exec 1>/dev/null # squelch output for non-interactive # umount all sshfs mounts mounted=`grep 'fuse.sshfs\|sshfs#' /etc/mtab | awk '{ print $2 }'` [ -n "$mounted" ] && { for mount in $mounted; do umount -l $mount; done; } 

Upstart是现在在Ubuntu发布启动脚本或服务的首选方法,尽pipe编辑/etc/rc.local仍然有效。 Upstart允许您控制何时运行服务,确保在启动networking连接后发生。

也可以直接编辑/etc/rc.Xd中的符号链接(将Xreplace为正在使用的运行级别),并添加一个名称,例如S99mount,以确保在networking设置之后运行它。 这将需要指向一个脚本文件,该文件可以挂载您所请求的sshfs。

我相信_netdev作为一个select应该解决这个问题

只是一个想法,但如果你使用这个作为文件服务器,也许NFS或Samba将是比ssh更好的解决scheme。

如果您没有来自远程主机的证书,而必须使用login名/密码,那么这是另一种解决scheme。 我在这个例子中使用了jldugger使用的相同的用户名和目录,以避免添加混淆。

  1. 在主目录中创build一个包含密码的文件,并保护它:

     echo 'YourRemoteUserPassword' > ~jldugger/.credentials chmod 600 ~jldugger/.credentials 
  2. 编辑/etc/rc.local文件并在底部插入以下命令,但在“退出0”之前:

     sshfs -o password_stdin -o nonempty jldugger@storage:/mnt/HD_a2/ /mnt/storage < ~jldugger/.credentials