第二个Linux命令autoreply

在Linux安装Cache的时候,有很多选择项需要用户输入。比如安装目录、用户密码、使用使用Unicode、所属用户、CSP密码等等。不利于实现一键部署检验web和数据库计划。之前的一键部署在安装Cache软件时候没有达到自动化。为此开发自动回复命令,通过他调用Cache安装命令,按指定文件一行行回复安装需要的选项。原理认为安装程序输入10秒没变化就认为他在等待输入,就回复一个信息给他的标准输入里。

C#代码

using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Collections.Generic;
using System.Threading;

namespace autoreply
{
    /// <summary>
    /// [功能描述: 自动按步骤回复内容工具]<para/>
    /// [创建者:   zlz]<para/>
    /// [创建时间: 20210801]<para/>
    /// <说明>
    ///    自动安装软件时候用
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///        
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    class Program
    {
        /// <summary>
        /// 最后读取传
        /// </summary>
        private static string lastStr = "";

        /// <summary>
        /// 前一个传
        /// </summary>
        private static string preStr = "";

        /// <summary>
        /// 串相同判断次数
        /// </summary>
        private static int sameNum = 0;

        /// <summary>
        /// 进程
        /// </summary>
        private static Process proc = null;

        /// <summary>
        /// 回复队列
        /// </summary>
        private static Queue<string> replyQueue = new Queue<string>();

        /// <summary>
        /// 没变化秒数
        /// </summary>
        private static int second = 10;

        /// <summary>
        /// main
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            //没参数提示
            if (args == null || args.Length == 0)
            {
                Console.WriteLine("没有传入参数,尝试 autoreply --help");
                return;
            }
            //第一个参数为要执行的命令
            string cmd = "";
            cmd = args[0];
            if (cmd == "")
            {
                Console.WriteLine("没有传入调用命令!");
                return;
            }
            else
            {
                Console.WriteLine("传入调用命令:"+ cmd);
            }
            //命令帮助
            if (cmd == "--help")
            {
                string helpPath = AppContext.BaseDirectory + "help.txt";
                if (File.Exists(helpPath))
                {
                    Console.WriteLine(TxtUtil.ReadTxt(helpPath));
                }
                else
                {
                    Console.WriteLine("autoreply /zlz/cache-2016.2.3.907.11.20446-lnxrhx64/cinstall /zlz/net5.0/cache.reply");
                }
                return;
            }
            //命令版本
            else if (cmd == "--vertion")
            {
                Console.WriteLine("autoreply 0.0.1 20210801 zlz");
                return;
            }
            //参数不足
            if (args.Length < 2)
            {
                Console.WriteLine("没有传入回复文件路径!");
                return;
            }
            //传入了秒数
            if (args.Length>=3)
            {
                second = Convert.ToInt32(args[2]);
            }
            //自动按步骤回复的文件,第二个参数会按步骤回复文件
            string replyFile = args[1];
            
            //读取配置到队列
            if (File.Exists(replyFile))
            {
                Console.WriteLine("读取" + replyFile + "回复信息,将依次回复以下信息(10秒内回复):");
                StreamReader sr = new StreamReader(replyFile, Encoding.UTF8);
                string line;
                while ((line = sr.ReadLine()) != null)
                {
                    replyQueue.Enqueue(line);
                    Console.WriteLine(line);
                }
                sr.Close();
                sr.Dispose();
            }
            else
            {
                Console.WriteLine(replyFile + " 不存在!");
                return;
            }
            //启动定时器
            Timer myTimer = new Timer(Reply, "执行定时事件", 0, 1000);
            //创建一个ProcessStartInfo对象 使用系统shell指定命令和参数 设置标准输出
            string para = "";
            string [] paraArr = cmd.Split(' ');
            //提取命令和参数
            if(paraArr.Length>1)
            {
                for(int i=1;i<paraArr.Length;i++)
                {
                    if(para!="")
                    {
                        para += " " + paraArr[i];
                    }
                    else
                    {
                        para = paraArr[i];
                    }
                }
            }
            cmd = cmd.Split(' ')[0];
            var psi = new ProcessStartInfo(cmd, para)
            {
                RedirectStandardOutput = true,
                RedirectStandardInput = true
            };
            Console.WriteLine("执行:"+cmd+"命令");
            if(para!="")
            {
                Console.WriteLine("参数:" + para);
            }
            //启动进程
            proc = Process.Start(psi);
            if (proc == null)
            {
                Console.WriteLine("不能执行命令!");
                return;
            }
            else
            {
                //开始读取
                using (var sr = proc.StandardOutput)
                {
                    while (!sr.EndOfStream)
                    {
                        string oneStr = sr.ReadLine();
                        //累积输出到读取的信息串
                        if (oneStr != "")
                        {
                            lastStr += oneStr;
                        }
                        Console.WriteLine(oneStr);
                    }
                    if (!proc.HasExited)
                    {
                        proc.Kill();
                    }
                }
                Console.WriteLine("执行结束");
            }


            /// <summary>
            /// 监控回复信息
            /// </summary>
            static void Reply(object state)
            {
                //回复队列空了就不回复了
                if (replyQueue.Count == 0)
                {
                    return;
                }
                //输出串没变化就记录没输出监听次数
                if (lastStr == preStr)
                {
                    sameNum++;
                }
                else
                {
                    sameNum = 0;
                }
                //检测秒数次没变化就认为在等待输入
                if (sameNum > second)
                {
                    sameNum = 0;
                    string oneReply = replyQueue.Dequeue();
                    Console.WriteLine(oneReply);
                    proc.StandardInput.WriteLine(oneReply);
                }
                preStr = lastStr;
            }
        }
    }
}

