海运的博客

php ssh/expect登录服务器执行命令

发布时间:April 21, 2018 // 分类:PHP // No Comments

<?php
$conn = ssh2_connect('1.1.1.1', 22);
if (!$conn) {
  die("conn fail\n");
}
if (ssh2_auth_password($conn, 'root', 'password')) {
  echo "auth sus\n";
} else {
  die("auth fail\n");
}
$stream = ssh2_exec($conn, "df  --output=avail /|tail -n 1");  
stream_set_blocking($stream, true);  
$res = trim(stream_get_contents($stream));
var_dump($res);

php使用ssh交互式执行命令:

<?php
$host = '192.168.1.1';
$port = 2222;
$pass = 'xxxx';
if (!($conn = ssh2_connect($host, $port, array('hostkey'=>'ssh-rsa')))) {
  die("conn fail\n");
}
//注意路径不要使用~/.ssh/id_rsa.pub,会遇到段错误和其它莫名其妙的问题
if (ssh2_auth_pubkey_file($conn, 'root', '/root/.ssh/id_rsa.pub', '/root/.ssh/id_rsa')) {
  echo "auth sus\n";
} else {
  die("auth fail\n");
}
function expect($stream, $match) {
  $time = time();
  $res = '';
  while(!feof($stream)){
    //if (($buffer = fgets($stream, 4096)) !== false) {
    if (($buffer = fread($stream, 4096)) !== false) {
      $res .= $buffer;
    }
    if (stristr($res, $match)) {
      return 'sus';
    }
    $now = time();
    if (($now - $time) >= 10) {
      return 'timeout';
    }
    usleep(100);
  }
  return 'disconnect';
}

$shell=ssh2_shell($conn, 'xterm');
fwrite($shell, "/usr/bin/cryptroot-unlock\n");
$res = expect($shell, 'Please unlock disk');
if ($res == 'sus') {
  fwrite($shell, "{$pass}\n");
  $res = expect($shell, 'set up successfully');
  if ($res == 'sus') {
  }
  var_dump($res);
}

php也可安装expect扩展调用ssh命令交互式执行命令:

apt install php-dev tcl-dev tcl-expect-dev
wget https://pecl.php.net/get/expect-0.4.0.tgz
tar zxvf expect-0.4.0.tgz 
cd expect-0.4.0/
 phpize
./configure
make && make install
echo 'extension=expect.so' > /etc/php/7.4/cli/conf.d/20-expect.ini
php -m|grep expect

make时如果出现错误php_expect.h:34:10: fatal error: expect_tcl.h: 没有那个文件或目录:

sed -i 's/^INCLUDES =/INCLUDES = -I\/usr\/include\/tcl8.6/' Makefile

php使用expect连接ssh执行命令:

<?php
ini_set("expect.timeout", 2);
ini_set("expect.loguser", "off");

$stream = expect_popen("ssh -o StrictHostKeyChecking=no -p 22 root@www.haiyun.me");
$cases = array(
  array("password:", "password"),
  array("Last login", "shell"),
  array("yes/no)?",  "yes/no")
);

while (true) {
  switch (expect_expectl($stream, $cases)) {
  case "password":
    fwrite($stream, "password\n");
    break;
  case "yes/no":
    fwrite($stream, "yes\n");
    break;
  case "shell":
    fwrite($stream, "uptime\n");
    break;
  case EXP_TIMEOUT:
  case EXP_EOF:
    break 2; 
  default:
    die("Error has occurred!");
  }
}
fclose ($stream);

golang通过smartctl检测硬盘健康状态

发布时间:April 20, 2018 // 分类: // No Comments

先安装smartmontools,以管理员运行,不然不能正常开启smart,可使用smtp发送邮件

package main

import (
        "fmt"
        "io/ioutil"
        "os"
        "os/exec"
        "strings"
        "time"
)

func gethd() []string {
        cmd := exec.Command("smartctl", "--scan")
        //out, err := cmd.CombinedOutput()
        out, err := cmd.Output()
        //fmt.Println(string(out))
        if err != nil {
                fmt.Println("exec error", err)
        }
        stringSlice := strings.Split(string(out), "\n")
        devices := []string{}
        for _, v := range stringSlice {
                if v != "" {
                        s := strings.Fields(v)
                        devices = append(devices, s[0])
                }
        }
        return devices
}

func enable_smart(id string) bool {
        fmt.Println(id, "enable smart")
        cmd := exec.Command("smartctl", "-s", "on", id)
        _, err := cmd.Output()
        //fmt.Println(string(out))
        if err != nil {
                fmt.Println("exec smartctl -s on "+id, err)
                return false
        }
        return true
}

