镜像标签检索小工具

#!/bin/sh
#
# Simple script that will display docker repository tags.
#
# Usage:
#   $ docker-tags-search.sh centos gitea/gitea

function showUsage() {
  echo "Usage:"
  echo "`basename $0 .sh` centos gitea/gitea"
}

function search() {
  for str in $* ; do
    if [[ $str == *"/"* ]]; then
      project=`echo $str|awk -F '/' '{print $1}'`
      repo=`echo $str|awk -F '/' '{print $2}'`
    else
      project="library"
      repo=$str
    fi
    echo "$project/$repo tags:"
    curl -s -S "https://registry.hub.docker.com/v2/repositories/$project/$repo/tags/" | \
      sed -e 's/,/,\n/g' -e 's/\[/\[\n/g' | \
      grep '"name"' | \
      awk -F\" '{print $4;}' | \
      sort -fu | \
      sed -e "s/^/${Repo}:/"
  done
}

type curl >/dev/null 2>&1 || { echo >&2 "require curl but it's not installed, abort!"; exit 1; }
if [ $# -lt 1 ]; then
  showUsage
  exit 0
fi
search $*

CentOS防火墙

firewall-cmd --zone=public --add-port=80/tcp --permanent
firewall-cmd --zone=public --remove-port=80/tcp --permanent
firewall-cmd --zone=public --add-port=5000-5500/tcp --permanent
firewall-cmd --zone=public --remove-port=5000-5500/tcp --permanent
firewall-cmd --zone=public --add-service=ftp --permanent
firewall-cmd --zone=public --remove-service=ftp --permanent

firewall-cmd --reload
firewall-cmd --list-all

firewall-cmd --zone=public --add-port=7676/tcp --permanent
firewall-cmd --zone=public --add-port=17100-17200/tcp --permanent

firewall-cmd --add-rich-rule="rule family='ipv4' source address='178.128.120.175' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='185.165.190.34' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='199.195.249.201' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='198.98.57.49' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='195.144.21.56' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='45.79.116.95' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='167.248.133.44' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='162.142.125.222' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='138.255.12.128' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='178.155.186.8' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='185.165.190.34' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='54.87.86.170' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='194.87.151.116' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='34.140.248.32' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='188.166.3.224' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='46.254.19.135' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='34.66.65.152' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='185.246.220.98' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='74.82.47.4' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='103.178.229.13' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='103.173.157.248' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='44.200.122.193' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='103.180.149.22' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='109.237.98.226' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='210.74.130.162' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='111.90.150.36' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='171.22.30.125' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='85.192.62.238' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='188.166.225.200' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='164.52.36.213' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='170.64.190.132' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='47.92.209.253' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='15.206.158.169' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='165.232.90.114' reject"
firewall-cmd --add-rich-rule="rule family='ipv4' source address='109.237.97.180' reject"

C函数指针

在C语言中,函数存放在内存的代码区,跟基本的数据类型或者数组一样,也有一个内存的起始位置。函数的类型由其参数以及返回类型共同决定,跟函数名无关。

一个简单的例子

#include <stdio.h>

int add(int a, int b) {
    return a + b;
}

int main() {
    int (*pf)(int, int);
    pf = add;
    printf("   pf(1, 2) = %d\n", pf(1, 2));
    printf("(*pf)(1, 2) = %d\n", (*pf)(1, 2));
}
// 编译执行可以正常输出:
// cc demo1.c -o demo1
// demo1
//    pf(1, 2) = 3
// (*pf)(1, 2) = 3

函数指针定义

直接定义

返回数据类型 (*函数指针名称) (入参类型列表逗号分隔)

例子 int (*pf)(int, int);

使用typedef定义

typedef 返回数据类型 (*函数指针类型名称) (入参类型列表逗号分隔)

例子

type int (*PF)(int, int);
PF pf; 

此时PF是指针函数类型,不是真正的函数指针变量,需要使用该类型定义出函数指针变量使用。

函数指针的使用

作为变量

如同开头简单的例子所示,函数指针变量作为普通变量几乎没什么意义,还不如直接调用函数。放到结构体中,是不是有点像C++或者Java面向对象的味道了?

#include <stdio.h>

struct Student {
    unsigned int id;
    char *name;
    void (*print)(struct Student *stu);
};

void PrintInfo(struct Student *stu) {
    printf("%d -- %s\n", stu->id, stu->name);
}

int main() {
    struct Student stu = {1, "raveh", PrintInfo};
    stu.print(&stu);
}
// 编译执行可以正常输出:
// cc demo2.c -o demo2
// demo2
// 1 -- raveh

作为函数形参

一个例子,可以让数据给不同的函数去处理:

#include <stdio.h>
#include <stdlib.h>

int max(int a, int b) {
    return a > b ? a : b;
}

int min(int a, int b) {
    return a > b ? b : a;
}

void proc(int a, int b, int(*pf)(int, int)) {
    printf("a=%d, b=%d, pf(%d,%d)=%d\n", a, b, a, b, pf(a, b));
}

int main() {
    int a = rand(), b = rand();
    proc(a, b, max);
    proc(a, b, min);
}
// 编译执行可以正常输出:
// cc demo3.c -o demo3
// demo3
// a=1804289383, b=846930886, pf(1804289383,846930886)=1804289383
// a=1804289383, b=846930886, pf(1804289383,846930886)=846930886

这个程序可以使用typedef定义一个函数指针,使proc函数的参数列表看起来更清晰一点。

#include <stdio.h>
#include <stdlib.h>

typedef int(*PF)(int, int);

int max(int a, int b) {
    return a > b ? a : b;
}

int min(int a, int b) {
    return a > b ? b : a;
}

void proc(int a, int b, PF pf) {
    printf("a=%d, b=%d, pf(%d,%d)=%d\n", a, b, a, b, pf(a, b));
}

int main() {
    int a = rand(), b = rand();
    proc(a, b, max);
    proc(a, b, min);
}
// 编译执行可以正常输出:
// cc demo4.c -o demo4
// demo4
// a=1804289383, b=846930886, pf(1804289383,846930886)=1804289383
// a=1804289383, b=846930886, pf(1804289383,846930886)=846930886

作为函数返回值

#include <stdio.h>
#include <stdlib.h>

int max(int a, int b) {
    return a > b ? a : b;
}

int min(int a, int b) {
    return a > b ? b : a;
}

/**
 * 可以按照由内向外的顺序看这个函数的声明
 * getFun(char oper)有形参列表,则getFun是一个函数
 * getFun前面有*,所以getFun返回一个指针
 * 返回的指针本身也包含形参列表(int,int)
 * 因此返回的指针指向一个返回值为int的函数
 */
int (*getFun(char oper))(int, int) {
    switch(oper) {
        case '>':
            return max;
            break;
        case '<':
            return min;
            break;
    }
    return NULL;
}

int proc(int a, int b, char oper) {
    int(*pf)(int,int) = getFun(oper);
    if(pf) {
        return pf(a, b);
    }
    return -1;
}

int main() {
    int a = rand(), b = rand();
    printf("proc(%d, %d, %c) = %d\n", a, b, '>', proc(a, b, '>'));
    printf("proc(%d, %d, %c) = %d\n", a, b, '<', proc(a, b, '<'));
}
// 编译执行可以正常输出:
// cc demo5.c -o demo5
// demo5
// proc(1804289383, 846930886, >) = 1804289383
// proc(1804289383, 846930886, <) = 846930886

C++信号处理

信号是由操作系统传给进程的中断,会提早终止一个程序。在 LINUX 或 Windows 系统上,可以通过按 Ctrl+C 产生中断。有些信号不能被程序捕获,但是下表所列信号可以在程序中捕获,并可以基于信号采取适当的动作。这些信号是定义在 C++ 头文件 <csignal> 中。

使用 signal() 函数捕获 SIGINT 信号, 函数的定义signal(registered signal, signal handler)接收两个参数:第一个参数代表了信号的编号;第二个参数是一个指向信号处理函数的指针。不管您想在程序中捕获什么信号,您都必须使用 signal 函数来注册信号,并将其与信号处理函数关联。

使用函数 raise() 生成信号,该函数定义int raise (signal sig)带有一个整数信号编号作为参数

#include <cstdio>
#include <csignal>
#include <cstdlib>

#if defined(__linux__)
#include <unistd.h>
#elif defined(_WIN32)
#include <Windows.h>
// 可恶!VC中的Sleep函数头字母S是大写的,而且单位是毫秒
#define sleep(n) Sleep(n*1000)
#endif

void signalHandler(int sign) {
	std::printf("interrupt signal (%d) received, abort.\n", sign);
	exit(sign);
}

int main() {
	// 注册信号
	signal(SIGTERM, signalHandler);
	signal(SIGINT, signalHandler);
	// 业务循环
	while (true) {
		std::printf("Going to sleep 1 second..\n");
		sleep(1);
	}
}

可捕获的信号类型如下:

  • SIGABRT 程序的异常终止,如调用 abort。
  • SIGFPE 错误的算术运算,比如除以零或导致溢出的操作。
  • SIGILL 检测非法指令。
  • SIGINT 程序终止(interrupt)信号。普通的kill操作。
  • SIGSEGV 非法访问内存。
  • SIGTERM 发送到程序的终止请求。前台执行时Ctrl+C操作。

编译执行下试试,尝试按了Ctrl+C按键和使用kill命令,进程均正常接收到信号退出。

raveh@DESKTOP-MBGF84O:~/work/cpp$ g++ Day05.cpp
raveh@DESKTOP-MBGF84O:~/work/cpp$ ./a.out
Going to sleep 1 second..
Going to sleep 1 second..
Going to sleep 1 second..
^Cinterrupt signal (2) received, abort.
raveh@DESKTOP-MBGF84O:~/work/cpp$
raveh@DESKTOP-MBGF84O:~/work/cpp$
raveh@DESKTOP-MBGF84O:~/work/cpp$
raveh@DESKTOP-MBGF84O:~/work/cpp$ ./a.out
Going to sleep 1 second..
Going to sleep 1 second..
Going to sleep 1 second..
interrupt signal (15) received, abort.

# windows下调试
Going to sleep 1 second..
Going to sleep 1 second..
Going to sleep 1 second..
interrupt signal (2) received, abort.

D:\workspace\cpp\VSProjects\hiCPP\bin\Win32\Debug\hiCPP.exe (进程 2508)已退出,代码为 2。
按任意键关闭此窗口. . .
©raveh.net