博主日常工作中使用的shell脚本分享

d721b3797b5d562ab6e7d657dc746d94.png

前言:

今天给大家分享一篇在我工作中常用的一个shell脚本,里面有一些我们常用到的shell操作。该脚本用于本地电脑和服务器交互上,实现以下功能:

  1. 自动拉取自己个人电脑上的源码到服务器上yocto包的源码文件夹。

  2. 自动运行compile 、strip

  3. 自动把编译好的结果回传到个人电脑上。

  4. 拷贝执行文件到机器中

作者:良知犹存

转载授权以及围观:欢迎关注微信公众号:羽林君

或者添加作者个人微信:become_me


情节介绍:

在工作中,我们经常会遇到需要把修改的代码放到服务器去编译,然后把编译好的文件放到机器板卡对应的文件。这个过程如果我们使用命令的话,大概有七八条,完成操作完之后 ,大约会花费一分。虽然花费的时间不算多,但是你也会一直关注终端,然后等待输入命令,需要花费不小精力。但是我们可以写一些shell脚本来辅助我们的工作。今天就是给大家分享使用的脚本,一边分享使用过程,一边分享里面用到的shell技术点。包含,if判断、switch case条件、字符截取、远程调用脚本、两种免密登陆等。

86b111968cb822235bb70005682443e7.png

三者的使用过程为:本地通过脚本输入参数选择使用wifi分配的ip还是网线分配的ip,然后进行ip数据传参形式 远程调用预先放置好的——服务器编译脚本,服务器脚本通过传入的ip参数,免密scp拷贝本地的文件到服务器执行目录,服务器执行编译工作,然后拷贝到本地的指定目录,最后调用本地的expect免密登陆的脚本,拷贝文件到机器中。

脚本一:本地选择脚本auto_build.sh

脚本内容如下:

#/bin/bash
remote_ip=172.160.111.32
remote_hostname=lyncase $1 in1)  echo -e '\033[0;42m Ethernet dhcp \033[0m'VAR="eno1";;2)  echo -e '\033[0;46m wireless dhcp \033[0m'VAR="wlo1";;
esacHOST_IP=$(ifconfig $VAR | grep "inet" | grep -v inet6| awk '{ print $2}' | awk -F: '{print $1}')
echo "parse ip is:" $HOST_IP
if [[ ! -n "${HOST_IP}" ]] ;thenecho -e "\033[0;31m input local ip \033[0m"read local_ip
elseif [[ ! $(echo "${HOST_IP}" | awk -F. '{printf $1}') == "192"  ]] ;thenlocal_ip=$HOST_IPelseecho -e "\033[0;31m error ip \033[0m"exit 0fi
fi
#exit 0
if [[ $2 == 1 ]];thenbuild_opt="all_build"
elsebuild_opt=
fi
ssh -t ${remote_hostname}@${remote_ip} "/home/lyn/build.sh ip=${local_ip} ${build_opt}"

这个部分有几处技术使用:

switch case使用,if else、免密登陆,远程调用脚本。

首先是一个switch case

此处作用是进行ip地址的筛选,因为的在调试过程中,我的电脑有时候用网线连接,有时候会去测试房去测试,用wifi连接,这个时候会进行网络ip地址的区分,当我输入./auto_build.sh 1的时候,脚本会进行解析eno1网线分配的ip地址,当我输入./auto_build.sh 2的时候则会解析wlo1wifi分配的ip。

在里面我还用了颜色打印,进行关键词的标注,如下所示:

349bcab1741e0e02ad9f836732e58e63.png

关于颜色打印的部分这个是另一个知识,这是一个转义的实际使用过程,通过特定符号的转义识别,我们在Linux终端去显示不同颜色的打印输出,这个是我们经常使用的操作,例如log等级分级打印时候,error是红色,正常是绿色,普通是白色等。

颜色打印大致介绍如下:

转义序列以控制字符'ESC'开头。该字符的ASCII码十进制表示为27,十六进制表示为0x1B,八进制表示为033。多数转义序列超过两个字符,故通常以'ESC'和左括号'['开头。该起始序列称为控制序列引导符(CSI,Control Sequence Intro),通常由 '\033[' 或 '\e[' 代替。

通过转义序列设置终端显示属性时,可采用以下格式:

