Tag: linux

Mac远程桌面到Linux服务器

假期结束,回到学校开始干活 :]

为了远程使用Linux服务器,折腾了一个下午。最终看来还是用vnc最简单了。

实验室有两台强劲的Linux服务器用来做研究。之前我一直都是用ssh登到服务器上去码代码,反应速度很快,感觉很不错。但是因为在做机器视觉,难免需要看远程的图片。命令行虽然快,总不能每次都把图片拷贝到本地再看,有时候需要可视化中间结果,ssh也行不通。

当本地机器是Linux系统的时候比较好办。可以用ssh加X forwarding的方法。在本地开一个X,然后把远程服务器的X指令通过ssh转发到本地的X,码代码没有什么延迟,感觉还是很不错的。

sudo X :11 vt11 2>&1 >/dev/null &

这样可以在本地新开一个X,Ubuntu下用Ctrl+Alt+F11可以切到第11个虚拟终端

回到之前的终端,开ssh和xterm

xterm -display :11 -e ssh -X server-host &

然后可以切换到第11个虚拟终端来使用远程Linux服务器上的X了。

这样虽然好,但是要求本地机器上有安装X。在Windows和MacOS下虽然有解决方法,但是比较麻烦。

用VNC的话就没有这个问题,毕竟VNC的客户端是很容易找的。

当然需要先ssh登录到Linux服务器上安装vncserver

sudo apt-get install vnc4server

然后启动vncserver

vncserver

这样就搞定了。

在本地的Mac下可以用自带的Screen Sharing App或者著名的Chicken of the VNC连接到server-host:5901来查看和控制远程Linux桌面。

在服务器上启动了vncserver之后,可以通过修改

~/.vnc/xstartup

这个文件,来指定远程的X启动之后要执行什么命令。我喜欢用openbox,所以我的xstartup文件就是这样子

#!/bin/sh

# Uncomment the following two lines for normal desktop:
# unset SESSION_MANAGER
# exec /etc/X11/xinit/xinitrc

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
xsetroot -solid grey
vncconfig -iconic &
openbox-session&
#x-terminal-emulator -geometry 80x24+10+10 -ls -title "$VNCDESKTOP Desktop" &
#x-window-manager &

另外,在启动vncserver的时候可以使用参数修改远程桌面的分辨率

vncserver  -geometry 1280x1024

这么一来就可以在命令行下写代码,同时再开一个vnc窗口看图,感觉不错!

这篇文章有列举一些远程到Linux服务器上的其它解决方法,如果有服务器的root用户权限的话,freeNX貌似也是一个不错的选项。

dup, pipe 和 fork

(好久没更新了,呼…一大波死线刚刚结束…)

我几乎一直在用Bash,可是却少有接触到Unix系的系统编程,对系统调用还是知之甚少。这两天实验室里讨论了一个比较基础的问题: 在自己写的程序中,怎么样得到另一个可执行文件的输出?

比如我们有/bin/pwd这个可执行文件,我们可以在自己的程序中用

system("/bin/pwd");

或者是

execl("/bin/pwd",".",NULL);

调用它。

如果想要得到它的输出,应该怎么做比较好?

这个其实是作业题的范畴,涉及到了几个Unix的系统调用:

     #include 

     pid_t
     fork(void);
     #include 

     int
     pipe(int fildes[2]);
     #include 

     int
     dup(int fildes);

     int
     dup2(int fildes, int fildes2);

手册里有各个函数的详细解释。
在这个例子里,pipe用来生成一对文件描述子 (file descriptor,我觉得描述子这个翻译不是很好…),往第二个描述子里写内容,从第一个里面读内容。fork用来得到一个子进程,这里,我们会让子进程来执行pwd,并且把输出写到pipe的一端,然后父进程可以从另一端读入。

但是pwd默认输出到屏幕,也就是标准输出,我们需要使用dup2,把标准输出指向pipe的一端,这样就可以完成任务了。

所以,最终的代码是这样的

