• [技术干货] Rclone的介绍和使用-转载
     概述 Rclone是一个命令行程序,用于管理云存储上的文件。他打包了各大供应商云存储的接口提供统一的访问界面。rclone支持40多种云存储产品,包括对象存储、企业和消费者文件存储、服务以及标准传输协议。Rclone符合unix POSIX规范,支持于常见的shell工具,比如rsync、cp、 mv、mount、ls、ncdu、tree、rm 和cat等交互,Rclone使用我们耳闻能熟的语法,支持shell管道,支持---dry-run保护,同时为了保护数据的可靠性,Rclone可保留时间戳和始终进行文件验证校验和。Rclone多种文件传输协议,支持SFTP,HTTP,WebDAV,FTP和DLNA。Rclone是一个成熟的开源软件,最初受rsync的启发并采用Golang编写。其文档和社区也都非常好,提供广泛和友好的使用用例。  这里我们使用Rclone主要用来操作对象存储,可以用来上传对象、拉取对象,并可实现对象存储间的迁移。  安装 Rclone 是一个 Go 程序,以单个二进制文件的形式出现。  脚本安装 要在 Linux/macOS/BSD 系统上安装 rclone,请运行(确保能访问到rclone.org这个网址):  curl https://rclone.org/install.sh | sudo bash 对于 beta 安装,运行:  curl https://rclone.org/install.sh | sudo bash -s beta 此脚本首先检查安装的 rclone 的版本,如果不需要,将不会重新下载。  从预编译的二进制文件安装 Linux 获取并解包  curl -O https://downloads.rclone.org/rclone-current-linux-amd64.zip unzip rclone-current-linux-amd64.zip cd rclone-*-linux-amd64 复制二进制文件  sudo cp rclone /usr/bin/ sudo chown root:root /usr/bin/rclone sudo chmod 755 /usr/bin/rclone 运行rclone config设置基本参数,根据命令提示输入即可  rclone config 使用 docker 安装 rclone 为rclone 维护一个docker 映像。这些镜像是由 docker hub 从 rclone 源基于最小的 Alpine linux 镜像自动构建的。  该:latest标签将始终指向最新的稳定版本,也可以使用该:beta标签从 master 获取最新版本,还可以使用版本标签,例如:1.49.1,:1.49或:1。  $ docker pull rclone/rclone:latest latest: Pulling from rclone/rclone Digest: sha256:0e0ced72671989bb837fea8e88578b3fc48371aa45d209663683e24cfdaa0e11 ... $ docker run --rm rclone/rclone:latest version rclone v1.49.1 - os/arch: linux/amd64 - go version: go1.12.9 启动 rclone Docker 容器时,需要考虑一些命令行选项:  您需要将主机 rclone 配置目录挂载/config/rclone到 Docker 容器中。由于 rclone 在其配置文件中更新令牌,并且更新过程涉及文件重命名,因此您需要挂载整个主机 rclone 配置目录,而不仅仅是单个主机 rclone 配置文件。  您需要将主机数据目录挂载/data到 Docker 容器中。  默认情况下,Docker 容器内的 rclone 二进制文件以 UID=0(root)运行。因此,在运行中创建的所有文件的 UID=0。如果您的配置和数据文件驻留在具有非 root UID:GID 的主机上,您需要在容器启动命令行上传递这些文件。  如果要访问 RC 接口(通过 API 或 Web UI),则需要将 设置--rc-addr为:5572以便从容器外部连接到它。  源代码安装 确保您至少安装了Go 1.15。  git clone https://github.com/rclone/rclone.git cd rclone go build # If on macOS and mount is wanted, instead run: make GOTAGS=cmount ./rclone version 使用 配置 首先,需要配置 rclone,由于对象存储系统具有相当复杂的身份验证,因此它们保存在配置文件中,可以通过以下命令进行配置:  rclone config 基本按照命令提示输入信息即可  基本命令 通常语法是这样的  Syntax: [options] subcommand <parameters> <parameters...> 子命令列表 rclone config - 进入交互式配置会话。 rclone copy - 将文件从源复制到目标,跳过已经复制的。 rclone sync - 使源和目标相同,仅修改目标。 rclone bisync -两条路径之间的双向同步。 rclone move - 将文件从源移动到目标。 rclone delete - 删除路径的内容。 rclone purge - 删除路径及其所有内容。 rclone mkdir - 如果路径不存在,则创建路径。 rclone rmdir - 删除路径。 rclone rmdirs - 删除路径下的所有空目录。 rclone check - 检查源文件和目标文件是否匹配。 rclone ls - 列出路径中所有对象的大小和路径。 rclone lsd - 列出路径中的所有目录/容器/存储桶。 rclone lsl - 列出路径中的所有对象及其大小、修改时间和路径。 rclone size - 返回 remote:path 中对象的总大小和数量。 rclone version - 显示版本号。 rclone copyto - 将文件从源复制到目标,跳过已经复制的。 rclone mount - 将远程挂载为挂载点。 rclone moveto - 将文件或目录从源移动到目标。 具体使用大家可以看每个命令的链接,这里以rclone copy为例,比如拉取一个对象存储文件:  rclone copy remote:test.jpg /tmp/download 其中remote指的就是在config阶段配置的一个远程对象存储连接,这个命令将会把图片拉取到本地目录,这里注意的是本地必须指向一个目录。  选项配置 Rclone 有许多选项来控制其行为。  带参数的选项可以通过两种方式传递值, --option=value或者--option value。然而,布尔(真/假)选项的行为与其他选项略有不同,将选项 --boolean设置为true并且没有标志将其设置为false。也可以指定--boolean=false或 --boolean=true。请注意,这--boolean false是无效的 - 这被解析为--boolean并且false被解析为 rclone 的额外命令行参数。大家可以打开这个地址来查看所有的选项参数设置。  比如在命令后跟以下参数:  --bwlimit 10M 意味着将上传和下载带宽限制为 10 MiB/s。 注意这是每秒字节数而不是每秒位数。要使用单个限制,请以 KiB/s 为单位指定所需的带宽,或使用后缀 B|K|M|G|T|P。默认是0不限制带宽。上传和下载带宽可以单独指定,如 --bwlimit UP:DOWN,所以  --bwlimit 10M:100k 这意味着将上传带宽限制为 10 MiB/s,将下载带宽限制为 100 KiB/s。任何一个限制都可以“关闭”意味着没有限制,所以只限制您将使用的上传带宽  --bwlimit 10M:off 这会将上传带宽限制为 10 MiB/s,但下载带宽将不受限制。  其他相关追加参数设置大家可以自行查看。  HTTP调用 web界面 Rclone 可以提供基于 Web 的 GUI(图形用户界面),不过目前官方说明目前属于实验阶段,不过目前使用也没有出现什么大问题。基于上面讲的命令,在终端中运行此命令,rclone 将下载并在 Web 浏览器中显示 GUI:  rclone rcd --rc-web-gui 如果您想检查更新,则可以添加--rc-web-gui-update 到命令行。  如果你发现你的 GUI 坏了,你可以通过 add 强制它更新--rc-web-gui-force-update。  默认情况下,rclone 将打开您的浏览器。添加--rc-web-gui-no-open-browser 以禁用此功能。  HTTP监听 如果 rclone 使用该--rc标志运行,那么它会启动一个 HTTP 服务器,该服务器可用于使用其 API 远程控制 rclone。  具体使用大家可以查看Remote Control / API页面,里面有具体的说明,可以设置认证信息等,结合web界面展示加上远程调用,可以很方便的实现一些对象存储迁移等高级功能,并且方便的查看执行情况,启动http监听后,通常可以使用的rc命令,都可以通过http的方式进行调用,大家可以自行尝试。  以上就是分享的关于rclone的一些基本用法以及高级使用,欢迎大家共同探讨!  程序之路漫漫,吾将上下而求索  ———————————————— 版权声明:本文为CSDN博主「拓荒程序猿」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_34466488/article/details/124381783 
  • [技术干货] 详解Python常用标准库之时间模块time和datetime(转载)
    time和datetime是Python中常用的两个时间模块,本文将通过示例详细为大家讲讲二者的使用方法,感兴趣的小伙伴可以跟随小编一起学习学习目录time时间模块time -- 获取本地时间戳localtime -- 获取本地时间元组(UTC)gmtime -- 获取时间元组(GMT)mktime -- 时间元组获取时间戳ctime -- 获取时间字符串asctime -- 时间元组获取时间字符串strftime -- 格式化时间strptime -- 格式化时间sleep -- 时间睡眠perf_counter -- 时间计时模拟进度条程序计时时间转换示意图datetime时间模块date类time类datetime类timedelta类time时间模块import timetime -- 获取本地时间戳时间戳又被称之为是Unix时间戳,原本是在Unix系统中的计时工具。它的含义是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。UNIX时间戳的 0 按照ISO 8601规范为 :1970-01-01T00:00:00Z。比如:时间戳 60 表示 1970-01-01T00:01:00Z时间戳 120 表示 1970-01-01T00:02:00Z时间戳 3600 表示 1970-01-01T01:00:00Z小知识:最开始的时候,时间戳的开始年份是1971年,那个时候Unix系统和C语言刚刚诞生,所以时间戳0也就是Unix系统和C语言的生日。那时候的时间位数只有32位,而且每秒中有60个数字,发现只要两年多的时间时间戳就能完成一个轮回,十分的不方便!所以后来的一系列改革,将时间戳的数值改为每秒1个数字,还有一些新的系统可以将时间戳的位数增大,可以让时间戳的轮回扩展到一百多年,再后来为了方便人们记忆,将时间戳的起始年份定位1970年整。1234import time stamp_time = time.time()print(stamp_time)  # 1635768368.2838552localtime -- 获取本地时间元组(UTC)参数为时间戳,默认为本地时间戳,获取时间元组。时间元组是python中的一个特殊的数据类型type: time.struct_time,但是它和tuple的特性是相同的。12345678910111213141516171819202122import time # 时间元组中的值分别表示:    # tm_year: 年    # tm_mon: 月    # tm_mday: 日    # tm_hour: 时    # tm_min: 分    # tm_sec: 秒    # tm_wday: 周几(0表示星期一)    # tm_yday: 一年中的第几天(从1开始)    # tm_isdst: 夏令标识(1夏令时、0非夏令时、-1未知) # 默认当前时间time_tuple = time.localtime()print(time_tuple)# time.struct_time(tm_year=2021, tm_mon=11, tm_mday=1, tm_hour=20, tm_min=7, tm_sec=50, tm_wday=0, tm_yday=305, tm_isdst=0) # 指定时间戳time_tuple = time.localtime(3600)print(time_tuple)# time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=9, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=0)有大问题啦!!!时间戳的起始时间是1970-1-1 0:0:0, 这个时候的时间戳是0,那么时间戳3600就是整整一个小时之后,那么时间就应该是1970-1-1 0:1:0 才对的呀!怎么上面的3600确实9点钟了呢?怎么起始时间变成了8点了呢?然后你发现你在中国,时间是北京时间,北京在东八区时区,嘶,怎么正好也是个八?是这样的,按照道理来说的话全世界任何一个地方的时间戳所代表的时间都应该是一样的,而且时间戳的起始时间确实是 1970-1-1 0:0:0 ,但是这个时间是位于英国的一个叫做格林威治的小镇的,格林威治有一个天文台叫做皇家格林尼治天文台,后来国际上将这个地方的经线作为本初子午线,作为时间计算时间和地理精度的起点。那么,有时区的存在打破了这个可能,我们在中国,所有的设备都是按照中国的时区编码的,中国位于东八区,在时间上比英国快八个小时,所以我们中国的本地时间戳就是 1970-1-1 8:00:00。gmtime -- 获取时间元组(GMT)在不知道这个函数的时候,我就很好奇为什么localtime的初始时间比格林威治时间要快8小时,现在就明白了:函数描述gmtime获取时间元组(GMT格林威治时间)localtime获取时间元组(UTC协调世界时)mktime -- 时间元组获取时间戳注意:参数必须是时间元组time.struct_time 或者元组 tuple 类型;元组中的元素一个也不能少,必须九个元素都存在;得到的时间戳只收到前六个值的影响,即:年月日时分秒;时间元组中的时间表示,最小时间不能低于当地的最小时间戳;时间元组中的时间表示,单位可以超出原本的范围,比如秒满60进1,我们将秒写成100,系统也不会报错,但是时间上会自动的将多出的时间进位。但是数字也不能过大,因为数据类型的大小是有极限的。mktime返回的数值是浮点型的,但是精度只能到1;123456import time # 在中国的最小时间单位tst = (1970, 1, 1, 8, 0, 0, 0, 0, 0)time_stamp = time.mktime(tst)print(time_stamp)  # 0.0ctime -- 获取时间字符串参数默认为本地时间戳,获取的数据类型是 str,这个时间字符串不像时间元组是一个单独的数据类型。12345678910111213import time # 时间字符串中的含义是:    # Mon Nov  1 21:34:39 2021    # 星期 月   日 时 分 秒  年 # 默认为本地时间戳time_char = time.ctime()print(time_char)  # Mon Nov  1 21:34:39 2021 # 指定时间戳time_char = time.ctime(0)print(time_char)  # Thu Jan  1 08:00:00 1970asctime -- 时间元组获取时间字符串注意,asctime有弊端,看下例:123456789import time tst = (1970, 1, 1, 8, 24, 61, 1, 0, 0)time_char = time.asctime(tst)print(time_char)  # Tue Jan  1 08:24:61 1970 tst = (1970, 1, 1, 8, 24, 61, 2, 0, 0)time_char = time.asctime(tst)print(time_char)  # Tue Jan  1 08:24:61 1970看上面的例子,时间元组变成时间字符串的时候,会将星期的数据也读取到,但是却不会分辨数据是否正确,所以asctime并不常用。如果要将一个不确定正确性的时间元组变成时间字符串的话,先通过 mktime 获取时间戳(mktime可以分辨出正确的时间信息),然后在将时间戳通过 ctime 变成时间字符串。strftime -- 格式化时间格式化时间,按照指定的格式(一段格式化字符串,就像字符串的格式化一样)将时间元组变成时间字符串。我们先来学习一下时间占位符的含义是什么:注意!!!这些占位符的大小写的含义是不同的:占位符含义%Y以十进制数字表示以世纪为单位的年份(四位数)%y以十进制数字表示年份(两位数)%m以十进制数字表示月份%D以月/日/年(两位数)的格式表示年月日%d以十进制数字表示日期%H以十进制数字表示二十四小时制的时%M以十进制数字表示分钟%S以十进制数字表示秒%z与UTC的时区偏移%a区域设置的缩写工作日名称%A区域设置的完整工作日名称%b区域设置的缩写月份名称%B区域设置的完整月份名称%c语言环境的适当日期和时间表示%I以十进制数表示十二小时制的时(大写 ‘爱’)%p语言环境的等效值:AM 或者 PM现在根据使用时间占位符用字符串格式化将时间元组变成字符串。123456789101112import time # 注意,如果格式化字符串中出现中文字符,只能在linux系统下运行,windows下不能解析,直接报错。 tst = (1970, 1, 1, 8, 0, 0, 0, 0, 0)time_tuple = time.strftime('%Y-%m-%d-%H-%m-%S',tst)print(time_tuple)  # 1970-01-01-08-01-00 # 有中文在windows下报错tst = (1970, 1, 1, 8, 0, 0, 0, 0, 0)time_tuple = time.strftime('%Y-%m哈哈-%d-%H-%m-%S',tst)print(time_tuple)  # 1970-01-01-08-01-00strptime -- 格式化时间格式化时间,通过格式化字符串将一个字符串中的时间变成时间元组。12345678import time # 格式化字符串要和原字符串一模一样,只是将需要提出的部分使用占位符替换char = '2000年10月30日一个伟大的中国少年在三晋大地诞生了'format_char = '%Y年%m月%d日一个伟大的中国少年在三晋大地诞生了' tst = time.strptime(char, format_char)print(tst)sleep -- 时间睡眠等待指定秒数的时间:12345import time print('开始睡觉')time.sleep(2)print('睡了两秒钟,神清气爽')perf_counter -- 时间计时用于计算程序运行的时间1234567891011121314151617import time # perf_counter 用于计算程序运行的时间 # 记录开始时间start_time = time.perf_counter() # 程序运行for i in range(10000):    pass # 记录时间end_time = time.perf_counter() # windows系统直接拿到第二次的值就可以了,不用减去第一次的值也行print(end_time, '秒')  # 0.0003918 秒print(end_time - start_time, '秒')  # 0.0003916 秒如果使用多次perf_counter()函数,直接输出其的值是距第一次使用的时间长度:123456789101112131415161718192021import time time1 = time.perf_counter()time.sleep(1)time2 = time.perf_counter()print(time2) time.sleep(2)time3 = time.perf_counter()print(time3) time.sleep(3)time4 = time.perf_counter()print(time4) """结果:1.00025583.00489416.019172"""注意:windows系统下使用perf_counter()函数可以直接输出耗时长度,每次的耗时默认都是距离第一次使用perf_counter()函数的时间长度;如果在linux系统下使用perf_counter()函数则必须要使用第二次的结果减去之前的结果,因为在linux系统中perf_counter()函数的值和time()函数的值都是一样的,那就是返回一个时间戳。使用time.time()计算时间123456789101112131415import time # perf_counter 用于计算程序运行的时间 # 记录开始时间start_time = time.time() # 程序运行for i in range(10000):    pass # 记录时间end_time = time.time() print(end_time - start_time, '秒')  # 0.001001119613647461 秒耗时短的计时推荐使用pref_counter,耗时长的推荐使用time。模拟进度条123456# 1、定义进度条样式print('[%-50s]' % ('###########'))print('[%-50s]' % ('###################'))print('[%-50s]' % ('###########################'))print('[%-50s]' % ('####################################'))print('[%-50s]' % ('########################################'))12345678910# 2、让进度条动起来import time progress_char = ''for i in range(50):    progress_char += '#'    time.sleep(0.05)  # 延时看起来不是很快    # end使不能换行,\r使进度条不断刷新,保持在同一行显示;    print('\r[%-50s]' % (progress_char), end='')print('\n')1234567891011121314151617181920212223242526272829# 3、根据文件的大小调整进度条的进度import time def progress(percent):    """控制进度条的显示    参数是下载的百分比,用来控制进度条的进展    """    # 如果百分比超过了1,说明数据已经接受完毕    if percent > 1:        percent = 1     # 打印对应的进度条效果    char = '#' * int(percent * 50)    print('\r[%-50s]%d%%' % (char, int(percent * 100)), end='')  # 已下的大小rec_size = 0 # 下载文件的大小total_size = 102400 # 模拟下载过程while rec_size < total_size:    rec_size += 10240  # 下载速度    time.sleep(0.05)  # 模拟网络延迟    percent = rec_size / total_size  # 计算下载的进度(百分比)    # 调用进度条    progress(percent)程序计时在学习了perf_counter计时后,我们知道有很多种方法可以用于计时:1.time函数:返回当前时间戳,使用time函数计时是获取两个节点各自的时间戳,然后计算其之间的差值,即为耗时时长。优点:计算的是真实世界中的时间长度,而且计时本身不消耗计算机资源,计算长时间的程序优势较大;缺点:time函数的时间获取来源于计算机本身的时间,如果在计时途中计算机的时间发生变化,比如人为的调快一小时,那么计时就会比正确的时间慢一个小时的时间。2.perf_counter函数:是time模块中专门用于性能计时的函数,具有高分辨率的时钟,已测量短持续的时间。优点:是专门用于性能计时的函数,精确度高,适合计算耗时短的程序;缺点:专门用于计时的函数,计时本身就会消耗计算机资源,所以计时过长难免会有一定的影响;3.process_time函数:用于评测处理时间,计算内核和用户空间CPU时间之和,这个时间不包含程序阻塞的时间,比如time.sleep()、input()等。优点:专门用于计算程序本身内在的时间消耗,排除外来因素、提升系统本身效率、优化程序使用;1234567891011121314151617181920212223242526272829303132333435import time  def loop():    time.sleep(1)    input('请输入:')  # 这个位置人为数三秒回车执行    num = 10 ** 8    for _ in range(num):        pass    time.sleep(1)  # time.timestart_time = time.time()loop()end_time = time.time()print(start_time)  # 1640270620.4077902print(end_time)  # 1640270628.1165576print(end_time - start_time)  # 7.708767414093018 # time.perf_counterstart_time = time.perf_counter()loop()end_time = time.perf_counter()print(start_time)  # 3e-07print(end_time)  # 7.823952print(end_time - start_time)  # 7.8239517 # time.process_timestart_time = time.process_time()loop()end_time = time.process_time()print(start_time)  # 3.234375print(end_time)  # 4.8125print(end_time - start_time)  # 1.578125除此之外,python3.7之后,新增了精确到纳秒的函数:time.time_ns()time.perf_counter_ns()time.process_time_ns()还有标准库timeit用于程序的性能计时。datetime时间模块import datatimedatatime模块重新封装了time模块,提供更多的接口。date类date类专门用于描述日期,实例化对象时必须填入参数,分别表示:年、月、日,返回datetime.date对象。datetime.date(year, month, day)123456789101112from datetime import date date_o = date(2022, 3, 1) print(date_o)print(type(date_o)) """结果:2022-03-01<class 'datetime.date'>"""常用属性属性作用yeardate对象表示的具体年份(实例化对象调用达到效果);monthdate对象表示的具体月份(实例化对象调用达到效果);daydate对象表示的具体日(实例化对象调用达到效果);maxdate类能够表示的最大日期;mindate类能够表示的最小日期;resolutiondate类能够表示的最小单位;常用方法注意,以下方法如果可以返回新的对象,使用对象调用时,返回新的对象,原对象不变;如果根据对象值返回对应的值,则使用类调用达不到目标效果;方法作用today()返回本地日期对象;fromtimestamp(time_stamp)给定时间戳返回日期对象;replace(y, m, d)给定年月日返回日期对象;timetuple()返回本地当前时间元组time.struct_time对象;weekday()返回星期序号,星期一返回0;isoweekday()返回星期序号,星期一返回1;isocalendar()返回元组,表示日期的年份、第几周、第几周之后的第几天;isoformat()返回时间字符串;strftime()格式化日期,参考time.strftime();time类time类是datetime模块中专门用于描述时间的类,四个参数:hour、minute、second、microsecond默认都为0。datetime.time(hour=0, minute=0, second=0, microsecond=0)123456789101112from datetime import time time_0 = time() print(time_0)print(type(time_0)) """结果:00:00:00<class 'datetime.time'>"""time的属性和date类的属性方法基本相同,可以参考使用;datetime类相同于date和time两个类的结合,使用基本相同;timedelta类timedelta类用于时间运算,类的参数有datetime模块支持的所有时间单位,使用其它的时间和日期对象可以和timedelta对象进行时间加减运算,注意在实例化时使用关键字传参;123456789101112131415161718192021from datetime import datetimefrom datetime import timedelta # 日期对象datetime_o = datetime(2000, 10, 30, 14, 40, 6)print(datetime_o) # ## 假设我们要计算这个时间5天4小时23分6秒之后的时间 # 实例化 5天4小时23分6秒 的timedelta对象timedelta_o = timedelta(days=5, hours=4, minutes=23, seconds=6) # 将时间对象和timedelta对象相加datetime_o += timedelta_oprint(datetime_o) """结果:2000-10-30 14:40:062000-11-04 19:03:12"""
  • [技术干货] shell 输入与输出重定向
    输出重定向重定向一般通过在命令间插入特定的符号来实现。特别的,这些符号的语法如下所示:command1 > file1上面这个命令执行command1然后将输出的内容存入file1。注意任何file1内的已经存在的内容将被新内容替代。如果要将新内容添加在文件末尾,请使用>>操作符。实例执行下面的 who 命令,它将命令的完整的输出重定向在用户文件中(users):$ who > users执行后,并没有在终端输出信息,这是因为输出已被从默认的标准输出设备(终端)重定向到指定的文件。你可以使用 cat 命令查看文件内容:$ cat users_mbsetupuser console  Oct 31 17:35 tianqixin    console  Oct 31 17:35 tianqixin    ttys000  Dec  1 11:33 输出重定向会覆盖文件内容,请看下面的例子:$ echo "华为云官网:www.华为云.com" > users$ cat users华为云官网:www.华为云.com$如果不希望文件内容被覆盖,可以使用 >> 追加到文件末尾,例如:$ echo "华为云官网:www.华为云.com" >> users$ cat users华为云官网:www.华为云.com华为云官网:www.华为云.com$输入重定向和输出重定向一样,Unix 命令也可以从文件获取输入,语法为:command1 < file1这样,本来需要从键盘获取输入的命令会转移到文件读取内容。注意:输出重定向是大于号(>),输入重定向是小于号(<)。实例接着以上实例,我们需要统计 users 文件的行数,执行以下命令:$ wc -l users       2 users也可以将输入重定向到 users 文件:$  wc -l < users       2 注意:上面两个例子的结果不同:第一个例子,会输出文件名;第二个不会,因为它仅仅知道从标准输入读取内容。command1 < infile > outfile同时替换输入和输出,执行command1,从文件infile读取内容,然后将输出写入到outfile中。重定向深入讲解一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到 file。如果希望 stderr 重定向到 file,可以这样写:$ command 2>file如果希望 stderr 追加到 file 文件末尾,可以这样写:$ command 2>>file2 表示标准错误文件(stderr)。如果希望将 stdout 和 stderr 合并后重定向到 file,可以这样写:$ command > file 2>&1或者$ command >> file 2>&1如果希望对 stdin 和 stdout 都重定向,可以这样写:$ command < file1 >file2command 命令将 stdin 重定向到 file1,将 stdout 重定向到 file2。Here DocumentHere Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。它的基本的形式如下:command << delimiter    documentdelimiter它的作用是将两个 delimiter 之间的内容(document) 作为输入传递给 command。注意:结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。开始的delimiter前后的空格会被忽略掉。实例在命令行中通过 wc -l 命令计算 Here Document 的行数:$ wc -l << EOF    欢迎来到华为云官网www.华为云.comEOF3          # 输出结果为 3 行$我们也可以将 Here Document 用在脚本中,例如:#!/bin/bash# author:华为云官网# url:www.华为云.comcat << EOF欢迎来到华为云官网www.华为云.comEOF执行以上脚本,输出结果:欢迎来到华为云官网www.华为云.com/dev/null 文件如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:$ command > /dev/null/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到"禁止输出"的效果。如果希望屏蔽 stdout 和 stderr,可以这样写:$ command > /dev/null 2>&1
  • [技术干货] Unix和Linux有什么区别?
    Linux和Unix都是功能强大的操作系统,都是应用广泛的服务器操作系统,有很 多相似之处,甚至有一部分人错误地认为Unix和Linux操作系统是一样的,然 而,事实并非如此,以下是两者的区别。开源性 Linux是一款开源操作系统,不需要付费,即可使用;Unix是一款对源码实行知 识产权保护的传统商业软件,使用需要付费授权使用。
  • [技术干货] 嵌入式开发——进程间通信
    Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的。而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间的通信方面的侧重点有所不同。 - 前者是对UNIX早期的进程间通信(IPC,Interprocess communication)手段进行了系统的改进和扩充,形成了“system V IPC”,其通信进程主要局限在单个计算机内; - 后者则跳过了该限制,形成了基于套接口(socket)的进程间通信机制。 而Linux则把两者的优势都继承了下来。 ## 进程间通信 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内核,在内核中开辟一块缓冲区,进程1把数据从用户空间拷到内核缓冲区,进程2再从内核缓冲区把数据读走。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202107/27/211447yp48b4c2iefmhfe3.png) - 1.UNIX进程间通信(IPC)方式包括管道、FIFO以及信号。 - 2.System V进程间通信(IPC)包括消息队列、信号量以及共享内存区。 - 3.POSIX ( Portable Operating System Interface of UNIX )进程间通信(IPC)包括Posix消息队列、Posix信号量以及Posix共享内存区。 ![image.png](https://bbs-img.huaweicloud.com/data/forums/attachment/forum/202107/27/211539clopmwtlce9nva7i.png) ## 进程间通信方式的种类 - (1)管道(Pipe)及命名管道(named pipe):管道可用于具有亲缘关系进程间的通信;命名管道,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。 - (2)信号(Signal):信号是在软件层次上对中断机制的一种模拟,它是比较复杂的通信方式,用于通知进程有某事件发生,一个进程收到一个信号与处理器收到一个中断请求效果上可以说是一样的。 - (3)消息队列(Messge Queue):消息队列是消息的链接表,包括Posix消息队列SystemV消息队列。它克服了前两种通信方式中信息量有限的缺点,具有写权限的进程可以按照一定的规则向消息队列中添加新消息;对消息队列有读权限的进程则可以从消息队列中读取消息。 - (4)共享内存(Shared memory):可以说这是最有用的进程间通信方式。它使得多个进程可以访问同一块内存空间,不同进程可以及时看到对方进程中对共享内存中数据的更新。这种通信方式需要依靠某种同步机制,如互斥锁和信号量等。 - (5)信号量(Semaphore):主要作为进程之间以及同一进程的不同线程之间的同步和互斥手段。 - (6)套接字(Socket):这是一种更为一般的进程间通信机制,它可用于网络中不同机器间的进程间通信,应用非常广泛。
  • [技术干货] 操作系统的运行机制
          计算机系统中,通常CPU执行两种不同性质的程序:一种是操作系统内核程序;另一种是用户自编程序(即系统外层的应用程序,或简称“应用程序”)。对操作系统而言,这两种程序的作用不同,前者是后者的管理者,因此“管理程序”(即内核程序)要执行一些特权指令,而“被管理程序”(即用户自编程序)出于安全考虑不能执行这些指令。所谓特权指令,是指计算机中不允许用户直接使用的指令,如I/O 指令、置中断指令,存取用于内存保护的寄存器、送程序状态字到程序状态字寄存器等的指令。在具体实现上,将CPU的状态划分为用户态(目态)和核心态(又称管态、内核态)。可以理解为CPU内部有一个小开关,当小开关为1时,CPU处于核心态,此时CPU可以执行特权指令;当小开关为0时,CPU处于用户态,此时CPU只能执行非特权指令。用户自编程序运行在用户态,操作系统内核程序运行在核心态。      在软件工程思想和结构化程序设计方法影响下诞生的现代操作系统,几乎都是层次式的结构。操作系统的各项功能分别被设置在不同的层次上。一些与硬件关联较紧密的模块,如时钟管理、中断处理、设备驱动等处于最低层。其次是运行频率较高的程序,如进程管理、存储器管理和设备管理等。这两部分内容构成了操作系统的内核。这部分内容的指令操作工作在核心态。      内核是计算机上配置的底层软件,是计算机功能的延伸。不同系统对内核的定义稍有区别,大多数操作系统的内核包括4方面的内容。1.时钟管理      在计算机的各种部件中,时钟是最关键的设备。时钟的第一功能是计时,操作系统需要通过时钟管理,向用户提供标准的系统时间。另外,通过时钟中断的管理,可以实现进程的切换。例如,在分时操作系统中采用时间片轮转调度,在实时系统中按截止时间控制运行,在批处理系统中通过时钟管理来衡量一个作业的运行程度等。因此,系统管理的方方面面无不依赖于时钟。2.中断机制      引入中断技术的初衷是提高多道程序运行环境中CPU的利用率,而且主要是针对外部设备的。后来逐步得到发展,形成了多种类型,成为操作系统各项操作的基础。例如,键盘或鼠标信息的输入、进程的管理和调度、系统功能的调用、设备驱动、文件访问等,无不依赖于中断机制。可以说,现代操作系统是靠中断驱动的软件。      中断机制中,只有一小部分功能属于内核,它们负责保护和恢复中断现场的信息,转移控制权到相关的处理程序。这样可以减少中断的处理时间,提高系统的并行处理能力。3.原语      按层次结构设计的操作系统,底层必然是一些可被调用的公用小程序,它们各自完成一个规定的操作。它们的特点如下:1)处于操作系统的最低层,是最接近硬件的部分。2)这些程序的运行具有原子性,其操作只能一气呵成(主要从系统安全性和便于管理考虑)。3)这些程序的运行时间都较短,而且调用频繁。      通常把具有这些特点的程序称为原语((Atomic Operation)。定义原语的直接方法是关闭中断,让其所有动作不可分割地完成后再打开中断。      系统中的设备驱动、CPU切换、进程通信等功能中的部分操作都可定义为原语,使它们成为内核的组成部分。4.系统控制的数据结构及处理      系统中用来登记状态信息的数据结构很多,如作业控制块、进程控制块(PCB)、设备控制块、各类链表、消息队列、缓冲区、空闲区登记表、内存分配表等。为了实现有效的管理,系统需要一些基本的操作,常见的操作有以下3种:1)进程管理。进程状态管理、进程调度和分派、创建与撤销进程控制块等。2)存储器管理。存储器的空间分配和回收、内存信息保护程序、代码对换程序等。3)设备管理。缓冲区管理、设备分配和回收等。*所以核心态指令实际上包括系统调用类指令和一些针对时钟、中断和原语的操作指令。
  • [云桌面百科] Linux中输入输出重定向
    一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。输出重定向是大于号(>),输入重定向是小于号(<)。输出重定向输出重定向则是指把原本要输出到屏幕的数据信息写入到指定文件中对于重定向中的标准输出模式,可以省略文件描述符1不写,而错误输出模式的文件描述符2是必须要写的。输出重定向技术中的覆盖写入与追加写入这两种不同模式带来的变化。1)首先通过覆盖写入模式向xinwenjian.txt文件写入多行数据,但每一次都会覆盖掉上一次的输出内容,所以最终文件中只有最后一次的输出结果:2)通过追加写入模式向文件再写入一次数据,在执行cat命令之后,可以看到如下所示的文件内容:输入重定向输入重定向是指把文件导入到命令,用的较少。使用输入重定向把xinwenjian2.txt文件导入给wc -l命令,统计一下文件中的内容行数:
  • [经验交流] 浅谈 UNIX、Linux、IOS、Android、鸿蒙之间的关系
    Unix, 简化形成了Linux,Linux则是Android的内核,而苹果则是使用unix系统作为ios和macos的内核。几个系统出现的时间1969年,贝尔实验室的研究员肯•汤普森,编写了一款计算机游戏Space Travel,先后在多个系统上运行,然而效果不理想,所以决定自己开发操作系统,就这样UNIX诞生了。贝尔实验室存在的时候就是永久的神,最后却因为反垄断被拆分,也预示着一个贝尔实验室时代的结束,当真让人叹息。Linux系统的诞生1991年,李纳斯•托瓦兹大学读书时,为了个人爱好编写了Linux,相当于迷你版的UNIX。随后,李纳斯•托瓦兹公开了Linux源代码,邀请他人一块完善Linux。据说最后李纳斯•托瓦兹所写的代码只占Linux源代码的2%,但他的名字将会永远的留在互联网发展史上。基于unix系统,苹果ios诞生ios是苹果公司最早于2007年1月9日的Macworld大会上公布这个系统,最初是设计给iPhone使用的,后来陆续套用到iPod touch、iPad上。iOS与苹果的macOS操作系统一样,属于类Unix的商业操作系统。基于linux系统,安卓诞生2007年11月,Google与84家硬件制造商、软件开发商及电信营运商组建开放手机联盟共同研发改良Android系统。随后Google以Apache开源许可证的授权方式,安卓是一种基于Linux内核(不包含GNU组件)的自由及开放源代码的操作系统。最后不得不说还有华为的鸿蒙系统,其是和 Android 并列的,也是出自 Linux 内核。总    结因此我们就很清晰的理出了一条线路那就是Unix, 简化形成了Linux,Linux则是安卓的内核,而苹果则是使用unix系统作为ios和macos的内核。
  • 【转载】Linux内核发展史-2
    转自:https://openeuler.org/zh/blog/luoyuzhe/003History-of-Linux-kernel-2/003History-of-Linux-kernel-2.html 作者:罗宇哲正文:作者:罗宇哲,中国科学院软件研究所智能软件研究中心Linux是由赫尔辛基大学的Linus Torvalds开发的,在系统开发期间得到了因特网上广大UNIX程序员的帮助。它最初只是受Andy Tanenbaum教授的Minix(—个小型的类UNIX系统)启发而开发的一个程序,纯属个人爱好,但后来它逐步发展成为一个完整的系统。Linux的成功来源于其之前操作系统和应用软件的已有工作,主要是UNIX和GNU。本小结我们将介绍一下UNIX的发展简史。一、UNIX操作系统发展历史UNIX操作系统最初是由贝尔实验室开发的,当时的贝尔实验室是电信业巨头AT&T(美国电报电话公司)旗下的一员。UNIX是在20世纪70年代为DEC(数字设备公司)的PDP系列计算机设计的,它现在已成为一种非常流行的多用户、多任务操作系统。UNIX操作系统可以运行在大量不同种类的硬件平台上,其适用范围从PC工作站一直到多处理器服务器和超级计算机。UNIX系统的主要特点有[1]:1.简单性:许多很有用的UNIX工具是非常简单的,因此也是很小并易于理解的。2.集中性:在UNIX中,当用户出现新的需求时,我们通常是把小工具组合起来以完成更复杂的任务,而不是试图将一个用户期望的所有功能放在一个大程序里。3.可重用组件:将应用程序的核心实现为库。具有简单而灵活的编程接口、文档齐备的库可以常助其他人开发出同类程序,或者把这些技术应用到新的应用领域。4.过滤器:许多UNIX应用程序可用作过滤器。也就是说,它们对输入进行转换并产生输出。5.开放的文件格式:比较成功并流行的UNIX程序都使用纯ASCII码的文本文件或XML文件作为配置文件和数据文件。6.灵活性:你不能期待用户都能非常正确地使用你的程序。所以,你在編程时应尽景考虑到灵活性,尽量避免随意限制字段长度或记录数目。最初的Unix是用汇编语言编写的,一些应用是由叫做B语言的解释型语言和汇编语言混合编写的。B语言在进行系统编程时不够强大,所以汤普逊和里奇对其进行了改造,并与1971年共同发明了C语言。1973年汤普逊和里奇用C语言重写了Unix。在当时,为了实现最高效率,系统程序都是由汇编语言编写,所以汤普逊和里奇此举是极具大胆创新和革命意义的。用C语言编写的UNIX代码简洁紧凑、易移植、易读、易修改,为此后UNIX的发展奠定了坚实基础。1974年,汤普逊和里奇合作在ACM通信上发表了一篇关于UNIX的文章,这是UNIX第一次出现在贝尔实验室以外。此后UNIX被政府机关,研究机构,企业和大学注意到,并逐渐流行开来。1975年,UNIX发布了4、5、6三个版本。1978年,已经有大约600台计算机在运行UNIX。1979年,版本7发布,这是最后一个广泛发布的研究型UNIX版本。20世纪80年代相继发布的8、9、10版本只授权给了少数大学。此后这个方向上的研究导致了九号计划的出现,这是一个新的分布式操作系统。1982年,AT&T基于版本7开发了UNIX System Ⅲ的第一个版本,这是一个商业版本仅供出售。为了解决混乱的UNIX版本情况,AT&T综合了其他大学和公司开发的各种UNIX,开发了UNIX System V Release 1。这个新的UNIX商业发布版本不再包含源代码,所以加州大学柏克莱分校继续开发BSD UNIX,作为UNIX System III和V的替代选择。BSD对UNIX最重要的贡献之一是TCP/IP。BSD有8个主要的发行版中包含了TCP/IP:4.1c、4.2、4.3、4.3-Tahoe、4.3-Reno、Net2、4.4以及4.4-lite。这些发布版中的TCP/IP代码几乎是现在所有系统中TCP/IP实现的前辈,包括AT&T System V UNIX和Microsoft Windows。其他一些公司也开始为其自己的小型机或工作站提供商业版本的UNIX系统,有些选择System V作为基础版本,有些则选择了BSD。BSD的一名主要开发者,比尔·乔伊,在BSD基础上开发了SunOS,并最终创办了太阳计算机系统公司。1991年,一群BSD开发者(Donn Seeley、Mike Karels、Bill Jolitz和Trent Hein)离开了加州大学,创办了Berkeley Software Design, Inc (BSDI)。BSDI是第一家在便宜常见的Intel平台上提供全功能商业BSD UNIX的厂商。后来Bill Jolitz离开了BSDI,开始了386BSD的工作。386BSD被认为是FreeBSD、OpenBSD和NetBSD、DragonFlyBSD的先辈。AT&T继续为UNIX System V增加了文件锁定,系统管理,作业控制,流和远程文件系统。1987到19**,AT&T决定将Xenix(微软开发的一个x86-pc上的UNIX版本),BSD,SunOS和System V融合为System V Release 4(SVR4)。这个新发布版将多种特性融为一体,结束了混乱的竞争局面。1993年以后,大多数商业UNIX发行商都基于SVR4开发自己的UNIX变体了。UNIX System V Release 4发布后不久,AT&T就将其所有UNIX权利出售给了Novell。Novell期望以此来对抗微软的Windows NT,但其核心市场受到了严重伤害,最终Novell将SVR4的权利出售给了X/OPEN Consortium,后者是定义UNIX标准的产业团体。最后X/OPEN和OSF/1合并,创建了Open Group。Open Group定义的多个标准定义着什么是以及什么不是UNIX。实际的UNIX代码则辗转到了Santa Cruz Operation,这家公司后来出售给了Caldera Systems。Caldera原来也出售Linux系统,交易完成后,新公司又被重命名为SCO Group。下图以树状图的形式展示了从UNIX系统衍生出的各种操作系统[2]:二、总结本小节中我们简要介绍了有关Linux内核的一个重要基础——UNIX操作系统。下一小节我们将介绍Linux应用程序的一个重要来源——GNU。参考文献[1]《Linux程序设计(第四版)》[2] https://www.cnblogs.com/alantu2018/p/8991158.html
  • [交流分享] cygwin简介
    Cygwin是一个在windows平台上运行的类UNIX模拟环境,是cygnus solutions公司开发的自由软件(该公司开发的著名工具还有eCos,不过现已被Redhat收购)。它对于学习UNIX/Linux操作环境,或者从UNIX到Windows的应用程序移植,或者进行某些特殊的开发工作,尤其是使用GNU工具集在Windows上进行嵌入式系统开发,非常有用。随着嵌入式系统开发在国内日渐流行,越来越多的开发者对Cygwin产生了兴趣。 Cygwin 提供一个UNIX 模拟 DLL 以及在其上层构建的多种可以在 Linux 系统中找到的软件包,在 Windows XP SP3 以上的版本提供良好的支持。Cygwin主要由Red Hat及其下属社区负责维护。 cygnus当初首先把gcc,gdb,gas等开发工具进行了改进,使他们能够生成并解释win32的目标文件。然后,他们要把这些工具移植到windows平台上去。一种方案是基于win32 api对这些工具的源代码进行大幅修改,这样做显然需要大量工作。因此,他们采取了一种不同的方法——他们写了一个共享库(就是cygwin dll),把win32 api中没有的unix风格的调用(如fork,spawn,signals,select,sockets等)封装在里面,也就是说,他们基于 win32 api写了一个unix系统库的模拟层。这样,只要把这些工具的源代码和这个共享库连接到一起,就可以使用unix主机上的交叉编译器来生成可以在windows平台上运行的工具集。以这些移植到windows平台上的开发工具为基础,cygnus又逐步把其他的工具(几乎不需要对源代码进行修改,只需要修改他们的配置脚本)软件移植到windows上来。这样,在windows平台上运行bash和开发工具、用户工具,感觉好像在unix上工作。 简而言之,因为Windows本身不支持POSIX接口,Cygwin为此创建了一个兼容层,提供了一系列unix风格的接口,让软件源代码可以不经修改或者小修改就可以在 Windows 上面编译使用,提供给开发者一个轻量级的类unix开发环境。
  • [中间件] 【华为云鲲鹏云服务最佳实践】【工具篇】第125期Seismic Unix-44R14安装配置指南
    1、简介Seismic Unix(SU)是科罗拉多矿业学院的波场研究中心(CWP)开发的一款开源地震数据处理软件,当前很多学者在Linux下用SU做地震数据的处理与编程。类别: 软件2、基础环境类别子项版本获取地址(方法)华为云虚拟机RC3(916)--OSCentOS7.6Kernel4.14软件Seismic Unix44R14https://github.com/JohnWStockwellJr/SeisUnix/archive/master.zip3、依赖安装yum -y install gcc-gfortran gcc  gcc-c++  make  cmake  libtools4、组件编译安装(1) 下载组件wget  https://github.com/JohnWStockwellJr/SeisUnix/archive/master.zip(2)压下载的zip文件          (3)进入目录SeisUnix-master目录(4)配置环境变量export CWPROOT=/home/mxc/SU(这是我配置时的路径,即SU文件保存和安装目录)export PATH=$PATH:/home/mxc/SU/bin(bin是新建的一个文件夹)(5)进入src目录执行命令make installmake xtinstall5、系统配置无6、测试无7、参考信息https://github.com/JohnWStockwellJr/SeisUnix8、FAQ无