Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update readme and fix python tests #238

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
227 changes: 227 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
# SSHFS


## About

SSHFS is part of the [libfuse](https://github.com/libfuse) project.

SSHFS allows you to mount a remote filesystem using SFTP. Most SSH servers support and enable this
SFTP access by default, so SSHFS is very simple to use--there's nothing to do on the server-side.


## Development Status

SSHFS is shipped by all major Linux distributions and has been in production use across a wide range
of systems for many years. However, at present SSHFS does not have any active, regular contributors,
and there are a number of known issues (see all issues and bugs in the [SSHFS issue
tracker](https://github.com/libfuse/sshfs/issues)). The current maintainer continues to apply pull
requests and makes regular releases, but unfortunately has no capacity to do any development beyond
addressing high-impact issues. _When reporting bugs, please understand that unless you are including
a pull request or are reporting a critical issue, you will probably not get a response._


## How to use

Once `sshfs` is installed (see the "[Build and Install](#build)" section below) running it is very
simple.

```bash
sshfs -h # help menu
sshfs --version # see version
```

### 1. To mount a remote filesystem with `sshfs`:

General command syntax:
```bash
sshfs [user@]hostname_or_ip:[directory] mountpoint
```

For example, to connect to the username "john" on a host at local IP `10.0.0.1`, mounting the host's
root directory (`/`) in your local `~/mnt/sshfs` directory, you would do the following:

```bash
mkdir -p ~/mnt/sshfs # create the ~/mnt/sshfs directory, if it doesn't already exist
sshfs [email protected]:/ ~/mnt/sshfs
```

### 2. To unmount the remote filesystem:

General syntax:
```bash
# For most systems, including Ubuntu
fusermount -u mountpoint

# For BSD and MacOS, and also works fine on Ubuntu
umount mountpoint
```

For the example above:
```bash
# For most systems, including Ubuntu
fusermount -u ~/mnt/sshfs

# For BSD and MacOS, and also works fine on Ubuntu
umount ~/mnt/sshfs
```

### 3. Notes:
1. It is recommended to run SSHFS as a regular user (NOT as root). For this to work, the mount point
must be owned by the user. Therefore, mounting into a `mount` or `mnt` directory you create
inside your home directory is a good practice.
1. If the username (`user@` part of the command) is omitted, SSHFS will use the local username.
1. If the directory is omitted (while keeping the colon `:` just before it), SSHFS will mount the
(remote) home directory.
1. If you need to enter a password, SSHFS will ask for it (actually, it just runs `ssh` which asks
for the password if needed).

Also, many `ssh` options can be specified. See the manual pages for _sftp(1)_ (`man 1 sftp`) and
_ssh_config(5)_ (`man 5 ssh_config`). The remote port number (`-oport=PORT`) is one of the many
`ssh` options which works with `sshfs`.


<a id="build"></a>
## Build and Install

### 1. General overview

First, download the latest SSHFS release from https://github.com/libfuse/sshfs/releases. On Linux
and BSD (as opposed to MacOS), you will also need to install [libfuse][libfuse] 3.1.0 or newer. On
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On MacOS, you need to install OSXFUSE I believe.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is stated just one line below.

MacOS, you need [OSXFUSE][OSXFUSE] instead. Finally, you need the [Glib][Glib] library with
development headers, which should be available from your operating system's package manager.

To build and install, you must use [Meson][Meson] (version 0.38 or newer) and
[Ninja][Ninja]. After extracting the `sshfs` tarball, create a (temporary) build directory and run
Meson:

```bash
mkdir build; cd build
meson ..
```

Normally, the default build options will work fine. If you nevertheless want to adjust them, you can
do so with the `meson configure` command:

```bash
meson configure # list options
meson configure -D strip=true # set an option
```

To build, test and install SSHFS, you then use Ninja. Running the tests requires the
[`py.test`][py.test] Python module. It also requires configuring ssh keys for passwordless login to
yourself via _localhost_. See the [detailed notes about ssh key generation and setup](#sshkeygen)
below.

```bash
ninja
python3 -m pytest test/ # (Optional, but recommended) run the tests
sudo ninja install
```

### 2. Detailed instructions

_Tested 22 Dec. 2020 on Ubuntu 20.04._

1. Download and `cd` into the source code
1. To download the latest source code:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The people who install from Git should not need these instructions, so I think this can be safely dropped.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to write with the lowest common denominator in mind, meaning even for the beginner developer who may need this help. With your permission, I'd like to leave these details. Just a handful of years ago I needed these instructions myself, and not having many repos with these instructions slowed my progress into making contributions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense, thanks for explaining. How about keeping the instructions but moving them into a separate file ("contributor_info.md" or something like that?). That way, the information is available for those who need it without getting in the way of people who don't need it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍, moving how to build from git to CONTRIBUTING.md would be good.

```bash
git clone https://github.com/libfuse/sshfs.git
cd sshfs
```
1. OR (recommended): To download the latest `sshfs` _release_:
1. Find the release you want here: https://github.com/libfuse/sshfs/releases.
1. Find the link to the `*.tar.gz` file you want. Example: https://github.com/libfuse/sshfs/archive/sshfs-3.7.1.tar.gz.
1. Download, extract, and `cd` into it:
```bash
wget https://github.com/libfuse/sshfs/archive/sshfs-3.7.1.tar.gz
tar -xvzf sshfs-3.7.1.tar.gz
cd sshfs-sshfs-3.7.1
```
1. Install dependencies
```bash
sudo apt update
sudo apt install meson cmake fuse3 libfuse3-dev libglib2.0-dev
```
1. Create a **build** dir, `cd` into it, run `meson`, and build and link with `ninja`:
```bash
mkdir build
cd build
meson ..
ninja # this builds and produces the new `sshfs` executable
```
<!-- Important: this HTML anchor is referenced inside "test_sshfs.py". If you change its name here,
change it there too. -->
<a id="sshkeygen"></a>
1. (Optional, but recommended) test your new `sshfs` executable. [This also includes detailed notes
about ssh key generation and setup].
1. Note: ssh key generation notes come [from GitHub here](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent).
```bash
# install the `pytest` python3 module in case you don't already have it
pip3 install pytest
# install `sshd`
sudo apt update
sudo apt install openssh-server

# Configure passwordless ssh key-based login so you can ssh into yourself
# (via `localhost`) for testing; see GitHub link above.
# 1. Generate a new public-private key pair.
ssh-keygen -t ed25519 -C "[email protected]"
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# 2. Now add your new "~/.ssh/id_ed25519.pub" public key to your
# "~/.ssh/authorized_keys" file so you can have key-based password-less
# ssh sessions into yourself via `localhost` for testing.
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys

# run the python3 tests in the "test" dir
python3 -m pytest test/
```
For [sample test output, see here](test/README.md).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why it's important to have example output? The tests clearly state if they fail or pass....

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It took my a lot of effort and time to get the tests to pass, as you can see from my ssh setup instructions, so I was never able to see what was being tested or what was supposed to happen until I had solved many problems and gotten the tests to run. This removes that mystery.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That being said, there's not a ton of value in it. It's just nice to see what's supposed to happen is all.

1. Install `sshfs`:
1. Normal method. This installs `sshfs` at `/usr/local/bin/sshfs`, whereas your normal Linux
distribution's executable is likely in `/usr/bin/sshfs`.
```bash
# To install
sudo ninja install
```
1. Alternative method. This technique simply creates a symlink to the executable in your `~/bin`
dir so your Linux distro's install still remain's intact and untouched. (For Ubuntu).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case also when using ninja install. Your system's sshfs is in /usr/bin, ninja install into /usr/local/bin.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the ninja uninstall command?

Copy link
Contributor

@Nikratio Nikratio Dec 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. But I also don't see the connection to what I'm saying...? If you install in /usr/locl, then your Linux distro's install remains intact and untouched.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you install in /usr/locl, then your Linux distro's install remains intact and untouched.

Agreed. So, if someone wants to go back to using their Linux distro's version of sshfs, how do they do that? The logical answer is: run the ninja uninstall command. That's why I asked "what's the ninja uninstall command?" I'd like to write it down here too.

For the "Alternative method" here, I show: rm ~/bin/sshfs.

A few options to uninstall the ninja install might be:

rm /usr/local/bin/sshfs

Or: modify the path to include /urs/local/bin after /usr/bin instead of before it (probably not recommended), or (best, if such a thing exists): sudo ninja uninstall.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you tried running ninja uninstall? If I understand https://mesonbuild.com/Release-notes-for-0-38-0.html correctly, then this should exist and is probably the best approximation to a true uninstall that we have.

```bash
# "Install" via a symlink. Note: ensure you are in the same dir as the new `sshfs`
# executable first.
mkdir -p ~/bin
ln -si "$(pwd)/sshfs ~/bin"
. ~/.bashrc # re-source your .bashrc file to bring the ~/bin dir into your PATH

# To "Uninstall"
rm ~/bin/sshfs
```
1. Check your version from another dir to ensure the installation worked correctly.
```bash
cd ~
sshfs --version
```
Sample version output:
```
SSHFS version 3.7.1
FUSE library version 3.9.0
using FUSE kernel interface version 7.31
fusermount3 version: 3.9.0
```


## Getting Help

If you need help, please ask on the <[email protected]> mailing list. Subscribe at
https://lists.sourceforge.net/lists/listinfo/fuse-sshfs.

Please report any bugs on the main parent project's (`libfuse`'s) GitHub issue tracker here:
https://github.com/libfuse/libfuse/issues.


[libfuse]: http://github.com/libfuse/libfuse
[OSXFUSE]: https://osxfuse.github.io/
[Glib]: https://developer.gnome.org/glib/stable/
[Meson]: http://mesonbuild.com/
[Ninja]: https://ninja-build.org/
[py.test]: http://www.pytest.org/
100 changes: 0 additions & 100 deletions README.rst

This file was deleted.

32 changes: 32 additions & 0 deletions test/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

To set up and run the tests, see the [detailed instructions here](https://github.com/libfuse/sshfs#sshkeygen).

Sample test output:

```bash
~/GS/dev/sshfs/src/sshfs/build$ python3 -m pytest test/
============================================================================================ test session starts =============================================================================================
platform linux -- Python 3.8.5, pytest-6.2.1, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/user/GS/dev/sshfs/src/sshfs/build/test, configfile: pytest.ini
collected 16 items

test/test_sshfs.py::test_sshfs[True-True-0-False] PASSED [ 6%]
test/test_sshfs.py::test_sshfs[True-True-0-True] PASSED [ 12%]
test/test_sshfs.py::test_sshfs[True-True-1-False] PASSED [ 18%]
test/test_sshfs.py::test_sshfs[True-True-1-True] PASSED [ 25%]
test/test_sshfs.py::test_sshfs[True-False-0-False] PASSED [ 31%]
test/test_sshfs.py::test_sshfs[True-False-0-True] PASSED [ 37%]
test/test_sshfs.py::test_sshfs[True-False-1-False] PASSED [ 43%]
test/test_sshfs.py::test_sshfs[True-False-1-True] PASSED [ 50%]
test/test_sshfs.py::test_sshfs[False-True-0-False] PASSED [ 56%]
test/test_sshfs.py::test_sshfs[False-True-0-True] PASSED [ 62%]
test/test_sshfs.py::test_sshfs[False-True-1-False] PASSED [ 68%]
test/test_sshfs.py::test_sshfs[False-True-1-True] PASSED [ 75%]
test/test_sshfs.py::test_sshfs[False-False-0-False] PASSED [ 81%]
test/test_sshfs.py::test_sshfs[False-False-0-True] PASSED [ 87%]
test/test_sshfs.py::test_sshfs[False-False-1-False] PASSED [ 93%]
test/test_sshfs.py::test_sshfs[False-False-1-True] PASSED [100%]

======================================================================================= 16 passed in 88.42s (0:01:28) ========================================================================================
```
2 changes: 1 addition & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def register_output(self, pattern, count=1, flags=re.MULTILINE):
# relies on tests running sequential (i.e., don't dare to use e.g. the xdist
# plugin)
current_capfd = None
@pytest.yield_fixture(autouse=True)
@pytest.fixture(autouse=True)
def save_cap_fixtures(request, capfd):
global current_capfd
capfd.false_positives = []
Expand Down
2 changes: 2 additions & 0 deletions test/pytest.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
[pytest]
addopts = --verbose --assert=rewrite --tb=native -x -r a
markers =
uses_fuse
Loading