#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
    int fd[2];
    int pid;
    pipe(fd);
    int rpipe = fd[0];
    int wpipe = fd[1];
    pid = fork();
    if (pid == 0)
    {   
        /* 子进程关掉读的那端,只用写的一端 */
        close(rpipe); 

        /* 把标准输入指向pipe的写的一端 */
        dup2(wpipe, STDOUT_FILENO);

        /* 执行pwd */
        execl("/bin/pwd",".",NULL);

        /* 嗯 */
        exit(0);
    }   
    else
    {   
        /* 父进程关掉写的那端,只用读的一端 */
        close(wpipe);

        printf("begin parent process\n");
        char readbuffer[1024];

        /* 从读的这端读出pwd的输出 */
        int nbytes = read(rpipe, readbuffer, sizeof(readbuffer));

        printf("Received string: %s | %d\n", readbuffer, nbytes);
        printf("end parent process\n");

        wait(&pid);
    }   
    return 0;
}

所以最后的输出就是像这样的

begin parent process
Received string: /Users/XXX/XXXX
 | 16
end parent process

话说fork除了考试之外,似乎就没有用过了,代码还是写得太少了…

(Image from Github)

Linux Swap文件

想象一下,两个实验进程跑了两天,还有一天就跑完了,这个时候你发现如果再跑一会儿内存就要爆了…怎么办? (好惊险的感觉 XD)

好吧,其实用到的只是很基本的操作系统知识,不过还真难得用到一回。

程序面对的都是虚拟内存。64位的操作系统下,虚拟内存非常大,但是实际物理内存相对而言小得多。所以,操作系统对内存分页 (就是分成一块一块的,每一块儿叫做一页) 物理内存一旦满了,把暂时不需要的页写到硬盘里。过了一会儿程序又要访问被写到硬盘里的那部分内容,操作系统就在物理内存中选一个页 (怎么选很讲究的),把硬盘里的那个给换回来。程序不停的运行,操作系统就换来换去…

所以,上面我们遇到的情形就可以解决了。把其中一个进程挂起 (suspend),Linux下可以用

Ctrl+Z

,然后这部分内存就是暂时不用的了。这个时候用

$top

查看内存使用情况,可以看到一个CPU占用率为0的进程占用的内存越来越少,另一个越来越多。这样就行了,等一个进程跑完,再用

$fg

命令把挂起的进程调到前台就可以了。

但是等等。虚拟内存具体是在哪里呢?数据终究是写在内存/硬盘上的,Linux下被换到硬盘上的内存在Swap分区 (交换分区) 里。安装系统的时候需要格式化一个分区为Swap格式,就是这个分区。

$swapon -s

可以查看交换分区的大小。

糟糕!刚才那个被挂起的进程占用了24G的内存,但是现在看到我的交换分区只用12G,怎么办?一旦交换分区和内存都满了,会发生神马事情,我也没有体验过,估计应该是系统卡死或者卡而不死吧。

所以,应该赶紧增加交换分区的大小才是。可是如果你和我一样,很悲催的没有Root权限 (Root权限貌似是必须的…),而且也根本没有多余的分区可以挂载了,怎么办?

可以用Swap文件 (点题) ! 就是把一个文件用做swap分区,Linux下什么都是文件,分区应该也是吧。要增加系统可用的虚拟内存,当然这要求你硬盘剩余空间够大…

$dd if=/dev/zero of=~/swapfile bs=1024 count=41943040

会在HOME下创建一个40G的文件”~/swapfile”,命令要执行一会儿,需要写一段时间硬盘,执行完了会显示写硬盘的速度,可以用来做测速的。
然后告诉系统用这个文件做交换文件

mkswap ~/swapfile

就没问题了。
(实际上不行,还需要这个命令, –!)

sudo swapon ~/swapfile

其实最一开始那个情形下,如果两个进程继续跑下去,操作系统仍然会把一部分内容换出来的。只是大量换页操作会让程序执行的时间更长,而且如果交换空间不够大,系统最终仍然可能会被卡死。

感叹一下,一个实验要跑三天的同学伤不起啊..