文本工具

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace autoreply
{
    ///<summary  NoteObject="Class">
    /// [功能描述: Txt操作工具]<br></br>
    /// [创建者:   zlz]<br></br>
    /// [创建时间: 20210711]<br></br>
    /// <说明>
    ///    
    /// </说明>
    /// <修改记录>
    ///     <修改时间></修改时间>
    ///     <修改内容>
    ///            
    ///     </修改内容>
    /// </修改记录>
    /// </summary>
    public static class TxtUtil
    {
        /// <summary>
        /// 读取文件数据
        /// </summary>
        /// <param name="path">文件全路径</param>
        /// <returns></returns>
        public static string ReadTxt(string path)
        {
            //文件流
            FileStream fs = null;
            StreamReader sr = null;
            try
            {
                //创建文件流
                fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                //创建字符串读取器
                sr = new StreamReader(fs);
                //读到尾
                string str = sr.ReadToEnd();
                return str;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
                if (sr != null)
                {
                    sr.Close();
                }
            }
        }

        /// <summary>
        /// 写入数据到指定文件
        /// </summary>
        /// <param name="path">文件全路径</param>
        /// <param name="str">数据</param>
        /// <param name="isReplace">是否提换,默认为替换,否则为添加</param>
        /// <returns></returns>
        public static bool WriteTxt(string path, string str, bool isReplace = true)
        {
            FileStream fs = null;
            StreamWriter sw1 = null;
            try
            {
                //如果是替换,先清除之前的内容
                if (isReplace)
                {
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                    }
                }
                //创建文件流
                fs = new FileStream(path, FileMode.Append,FileAccess.Write);
                //创建字符串写入器
                sw1 = new StreamWriter(fs);
                //写入字符串
                sw1.Write(str);
                return true;
            }
            finally
            {
                if (sw1 != null)
                {
                    sw1.Close();
                }
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }
    }
}

工具打包
在这里插入图片描述

工具安装命令

#!/bin/bash
#shell放在网站上供在线执行下载和初步部署数据库目录等
#20210801
#zlz
#----------------------------------------------------------
#清空老文件夹
if [ -d /usr/local/autoreply ];then 
	echo "已安装autoreply,删除/usr/local/autoreply文件夹"
    rm -rf /usr/local/autoreply
else
	echo "alias autoreply='dotnet /usr/local/autoreply/autoreply.dll'">>~/.bashrc
fi
if ! type dotnet >/dev/null 2>&1; then
	sudo yum install dotnet-runtime-5.0
fi
apppath=$(cd "$(dirname "$0")";pwd)"/autoreply"
cp -r ${apppath} /usr/local/
source ~/.bashrc
echo "安装成功"

Cache第一次安装的回复文件

1
cache
/intersystem/cache
Yes
1
2
root
SYS
SYS
SYS
SYS
root
y
n
y

调用命令

[root@localhost net5.0]# dotnet autoreply.dll /zlz/cache-2016.2.3.907.11.20446-lnxrhx64/cinstall /zlz/net5.0/cache.reply
读取回复信息,将依次回复以下信息(10秒内回复):
1
cache
/intersystem/cache
Yes
1
2
root
SYS
SYS
SYS
SYS
root
y
n
y
1

Your system type is 'Red Hat Enterprise Linux (x64)'.

Enter instance name <CACHE>: cache

Enter a destination directory for the new instance.
Directory: /intersystem/cache
Directory '/intersystem/cache' does not exist.
Do you want to create it <Yes>? Yes

Select installation type.
    1) Development - Install Cache server and all language bindings
    2) Server only - Install Cache server
    3) Custom
Setup type <1>? 1

Disk blocks required  = 3492316
Disk blocks available = 46249336

How restrictive do you want the initial Security settings to be?
"Minimal" is the least restrictive, "Locked Down" is the most secure.
    1) Minimal
    2) Normal
    3) Locked Down
Initial Security settings <1>? 2

What user should be the owner of this instance? root
A Cache account will also be created for user root.


