IT办公室的故事 2023-04
NoMachine就像远端桌面Remote Desktop是一款远程桌面软件。它允许用户从自己的电脑上连接到另一个Linux服务器上面,并在本地使用远程服务器的桌面环境和应用程序。
对使用Linux系统的人来说,这时候可能会问为什么不用SSH链接?还要劳什子地使用桌面?
这是因为电子工程系不想花钱买微软多人连线的授权;所以迫使所有的学生不得不使用一个根本不熟悉的操作系统,要是在逼迫他们使用命令行界面那就抓瞎了。当然啦,有些他们使用的软件也需要GUI。
NoMachine本身是一个挺好用的软件,可以管理用户登录的session,自动踢出短线的账号等等。
但是电子工程系往往要使用一些一运行就需要一个多星期的程序;导致我们不能处理断线的终端。再加上学生们会在不同的电脑短程登录,我们时常会收到学生的投诉说自己又连接不上系统了。
因此教授们总是会抱怨IT不能给与自己的学生最方便的服务。但是我们也不能时时地盯着一个系统吧?再说我们也不知道断线的学生是不是登录不了了。
原本这种需要手动操作的工作是由去年愤怒辞职的前同事管理的;我不会处理这种事情。不过新同事来了之后,我也或多或少开始客服工作。
随着越来越多的人使用这个系统。手动操作就比较烦了。于是,我和同事商量何必登录服务器手动做这些事情?
人都是懒的,为了懒所以努力推动科技发展以便让自己更懒。完全可以做一个监视系统,起码可以先检查是不是因为断线造成用户登录不了。要知道NoMachine的指令运行起来不是很快,每次手动操作也恨废时间。
好嘞,开始写程序……
手动操作时,查询用户的登录状况会打出上面的信息。完全可以用Python抓取下来。
import subprocess import json # Run the "nxserver --list" command and capture its output output = subprocess.check_output(["/usr/NX/bin/nxserver", "--list"]) #print(output) # Convert the output to a string output_str = output.decode("utf-8") # Split the output into lines lines = output_str.split("\n") # create a list to hold the session information sessions = [] # Loop through the lines and print the information for each server for line in lines:if line.startswith("NX>"): # Skip any informational lines that start with "NX>"continueif line.startswith("Display") :continueif line.startswith("---") :continue#print(line)cols = line.split()#if len(cols) > 4 and cols[2] == "-" : # Check that the line has the expected number of columnsif len(cols) > 4 : # Check that the line has the expected number of columnssessions.append({"session": cols[0], "user": cols[1], "ip": cols[2]}) # save sessions into a JSON file with open("/user/nxserver-cleanup/sessions.json", "w") as f :json.dump(sessions, f)
Python的subprocess库可以直接收录系统指令的输出。
剩下的就是通过阵列Array收录自己想要的用户信息,IP地址,以及进程ID了。
上面的程序里把Python抓取的数据放到了一个JSON文件中。这是因为每次调取系统指令都需要一定的时间。监控系统调用这些数据的时候未免需要很长的时间,导致读取中断。
放在一个文件中,用Cronjob一定时间更新就能解决这个问题。
下面就是找一个有web服务的服务器调取信息了。我们有一个PHP 8.0的系统主要存储着各种inventory信息;正好可以用这个网络应用。
public function List($val) {if ($this->err["errno"] === 1) {if ($this->session->AdminAuthed($val["admin"])) {// Remote file path$json_file = $this->config["nx"]["sessions"];// Open SFTP subsystem$sftp = ssh2_sftp($this->connection);// Open remote file on SFTP subsystem$remote_file = fopen("ssh2.sftp://$sftp$json_file", "r");// Read from remote file into a string variable$content = stream_get_contents($remote_file);// close file handlefclose($remote_file);// Decode the JSON string into an array$data = json_decode($content, true);$this->err = ["count" => count($data),"errmsg" => $data,"errno" => 1,"status" => "success"];}else {$this->err = ["errno" => 3,"note" => "review NX server"];}}if ($this->err["errno"] === 1 && !empty($this->err["count"]) && (int)$this->err["count"] > 0) {$search = [];foreach ($this->err["errmsg"] as $users) {array_push($search, $users["user"]);}$result = $this->ldap->FetchUsersById($search);$UserCount = count($result);if ((int)$UserCount > 0) {$this->err["users"] = ["count" => $UserCount,"errno" => 1,"errmsg" => $result];}}return $this->err;}
PHP有一个ssh2.sftp方程,可以通过SSH进入到另一个系统中读取上面的数据。
登录的用户都是Active Directory下面的用户,用LDAP可以调用户信息。那就顺便弄些信息出来,前端监控的时候可以看到除了用户ID之外更多的信息。
就这样,将数据从PHP传到前端;我们的学生工也能在没有sudo权限的情况下看到远程连接的用户信息了。
因为是读取服务器上面的JSON文件,所以可以在前端设置定期更新。
要学生工能够踢出断线的用户则需要PHP能够真正拥有远程操控的权限。这里就不贴程序了。
需要一个sudo不使用密码的账户,ansible
就是利用这种方式安装、删除远程系统软件。设置id_ed25519
密钥,然后在远程系统中更新authorized_key
。
这么一来,学生工可以直接点击黄色的用户就可以删除断线用户的连接中断了。
因为这个操作不需要定期更新,所以远程调用系统指令的延时并不是我们需要考虑的问题。
新程序上线。同事笑着说:“为了让自己懒,指派学生工干活,花了一天的时间,值得!!我们可以继续懒了……”