2

I would like to get back the question of this post.

When a user in a remote client mounts a directory from a local server on his filesystem through sshfs, he is not visible in the server through who or last. The following work-around for the server is proposed in the linked question:

ps aux | grep -i sftp | grep -v grep

But it provides modest information: just the username and the presence of a sftp connection. As in the comment to the chosen answer, I would like to ask (regarding the server):

1) Is there a more compact, dedicated command?

2) Is there a way to obtain more informations? I would like to know (from the server): the username which performed the operation and the hostname or ip address of the remote client, the mounted directory of the server and the time at which the mount begun.

Suppose that the server is running Ubuntu 14.04, but it would be nice if the commands were available in all the *nix systems.

BowPark
  • 4,895

2 Answers2

1

It is impossible to distinguish from the server side an SFTP session that the client accesses via SSHFS from an SFTP session that the client accesses via some other client software. But you can definitely obtain more information about the SFTP session.

Each SFTP session has an associated sftp-server process. On Linux, you can list the process IDs running sftp-server with pgrep -x sftp-server or ps -C sftp-server. Alternatively, you can use the following POSIX-compliant command (adjust the path to sftp-server if necessary):

ps -e -o pid,cmd | sed -n 's!^\([0-9]*\) /usr/lib/openssh/sftp-server$!\1!p'

That process is running under the user account used to log in for SFTP. It was started when the SFTP session started.

ps -e -o pid,user,etime,cmd |
awk '$4 == "/usr/lib/openssh/sftp-server" {print "pid=" $1, "user=" $2, $3 " ago"}'

The start time display is cumbersome in POSIX: you get the elapsed time since the process started, rather than a date. Most systems have something more convenient. On Linux, a few more formats are available, but none of them are really convenient. The date comes from field 22 of /proc/$pid/stat, but it's cumbersome too: it's the start date in clock ticks (divide by the value returned by getconf CLK_TCK or sysconf(_SC_CLK_TCK)), except on older (<2.6) kernels where it's in jiffies (whose value is even harder to find out reliably); the boot time is the value on the btime line of /proc/stat expressed in seconds since the epoch (which you may want to convert to a human-readable format).

cat /proc/$pid/stat | awk '
    BEGIN {
        "getconf CLK_TCK" | getline ticks;
        while (!btime) {
            getline <"/proc/stat";
            if ($1 == "btime") btime = $2;
        }
    }
    { print "pid=" $1, "start_time=" int($22 / ticks + btime) }'

You can find out the client's IP address and port by looking at the SSH_CLIENT variable in that process's environment. Most Unix variant have a way to do that but it hasn't been standardized by POSIX. On Linux, you can use

</proc/$pid/environ grep -z '^SSH_CLIENT='

I don't think you can find out what the mounted directory is. The SSHFS client just sends information about each file it wants to access.

I'm not aware of any program that collects all of this data for you, but I don't do this kind of stuff much, so there may well be one that I'm not aware of.

  • First of all thank you so much for your post. Running your commands, I would like to clarify a couple of issues: 1) what exactly is the (very large) output number from your last little awk script? 2) Unfortunately, /proc/$pid/environ grep -z '^SSH_CLIENT=' doesn't work, neither with sudo. The file environ exists, but it seems to be an empty, read-only file. – BowPark Jun 11 '15 at 15:23
  • 1
    @BowPark The number is the process's start time, in seconds since the epoch (1970-01-01 00:00 GMT). In the last command I forgot a redirection character before /proc/$pid/environ. I edited my answer. – Gilles 'SO- stop being evil' Jun 11 '15 at 17:46
  • Just to integrate your answer, this is very useful to obtain a date from the numeric output of your awk script. It is one of your answers too :). Thanks again. – BowPark Jun 12 '15 at 10:51
1
 ~ % mount -l -t fuse.sshfs
i@somewhere:/mnt/x on /mnt/x type fuse.sshfs (ro,nosuid,nodev,relatime,user_id=1000,group_id=100)
~ % mount --version
mount from util-linux 2.36.2 (libmount 2.36.2: btrfs, namespaces, assert, debug)

Maybe mount -l -t fuse.sshfs is what you need.

hol
  • 11