IT办公室的故事 2023-04

阿酷
·
·
IPFS
图像源自:https://www.pexels.com/

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

这么一来,学生工可以直接点击黄色的用户就可以删除断线用户的连接中断了。

因为这个操作不需要定期更新,所以远程调用系统指令的延时并不是我们需要考虑的问题。


新程序上线。同事笑着说:“为了让自己懒,指派学生工干活,花了一天的时间,值得!!我们可以继续懒了……”

CC BY-NC-ND 2.0 授权

喜欢我的作品吗?别忘了给予支持与赞赏,让我知道在创作的路上有你陪伴,一起延续这份热忱!