\033[ Param {;Param;...}m或\e[ Param {;Param;...}m

其中,'\033['或'\e['引导转义序列,'m'表示设置属性并结束转义序列。

因此,通过转义序列设置终端显示属性时,常见格式为:

\033[显示方式;前景色;背景色m输出字符串\033[0m或\e[显示方式;前景色;背景色m输出字符串\033[0m

其中 ,'\033[0m'用于恢复默认的终端输出属性,否则会影响后续的输出。

示例:我在此处使用 echo -e '\033[0;42m Ethernet dhcp \033[0m' 进行网线端口ip分配的打印,通过转义之后,打印颜色为带背景色的绿色显示。具体对应的颜色,大家可以看一下小麦老兄写的这篇文章 printf打印还能这么玩。

注:打印log时候记得echo 要使用 -e参数。

其次还有组合使用命令实现获取本地ip

HOST_IP=$(ifconfig $VAR | grep "inet" | grep -v inet6| awk '{ print $2}' | awk -F: '{print $1}')

我们一步步查看执行情况

第一步:ifconfig eno1

lyn@lyn:~/Documents/work-data/download_data$ ifconfig eno1 
eno1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500inet 172.16.30.147  netmask 255.255.255.0  broadcast 172.16.30.255inet6 fe80::ca7:d954:67e0:7c60  prefixlen 64  scopeid 0x20<link>ether f8:b4:6a:bd:dd:92  txqueuelen 1000  (Ethernet)RX packets 3678600  bytes 3470673356 (3.4 GB)RX errors 0  dropped 36842  overruns 0  frame 0TX packets 2229431  bytes 995696588 (995.6 MB)TX errors 0

我们经常使用ifconfig查看ip,但是使用ifconfig返回的数据过多,而我们实际使用的部分只是一部分而已。

ffbbf4552a711e02a23040da95b72d07.png

所以我们使用ifconfig指定设备查找ip,筛去无用信息。

第二步:ifconfig eno1    | grep "inet"

把第一步查询的信息通过 | 产生一个管道传递给下一个命令,用grep查找有inet字符的行数据,显示如下:

lyn@lyn:~/Documents/work-data/download_data$ ifconfig eno1  | grep "inet"inet 172.16.30.147  netmask 255.255.255.0  broadcast 172.16.30.255inet6 fe80::ca7:d954:67e0:7c60  prefixlen 64  scopeid 0x20<link>

因为我们只需要ipv4协议的ip,所以我们要去掉inet6对应的地址

第三步:ifconfig eno1  | grep "inet" | grep -v inet6

使用grep -v命令去掉 inet6 关键词的对应一行信息

lyn@lyn:~/Documents/work-data/download_data$ ifconfig eno1  | grep "inet" | grep -v inet6inet 172.16.30.147  netmask 255.255.255.0  broadcast 172.16.30.255

第四步:ifconfig eno1  | grep "inet" | grep -v inet6 | awk '{ print$2}'

使用 awk处理文本文件的语言进行处理数据,$2 表示默认以空格分割的第二组 ,-F:-F指定分隔符为 ‘ : ’

lyn@lyn:~/Documents/work-data/download_data$ ifconfig eno1  | grep "inet" | grep -v inet6| awk '{ print$2}' 
172.16.30.147

关于grep sed awk的使用大家也可以网上具体查看一下,但是我们一般使用过程中,grep 更适合单纯的查找或匹配文本, sed 更适合编辑匹配到的文本,awk 更适合格式化文本,对文本进行较复杂格式处理。

ca89f5d0eacabacc20f7b27e91279e80.png

这个时候我们从本机得到了ip地址。我们需要进行远程调用服务器脚本,并把ip以参数形式传入。

其次ssh免密登陆和ssh远程执行任务

首先第一个部分就是ssh免密登陆

本地执行ssh到服务的相关操作命令需要免密,服务器scp本地文件也要免密登陆,那么如何设置我们ssh相关命令操作,无需密码呢?

SSH分客户端openssh-client和服务器openssh-server如果你只是想登陆别的机器,只需要安装openssh-client(ubuntu有默认安装,如果没有则sudo apt-get install openssh-client),如果要使别的机器登陆本机就需要在本机安装openssh-server(sudo apt-get install openssh-server)

我们可以使用 ps -e | grep ssh  来查看对应的openssh-client和openssh-server运行情况,其中ssh是client ,sshd是server,哪个缺我们就使用apt-get install 。

0a49a335211bc84b69103d7b92085f87.png

sudo service ssh start 安装之后可以使用这个命令启动。

准备好了对应的server和client接下来,把我们生成的rsa公钥拷贝要对应要登陆的机器,即可免密登陆。

1.客户端生成公私钥

ssh-keygen 命令一路回车默认生成

这个命令会在用户目录.ssh文件夹下创建公私钥,id_rsa (私钥),id_rsa.pub (公钥)。

2.上传公钥到服务器

ssh-copy-id -i ~/.ssh/id_rsa.pub lyn@172.160.111.32

上面这条命令是写到服务器上的ssh目录下去了

vi  ~/.ssh/authorized_keys

可以看到客户端写入到服务器的 id_rsa.pub (公钥)内容。

3.测试免密登录 客户端通过ssh连接远程服务器,就可以免密登录了。

ssh lyn@172.160.111.32

第二个部分就是ssh远程执行服务器脚本

有时候我们需要远程执行一些有交互操作的命令。这个时候我们就可以使用ssh加参数进去进行远程执行。

格式如下:

远程执行一个命令

ssh lyn@172.160.111.32 "ls -l"

执行多条命令,使用分号把不同的命令隔起来

ssh lyn@172.160.111.32 "ls;cat test.txt "

远程执行本地脚本

ssh lyn@172.160.111.32 < test.sh

远程执行本地的脚本(执行带有参数的脚本),需要为 bash 指定 -s 参数:

ssh lyn@172.160.111.32 'bash -s' < test.sh helloworld

执行远程的脚本

ssh lyn@172.160.111.32 "/home/lyn/test.sh"

注,此时需要指定脚本的绝对路径!

而我们使用的为远程执行脚本,最终ssh远程执行如下:

remote_ip=172.160.111.32
remote_hostname=lyn
local_ip=172.16.30.147
build_opt=
ssh -t ${remote_hostname}@${remote_ip} "/home/lyn/build.sh ip=${local_ip} ${build_opt}"

脚本二:服务器编译脚本 build.sh

脚本内容如下:

#!/bin/bash -e
scp_dir=/media/lyn/win_data/lyn_workdata/working/robot-ctl
download_data=/home/lyn/Documents/work-data/download_databuild_dir=/home/lyn/projects/yocto/yocto-build/tmp/work/aarch64-poky-linux/robot-ctl/git-r0/git/
image_dir=/home/lyn/projects/yocto/yocto-build/tmp/work/aarch64-poky-linux/robot-ctl/git-r0/image/robot-ctl/remote_exec_file_dir=/home/lyn/Documents/work-data/download_data/scp_exec.shall_build=No
wifi_src=No
only_scp_robot=No
strip_mode=No
ip_wireless_dhcp=170.160.111.45
ip_ethernet_dhcp=170.160.111.147
local_ip=${ip_wireless_dhcp}
host_name=lyndate
echo -e "\033[0;31m Loading options.\033[0m"# Load all the options.if [ $# -eq 0 ];thenecho -e "\033[33;5m no argument \033[0m"
fi
for arg in "${@}"
doif [[ -n "${arg}" ]] && [[ "${arg}" == "wifi" ]] ; thenwifi_src="Yes"local_ip=${ip_ethernet_dhcp}echo -e "local connect robot wifi \n --${wifi_src}\n --ip:${local_ip}."fi    if [[ -n "${arg}" ]] && [[ "${arg}" == "scp" ]] ; thenonly_scp_robot="Yes"local_ip=${ip_ethernet_dhcp}echo -e "scp robot local connect robot wifi  \n --scp:${only_scp_robot} --${wifi_src}\n --ip:${local_ip}."fiif [[ -n "${arg}" ]] && [[ "${arg}" == "all_build" ]] ; thenall_build="Yes"echo -e "all bulid"fiif [[ -n "${arg}" ]] && [[ "${arg}" == "ip" ]] ; thenecho -e "\033[32m ip:=\033[0m"read ip_addrlocal_ip=${ip_addr}wifi_src="Yes"echo -e "scp robot local ip insert  \n --scp:${only_scp_robot} --${wifi_src}\n --ip:${local_ip}."fi   if [[ -n "${arg}" ]] && [[ "${arg:0:3}" == "ip=" ]] ; thenecho -e "\033[32m ip put:=\033[0m" ${arg#*=}local_ip=${arg#*=}wifi_src="Yes"echo -e "scp robot local ip insert  \n --scp:${only_scp_robot} --${wifi_src}\n --ip:${local_ip}."fiif [[ -n "${arg}" ]] && [[ "${arg}" == "debug" ]] ; thenecho -e "\033[32m need \033[0m" ${arg}strip_mode="Yes"echo -e "scp robot local ip insert  \n --scp:${only_scp_robot} --${wifi_src}\n --ip:${local_ip}."fidone
if [  "${only_scp_robot}" == "No" ];thenif [ ! "${wifi_src}" == "Yes"  ] ; thenecho -e "local don't connect robot wifi \n --${wifi_src}\n --ip:${local_ip}."fiif [ -d "${build_dir}" ]; thencd ${build_dir}scp -rp lyn@{local_ip}:${scp_dir}/src \lyn@{local_ip}:${scp_dir}/include \lyn@{local_ip}:${scp_dir}/CMakeLists.txt .//ssh ${host_name}@${local_ip} "${remote_scp_code_dir}"#git pullif [ "${all_build}" == "Yes"  ] ; then./../temp/run.do_generate_toolchain_file./../temp/run.do_configurefi./../temp/run.do_compile./../temp/run.do_install    #cd /home/lyn/ if [ "${strip_mode}" == "No"  ]; then#./strip_x1000.shcd ${image_dir}aarch64-linux-gnu-strip ppfielseecho -e "\033[0;31m dir is not exist.\033[0m"fifiscp ${image_dir}/exec ${host_name}@${local_ip}:${download_data}if [[ "${wifi_src}" == "Yes" ]] || [[ "${only_scp_robot}" ]]  ; then ssh ${host_name}@${local_ip} "${remote_exec_file_dir}"elseecho -e "no robot wifi\n"fi

服务器执行的脚本内容比较长,从执行的流程来说,在这个脚本中,大致为初始化读取脚本执行传入的参数,通过参数配置不同的变量匹配不同机器状态,紧接着,拷贝本地的文件到服务器编译,服务器编译完成之后拷贝可执行文件到本地,再调用本地的脚本把可执行文件拷贝到机器对应的目录。

这个脚本有些使用技术和第一个脚本有重合,此处仅说没有讲到的部分。

首先第一个使用的就是 { $# } 和 {$@ }

下面是从菜鸟教程拷贝的shell传参的特殊字符介绍

参数处理说明
$#传递到脚本的参数个数
$*以一个单字符串显示所有向脚本传递的参数。 如"用「」括起来的情况、以1 n"的形式输出所有参数。
$$脚本运行的当前进程ID号
$!后台运行的最后一个进程的ID号
$@与相同,但是使用时加引号,并在引号中返回每个参数。如@"用「"」括起来的情况、以"2" … "$n" 的形式输出所有参数。
$-显示Shell使用的当前选项
$?显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。

我在其中使用了$#用来辅助提醒输入的参数数量,防止出错;

if [ $# -eq 0 ];thenecho -e "\033[33;5m no argument \033[0m"
fi

然后使用$@把传入的参数一个个解析出了来,进行变量的配置。

for arg in "${@}"
doif [[ -n "${arg}" ]] && [[ "${arg}" == "wifi" ]] ; thenwifi_src="Yes"local_ip=${ip_ethernet_dhcp}echo -e "local connect robot wifi \n --${wifi_src}\n --ip:${local_ip}."fi ...
done

其次使用了字符串截取的操作

if [[ -n "${arg}" ]] && [[ "${arg:0:3}" == "ip=" ]] ; thenecho -e "\033[32m ip put:=\033[0m" ${arg#*=}local_ip=${arg#*=}wifi_src="Yes"echo -e "scp robot local ip insert  \n --scp:${only_scp_robot} --${wifi_src}\n --ip:${local_ip}."
fi

${arg:0:3}  意思为从左边第0个字符开始,字符的个数为3个

${arg#*=} 意思为 # 号截取,删除 '='左边字符,保留右边字符。

至于为什么这么使用,以及其他使用的介绍,这里我摘录其他博主的文章给大家做一个简单的分享

摘录自:《shell脚本字符串截取的8种方法》

假设有变量 var=http://www.aaa.com/123.htm.

1. # 号截取,删除左边字符,保留右边字符。

echo ${var#*//}

其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符 即删除 http:// 结果是 :www.aaa.com/123.htm

2. ## 号截取,删除左边字符,保留右边字符。

echo ${var##*/}

##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符 即删除 http://www.aaa.com/

结果是 123.htm

3. %号截取,删除右边字符,保留左边字符

echo ${var%/*}

%/* 表示从右边开始,删除第一个 / 号及右边的字符

结果是:http://www.aaa.com

4. %% 号截取,删除右边字符,保留左边字符

echo ${var%%/*}

%%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符 结果是:http:

**5. 从左边第几个字符开始,及字符的个数 **

echo ${var:0:5}

其中的 0 表示左边第一个字符开始,5 表示字符的总个数。 结果是:http:

6. 从左边第几个字符开始,一直到结束。

echo ${var:7}

其中的 7 表示左边第8个字符开始,一直到结束。 结果是 :www.aaa.com/123.htm

7. 从右边第几个字符开始,及字符的个数

echo ${var:0-7:3}

其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。 结果是:123

8. 从右边第几个字符开始,一直到结束。

echo ${var:0-7}

表示从右边第七个字符开始,一直到结束。 结果是:123.htm

注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

此外我们也可以使用awk、cut进行截取,这里就不一一列举了。

脚本三:本地expect登陆拷贝scp_exec.sh脚本

脚本内容如下:

#!/bin/expectset timeout 30set host 192.168.1.1
set user root
spawn scp /home/lyn/Documents/work-data/download_data/ $user@$host:/opt/lib/exec#spawn ssh $user@$host
expect {"*yes/no*"{send "yes\r"expect  "*password:*" { send "123456\r" }}"*password:*"{send "123456\r"}}
expect eof

因为服务器地址相对固定,并且方便设置ssh公钥免密登陆,但是机器而言,你需要调试的机器有很多,我就没有考虑使用了expect命令。先给大家简单介绍一下expect:

Expect是等待输出内容中的特定字符。然后由send发送特定的相应。其交互流程是:

spawn启动指定进程 -> expect获取指定关键字 -> send想指定进程发送指定指令 -> 执行完成, 退出.

首先使用expect 我们需要安装expect

sudo apt-get install tcl tk expect

因为我写的这个部分也比较简单,所以就一点点给大家说明里面执行细节:

#!/bin/expect

expect的目录,类似与shell目录

set timeout 30

set  自定义变量名”:设置超时时间,单位为秒,有些拷贝大文件的朋友可能会遇到

expect: spawn id exp4 not open这里没有等到expect eof是,ssh连接已经关闭了。一般是超时时间太短了,

建议可以直接设置成 timeout -1,这意味着用不超时,拷贝结束之后才会断开。

**set host 192.168.1.1 set user root spawn scp /home/lyn/Documents/work-data/download_data/ $user@$host:/opt/lib/exec**

spawn(expect安装后的命令)是进入expect环境后才可以执行的expect内部命令,它主要的功能是给ssh运行进程加个壳,用来传递交互指令。可以理解为启动一个新进程 。

expect { "*yes/no*" { send "yes\r" expect "*password:*" { send "123456\r" } } "*password:*" { send "123456\r" } }

expect {}: 多行期望,从上往下匹配,匹配成功里面的哪一条,将执行与之的 send命令,注意,这里面的匹配字符串只会执行一个,即匹配到的那个,其余 的将不会执行,如果想匹配这句命令执行成功后(如登录成功后等待输入的root @ubuntu:~#)的其他字符,需要另起一个expect命令,并保证不在expect{}里 面。

send "yes\r"

send接收一个字符串参数,并将该参数发送到进程。这里就是执行交互动作, 与手工输入密码的动作等效。 命令字符串结尾别忘记加上“\r”,表示“回车 键”。

expect eof

expect执行结束, 退出交互程序。

这里我只是简单描述了一下我使用expect文件,更多expect命令学习,有兴趣的朋友,可以自行搜索学习。

结语

这就是我分享我在工作中使用的shell脚本,如果大家有更好的想法和需求,也欢迎大家加我好友交流分享哈。


作者:良知犹存,白天努力工作,晚上原创公号号主。公众号内容除了技术还有些人生感悟,一个认真输出内容的职场老司机,也是一个技术之外丰富生活的人,摄影、音乐 and 篮球。关注我,与我一起同行。

‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧  END  ‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧‧

推荐阅读

【1】在球场上我向人民币玩家低了头

【2】嵌入式底层开发的软件框架简述

【3】CPU中的程序是怎么运行起来的 必读

【4】cartographer环境建立以及建图测试

【5】设计模式之简单工厂模式、工厂模式、抽象工厂模式的对比

本公众号全部原创干货已整理成一个目录,回复[ 资源 ]即可获得。


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

7750b48e354009ff8b78d6677a7f9c70.png

嵌入式Linux

微信扫描二维码,关注我的公众号

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/465020.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

JSON数据提取

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式&#xff0c;它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。JSON在数据交换中起到了一个载体的作用&#xff0c;承载着相互传递的数据。JSON适用于进行数据交互的场景&#xff0c;比如网站前…

C语言面试大集合

1、static有什么用途&#xff08;至少说明两种&#xff09;&#xff1f; &#xff08;1&#xff09;限制变量的作用域 &#xff08;2&#xff09;设置变量的存储域 2、引用与指针有什么区别&#xff1f; &#xff08;1&#xff09;引用必须被初始化&#xff0c;指针不必。 &am…

ARP 地址解析协议

目的 作用是IP地址和MAC地址关联。只要有TCP/IP协议的机器中会有一张ARP表&#xff0c;在windows系统中 运行-----cmd------arp –a&#xff0c;就可以看到当前所连接的设备的ip地址和对应的MAC地址。 所谓地址解析&#xff08;address resolution&#xff09;就是主机在发送前…

陆奇给工程师们的5个建议

大家好&#xff0c;我是写代码的篮球球痴今天分享的文章是陆奇以前在百度一次内部演讲给工程师们提的5点要求&#xff0c;个人觉得对很多人非常有益&#xff0c;大家可以耐心一读。至于陆奇是谁&#xff0c;可以直接搜索&#xff0c;借微软CEO斯蒂芬鲍尔默对他的评价 : 陆奇集资…

leetcode 764.Largest Plus Sign

根据题意的话就是在非0的地方开始寻找上下左右分别能够走到的最大步长的。 那么使用暴力的方法竟然leetcode还是给过了。 class Solution { public:int orderOfLargestPlusSign(int N, vector<vector<int>>& mines) {int res0;vector<vector<int>>…

16道C面试试题

预处理器&#xff08;Preprocessor&#xff09; 用预处理指令#define 声明一个常数&#xff0c;用以表明1年中有多少秒&#xff08;忽略闰年问题&#xff09; #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在这想看到几件事情&#xff1a; 1). #define 语法的基本知识…

云服务器成势?

在许多应用领域&#xff0c;刀片服务器正在大规模替代传统的塔式服务器。螳螂捕蝉&#xff0c;黄雀在后。刚刚兴起的云服务器会不会成为刀片服务器的替代者呢&#xff1f; 2010年12月&#xff0c;北京天地超云科技有限公司&#xff08;以下简称天地超云&#xff09;首台云服务器…

每个电子工程师都埋藏着一颗游戏的心

在电子森林推文 700个字节的代码在ATtiny10里跑一个游戏[1] 介绍了一个 开源小游戏RunTiny[2] .用了&#xff1a;一个AVR单片机ATtiny10微控制器&#xff08;只有6个脚&#xff0c;Digikey上0.3美元一颗&#xff09;一个128*32的OLED显示屏一个按键一个电池 - 3.3V&#xff5e;…

python之file 方法

file 对象使用 open 函数来创建&#xff0c;下表列出了 file 对象常用的函数&#xff1a; 1 file.close() close() 方法用于关闭一个已打开的文件。关闭后的文件不能再进行读写操作&#xff0c; 否则会触发 ValueError 错误。 close() 方法允许调用多次。 当 file 对象&a…

100条经典C笔试题

题目来源&#xff1a; 1、中兴、华为、慧通、英华达、微软亚洲技术中心等中 外企业面试题目&#xff1b; 2、C 语言面试宝典(林锐《高质量编程第三版》)。 说明&#xff1a; 1、部分C 语言面试题中可能会参杂部分和C 相关的知 识&#xff0c;为了保持题目的灵活性故保留&#x…

Linux kernel 中模块化的平台驱动代码介绍

介绍在linux kernel中通过module_platform_driver来实现模块化平台驱动。大量的设备驱动程序都基于该种方式来实现&#xff0c;使用频次非常的高&#xff0c;在linux kernel 5.4.124的代码中搜索module_platform_driver共有2356次引用。这个宏的使用方式大相径庭&#xff0c;有…

Golang切片的三种简单使用方式及区别

概念 切片&#xff08;slice&#xff09;是建立在数组之上的更方便&#xff0c;更灵活&#xff0c;更强大的数据结构。切片并不存储任何元素而只是对现有数组的引用。 三种方式及细节案例 ①定义一个切片&#xff0c;然后让切片去引用一个已经创建好的数组 package main import…

这样给数组初始化,你肯定没有见过

今天在朋友圈看到一个朋友发的图片是给数组初始化的代码截图如下&#xff1a;我看到这个代码&#xff0c;也让我着实惊了一下&#xff0c;写代码这么久&#xff0c;也没有见过这样子初始化的。这个代码是出自海思的SDK里面的&#xff0c;华为的大牛还是很多啊&#xff0c;学习C…

如何让自己升薪

1) 经理应该好好看一看年度工作总结&#xff0c;这样他就能知道我对同事提供了多大的帮助。 2)如果一个程序员的工作很容易完成&#xff0c;那就不要等他主动来索取更多的任务。相反&#xff0c;积极交给他更加有挑战性的复杂的任务。 3) 在谈话中不要阻止建设性的批评。这个经…

ARM知识点

1、ARM有几种工作模式&#xff1f; 答&#xff1a;有7个基本工作模式&#xff1a;用户模式&#xff08;user&#xff09;、系统模式&#xff08;system&#xff09;、数据访问中止模式&#xff08;abort&#xff09;、未定义指令中止模式&#xff08;undef&#xff09;、快速中…

《你不知道的JavaScript》中卷 KYLE SIMPSON 著 单业 姜南 译

一部分 类型和语法 1.内置类型&#xff08;7&#xff09; null、undefined、boolean、number、string、object、symbol(ES6新增&#xff0c;符号) 2.toString()和Json.stringify() (1)字符串、数字、布尔值和null的JSON.stringify()规则与toString基本相同 (2)如果传递给JSON.…

CP命令引发的思考

转自&#xff1a;OSC开源社区今天同事用 cp 命令&#xff0c;把他给惊到了&#xff01;背景是这样的&#xff1a;他用 cp 拷贝了一个 100 G的文件&#xff0c;竟然一秒不到就拷贝完成了&#xff01;用 ls 看一把文件&#xff0c;显示文件确实是 100 G。sh-4.4# ls -lh -rw-r-…

安装windows XP或者2003时提示找不到硬盘驱动器的解决办法(总结)转载

&#xff08;本文属于转载&#xff09; 由于SATA接口在近年才推出&#xff0c;Windows XP问世的时候&#xff0c;还没有它&#xff0c;所以安装Windows XP时&#xff0c;需要调用SATA驱动程序&#xff0c;而你又没有提供相应的驱动&#xff0c;就会出现无法识别硬盘的错误。 不…

C宏定义注意事项

1、带参数的宏与函数的优缺点 2、宏定义一个函数时&#xff0c;需要注意每个参数都需要用括号括起来。 如&#xff1a;#define Min(a,b) ((a)<(b)?(a):(b)) 3、宏定义一年中的秒数 #define SECONDE_OF_YEAR 606024365UL &#xff08;√&#xff09; #define SECONDE_OF_YE…

不要再来北上广深了

大家好&#xff0c;我是写代码的篮球球痴最近我们的一个离职群里面讨论一个问题&#xff0c;就是在北上广深工作的性价比问题&#xff0c;我有几个同事这样描述。一线城市确实会遇到一些机会&#xff0c;也有可能会遇到一些改变命运的机会。不过对于生活来说&#xff0c;一线城…