思路:ubantu通过IP地址以及指定端口向Windows端发送命令,Windows端用python脚本监听端口变化,收到ubantu发来的指令后去执行对应指令。因为本人从事Linux、android底层驱动工作,实现该功能的代码主要是面相过程的风格。
1、ubantu端,将要打开的文件或目录的路径转化为Windows端能识别并访问的路径,具体代码实现如下:
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
char shell_cmd(char *cmd, char *cmd_result)
{
FILE *fp = NULL;
char result[1024] = {0};
if(cmd_result != NULL){
fp = popen(cmd, "r");
if(fp == NULL){
printf("Failed to run command %s
", cmd);
return -1;
}
// 读取命令输出
while (fgets(result, sizeof(result), fp) != NULL);
// 关闭管道
pclose(fp);
fp = NULL;
memcpy(cmd_result, result, strlen(result)-1);
}else{
//system("curl -d "explorer.exe \\\\192.168.1.162\lxx\lxx_test" http://192.168.1.83:8080 > /dev/null 2>&1");
system(cmd);
}
return 0;
}
int main(int argc, char const *argv[])
{
int ret = -1;
char windows_ip[1024] = {0};
char ubantu_ip[1024] = {0};
char file_path[1024] = {0};
//char samba_path[1024] = {0};
char new_path[1024] = {0};
char open_path[1024] = {"\\"};
char curl_cmd[1024] = {0};
struct stat path_stat;
//printf("argc:%d
", argc);
//if(argv[1] != NULL)
// printf("argv:%s len:%lu
", argv[1], strlen(argv[1]));
ret = shell_cmd("echo $SSH_CLIENT | awk '{print $1}'", windows_ip);
if(ret)
printf("get windows_ip Failed
");
//printf("windows_ip:%s len:%lu
", windows_ip, strlen(windows_ip));
ret = shell_cmd("ifconfig | awk '/inet 192/ {print $2}'", ubantu_ip);
if(ret)
printf("get ubantu_ip Failed
");
//printf("ubantu_ip:%s len:%lu
", ubantu_ip, strlen(ubantu_ip));
ret = shell_cmd("echo "$PWD" | sed 's|/[^/]*/|/|'", new_path);
if(ret)
printf("get new_path Failed
");
//printf("new_path:%s len:%lu
", new_path, strlen(new_path));
ret = shell_cmd("echo "$PWD"", file_path);
if(ret)
printf("get file_path Failed
");
//printf("file_path:%s len:%lu
", file_path, strlen(file_path));
//samba_path = shell_cmd("awk "/$USER/" /etc/samba/smb.conf | sed -n '/path/p' | awk '{print $3}'", samba_path);
//if(ret)
// printf("get samba_path Failed
");
//printf("samba_path:%s len:%lu
", samba_path, strlen(samba_path));
strcat(open_path, ubantu_ip);
strcat(open_path, new_path);
if(argv[1] != NULL){
if(argv[1][0] == '.' && argv[1][1] == '/'){
sprintf(open_path + strlen(open_path), "/%s", &argv[1][2]);
sprintf(file_path + strlen(file_path), "/%s", &argv[1][2]);
}else{
sprintf(open_path + strlen(open_path), "/%s", argv[1]);
sprintf(file_path + strlen(file_path), "/%s", argv[1]);
}
}
for (int i = 0; i < strlen(open_path); ++i){
if(open_path[i] == '/')
open_path[i] = '\';
}
//printf("
###open_path###: %c
", open_path[strlen(open_path)-1]);
if(open_path[strlen(open_path)-1] == '\')
open_path[strlen(open_path)-1] = ' ';
printf("########################################################################
");
if(stat(file_path, &path_stat) == 0){
if(S_ISDIR(path_stat.st_mode)){//文件夹
printf("
###打开目录###: %s
", open_path);
sprintf(curl_cmd, "%s%s%s%s%s", "curl -d "\\", open_path,"" http://", windows_ip, ":6666 > /dev/null 2>&1");
//printf("
###curl_cmd###: %s
", curl_cmd);
}else{//文件
printf("
###打开文件###: %s
", open_path);
sprintf(curl_cmd, "%s%s%s%s%s", "curl -d "\\", open_path,"" http://", windows_ip, ":6666 > /dev/null 2>&1");
//printf("
###curl_cmd###: %s
", curl_cmd);
}
ret = shell_cmd(curl_cmd, NULL);
if(ret)
printf("curl_cmd Failed
");
}else{
perror("无法获取状态,请检查路径是否正确");
}
printf("
########################################################################
");
return 0;
}
2、文件命名为fw.c,在ubantu上将fw.c编译成可执行文件,对应命令如下
gcc -o fw fw.c
3、这一步主要针对uabntu 没有root操作权限的同学,在当前用户根目录下创建.bashrc和.profile两个文件,.profile主要是在登录时候去引导执行.bashrc内的命令,.bashrc中主要是将我们的fw命令全局到当前用户,不需要每次执行都要加上fw命令的路径
.profile文件内容:
# ~/.profile: executed by the command interpreter for login shells.
# This file is not read by bash(1), if ~/.bash_profile or ~/.bash_login
# exists.
# see /usr/share/doc/bash/examples/startup-files for examples.
# the files are located in the bash-doc package.
# the default umask is set in /etc/profile; for setting the umask
# for ssh logins, install and configure the libpam-umask package.
#umask 022
# if running bash
if [ -n "$BASH_VERSION" ]; then
# include .bashrc if it exists
if [ -f "$HOME/.bashrc" ]; then
. "$HOME/.bashrc"
fi
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/bin" ] ; then
PATH="$HOME/bin:$PATH"
fi
# set PATH so it includes user's private bin if it exists
if [ -d "$HOME/.local/bin" ] ; then
PATH="$HOME/.local/bin:$PATH"
fi
.bashrc内容:主要是添加alias fw=‘~/bin/fw’,fw命令也需要放到对应路径,不然找不到
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
#force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}[33[01;32m]u@h[33[00m]:[33[01;34m]w[33[00m]$ '
else
PS1='${debian_chroot:+($debian_chroot)}u@h:w$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="[e]0;${debian_chroot:+($debian_chroot)}u@h: wa]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
alias fw='~/bin/fw'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '''s/^s*[0-9]+s*//;s/[;&|]s*alert$//''')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
export JAVA_HOME=/opt/jdk1.6.0_45
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export LC_ALL="en_US.UTF-8"
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && . "$NVM_DIR/bash_completion" # This loads nvm bash_completion
2、Windows端,监听端口并解析收到的命令,并执行收到的命令。cmd命令行直接输入python,如果电脑不支持python命令,可以在弹出的窗口直接安装就行
python脚本代码:
import os
import time
import ctypes
import socket
import logging
import threading
import subprocess
from datetime import datetime
from pathlib import Path
LOG_FILE = "D:\logs\logcat\python.log"
class PortListener:
def __init__(self, host='0.0.0.0', port=6666):
self.host = host
self.port = port
self.running = False
self.server_socket = None
def start_listening(self):
"""启动端口监听服务"""
try:
# 创建TCP socket
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
# 绑定地址和端口
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(5)
self.running = True
logging.info("####日志系统初始化成功")
logging.info(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 开始监听端口 {self.port}")
while self.running:
try:
# 接受客户端连接
client_socket, client_address = self.server_socket.accept()
logging.info(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 客户端连接: {client_address}")
# 为每个客户端创建新线程处理
client_thread = threading.Thread(
target=self.handle_client,
args=(client_socket, client_address)
)
client_thread.daemon = True
client_thread.start()
except socket.error:
if self.running:
continue
break
except Exception as e:
logging.info(f"监听端口时发生错误: {e}")
finally:
self.stop_listening()
def handle_client(self, client_socket, client_address):
"""处理客户端连接"""
try:
# 接收客户端数据
data = client_socket.recv(1024)
if data:
message = data.decode('utf-8')
logging.info(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 来自 {client_address} 的消息: {message}")
lines = data.splitlines() # 按行分割为列表
line_count = len(lines) # 行数统计
last_line = lines[-1] if lines else "" # 安全获取最后一行
path = last_line.decode('utf-8')
logging.info(path)
if os.path.exists(path):
if os.path.isfile(path):
logging.info(f"打开文件:{path}")
subprocess.run(['D:\wake_apk\SublimeText3\sublime_text.exe', path])
elif os.path.isdir(path):
logging.info(f"打开目录:{path}")
os.startfile(path)
else:
logging.info(f"未知路径")
else:
logging.info(f"路径不存在")
# 发送响应
response = f"服务器已收到消息: {message}"
client_socket.send(response.encode('utf-8'))
except Exception as e:
logging.info(f"处理客户端 {client_address} 时发生错误: {e}")
finally:
client_socket.close()
def stop_listening(self):
"""停止监听服务"""
self.running = False
if self.server_socket:
self.server_socket.close()
logging.info(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] 已停止监听端口 {self.port}")
# 初始化日志
def setup_logger():
try:
log_path = Path(LOG_FILE)
log_path.parent.mkdir(parents=True, exist_ok=True) # 自动创建日志目录
logging.basicConfig(
filename=str(log_path),
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logging.info("日志系统初始化成功")
except PermissionError as e:
print(f"权限错误: {e}
请检查日志目录写入权限")
except Exception as e:
print(f"日志初始化失败: {e}")
if __name__ == "__main__":
ctypes.windll.user32.ShowWindow(ctypes.windll.kernel32.GetConsoleWindow(), 0) # 隐藏窗口
setup_logger()
# 创建监听器实例
listener = PortListener(port=6666)
# 在后台线程中启动监听
listener_thread = threading.Thread(target=listener.start_listening)
listener_thread.daemon = True
listener_thread.start()
logging.info("端口监听服务已启动,按Ctrl+C停止...")
try:
# 主线程保持运行
while True:
time.sleep(1)
except KeyboardInterrupt:
logging.info("
正在停止服务...")
listener.stop_listening()
python脚本需要设置成开机启动,具体方法可以直接百度,以下方法可做参考:
创建基本任务
按 Win+R 输入 taskschd.msc 打开任务计划程序
操作步骤:
触发器:选择"登录时"(所有用户或特定用户)
操作:
程序/脚本:pythonw.exe(无窗口模式)
参数:脚本绝对路径(如 D:scriptmain.py)
条件:取消勾选"只有在计算机使用交流电源时才启动"
设置:勾选"如果任务失败,重新启动"
将编写好的python脚本放到C:UsersAdministratorAppDataRoamingMicrosoftWindowsStart MenuProgramsStartup下能达到开机运行的效果
还可以编写一个vbs脚本放到C:UsersAdministratorAppDataRoamingMicrosoftWindowsStart MenuProgramsStartup下也能达到开机启动效果
vbs脚本:
Set wshShell = WScript.CreateObject("WScript.Shell")
wshShell.Run "D:wake_apkPythonFilePythonFile.py", 1, True
注:使用过程中发现问题会持续更新优化!!!