Install will create the following Cache accounts for you: 
_SYSTEM, Admin, SuperUser, root and CSPSystem. 
Please enter the common password for _SYSTEM, Admin, SuperUser and root: stty: 标准输入: Inappropriate ioctl for device
SYS
stty: 标准输入: Inappropriate ioctl for device

Re-enter the password to confirm it: stty: 标准输入: Inappropriate ioctl for device
SYS
stty: 标准输入: Inappropriate ioctl for device



Please enter the password for CSPSystem: stty: 标准输入: Inappropriate ioctl for device
SYS
stty: 标准输入: Inappropriate ioctl for device

Re-enter the password to confirm it: stty: 标准输入: Inappropriate ioctl for device
SYS
stty: 标准输入: Inappropriate ioctl for device


What group should be allowed to start and stop
  this instance? root

Do you want to install Cache Unicode support <No>? y

Do you want to enter a license key <No>? n

Please review the installation options:
------------------------------------------------------------------
Instance name: cache
Destination directory: /intersystem/cache
Cache version to install: 2016.2.3.907.11.20446
Installation type: Development
Unicode support: Y
Initial Security settings: Normal
User who owns instance: root
Group allowed to start and stop instance: root
Effective group for Cache processes: cacheusr
Effective user for Cache SuperServer: cacheusr
SuperServer port: 1972
WebServer port: 57772
JDBC Gateway port: 62972
CSP Gateway: using built-in web server
Client components: all
------------------------------------------------------------------

Do you want to proceed with the installation <Yes>? y

Starting installation...

Starting up Cache for loading...
../bin/cinstall -s . -B -c c -C /intersystem/cache/cache.cpf*cache -W 1 -g2 
Starting Control Process
Allocated 94MB shared memory: 2MB global buffers, 35MB routine buffers
Cache startup successful.
System locale setting is 'zh_CN.UTF-8'
This copy of Cache has been licensed for use exclusively by:
License missing or unreadable.
Copyright (c) 1986-2020 by InterSystems Corporation
Any other use is a violation of your license agreement

^^/intersystem/cache/mgr/>

^^/intersystem/cache/mgr/>
Start of Cache initialization

Loading system routines


Updating Cachetemp and Cache database

Installing National Language support

Loading system classes

Updating Security database

Loading system source code


Building system indices

Updating Audit database

Updating Journal directory

Updating User database

Scheduling inventory scan

Cache initialization complete in 1 minute

See the cboot.log file for a record of the installation.

Starting up Cache...
Once this completes, users may access Cache
Starting CACHE
Using 'cache.cpf' configuration file

Starting Control Process
Automatically configuring buffers
Unable to allocate 312 MB shared memory...
Unable to allocate 285 MB shared memory...
Unable to allocate 257 MB shared memory...
Unable to allocate 230 MB shared memory...
Unable to allocate 202 MB shared memory...
Unable to allocate 175 MB shared memory...
Unable to allocate 147 MB shared memory...
Allocated 120MB shared memory: 26MB global buffers, 35MB routine buffers
This copy of Cache has been licensed for use exclusively by:
License missing or unreadable.
Copyright (c) 1986-2020 by InterSystems Corporation
Any other use is a violation of your license agreement

2 alert(s) during startup. See cconsole.log for details.


You can point your browser to http://localhost.localdomain:57772/csp/sys/UtilHome.csp
to access the management portal.

stty: 标准输入: Inappropriate ioctl for device
执行结束
[root@localhost net5.0]# 
[root@localhost net5.0]# 
[root@localhost net5.0]# 
[root@localhost net5.0]# 
[root@localhost net5.0]# 
[root@localhost net5.0]# cache

Node: localhost.localdomain, Instance: CACHE

Username: _system
Password: ***
USER>h

测试bc命令回复

[root@localhost zlz]# autoreply --help
作为用dotnet对shell的补充工具,实现自动安装软件回复
#查看帮助
autoreply --help
#查看版本
autoreply --vertion
#执行指定命令,用指定文件路径的信息一行行回复
autoreply /zlz/cache-2016.2.3.907.11.20446-lnxrhx64/cinstall /zlz/net5.0/cache.reply

由zlz提供,后期陆续加入shell实现麻烦的功能进来
[root@localhost zlz]# echo "2*3" >> bc.rep
[root@localhost zlz]# echo "2*32" >> bc.rep
[root@localhost zlz]# echo "1024.4" >> bc.rep
[root@localhost zlz]# autoreply bc /zlz/bc.rep
读取/zlz/bc.rep回复信息,将依次回复以下信息(10秒内回复):
2*3
2*32
1024.4
执行:bc命令
2*3
6
2*32
64
1024.4
1024.4
^C执行结束

[root@localhost zlz]# autoreply bc /zlz/bc.rep 2
读取/zlz/bc.rep回复信息,将依次回复以下信息(10秒内回复):
2*3
2*32
1024.4
执行:bc命令
2*3
6
2*32
64
1024.4
1024.4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小乌鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值