func check_smart(id string) bool {
        fmt.Println(id, "check smart")
        cmd := exec.Command("smartctl", "-i", id)
        out, err := cmd.Output()
        if err != nil {
                fmt.Println("exec smartctl -i "+id, err)
        }
        if strings.Contains(string(out), "SMART support is: Available") {
                fmt.Println(id, "SMART support is: Available")
                if strings.Contains(string(out), "SMART support is: Disabled") {
                        fmt.Println(id, "SMART support is: Disabled")
                        if !enable_smart(id) {
                                return false
                        }
                }
                return true
        } else {
                fmt.Println(id, "SMART support is: Unavailable")
        }
        return false
}
func main() {
        err := ioutil.WriteFile("C:/Windows/check_smart.txt", []byte("TESTING!"), 0644)
        if err != nil {
                fmt.Println("请以管理员身份运行")
                time.Sleep(time.Second * 3)
                os.Exit(1)
        }

        devices := gethd()
        //fmt.Println(devices)
        for _, v := range devices {
                if check_smart(v) {
                        fmt.Println(v, "check health")
                        cmd := exec.Command("smartctl", "-H", v)
                        out, err := cmd.Output()
                        //fmt.Println(string(out))
                        if err != nil {
                                fmt.Println("exec smartctl -H "+v, err)
                        }
                        if strings.Contains(string(out), "test result: PASSED") {
                                fmt.Println(v, "test result: PASSED")
                        } else if strings.Contains(string(out), "SMART Disabled") {
                                fmt.Println(v, "SMART Disabled")
                        } else {
                                fmt.Println(v, "test result: FAILED!")
                        }
                }
                fmt.Println("********************************************")
        }
}

golang通过qq mail smtp ssl发送邮件

发布时间:April 15, 2018 // 分类: // No Comments

转自:https://www.oschina.net/code/snippet_166520_34694

package main
 
import (
    "crypto/tls"
    "fmt"
    "log"
    "net"
    "net/smtp"
)
 
func main() {
    host := "smtp.qq.com"
    port := 465
    email := "xxx@qq.com"
    password := "xxx"
    toEmail := "xxx@qq.com"
 
    header := make(map[string]string)
    header["From"] = "test" + "<" + email + ">"
    header["To"] = toEmail
    header["Subject"] = "邮件标题"
    header["Content-Type"] = "text/html; charset=UTF-8"
 
    body := "我是一封电子邮件!golang发出."
 
    message := ""
    for k, v := range header {
        message += fmt.Sprintf("%s: %s\r\n", k, v)
    }
    message += "\r\n" + body
 
    auth := smtp.PlainAuth(
        "",
        email,
        password,
        host,
    )
 
    err := SendMailUsingTLS(
        fmt.Sprintf("%s:%d", host, port),
        auth,
        email,
        []string{toEmail},
        []byte(message),
    )
 
    if err != nil {
        panic(err)
    }
}
 
//return a smtp client
func Dial(addr string) (*smtp.Client, error) {
    conn, err := tls.Dial("tcp", addr, nil)
    if err != nil {
        log.Println("Dialing Error:", err)
        return nil, err
    }
    //分解主机端口字符串
    host, _, _ := net.SplitHostPort(addr)
    return smtp.NewClient(conn, host)
}
 
//参考net/smtp的func SendMail()
//使用net.Dial连接tls(ssl)端口时,smtp.NewClient()会卡住且不提示err
//len(to)>1时,to[1]开始提示是密送
func SendMailUsingTLS(addr string, auth smtp.Auth, from string,
    to []string, msg []byte) (err error) {
 
    //create smtp client
    c, err := Dial(addr)
    if err != nil {
        log.Println("Create smpt client error:", err)
        return err
    }
    defer c.Close()
 
    if auth != nil {
        if ok, _ := c.Extension("AUTH"); ok {
            if err = c.Auth(auth); err != nil {
                log.Println("Error during AUTH", err)
                return err
            }
        }
    }
 
    if err = c.Mail(from); err != nil {
        return err
    }
 
    for _, addr := range to {
        if err = c.Rcpt(addr); err != nil {
            return err
        }
    }
 
    w, err := c.Data()
    if err != nil {
        return err
    }
 
    _, err = w.Write(msg)
    if err != nil {
        return err
    }
 
    err = w.Close()
    if err != nil {
        return err
    }
 
    return c.Quit()
}

windows获取硬盘健康状态

发布时间:April 15, 2018 // 分类: // No Comments

wmic diskdrive get status,deviceid,model

也可使用smartctl windows版查看:
列出硬盘列表:

