Hello there!
I am trying to create a go application that would run a docker container and mount a host directory inside a container using sshfs( rejected using volumes because they mess up directory ownership, btw if anyone is using docker and might know this:can you create a file inside a mounted directory using volumes which ownership can be somehow specified? So it does not have to be "root created" but specific suer created? sshfs has "idmap=user" flag which is great, is there something analogical in docker?)
So I create a daemonized container:
sudo docker run -i -t -privileged -dns=[172.25.0.10] -p 22 -d orobix/sshfs_startup_key2 /bin/bash -c "/usr/sbin/sshd -D"
And then I can ssh into it and mount directories using sshfs(which is preinstalled in the image):
sshfs pi...@172.17.42.1:/home/piotr/helloworld/ /mnt -o idmap=user
And when I ssh out of it (type exit) and ssh back into it, the mountpoint is still there which is great and desired behaviour.
However when I execute the same steps using Go and crypto/ssh client it will create create mountpoints using sshfs, but after the Go program terminates the mountpoint dissapears and I do not know why...
From my perspective I am recreating the same steps in go code as i would do it manually but for some reason the mountpoint disappears..
I tried using sshfs "-o reconnect" option inside the go code which seems to keep the mountpoints inside the container(after typing "mount" command inside the container I can see that the mountpoint is there:
root@bd901e2:~# mount
none on / type aufs (rw,relatime,si=d49df04d58206c91)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /etc/hostname type ext4 (ro,relatime,errors=remount-ro,data=ordered)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /etc/hosts type ext4 (ro,relatime,errors=remount-ro,data=ordered)
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
shm on /dev/shm type tmpfs (rw,nosuid,nodev,noexec,relatime,size=65536k)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /.dockerinit type ext4 (ro,relatime,errors=remount-ro,data=ordered)
/dev/disk/by-uuid/7e1d6bab-b3f2-4ac3-8bff-0779f5bf40f2 on /etc/resolv.conf type ext4 (ro,relatime,errors=remount-ro,data=ordered)
devpts on /dev/tty1 type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=666)
devpts on /dev/ptmx type devpts (rw,relatime,mode=600,ptmxmode=666)
pi...@172.17.42.1:/home/piotr/helloworld/ on /mnt type fuse.sshfs (rw,nosuid,nodev,relatime,user_id=0,group_id=0,max_read=65536)
However when I try to access it in any way I am getting errors:
root@bd901e2:~# cd /mnt/
root@bd901e2:/mnt# ls
ls: reading directory .: Input/output error
This is my sshclient code:
package main
import (
//"bytes"
"code.google.com/p/go.crypto/ssh"
//"fmt"
"io"
"log"
"os"
)
var (
server = "172.17.42.1:49155"
username = "root"
password = clientPassword("orobix2013")
)
type clientPassword string
func (p clientPassword) Password(user string) (string, error) {
return string(p), nil
}
type TerminalModes map[uint8]uint32
const (
VINTR = 1
VQUIT = 2
VERASE = 3
VKILL = 4
VEOF = 5
VEOL = 6
VEOL2 = 7
VSTART = 8
VSTOP = 9
VSUSP = 10
VDSUSP = 11
VREPRINT = 12
VWERASE = 13
VLNEXT = 14
VFLUSH = 15
VSWTCH = 16
VSTATUS = 17
VDISCARD = 18
IGNPAR = 30
PARMRK = 31
INPCK = 32
ISTRIP = 33
INLCR = 34
IGNCR = 35
ICRNL = 36
IUCLC = 37
IXON = 38
IXANY = 39
IXOFF = 40
IMAXBEL = 41
ISIG = 50
ICANON = 51
XCASE = 52
ECHO = 53
ECHOE = 54
ECHOK = 55
ECHONL = 56
NOFLSH = 57
TOSTOP = 58
IEXTEN = 59
ECHOCTL = 60
ECHOKE = 61
PENDIN = 62
OPOST = 70
OLCUC = 71
ONLCR = 72
OCRNL = 73
ONOCR = 74
ONLRET = 75
CS7 = 90
CS8 = 91
PARENB = 92
PARODD = 93
TTY_OP_ISPEED = 128
TTY_OP_OSPEED = 129
)
func main() {
// An SSH client is represented with a slete). Currently only
// the "password" authentication method is supported.
//
// To authenticate with the remote server you must pass at least one
// implementation of ClientAuth via the Auth field in ClientConfig.
config := &ssh.ClientConfig{
User: username,
Auth: []ssh.ClientAuth{
// ClientAuthPassword wraps a ClientPassword implementation
// in a type that implements ClientAuth.
ssh.ClientAuthPassword(password),
},
}
client, err := ssh.Dial("tcp", "172.17.42.1:49155", config)
if err != nil {
panic("Failed to dial: " + err.Error())
}
// Each ClientConn can support multiple interactive sessions,
// represented by a Session.
defer client.Close()
// Create a session
session, err := client.NewSession()
if err != nil {
log.Fatalf("unable to create session: %s", err)
}
defer session.Close()
// Set up terminal modes
modes := ssh.TerminalModes{
ECHO: 0, // disable echoing
TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
}
// Request pseudo terminal
if err := session.RequestPty("xterm", 80, 40, modes); err != nil {
log.Fatalf("request for pseudo terminal failed: %s", err)
}
//var b bytes.Buffer
//session.Stdout = &bi
stdin, _ := session.StdinPipe()
stdout, _ := session.StdoutPipe()
go io.Copy(os.Stdout, stdout)
go io.Copy(stdin, os.Stdin)
//go io.Copy(os.Stderr, stderr)
if err := session.Run("/bin/bash -c \"sshfs pi...@172.17.42.1:/home/piotr/helloworld/ /mnt -o idmap=user;touch /mnt/ofoo\""); err != nil {
panic("Failed to run: " + err.Error())
}
After I run this code the "ofoo" file will be created on host which is a proof that sshfs worked correctly. However when I ssh into the container, the mountpoints is gone and I would like it to stay there until the container is killed/stoped. I do not have this issue when doing everything manually. So how I can make the mountpoint persistent?
I would imagine that something is getting killed when the session ends.Do you have to do /bin/bash -x -e -c "<command snippet>" ?
What happens if you do this?session.Run("sshfs pi...@172.17.42.1:/home/piotr/helloworld/ /mnt/ -o idmap=user && touch /mnt/aaa && /usr/sbin/sshd &")
Here is an example using RequestPty and Shell.http://godoc.org/code.google.com/p/go.crypto/ssh#example-Session-RequestPty
I would actually really like to test this out myself to dig into the issue, but I am unable to look at this in detail for the next few weeks. Maybe someone else on this list will have more time sooner.