python运维小工具_Python实现跨平台运维小神器

article/2025/11/11 15:22:40

(本文已不再同步更新,最新代码请移步github)

这阵子一直在学python,碰巧最近想把线上服务器环境做一些规范化/统一化,于是便萌生了用python写一个小工具的冲动。就功能方面来说,基本上是在“重复造轮子”吧,但是当我用这小工具完成了30多台服务器从系统层面到应用层面的一些规范化工作之后,觉得效果还不算那么low(高手可忽略这句话~~),这才敢拿出来跟小伙伴们分享一下。

(注:笔者所用为python版本为3.5,其他版本未经测试~~)

现在主要功能包括:可批量执行远程命令,上传下载文件支持多线程并发执行(对于某些耗时的命令或上传文件,可大大减少等待时间)严格模式(批量执行中若某一台server执行错误则退出)和非严格模式上传下载文件实现了类似rsync的机制完善的命令行提示跨平台,Linux和Windows均可

大致实现思路如下:

外部包依赖docopt和paramiko    有一个server信息文件,内容格式为 : “主机名-IP:端口”。脚本读取此文件来决定要对哪些server进行操作(该文件内部支持#注释掉某些server)    采用了docopt提供命令行界面    paramiko模块实现远程命令和sftp客户端功能。这里paramiko的sftp实例其只包含了基本的单个文件传输功能;并且不保存文件相关时间信息。    paramiko 通过sftp实例传输文件环节,这里额外实现“保持文件时间信息”和“实现目录传输”以及“实现类似rsync的传输机制”是要考虑很多问题和逻辑的。传输机制模仿rsync的默认机制,检查文件的mtime和size,有差异才会真正传输。    实现了参数中原路径和目标路径的自动判断,例如传输目录时不要求路径后面加‘/’    对于远程命令(cmd),可以通过设置(--skip-err)跳过某些server的错误继续执行。例如批量执行‘ls’命令,一般情况会因为某些server上不存在而报错退出    全面的错误信息提示。对于执行中的几乎所有可能出现的错误,都有捕获机制获取并输出

下面先来看一些基本的使用截图吧

帮助信息:

420e10cb8cfe5ec56c40466603af157b.png

批量执行远程命令:

9cb3fd325adfd553b3769d120e16d08a.png

上传:

08d30aecd16e98acbe84ed19c3940ab1.png

下载:

3df8f57fca1a1a59f69884fd592dd04c.png

其实批量执行命令,传输文件在Linux上用shell也是可以很好的实现(而且ssh或rsync等也肯定比这套脚本功能点更多),但是考虑到并发执行以及在Linux和win平台的通用性,用Python来实现就有必要了。尤其是想在Win客户端和Linux服务器之间模仿rsync机制传输文件时,这个脚本就能派上用场了。

接下来直接看代码吧(我的老(lan)习惯,代码里注释还算详细,所以我就懒得再解释那么多喽)

#!/bin/env python3

# coding:utf-8

"""

Usage:

auto_task [options] cmd [--skip-err] [--parallel]

auto_task [options] put [--parallel]

auto_task [options] get

Options:

-h --help             Show this screen.

-u              Remote username [default: root]

-p          User's password

--pkey   Local private key [default: /root/.ssh/id_rsa]

--server

File include the remote server's information,

With the format of 'name-ip:port', such as 'web1-192.168.1.100:22',one server one line.

--skip-err            Use with cmd, if sikp any server's error and continue process the other servers [default: False].

--parallel            Parallel execution, only use with cmd or put. This option implies the --skip-err [default: False].

cmd                   Run command on remote server(s),multiple commands sperate by ';'

put                   Transfer from local to remote. Transport mechanism similar to rsync.

get                   Transfer from remote to local. Transport mechanism similar to rsync.

Notice:       cmd, get, put can only use one at once

For Windows:  always use double quotes for quote something;

it's highly recommend that with get or put in Windows,always use '/' instead of '\\'

"""

"""

by ljk 20160704

update at 2017011,20170320

"""

from docopt import docopt

from paramiko import SSHClient, AutoAddPolicy

from os import path, walk, makedirs, stat, utime

from re import split, match, search

from sys import exit, stdout

import platform

from math import floor

import threading

"""

因为涉及了(多)线程,所以我们将串行也归为单线程,这样可以统一用线程的一些思路,而不必编写一套多线程模型一套串行模型。

也因为多线程,所以输出用print()的话,各server的输出会对不上号,所以引入了OutputText类,将每个server的输出统一保存起来,最后打印出来

但是这样依然无法避免多个线程同时完成了,同时打印各自的最终结果。也就是说多线程任务最终需要输出时,输出这个动作必须要串行

"""

class OutputText:

"""该类的对象具有write()方法,用来存储每台server的执行结果.

因为引入了多线程异步执行才需要这么做,以保证异步执行多台server的输出不会乱.

为了简洁,并行与串行的输出就都用这一套东西了"""

def __init__(self):

self.buffer = []

def write(self, *args, color=None):

if color:

if platform.uname().system == 'Windows':

self.buffer.extend(args)

else:

self.buffer.extend('\033[0;{}m'.format(color))

self.buffer.extend(args)

self.buffer.extend('\033[0m')

else:

self.buffer.extend(args)

def print_lock(self):

"""并发模式下,所有的输出动作都要加锁"""

global_lock.acquire()

for line in self.buffer:

print(line, end='')

global_lock.release()

def print_color(text, color=31, sep=' ', end='\n', file=stdout, flush=False):

"""打印彩色字体,color默认为红色

该方法只针对Linux有效"""

if platform.uname().system == 'Windows':

print(text, sep=sep, end=end, file=file, flush=flush)

else:

print('\033[0;{}m'.format(color), end='')

print(text, sep=sep, end=end, file=file, flush=flush)

print('\033[0m', end='')

def get_ip_port(fname):

"""从制定文件(特定格式)中,取得主机名/主机ip/端口

output:存储输出的对象"""

try:

with open(fname, 'r') as fobj:

for line in fobj.readlines():

if line != '\n' and not match('#', line):  # 过滤空行和注释行

list_tmp = split('[-:]', line)

server_name = list_tmp[0]

server_ip = list_tmp[1]

port = int(list_tmp[2])

yield (server_name, server_ip, port)

except Exception as err:

print_color('{}\n'.format(err))

exit(10)

def create_sshclient(server_ip, port, output):

"""根据命令行提供的参数,建立到远程server的ssh链接.这段本应在run_command()函数内部。

摘出来的目的是为了让sftp功能也通过sshclient对象来创建sftp对象,因为初步观察t.connect()方法在使用key时有问题

output:存储输出的对象"""

local_client = threading.local()  # 多线程中每个线程要在函数内某些保持自己特定值

local_client.client = SSHClient()

local_client.client.set_missing_host_key_policy(AutoAddPolicy())

try:

local_client.client.connect(server_ip, port=port, username=arguments['-u'], password=arguments['-p'], key_filename=arguments['--pkey'])

except Exception as err:  # 有异常,打印异常,并返回'error'

output.write('{}----{} ssh connect error: {}\n'.format(' ' * 4, server_ip, err), color=31)

return 'error'

else:

return local_client.client  # 返回的client对象在每个线程内是不同的

# ----------

# run_command()执行远程命令

# ----------

def run_command(client, output):

"""

执行远程命令的主函数

client: paramiko.client.SSHClient object

output: 存储输出的对象

"""

# stdout 假如通过分号提供单行的多条命令,所有命令的输出(在linux终端会输出的内容)都会存储于stdout

# 据观察,下面三个变量的特点是无论"如何引用过一次"之后,其内容就会清空

# 有readlines()的地方都是流,用过之后就没有了

stdin, stdout, stderr = client.exec_command(arguments[''])

copy_out, copy_err = stdout.readlines(), stderr.readlines()

if len(copy_out) and len(copy_err):

output.write('%s----result:\n' % (' ' * 8))

for i in copy_out:

output.write('%s%s' % (' ' * 12, i))

for i in copy_err:

output.write('%s%s' % (' ' * 12, i), color=31)

if not arguments['--skip-err']:    # 忽略命令执行错误的情况

output.print_lock()

exit(10)

elif len(copy_out):

output.write('%s----result:\n' % (' ' * 8))

for i in copy_out:

output.write('%s%s' % (' ' * 12, i))

elif len(copy_err):

output.write('%s----error:\n' % (' ' * 8), color=31)

for i in copy_err:

output.write('%s%s' % (' ' * 12, i), color=31)

if not arguments['--skip-err']:

client.close()

output.print_lock()

exit(10)

client.close()

# ----------

# sftp_transfer() 远程传输文件的主函数

# ----------

def sftp_transfer(source_path, destination_path, method, client, output):

"""

文件传输的 主函数

paramiko的sftp client传输,只能单个文件作为参数,并且不会保留文件的时间信息,这两点都需要代码里额外处理

client: paramiko.client.SSHClient object

output:存储输出的对象

"""

sftp = client.open_sftp()

if platform.system() == 'Windows':

'''根据put或get,将windows路径中的 \ 分隔符替换为 / '''

if arguments["put"]:

source_path = source_path.replace('\\', '/')

elif arguments["get"]:

destination_path = destination_path.replace('\\', '/')

# -----下面定义sftp_transfer()函数所需的一些子函数-----

def process_arg_dir(target):

"""处理目录时,检查用户输入,在路径后面加上/"""

if not target.endswith('/'):

target = target + '/'

return target

def sftp_put(src, dst, space):

"""封装put,增加相应输出,并依据m_time和size判断两端文件一致性,决定是否传输该文件"""

if check_remote_path(dst) == 'file':

src_stat = stat(src)

dst_stat = sftp.stat(dst)

else:

src_stat = ''

dst_stat = ''

if (src_stat == '' and dst_stat == '') or not (floor(src_stat.st_mtime) == dst_stat.st_mtime and src_stat.st_size == dst_stat.st_size):

try:

sftp.put(src, dst)

output.write('%s%s\n' % (' ' * space, src))

except Exception as err:

output.write('%s----Uploading %s Failed\n' % (' ' * (space-4), src), color=31)

output.write('{}----{}\n'.format(' ' * (space-4), err), color=31)

client.close()

output.print_lock()

exit(10)

def sftp_get(src, dst, space):

"""封装get,增加相应输出,并依据m_time和size判断两端文件一致性,决定是否传输该文件"""

if path.isfile(dst):

src_stat = sftp.stat(src)

dst_stat = stat(dst)

else:

src_stat = ''

dst_stat = ''

if (src_stat == '' and dst_stat == '') or not (src_stat.st_mtime == floor(dst_stat.st_mtime) and src_stat.st_size == dst_stat.st_size):

try:

sftp.get(src, dst)

output.write('%s%s\n' % (' ' * space, src))

except Exception as err:

output.write('%s----Downloading %s Failed\n' % (' ' * (space-4), src), color=31)

output.write('{}----{}\n'.format(' ' * (space-4), err), color=31)

client.close()

output.print_lock()

exit(10)

def sftp_transfer_rcmd(cmd=None, space=None):

"""

在文件传输功能中,有些时候需要在远程执行一些命令来获取某些信息

client: paramiko.client.SSHClient object

output:存储输出的对象

"""

stdin, stdout, stderr = client.exec_command(cmd)

copy_out, copy_err = stdout.readlines(), stderr.readlines()

if len(copy_err):

for i in copy_err:

output.write('%s----%s' % (' ' * space, i), color=31)

output.print_lock()

exit(10)

elif len(copy_out):

return copy_out

def check_remote_path(r_path):

"""通过client对象在远程linux执行命令,来判断远程路径是否存在,是文件还是目录"""

check_cmd = 'if [ -e {0} ];then if [ -d {0} ];then echo directory;elif [ -f {0} ];then echo file;fi;else echo no_exist;fi'.format(r_path)

# check_cmd命令会有三种‘正常输出’directory  file  no_exist

check_result = sftp_transfer_rcmd(cmd=check_cmd)[0].strip('\n')

if check_result == 'directory':

return 'directory'

elif check_result == 'file':

return 'file'

else:

return 'no_exist'

def file_time(target, location):

"""获取源文件的atime和mtime"""

if location == 'local':

target_stat = stat(target)

elif location == 'remote':

target_stat = sftp.stat(target)

return target_stat.st_atime, target_stat.st_mtime

def create_dir(target, location, space):

"""将创建目录的代码集中到一个函数"""

if location == 'local':

try:

output.write('%s----Create Local Dir: %s\n' % (' ' * space, target))

makedirs(target)

except Exception as err:

# print_color('%s----%s' % (' ' * space, str(err)))

output.write('%s----%s\n' % (' ' * space, str(err)), color=31)

output.print_lock()

exit(10)

elif location == 'remote':

output.write('%s----Create Remote Dir: %s\n' % (' ' * space, target))

sftp_transfer_rcmd(cmd='mkdir -p {}'.format(target), space=space)

# -----子函数定义完毕-----

# -----上传逻辑-----

if method == 'put':

output.write('%s----Uploading %s TO %s\n' % (' ' * 4, source_path, destination_path))

if path.isfile(source_path):

'''判断src是文件'''

check_remote_path_result = check_remote_path(destination_path)

if check_remote_path_result == 'file':

pass

elif check_remote_path_result == 'directory':  # dst经判断为目录

destination_path = process_arg_dir(destination_path) + path.basename(source_path)

else:

if not check_remote_path(path.dirname(destination_path)) == 'directory':

create_dir(path.dirname(destination_path), 'remote', 8)

if destination_path.endswith('/') or destination_path.endswith('\\'):

destination_path = destination_path + path.basename(source_path)

sftp_put(source_path, destination_path, 12)

sftp.utime(destination_path, file_time(source_path, 'local'))

elif path.isdir(source_path):

'''判断src是目录'''

if check_remote_path(destination_path) == 'file':

output.write('%s----%s is file\n' % (' ' * 8, destination_path), color=31)

output.print_lock()

exit(10)

source_path, destination_path = process_arg_dir(source_path), process_arg_dir(destination_path)

for root, dirs, files in walk(source_path):

'''通过 os.walk()函数取得目录下的所有文件,此函数默认包含 . ..的文件/目录,需要去掉'''

for file_name in files:

s_file = path.join(root, file_name)  # 逐级取得每个sftp client端文件的全路径

if not search('.*/\..*', s_file):

'''过滤掉路径中包含以.开头的目录或文件'''

d_file = s_file.replace(source_path, destination_path, 1)  # 由local_file取得每个远程文件的全路径

d_path = path.dirname(d_file)

if check_remote_path(d_path) == 'directory':

sftp_put(s_file, d_file, 12)

else:

create_dir(d_path, 'remote', 8)

sftp_put(s_file, d_file, 12)

sftp.utime(d_file, file_time(s_file, 'local'))

else:

output.write('%s%s is not exist\n' % (' ' * 8, source_path), color=31)

output.print_lock()

exit(10)

# -----下载逻辑-----

elif method == 'get':

output.write('%s----Downloading %s TO %s\n' % (' ' * 4, source_path, destination_path))

check_remote_path_result = check_remote_path(source_path)

if check_remote_path_result == 'file':

'''判断source_path是文件'''

if path.isfile(destination_path):  # destination_path为文件

pass

elif path.isdir(destination_path):  # destination_path为目录

destination_path = process_arg_dir(destination_path) + path.basename(source_path)

else:

if not path.isdir(path.dirname(destination_path)):

create_dir(path.dirname(destination_path), 'local', 8)

if destination_path.endswith('/') or destination_path.endswith('\\'):

destination_path = destination_path + path.basename(source_path)

sftp_get(source_path, destination_path, 12)

utime(destination_path, file_time(source_path, 'remote'))

elif check_remote_path_result == 'directory':

'''判断source_path是目录'''

if path.isfile(destination_path):

output.write('%s----%s is file\n' % (' ' * 8, destination_path), color=31)

output.print_lock()

exit(10)

source_path, destination_path = process_arg_dir(source_path), process_arg_dir(destination_path)

def process_sftp_dir(path_name):

"""

此函数递归处理sftp server端的目录和文件,并在client端创建所有不存在的目录,然后针对每个文件在两端的全路径执行get操作.

path_name第一次的引用值应该是source_path的值

"""

d_path = path_name.replace(source_path, destination_path, 1)

if not path.exists(d_path):  # 若目标目录不存在则创建

create_dir(d_path, 'local', 8)

for name in (i for i in sftp.listdir(path=path_name) if not i.startswith('.')):

'''去掉以.开头的文件或目录'''

s_file = path.join(path_name, name)  # 源文件全路径

d_file = s_file.replace(source_path, destination_path, 1)  # 目标端全路径

chk_r_path_result = check_remote_path(s_file)

if chk_r_path_result == 'file':  # 文件

sftp_get(s_file, d_file, 12)

utime(d_file, file_time(s_file, 'remote'))

elif chk_r_path_result == 'directory':  # 目录

process_sftp_dir(s_file)  # 递归调用本身

process_sftp_dir(source_path)

else:

output.write('%s%s is not exist\n' % (' ' * 8, source_path), color=31)

output.print_lock()

exit(10)

client.close()

def process_single_server(server_name, server_ip, port):

"""处理一台server的逻辑"""

local_data = threading.local()  # 可以看到多线程情况下,确实是不同的OutputText实例,说明threading.local()起到了预期作用

local_data.output = OutputText()

local_data.output.write('\n--------{}\n'.format(server_name))  # 这行写入的数据可以在多线程环境下正常打出

client = create_sshclient(server_ip, port, local_data.output)

if client == 'error':

if not arguments['--skip-err']:

exit(10)

else:

return

# 区别处理 cmd put get参数

if arguments['cmd']:

run_command(client, local_data.output)

elif arguments['put']:

sftp_transfer(arguments[''], arguments[''], 'put', client, local_data.output)

elif arguments['get']:

sftp_transfer(arguments[''], arguments[''], 'get', client, local_data.output)

# 前面的逻辑可以并行,打印必须要加锁实现串行

local_data.output.print_lock()

if __name__ == "__main__":

global global_lock

global_lock = threading.Lock()

arguments = docopt(__doc__)

try:

if not arguments['--parallel']:

for server_name, server_ip, port in get_ip_port(arguments['--server']):

'''循环处理每个主机'''

process_single_server(server_name, server_ip, port)

else:

for server_name, server_ip, port in get_ip_port(arguments['--server']):

# executor.submit(process_single_server, server_name, server_ip, port)

t = threading.Thread(target=process_single_server, args=(server_name, server_ip, port))

t.start()

# t.join()  # 谁对t线程发起join,谁就阻塞直到t线程执行完

except KeyboardInterrupt:

print_color('\n-----bye-----')

另外脚本里包含了两个有用的函数(类):print_color()函数方便的在Linux下实现打印不同颜色的字体;OutputText类在多线程任务需要在中终端打印结果时会非常有用

其实之所以想造这么一个轮子,一方面能锻炼python coding,另一方面当时确实有这么一个需求。而且用自己的工具完成工作也是小有成就的(请勿拍砖~)。

另外,在开发过程中对于一些概念性的东西也都有了更深入的了解:例如在使用paramiko模块的过程中,又促使我深入的了解了一些ssh登陆的详细过程。又如用到了线程模型,更深入的了解了线程进程相关的概念。

所以作为一枚运维老司机,越来越深刻的理解到“运维”和“开发”这俩概念之间的相互促进。希望大家共勉。


http://chatgpt.dhexx.cn/article/sGQ95SCq.shtml

相关文章

输入密码错误次数超过5次,请在1小时后再登录的解决方法

输入密码错误次数超过5次,请在1小时后再登录的解决方法 这个教程是用于微擎登录解除限制的 解决方法: 在数据库中找到ims_users_failed_login表把count中的5改成1,然后就可以登录了 如图 最后就可以登录了,小伙伴们如遇到这种…

在尝试使用预登录握手确认时超过了此超时时间。这可能是因为预登录握手失败或服务器未能及时响应。

.net的bs系统,sqlserver数据库 服务器断电和,系统无法访问 报sa登录名或密码错误 sqlserver也登陆不上(确定密码没错) 只好重置密码服务器部署环境(8)sqlserver修改sa密码 用sa账号可以正常登陆数据库 但系统还是打不开 System.Data.SqlClient.SqlE…

模拟用户登录只能登陆三次(只允许输入三次)密码正确登陆成功,三次都错误则退出程序。

设置密码为123456 注意&#xff1a;判断跳出循环条件 #include<stdio.h> #include<stdlib.h> #include<string.h> int main() { char password[]“123456”; int i0; for(;i<3;i1) { printf(“请输入密码:”); char input[100]{0}; scanf("%s"…

由于失败的登录次数过多或重复关机,此登录选项已被禁用。请使用其他登录选项,或者保持设备开机至少2小时,然后重试。...

参考资料&#xff1a; https://docs.microsoft.com/en-us/windows/security/threat-protection/security-policy-settings/account-lockout-threshold 当你找到这个博客的时候&#xff0c;说明你遇到了和我一样的尴尬境地。 你的电脑上会显示如下字样(英文版)&#xff1a; 你搜…

使用secureCRT连接超时(最详细最有效的解决,就这一篇就够了)

从昨天下午到现在&#xff0c;可谓是一波三折&#xff0c;在网上查阅的文章不下100篇&#xff0c;结果很多都是没用的千篇一律&#xff0c;即使一些浏览器破千的文章&#xff0c;发现都是无头无尾&#xff0c;整个逻辑都很烂&#xff0c;最终通过一次次的失败到最后的成功使我不…

解决go-cqhttp登录失败:密码错误或账号被冻结

目录 前言解决方法一&#xff1a;下载最新go-cqhttp使用方法 解决方法二&#xff1a;总结 &#x1f525;推荐阅读&#xff1a;[http://t.csdn.cn/nQfIY]&#x1f525; 前言 解决go-cqhttp登录失败&#xff1a;密码错误或账号被冻结 解决方法一&#xff1a; 下载最新go-cqht…

MySQL数据库限制多次登录失败重试时间

一、需求&#xff1a;如果连续5次输入密码错误&#xff0c;限制登录数据库30分钟 二、解决方法&#xff08;通过MySQL插件控制&#xff09; 1、登录数据库&#xff0c;安装插件&#xff08;CONNECTION_CONTROL和CONNECTION_CONTROL_FAILED_LOGIN_ATTEMPTS&#xff09; mysql …

element表格tooltip内容换行展示(本人第一次写帖子效果图在最后如果是各位想要的效果请点个赞,写的不好的地方也可以指导一下万分感谢)

前言 在使用element的table中咱们有可能会遇到后端返回的单个字段有多个内容这个时候想一个单元格展示换行其实很简单直接就是template加个块标签v-for就可以了如果是很多的话这样表格就不美观如下图&#xff0c;这个时候大家会想到是show-overflow-tooltip&#xff0c;但是如…

解决Go-CQhttp无法登录(服务器如何登录)的问题

既然你能看到这篇帖子&#xff0c;说明你一定对这个东西不陌生了 这是某讯的登录检查机制.. 解决方法&#xff0c;也很简单&#xff0c;保证手机与电脑处于同一wifi以内 那这时候有人叫要问了 “可是我明明开了wifi&#xff0c;为什么还是登陆不了呢” “麻烦你不要一边开wifi一…

Twitter限制12个小时,只要我登陆账号过12个小时就能恢复正常,但是我根本登陆进去账号,一直提示技术问题请重试,有哪位大哥知道怎么弄吗?

1我的推特账号前段时间被限制了&#xff0c;让我验证邮箱&#xff0c;过12个小时就能解封我所有的功能。 2问题是我的账号根本就等不进去。 3输入邮箱>收到验证码>输入验证码>确认和之后一直出现下面的提示 > 由于技术困难&#xff0c;我们无法完成您的请求。请…

登陆后会经常提示登陆超时,重新登陆

问题&#xff1a;项目在部署到服务器后&#xff0c;一登录&#xff0c;就会跳出系统&#xff0c;提示登录超时。 1.用户未登录 2.用户登录在线超时 3.session中记录的用户id和动作传递的用户id不同(非本人操作) 解决&#xff1a;创建sessionListener&#xff0c;通过监听来确…

AI人工智能之科研论文搜索集锦

AI人工智能之科研论文搜索集锦 前言2023.06.19 补充了在Arxiv下载论文的Latex文件的方法&#xff0c;见第3节的Example 2&#xff01;&#xff01;&#xff01; 1. Google学术搜索2. Google搜索3. Arxiv#Example 1&#xff1a;#Example 2&#xff1a; 4. Github#Example&#x…

中科院学术专用版GPT Academic项目实现

【写在最前】要完成GPT 学术优化 (GPT Academic)这个项目需要一些值得注意的地方&#xff1a; chatGPT账户有余额且未过期&#xff01;&#xff01;&#xff01;有代理工具&#xff08;类似Clash&#xff09; 1、代码克隆 https://github.com/binary-husky/gpt_academic 根据…

【3】SCI易中期刊推荐——人工智能领域(中科院1区)

💖💖>>>加勒比海带,QQ2479200884<<<💖💖 🍀🍀>>>【YOLO魔法搭配&论文投稿咨询】<<<🍀🍀 ✨✨>>>学习交流 | 温澜潮生 | 合作共赢 | 共同进步<<<✨✨ 📚📚>>>人工智能 | 计算机视觉…

【22】核心易中期刊推荐——人工智能与识别图像处理与应用

🚀🚀🚀NEW!!!核心易中期刊推荐栏目来啦 ~ 📚🍀 核心期刊在国内的应用范围非常广,核心期刊发表论文是国内很多作者晋升的硬性要求,并且在国内属于顶尖论文发表,具有很高的学术价值。在中文核心目录体系中,权威代表有CSSCI、CSCD和北大核心。其中,中文期刊的数…

2021年最新中科院人工智能领域顶级期刊及顶级会议

以上是人工智能 计算机 科学 类 顶级期刊。 《 如果我的分享对您有用&#xff0c;欢迎点赞和收藏》。谢谢各位客官 下面是 国际顶级会议 A类 CVPR: Computer Vision and Pattern Recognition (240) NIPS&#xff1a;Advances in Neural Information Processing (169) ICML&…

一、尚医通上传医院接口

文章目录 一、上传医院接口1、集成mongodb1.1添加依赖1.2添加配置 2、添加医院基础类2.1 添加model2.2 添加Repository2.3 添加service接口及实现类2.4 添加controller 3、上传医院3.1 接口数据分析3.2 添加service接口3.3 添加repository接口3.4 添加controller接口3.5 添加帮…

安科瑞AWT100无线数据采集通信终端

安科瑞AWT100无线数据采集通信终端 安科瑞 崔丽洁

佳信客服全渠道接入手册

包括网页、微信、app、微博、邮箱、字节小程序等几种常见渠道接入配置&#xff0c;今天手把手教你如何配置。 网页渠道插入配置和使用 企业可以通过在web网站或微官网植入网页插件代码&#xff0c;让您的客户可以通过web网站和微官网的“联系客服”按钮&#xff0c;与企业客服…

NC与单一窗口数据对接丨外贸软件

在国际贸易通关过程中&#xff0c;所涉及相关部门的信息管理&#xff0c;主要是以数字化流程系统为主&#xff0c;让每个部门业务的申请、办理、回复采用电子化和互联网化。由于每个环节部分的数据壁垒未打通&#xff0c;数据无法协同共享&#xff0c;导致在口岸通关的过程中&a…