smartctl --scan
/dev/sda -d ata # /dev/sda, ATA device
/dev/sdb -d ata # /dev/sdb, ATA device
/dev/sdc -d ata # /dev/sdc, ATA device
/dev/sdd -d ata # /dev/sdd, ATA device
/dev/sde -d ata # /dev/sde, ATA device

查看是否开启smart:

smartctl -i /dev/sda
smartctl 6.6 2017-11-05 r4594 [x86_64-w64-mingw32-w10-1709] (sf-6.6-1)
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Model Family:     Marvell based SanDisk SSDs
Device Model:     SanDisk SDSSDHII240G
Firmware Version: X31200RL
User Capacity:    240,057,409,536 bytes [240 GB]
Sector Size:      512 bytes logical/physical
Rotation Rate:    Solid State Device
Form Factor:      2.5 inches
Device is:        In smartctl database [for details use: -P show]
ATA Version is:   ACS-2 T13/2015-D revision 3
SATA Version is:  SATA 3.2, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is:    Fri Apr 20 14:49:55 2018
SMART support is: Available - device has SMART capability.  //此硬盘支持smart
SMART support is: Enabled //smart已开启,关闭为Disabled

开启/关闭smart:

smartctl -s on/dev/sda
smartctl -s off /dev/sda

查看硬盘健康状态:

smartctl -H /dev/sda
smartctl 6.6 2017-11-05 r4594 [x86_64-w64-mingw32-w10-1709] (sf-6.6-1)
Copyright (C) 2002-17, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF READ SMART DATA SECTION ===
SMART overall-health self-assessment test result: PASSED //正常,错误为FAILED!

php使用rpc xml管理rtorrent

发布时间:April 3, 2018 // 分类:PT // No Comments

rtorrent开启rpc:

scgi_port = 127.0.0.1:5000

通过nginx中转rpc请求:

server {
    listen 8000;
    server_name localhost;
    location ^~ /RPC2 {
        include scgi_params;
        scgi_pass   127.0.0.1:5000;
    }
}

php需安装xmlrpc扩展:

<?php
class XMLRPCClient
{
  public function __construct($uri)
  {
    $this->uri = $uri;
    $this->ch = null;
  }

  public function __destruct()
  {
    $this->close();
  }

  public function close()
  {
    if ($this->ch !== null)
    {
      curl_close($this->ch);
    }
    $this->ch = null;
  }

  public function get($method, $params = array())
  {
    $xml = xmlrpc_encode_request($method,$params);
    if ($this->ch === null)
    {
      $this->ch = curl_init();
      curl_setopt($this->ch, CURLOPT_URL, $this->uri);
      curl_setopt($this->ch, CURLOPT_HEADER, 0); 
      curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, true);
      curl_setopt($this->ch, CURLOPT_POST, true);
    }
    curl_setopt($this->ch, CURLOPT_POSTFIELDS, $xml);
    $response = curl_exec($this->ch);
    $response = str_replace('i8>', 'string>', $response);
    $result = xmlrpc_decode_request($response, $method);
    return $result;
  }
}

$client = new XMLRPCClient("http://127.0.0.1:8000/RPC2");
//查看rpc命令列表
var_dump($client->get("system.listMethods"));
//查看任务列表
$list = $client->get("download_list", array("","started"));
//文件路径
$filepath = $client->get("d.get_base_path", $list[0]);
//上传速度
$up_rate = $client->get("d.get_up_rate", $list[0]);
$down_rate = $client->get("d.get_down_rate", $list[0]);
echo $up_rate.'/'.$down_rate.PHP_EOL;
//删除下载
//$client->get("d.erase", $list[0]);
//删除文件
//unlink($filepath);

rpc命令列表:https://github.com/rakshasa/rtorrent/wiki/rTorrent-0.9-Comprehensive-Command-list-(WIP)

分类
最新文章
最近回复
  • liyk: 这个方法获取的IPv6大概20分钟之后就会失效,默认路由先消失,然后Global IPV6再消失
  • 海运: 不好意思,没有。
  • zongboa: 您好,請問一下有immortalwrt設定guest Wi-Fi的GUI教學嗎?感謝您。
  • 海运: 恩山有很多。
  • swsend: 大佬可以分享一下固件吗,谢谢。
  • Jimmy: 方法一 nghtp3步骤需要改成如下才能编译成功: git clone https://git...
  • 海运: 地址格式和udpxy一样,udpxy和msd_lite能用这个就能用。
  • 1: 怎么用 编译后的程序在家里路由器内任意一台设备上运行就可以吗?比如笔记本电脑 m参数是笔记本的...
  • 孤狼: ups_status_set: seems that UPS [BK650M2-CH] is ...
  • 孤狼: 擦。。。。apcupsd会失联 nut在冲到到100的时候会ONBATT进入关机状态,我想想办...