mycpen-blog 0.0.0-fybgfnvvin → 0.0.0-wjbgetcphi

Sign up to get free protection for your applications and to get access to all the features.
package/search.json DELETED
@@ -1 +0,0 @@
1
- [{"title":"12_Hexo-GitHub Actions 发布博客静态资源至 NPM","url":"/posts/8d01af11.html","content":"\n\n\n## 前言\n\n将博客静态文件上传至 github,通过 github action 自动发包至 npm,使用 [npmmirror](https://npmmirror.com/) cdn\n\n\n\n## npm 命令\n\n网址: https://www.npmjs.com/\n\n\n\n**切换源**\n\n```bash\n# https://blog.anheyu.com/posts/sdxhu.html#npm-镜像\n\nnpm config set registry http://registry.npmmirror.com\n# 切回源\nnpm config set registry https://registry.npmjs.org/\n```\n\n**添加本地 npm 用户**\n\n```bash\n# 仅第一次使用需要添加用户,之后会提示你输入你的npm账号密码以及注册邮箱\nnpm adduser\n# 非第一次使用直接登录即可,之后会提示你输入你的npm账号密码以及注册邮箱\nnpm login\n```\n\n**初始化**\n\n```bash\nnpm init\n```\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202403242339716.jpg\" alt=\"image-20240324233905199\" style=\"zoom: 50%;\" />\n\n**发布**\n\n```bash\nnpm publish\n```\n\n**生成 npm token**\n\nnpm 官网 => 头像 => Access Tokens => Generate New Token => 勾选 Automation\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202403242343688.jpg\" alt=\"image-20240324234307284\" style=\"zoom: 33%;\" />\n\ngithub 仓库新增 `NPM_TOKEN` 的 secrets\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202403250021463.jpg\" alt=\"image-20240325002106180\" style=\"zoom: 25%;\" />\n\n\n\n## 示例\n\n### package.json\n\n`scripts/generate_package_json.js`,生成 public/package.json\n\n```javascript\n// 生成 public/.package.json\n// https://blog.anheyu.com/posts/72ea.html\n\nhexo.extend.generator.register('npmpackagejson', function(locals){\n// Object\nreturn {\npath: '/package.json',\ndata: `{\n \"name\": \"mycpen-blog\",\n \"version\": \"0.0.0\",\n \"description\": \"mycpen blog static file\",\n \"main\": \"index.js\",\n \"directories\": {\n \"lib\": \"lib\"\n },\n \"scripts\": {\n \"test\": \"echo \\\\\"Error: no test specified\\\\\" && exit 1\"\n },\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/mycpen/blog.git\"\n },\n \"author\": \"mycpen\",\n \"license\": \"ISC\",\n \"bugs\": {\n \"url\": \"https://github.com/mycpen/blog/issues\"\n },\n \"homepage\": \"https://github.com/mycpen/blog#readme\"\n}\n`};\n});\n\n```\n\n\n\n### npm push\n\n`scripts/npmpublish.js`,生成 public/.github/workflows/autopublish.yml\n\n```javascript\n// 生成 public/.github/workflows/autopublish.yml\n// 推送静态资源至 npm\n// https://akilar.top/posts/e82444a6/#具体操作步骤\n\nhexo.extend.generator.register('npmpush', function(locals){\n // Object\n return {\n path: '/.github/workflows/autopublish.yml',\n data: `name: Node.js Package\n# 监测分支,2020年10月后github新建仓库默认分支改为main,记得更改\non:\n push:\n branches:\n - main\n\njobs:\n publish-npm:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v2\n - uses: actions/setup-node@v1\n with:\n node-version: \"18.x\"\n registry-url: https://registry.npmjs.org/\n - run: npm publish\n env:\n NODE_AUTH_TOKEN: `+ '${{secrets.npm_token}}' + `\n\n - name: Wait for 3 minutes\n run: sleep 180 # 等待 3 分钟,单位为秒\n\n - name: Sync package from npm to npmmirror\n run: |\n npm install -g cnpm --registry=https://registry.npmmirror.com\n cnpm sync mycpen-blog\n`\n};\n});\n\n```\n\n\n\n### .npmignore\n\n`scripts/npmignore.js`,生成 public/.npmignore。目的 不提交 .html 这类文件至 npm\n\n```javascript\n// 生成 public/.npmignore\n// https://akilar.top/posts/e82444a6/\n\nhexo.extend.generator.register('npmignore', function(locals){\n// Object\nreturn {\npath: '/.npmignore',\ndata: `**/*.html\n.github/\ndownload/\nads.txt\nCNAME\nrobots.txt\n`};\n});\n\n```\n\n\n\n### change version\n\n`.github/replace-localfile-url.py`,修改 public/package.json version\n\n```python\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\n\n# 源码参考 https://blog.csdn.net/qq_38150250/article/details/118026219\n\nimport os\nimport re\nfrom datetime import datetime\nimport requests\nimport random\n\n# 文件查找 find . -name file_name -type f\n# 查找函数:search_path 查找根路径 \n\n# 获取文章路径\ndef search(search_path, search_result, search_fileType_list):\n # 获取当前路径下地所有文件\n all_file = os.listdir(search_path)\n # 对于每一个文件\n for each_file in all_file:\n # 若文件为一个文件夹\n if os.path.isdir(search_path + each_file):\n # 递归查找\n search(search_path + each_file + '/', search_result, search_fileType_list)\n # 如果是需要被查找的文件\n else:\n for i in search_fileType_list:\n if re.findall(f'.*\\\\{i}$', each_file) == [each_file]:\n search_result.append(search_path + each_file)\n\n\n# 替换 sed -i 's/old_str/new_str/'\n# 文本替换 replace_file_name 需要替换的文件路径,replace_old_str 要替换的字符,replace_new_str 替换的字符\ndef replace(replace_file_name, replace_old_str, replace_new_str):\n with open(replace_file_name, \"r\", encoding = \"UTF-8\") as f1: \n content = f1.read()\n f1.close()\n t = content.replace(replace_old_str, replace_new_str)\n with open(replace_file_name, \"w\", encoding = \"UTF-8\") as f2:\n f2.write(t)\n f2.close()\n\n# ==================================================================\n\n\n# npm time version | npm_converted_time\n# ------------------------------------------------------------------\n# 将数字和字母对应关系定义为字典\nnpm_num_mapping = {\n '0': ['a', 'b', 'u'], '1': ['c', 'd', 'v'], '2': ['e', 'f', 'w'], '3': ['g', 'h', 'x'],\n '4': ['i', 'j', 'y'], '5': ['k', 'l', 'z'], '6': ['m', 'n'], '7': ['o', 'p'],\n '8': ['q', 'r'], '9': ['s', 't']\n}\n# 当前时间\nnpm_now = datetime.now()\n# 格式化当前时间为指定格式 2403230741\nnpm_formatted_time = npm_now.strftime(\"%y%m%d%H%M\")\n# 数字替换为随机映射字母 ejugfhupjv\nnpm_converted_time = ''\nfor char in npm_formatted_time:\n if char.isdigit():\n npm_converted_time += ''.join(random.choice(npm_num_mapping[char]) if char in npm_num_mapping else char)\n else:\n npm_converted_time += char\n\n# 替换 package.json 0.0.0\nresult_npmPackageJson = ['./public/package.json']\nold_npmPackageJson_version = '0.0.0'\nnew_npmPackageJson_version = f'0.0.0-{npm_converted_time}'\ncount = 0\n# json\nfor file_name in result_npmPackageJson:\n replace(file_name, old_npmPackageJson_version, new_npmPackageJson_version)\n count += 1\n print(\"{} done {}\".format(file_name, count))\n\n```\n\n\n\n`.github/workflows/autodeploy.yml`,执行上方 py 脚本 `- name: Replace localFile URL`\n\n```yaml\nname: Auto deploy\n# 当有改动推送到master分支时,启动Action\non:\n workflow_dispatch:\n push:\n branches:\n - main\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - name: 检查分支\n uses: actions/checkout@v2\n with:\n ref: main\n\n - uses: szenius/set-timezone@v1.0 # 设置执行环境的时区\n with:\n timezoneLinux: \"Asia/Shanghai\"\n\n - name: 安装 Node\n uses: actions/setup-node@v1\n with:\n node-version: \"18.x\"\n\n - name: 安装 Hexo\n run: |\n export TZ='Asia/Shanghai'\n npm install hexo-cli -g\n\n - name: 缓存 Hexo\n uses: actions/cache@v1\n id: cache\n with:\n path: node_modules\n key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}\n\n - name: 安装依赖\n if: steps.cache.outputs.cache-hit != 'true'\n run: |\n npm install gulp-cli -g #全局安装gulp\n npm install --save\n\n - name: Generate static file\n run: |\n hexo clean ; hexo generate ; gulp\n\n - name: Set up Python 3.10\n uses: actions/setup-python@v3\n with:\n python-version: \"3.10\"\n - name: Install dependencies\n run: |\n python -m pip install --upgrade pip\n pip install requests\n - name: Replace imageBed URL\n run: |\n python .github/replace-imgbed-url-v2.py\n - name: Replace localFile URL\n run: |\n python .github/replace-localfile-url.py\n\n - name: Delete static file repository tags\n run: |\n mkdir tmp_mycpen\n cd tmp_mycpen\n git clone https://github.com/mycpen/blog.git\n cd blog\n git push --force --quiet \"https://mycpen:${{ secrets.GH_TOKEN }}@github.com/mycpen/blog.git\" --delete $(git tag -l)\n cd ../..\n rm -rf tmp_mycpen\n\n - name: Deploy static file\n run: |\n cd ./public\n git init\n git config --global user.email 'github-actions[bot]@users.noreply.github.com'\n git config --global user.name 'github-actions[bot]'\n git add .\n git commit -m \"$(date +'%Y/%m/%d')\"\n tag_name=$(date +'%y.%m.%d')\n git tag $tag_name\n git push --force --quiet \"https://mycpen:${{ secrets.GH_TOKEN }}@github.com/mycpen/blog.git\" $tag_name\n git push --force --quiet \"https://mycpen:${{ secrets.GH_TOKEN }}@github.com/mycpen/blog.git\" master:main\n\n - name: Purge JSD cache\n run: |\n jsd_purge_urls=(\"https://purge.jsdelivr.net/gh/mycpen/blog/\" \"https://purge.jsdelivr.net/gh/mycpen/blog@latest/\" \"https://purge.jsdelivr.net/gh/mycpen/blog@main/\")\n for url in \"${jsd_purge_urls[@]}\"; do curl -s $url; done\n\n - name: 推送百度 url\n run: |\n hexo deploy\n\n - name: Delete workflow runs\n uses: Mattraks/delete-workflow-runs@v2\n with:\n token: ${{ secrets.GH_TOKEN }}\n repository: ${{ github.repository }}\n retain_days: 30\n keep_minimum_runs: 6\n\n```\n\n\n\n## 参考\n\n1. [akilar | github-action推送博客部署仓库至NPM](https://akilar.top/posts/e82444a6/)\n2. [akilar | npm图床](https://akilar.top/posts/3e956346/)\n3. [安知鱼 | hexo博客工作流CI](https://blog.anheyu.com/posts/b228.html)\n4. [安知鱼 | npm图床](https://blog.anheyu.com/posts/72ea.html)\n5. [EtherDream | 文件一键上传到 NPM](https://www.cnblogs.com/index-html/p/npm-upload.html#无状态)\n6. [npmmirror | 同步模块 cnpm sync cnpmcore](https://npmmirror.com/)\n7. [github | CyanBlog/pkgpublish.js](https://github.com/ChenYFan/CyanBlog/blob/main/prescripts/pkgpublish.js)\n\n","tags":["Hexo","GitHub","NPM"],"categories":["Hexo"]},{"title":"06_转载-自我提升的8个好习惯","url":"/posts/85a8374a.html","content":"\n原文:https://blog.zhuxu.xyz/archives/343/\n\n\n\n| 自我提升的8个好习惯 | 自我提升的8个好习惯 |\n| ------------------- | ------------------- |\n| 学习新技能 | 学会和自己比较 |\n| 培养一个兴趣爱好 | 每天早起半小时 |\n| 不过度透支自己 | 反省自己 |\n| 保持阅读 | 保持好的心态 |\n\n\n\n## 1. 学习新技能\n\n&emsp;&emsp;很多人其实不敢承认,自己害怕接受新事物、学习新技能。不是因为畏惧艰难,而是不想改变旧有的思考方式。\n\n&emsp;&emsp;然而这个时代变化飞快,唯有不断提升自己,才能跟上时代的步伐。时间对每个人都是公平的,日日精进不懈怠,才能遇见更好的自己。\n\n## 2. 学会和自己比较\n\n&emsp;&emsp;这个世界上,有多少人就有多少种生活方式、多少种人生目标。不要拿别人的长处,否定自己的短处,也不要羡慕别人拥有的,放大自己没有的,更不要在比较中迷失自我,忽略自己的幸福。\n\n&emsp;&emsp;人各有各的活法,没什么好比较的,当你想明白这一点,自然就能静下心来。\n\n## 3. 培养一个兴趣爱好\n\n&emsp;&emsp;人若有自己的兴趣爱好,生活会呈现出另一番景象。悲伤失落时,投入到兴趣中,情绪就有了排解的出口。烦躁不安时,做点喜欢的事,也会忘记烦恼、渐渐开心起来。\n\n&emsp;&emsp;一旦有了精神食粮,你会变得越来越欣赏自己,身体自然也会充满无限力量。\n\n## 4. 每天早起半小时\n\n&emsp;&emsp;经常听到有人说,想要自律,但不知道从何做起。那你可以尝试从每天早起30分钟开始。\n\n&emsp;&emsp;早起,意味着你有比别人更充足的时间,去准备一天的工作和生活。更重要的是,早起会让你拥有人生的掌控感,找到自己生活的节奏。早起看似是一件微不足道的小事,但在日复一日的坚持后,你会发现人生已悄然改变。\n\n## 5. 不过度透支自己\n\n&emsp;&emsp;很多人往往意识不到健康的重要性,总以为自己是金刚不坏之身,于是通宵熬夜、暴饮暴食,肆无忌惮地透支身体。时间久了,生活将不得不按下暂停键,用来弥补这些毫无节制的消耗。\n\n&emsp;&emsp;按时吃饭、早睡早起、坚持运动,只有对自己的身体好,身体才会给你更好的回馈。只有拥有了健康,你才能去创造更精彩的人生。\n\n## 6. 反省自己\n\n&emsp;&emsp;一个人的优秀,离不开不断的复盘和总结。每天睡觉前,可以花15分钟对这一天的经历做个简单的复盘和总结。\n\n&emsp;&emsp;哪些地方没有做好,哪些地方还可以做得更好……在这个过程中,及时总结经验、改正错误,才能在人生的道路上行稳致远。\n\n## 7. 保持阅读\n\n&emsp;&emsp;阅读对一个人的重要性,不只在于习得新知识,更在于它能帮助我们保持深度思考的能力,继而获得更快的成长。\n\n\n&emsp;&emsp;有空时,记得多读书。读书是为自己的心注入更多光亮的过程。我们所读过的每一本书,都将引领我们走向更美好的明天。\n\n## 8. 保持好的心态\n\n&emsp;&emsp;我们在生活中常常要去面对各种未知、困境和麻烦,心态不好的人会觉得这是一场磨难,而心态好的人则会把它当成一场历练。\n\n&emsp;&emsp;很多时候,心态决定了人生的状态。我们不能决定生活中会发生什么,但可以决定自己以什么样的心态应对。 保持良好的心态,才能拥有美好的未来。\n\n\n\n> 来源:十点读书 | 作者:小嗲 | 主播:赵文龙\n\n","tags":["转载","习惯"],"categories":["转载"]},{"title":"05_转载-延寿指南-反向面试-文档写作规范","url":"/posts/285c50ae.html","content":"\n## 程序员延寿指南\n\n原文:https://github.com/geekan/HowToLiveLonger\nissue:https://github.com/geekan/HowToLiveLonger/issues/143\n\n\n最佳操作包括:\n\n1. 饮食方面:多吃蔬果和白肉,少吃蛋黄和超加工食物;中量碳水、多吃植物蛋白;多吃辣和坚果;少喝或不喝甜味饮料,喝咖啡、茶和牛奶;戒酒或每周饮酒量不超过100g。\n\n2. 运动方面:每周进行3次45分钟的挥拍运动。\n\n3. 日常生活方面:每天刷牙,睡眠时间为7小时,最好在22-24点间睡觉。\n\n4. 其他方面:保持健康体重,不吸烟,晒太阳,服用二甲双胍、复合维生素、亚精胺和葡萄糖胺等药物。\n\n以上操作可以降低全因死亡率,增加预期寿命,从而稳健地活得更久。但是需要注意,各个变量之间并不符合独立同分布假设,变量之间的实际影响也并不明确,因此需要谨慎实践。\n\n\n## 反向面试\n\n原文:https://github.com/yifeikong/reverse-interview-zh\n\n\n\n预期使用方式\n- 检查一下哪些问题你感兴趣\n- 检查一下哪些是你可以自己在网上找到答案的\n- 找不到的话就向面试官提问\n\n绝对不要想把这个列表里的每个问题都问一遍。(尊重面试官的时间,而且你可以通过查找已经发布的答案来显示\n你的主动性)\n\n请记住事情总是灵活的,组织的结构调整也会经常发生。拥有一个 bug 追踪系统并不会保证高效处理 bug。\nCI/CD (持续集成系统) 也不一定保证交付时间会很短。\n\n\n**职责**\n\n- On-call (电话值班)的计划或者规定是什么?值班或者遇到问题加班时候有加班费吗?\n- 我的日常工作是什么?\n- 有给我设定的特定目标吗?\n- 团队里面初级和高级工程师的比例是多少?(有计划改变吗)\n- 入职培训 (onboarding) 会是什么样的?\n- 每个开发者有多大的自由来做出决定?\n- 在你看来,这个工作做到什么程度算成功?\n- 你期望我在最初的一个月 / 三个月能够完成什么?\n- 试用期结束的时候,你会怎么样衡量我的绩效?\n- 自己单独的开发活动和按部就班工作的比例大概是怎样的?\n- 一个典型的一天或者一周的工作是怎样安排的?\n- 对我的申请你有什么疑虑么?\n- 在这份工作上,我将会和谁紧密合作?\n- 我的直接上级他们的上级都是什么样的管理风格?(事无巨细还是着眼宏观)\n- 我在这个岗位上应该如何发展?会有哪些机会?\n- 每天预期 / 核心工作时间是多少小时?\n- 我入职的岗位是新增还是接替之前离职的同事?(是否有技术债需要还)?(zh)\n- 入职之后在哪个项目组,项目是新成立还是已有的?(zh)\n\n**技术**\n\n- 公司常用的技术栈是什么?\n- 你们怎么使用源码控制系统?\n- 你们怎么测试代码?\n- 你们怎么追踪 bug?\n- 你们怎样监控项目?\n- 你们怎么集成和部署代码改动?是使用持续集成和持续部署吗 (CI/CD)?\n- 你们的基础设施搭建在版本管理系统里吗?或者是代码化的吗?\n- 从计划到完成一项任务的工作流是什么样的?\n- 你们如何准备故障恢复?\n- 有标准的开发环境吗?是强制的吗?\n- 你们需要花费多长时间来给产品搭建一个本地测试环境?(分钟 / 小时 / 天)\n- 你们需要花费多长时间来响应代码或者依赖中的安全问题?\n- 所有的开发者都可以使用他们电脑的本地管理员权限吗?\n- 介绍一下你们的技术原则或者展望。\n- 你们的代码有开发文档吗?有没有单独的供消费者阅读的文档?\n- 你们有更高层次的文档吗?比如说 ER 图,数据库范式\n- 你们使用静态代码分析吗?\n- 你们如何管理内部和外部的数字资产?\n- 你们如何管理依赖?\n- 公司是否有技术分享交流活动?有的话,多久一次呢?(zh)\n- 你们的数据库是怎么进行版本控制的?(zh)\n- 业务需求有没有文档记录?是如何记录的?(zh)\n\n**团队**\n\n- 工作是怎么组织的?\n- 团队内 / 团队间的交流通常是怎样的?\n- 你们使用什么工具来做项目组织?你的实际体会是什么?\n- 如果遇到不同的意见怎样处理?\n- 谁来设定优先级 / 计划?\n- 如果团队没能赶上预期发布日期怎么办?\n- 每周都会开什么类型的会议?\n- 会有定期的和上级的一对一谈话吗?\n- 产品 / 服务的规划是什么样的?(n 周一发布 / 持续部署 / 多个发布流 / ...)\n- 生产环境发生事故了怎么办?是否有不批评人而分析问题的文化?\n- 有没有一些团队正在经历还尚待解决的挑战?\n- 你们如何跟踪进度?\n- 预期和目标是如何设定的?谁来设定?\n- Code Review 如何实施?\n- 给我介绍下团队里一个典型的 sprint\n- 你们如何平衡技术和商业目标?\n- 你们如何共享知识?\n- 团队有多大?\n- 公司技术团队的架构和人员组成?(zh)\n- 团队内开发、产品、运营哪一方是需求的主要提出方?哪一方更强势?(zh)\n\n**问未来的同事**\n\n- 开发者倾向于从哪里学习?\n- 你对在这里工作最满意的地方是?\n- 最不满意的呢?\n- 如果可以的话,你想改变哪里?\n- 团队最老的成员在这里多久了?\n- 在小团队中,有没有出现成员性格互相冲突的情况?最后是如何解决的?\n\n**公司**\n\n- 公司为什么在招人?(产品发展 / 新产品 / 波动...)\n- 有没有会议 / 旅行预算?使用的规定是什么?\n- 晋升流程是怎样的?要求 / 预期是怎样沟通的?\n- 绩效评估流程是怎样的?\n- 技术和管理两条职业路径是分开的吗?\n- 对于多元化招聘的现状或者观点是什么?\n- 有公司级别的学习资源吗?比如电子书订阅或者在线课程?\n- 有获取证书的预算吗?\n- 公司的成熟度如何?(早期寻找方向 / 有内容的工作 / 维护中 / ...)\n- 我可以为开源项目做贡献吗?是否需要审批?\n- 你认为公司未来五年或者十年会发展成什么样子?\n- 公司的大多数员工是如何看待整洁代码的?\n- 你上次注意到有人成长是什么时候?他们在哪方面成长了?\n- 在这里成功的定义是什么?如何衡量成功?\n- 有体育活动或者团建么?\n- 有内部的黑客马拉松活动吗?\n- 公司支持开源项目吗?\n- 有竞业限制或者保密协议需要签吗?\n- 你们认为公司文化中的空白是什么?\n- 能够跟我说一公司处于不良情况,以及如何处理的故事吗?\n- 您在这工作了多久了?您觉得体验如何?(zh)\n- 大家为什么会喜欢这里?(zh)\n- 公司的调薪制度是如何的?(zh)\n\n**社会问题**\n\n- 你们关于多元化招聘什么看法?\n- 你们的公司文化如何?你认为有什么空白么?\n- 这里的工作生活平衡地怎么样?\n- 公司对气候变化有什么态度吗?\n\n**冲突**\n\n- 不同的意见如何处理?\n- 如果被退回了会怎样?(“这个在预计的时间内做不完”)\n- 当团队有压力并且在超负荷工作的时候怎么处理?\n- 如果有人注意到了在流程或者技术等其他方面又改进的地方,怎么办?\n- 当管理层的预期和工程师的绩效之间有差距的时候如何处理?\n- 能给我讲一个公司深处有毒环境以及如何处理的故事吗?\n- 如果在公司内你的同事因涉嫌性侵犯他人而被调查,请问你会如何处理?\n- 假设我自己很不幸是在公司内被性侵的受害者,在公司内部有没有争取合法权益的渠道?\n\n**商业**\n\n- 你们现在盈利吗?\n- 如果没有的话,还需要多久?\n- 公司的资金来源是什么?谁影响或者制定高层计划或方向?\n- 你们如何挣钱?\n- 什么阻止了你们挣更多的钱?\n- 公司未来一年的增长计划怎样?五年呢?\n- 你们认为什么是你们的竞争优势?\n- 你们的竞争优势是什么?\n- 公司未来的商业规划是怎样的?有上市的计划吗?(zh)\n\n**远程工作**\n\n- 远程工作和办公室工作的比例是多少?\n- 公司提供硬件吗?更新计划如何?\n- 使用自己的硬件办公可以吗?现在有政策吗?\n- 额外的附件和家具可以通过公司购买吗?这方面是否有预算?\n- 有共享办公或者上网的预算吗?\n- 多久需要去一次办公室?\n- 公司的会议室是否一直是视频会议就绪的?\n\n**办公室布局**\n\n- 办公室的布局如何?(开放的 / 小隔间 / 独立办公室)\n- 有没有支持 / 市场 / 或者其他需要大量打电话的团队在我的团队旁边办公?\n\n**终极问题**\n\n- 该职位为何会空缺?\n- 公司如何保证人才不流失?\n- 这份工作 / 团队 / 公司最好和最坏的方面是?\n- 你最开始为什么选择了这家公司?\n- 你为什么留在这家公司?\n\n**待遇**\n\n- 如果有奖金计划的话,奖金如何分配?\n- 如果有奖金计划的话,过去的几年里通常会发百分之多少的奖金?\n- 有五险一金(zh)/401k(us)或者其他退休养老金等福利吗?\n- 五险一金中,补充公积金一般交多少比例?/401k一般交多少比例?我可以自己选择这一比例吗?\n- 有什么医疗保险吗?如果有的话何时开始?\n- 有额外商业保险吗?例如人寿保险和额外的养老/医疗保险?\n- 更换工作地点,公司付费吗?\n\n**休假**\n\n- 带薪休假时间有多久?\n- 病假和事假是分开的还是一起算?\n- 我可以提前使用假期时间吗?也就是说应休假期是负的?\n- 假期的更新策略是什么样的?也就是说未休的假期能否滚入下一周期\n- 照顾小孩的政策如何?\n- 无薪休假政策是什么样的?\n- 学术性休假政策是怎么样的?\n\n\n\n## 技术文档写作规范\n\n摘自 https://www.forvs.com/231.html\n\n作者 https://github.com/ruanyf/document-style-guide\n\n\n\n### 标题\n\n#### 层级\n\n标题分为四级。\n\n- 一级标题:文章的标题\n- 二级标题:文章主要部分的大标题\n- 三级标题:二级标题下面一级的小标题\n- 四级标题:三级标题下面某一方面的小标题\n\n下面是示例。\n\n```\n# 一级标题\n\n## 二级标题\n\n### 三级标题\n\n#### 四级标题\n```\n\n#### 原则\n\n(1)一级标题下,不能直接出现三级标题。\n\n示例:下面的文章结构,缺少二级标题。\n\n```\n# 一级标题\n\n### 三级标题\n```\n\n(2)标题要避免孤立编号(即同级标题只有一个)。\n\n示例:下面的文章结构,`二级标题 A`只包含一个三级标题,完全可以省略`三级标题 A`。\n\n```\n## 二级标题 A\n\n### 三级标题 A\n\n## 二级标题 B\n```\n\n(3)下级标题不重复上一级标题的名字。\n\n示例:下面的文章结构,二级标题与下属的三级标题同名,建议避免。\n\n```\n## 概述\n\n### 概述\n```\n\n(4)谨慎使用四级标题,尽量避免出现,保持层级的简单,防止出现过于复杂的章节。\n\n如果三级标题下有并列性的内容,建议只使用项目列表(Item list)。\n\n示例:下面的结构二要好于结构一。结构一适用的场景,主要是较长篇幅的内容。\n\n```\n结构一\n\n### 三级标题\n\n#### 四级标题 A\n\n#### 四级标题 B\n\n#### 四级标题 C\n\n结构二\n\n### 三级标题\n\n**(1)A**\n\n**(2)B**\n\n**(3)C**\n```\n\n------\n\n### 文本\n\n#### 字间距\n\n(1)全角中文字符与半角英文字符之间,应有一个半角空格。\n\n```\n错误:本文介绍如何快速启动Windows系统。\n \n正确:本文介绍如何快速启动 Windows 系统。\n```\n\n(2)全角中文字符与半角阿拉伯数字之间,有没有半角空格都可,但必须保证风格统一,不能两种风格混杂。\n\n```\n正确:2011年5月15日,我订购了5台笔记本电脑与10台平板电脑。\n \n正确:2011 年 5 月 15 日,我订购了 5 台笔记本电脑与 10 台平板电脑。\n```\n\n半角的百分号,视同阿拉伯数字。\n\n```\n正确:今年我国经济增长率是6.5%。\n \n正确:今年我国经济增长率是 6.5%。\n```\n\n(3)英文单位若不翻译,单位前的阿拉伯数字与单位符号之间,应留出适当的空隙。\n\n```\n例1:一部容量为 16 GB 的智能手机\n \n例2:1 h = 60 min = 3,600 s\n```\n\n(4)半角英文字符和半角阿拉伯数字,与全角标点符号之间不留空格。\n\n```\n错误:他的电脑是 MacBook Air 。\n \n正确:他的电脑是 MacBook Air。\n```\n\n#### 句子\n\n(1)避免使用长句。\n\n不包含任何标点符号的单个句子,或者以逗号分隔的句子构件,长度尽量保持在 20 个字以内;20~29 个字的句子,可以接受;30~39 个字的句子,语义必须明确,才能接受;多于 40 个字的句子,任何情况下都不能接受。\n\n```\n错误:本产品适用于从由一台服务器进行动作控制的单一节点结构到由多台服务器进行动作控制的并行处理程序结构等多种体系结构。\n \n正确:本产品适用于多种体系结构。无论是由一台服务器(单一节点结构),还是由多台服务器(并行处理结构)进行动作控制,均可以使用本产品。\n```\n\n逗号分割的长句,总长度不应该超过 100 字或者正文的 3 行。\n\n(2)尽量使用简单句和并列句,避免使用复合句。\n\n```\n并列句:他昨天生病了,没有参加会议。\n \n复合句:那个昨天生病的人没有参加会议。\n```\n\n(3)同样一个意思,尽量使用肯定句表达,不使用否定句表达。\n\n```\n错误:请确认没有接通装置的电源。\n \n正确:请确认装置的电源已关闭。\n```\n\n(4)避免使用双重否定句。\n\n```\n错误:没有删除权限的用户,不能删除此文件。\n \n正确:用户必须拥有删除权限,才能删除此文件。\n```\n\n#### 写作风格\n\n(1)尽量不使用被动语态,改为使用主动语态。\n\n```\n错误:假如此软件尚未被安装,\n \n正确:假如尚未安装这个软件,\n```\n\n(2)不使用非正式的语言风格。\n\n```\n错误:Lady Gaga 的演唱会真是酷毙了,从没看过这么给力的表演!!!\n \n正确:无法参加本次活动,我深感遗憾。\n```\n\n(3)不使用冷僻、生造或者文言文的词语,而要使用现代汉语的常用表达方式。\n\n```\n错误:这是唯二的快速启动的方法。\n \n正确:这是仅有的两种快速启动的方法。\n```\n\n(4)用对“的”、“地”、“得”。\n\n```\n她露出了开心的笑容。\n(形容词+的+名词)\n \n她开心地笑了。\n(副词+地+动词)\n \n她笑得很开心。\n(动词+得+副词)\n```\n\n(5)使用代词时(比如“其”、“该”、“此”、“这”等词),必须明确指代的内容,保证只有一个含义。\n\n```\n错误:从管理系统可以监视中继系统和受其直接控制的分配系统。\n \n正确:从管理系统可以监视两个系统:中继系统和受中继系统直接控制的分配系统。\n```\n\n(6)名词前不要使用过多的形容词。\n\n```\n错误:此设备的使用必须在接受过本公司举办的正式的设备培训的技师的指导下进行。\n \n正确:此设备必须在技师的指导下使用,且指导技师必须接受过由本公司举办的正式设备培训。\n```\n\n#### 英文处理\n\n(1)英文原文如果使用了复数形式,翻译成中文时,应该将其还原为单数形式。\n\n```\n英文:⋯information stored in random access memory (RAMs)⋯\n \n中文:……存储在随机存取存储器(RAM)里的信息……\n```\n\n(2)外文缩写可以使用半角圆点(`.`)表示缩写。\n\n```\nU.S.A.\nApple, Inc.\n```\n\n(3)表示中文时,英文省略号(`⋯`)应改为中文省略号(`……`)。\n\n```\n英文:5 minutes later⋯\n \n中文:5 分钟过去了……\n```\n\n(4)英文书名或电影名改用中文表达时,双引号应改为书名号。\n\n```\n英文:He published an article entitled \"The Future of the Aviation\".\n \n中文:他发表了一篇名为《航空业的未来》的文章。\n```\n\n(5)第一次出现英文词汇时,在括号中给出中文标注。此后再次出现时,直接使用英文缩写即可。\n\n```\nIOC(International Olympic Committee,国际奥林匹克委员会)。这样定义后,便可以直接使用“IOC”了。\n\n \n \n \n```\n\n(6)专有名词中每个词第一个字母均应大写,非专有名词则不需要大写。\n\n```\n“American Association of Physicists in Medicine”(美国医学物理学家协会)是专有名词,需要大写。\n \n“online transaction processing”(在线事务处理)不是专有名词,不应大写。\n```\n\n------\n\n### 段落\n\n#### 原则\n\n- 一个段落只能有一个主题,或一个中心句子。\n- 段落的中心句子放在段首,对全段内容进行概述。后面陈述的句子为核心句服务。\n- 一个段落的长度不能超过七行,最佳段落长度小于等于四行。\n- 段落的句子语气要使用陈述和肯定语气,避免使用感叹语气。\n- 段落之间使用一个空行隔开。\n- 段落开头不要留出空白字符。\n\n#### 引用\n\n引用第三方内容时,应注明出处。\n\n```\nOne man’s constant is another man’s variable. — Alan Perlis\n\n \n \n \n```\n\n如果是全篇转载,请在全文开头显著位置注明作者和出处,并链接至原文。\n\n```\n本文转载自 WikiQuote\n\n \n \n \n```\n\n使用外部图片时,必须在图片下方或文末标明来源。\n\n```\n本文部分图片来自 Wikipedia\n\n \n \n \n```\n\n------\n\n### 数值\n\n#### 半角数字\n\n阿拉伯数字一律使用半角形式,不得使用全角形式。\n\n```\n错误:这件商品的价格是1000元。\n \n正确:这件商品的价格是 1000 元。\n```\n\n#### 千分号\n\n数值为千位以上,应添加千分号(半角逗号)。\n\n```\nXXX 公司的实收资本为 ¥1,258,000 人民币。\n\n \n \n \n```\n\n对于 4 位的数值,千分号是选用的,比如`1000`和`1,000`都可以接受。对于 4 位以上的数值,应添加千分号。\n\n#### 货币\n\n货币应为阿拉伯数字,并在数字前写出货币符号,或在数字后写出货币中文名称。\n\n```\n$1,000\n1,000 美元\n```\n\n英文的货币名称,建议参考国际标准 [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)。\n\n#### 数值范围\n\n表示数值范围时,用波浪线(`~`)或一字线(`—`)连接。参见《标点符号》一节的“连接号”部分。\n\n带有单位或百分号时,两个数字建议都要加上单位或百分号。\n\n```\n132 kg~234 kg\n \n67%~89%\n```\n\n#### 变化程度的表示法\n\n数字的增加要使用“增加了”、“增加到”。“了”表示增量,“到”表示定量。\n\n```\n增加到过去的两倍\n(过去为一,现在为二)\n \n增加了两倍\n(过去为一,现在为三)\n```\n\n数字的减少要使用“降低了”、“降低到”。“了”表示增量,“到”表示定量。\n\n```\n降低到百分之八十\n(定额是一百,现在是八十)\n \n降低了百分之八十\n(原来是一百,现在是二十)\n```\n\n不能用“降低 N 倍”或“减少 N 倍”的表示法,要用“降低百分之几”或“减少百分之几”。因为减少(或降低)一倍表示数值原来为一百,现在等于零。\n\n\n\n------\n\n### 标点符号\n\n#### 原则\n\n(1)中文语句的标点符号,均应该采取全角符号,这样可以与全角文字保持视觉的一致。\n\n(2)如果整句为英文,则该句使用英文/半角标点。\n\n(3)句号、问号、叹号、逗号、顿号、分号和冒号不得出现在一行之首。\n\n(4)点号(句号、逗号、顿号、分号、冒号)不得出现在标题的末尾,而标号(引号、括号、破折号、省略号、书名号、着重号、间隔号、叹号、问号)可以。\n\n#### 句号\n\n(1)中文语句的结尾处应该用全角句号(`。`)。\n\n(2)句子末尾用括号加注时,句号应在括号之外。\n\n```\n错误:关于文件的输出,请参照第 1.3 节(见第 26 页。)\n \n正确:关于文件的输出,请参照第 1.3 节(见第 26 页)。\n```\n\n#### 逗号\n\n(1)逗号(`,`)表示句子内部的一般性停顿。\n\n(2)注意避免“一逗到底”,即整个段落除了结尾,全部停顿都使用逗号。\n\n#### 顿号\n\n(1)句子内部的并列词,应该用全角顿号(`、`) 分隔,而不用逗号,即使并列词是英语也是如此。\n\n```\n错误:我最欣赏的科技公司有 Google, Facebook, 腾讯, 阿里和百度等。\n \n正确:我最欣赏的科技公司有 Google、Facebook、腾讯、阿里和百度等。\n```\n\n(2)英文句子中,并列词语之间使用半角逗号(`,`)分隔。\n\n```\n例句:Microsoft Office includes Word, Excel, PowerPoint, Outlook and other components.\n\n \n \n \n```\n\n(3)中文句子内部的并列词,最后一个尽量使用(`和`)来连接,使句子读起来更加连贯,下面两个句子都可以,第二个更优。\n\n```\n正确:我最欣赏的科技公司有 Google、Facebook、腾讯、阿里,以及百度等。\n \n正确:我最欣赏的科技公司有 Google、Facebook、腾讯、阿里和百度等。\n```\n\n#### 分号\n\n(1)分号(`;`)表示复句内部并列分句之间的停顿。\n\n#### 引号\n\n(1)引用时,应该使用全角双引号(`“ ”`),注意前后双引号不同。\n\n```\n例句:许多人都认为客户服务的核心是“友好”和“专业”。\n\n \n \n \n```\n\n(2)引号里面还要用引号时,外面一层用双引号,里面一层用单引号(`‘ ’`),注意前后单引号不同。\n\n```\n例句:鲍勃解释道:“我要放音乐,可萨利说,‘不行!’。”\n\n \n \n \n```\n\n#### 括号\n\n(1)补充说明时,使用全角圆括号(`()`),括号前后不加空格。\n\n```\n例句:请确认所有的连接(电缆和接插件)均安装牢固。\n\n \n \n \n```\n\n(2)几种括号的中英文名称。\n\n| | 英文 | 中文 |\n| ----- | --------------------------- | ------ |\n| `{ }` | braces 或 curly brackets | 大括号 |\n| `` | square brackets 或 brackets | 方括号 |\n| `< >` | angled brackets | 尖括号 |\n| `( )` | parentheses | 圆括号 |\n\n#### 冒号\n\n(1)全角冒号(`:`)常用在需要解释的词语后边,引出解释和说明。\n\n```\n例句:请确认以下几项内容:时间、地点、活动名称和来宾数量。\n\n \n \n \n```\n\n(2)表示时间时,应使用半角冒号(`:`)。\n\n```\n例句:早上 8:00\n\n \n \n \n```\n\n#### 省略号\n\n(1)省略号(`……`)表示语句未完、或者语气的不连续。\n\n(2)省略号占两个汉字空间、包含六个省略点,不要使用`。。。`或`...`等非标准形式。\n\n(3)省略号不应与“等”这个词一起使用。\n\n```\n错误:我们为会餐准备了香蕉、苹果、梨…等各色水果。\n \n正确:我们为会餐准备了各色水果,有香蕉、苹果、梨……\n \n正确:我们为会餐准备了香蕉、苹果、梨等各色水果。\n```\n\n#### 感叹号\n\n(1)应该使用平静的语气叙述,尽量避免使用感叹号(`!`)。\n\n(2)不得多个感叹号连用,比如`!!`和`!!!`。\n\n#### 破折号\n\n(1)破折号`————`一般用于进一步解释。\n\n(2)破折号应占两个汉字的位置。如果破折号本身只占一个汉字的位置,那么前后应该留出一个半角空格。\n\n```\n例句:直觉————尽管它并不总是可靠的————告诉我,这事可能出了些问题。\n \n例句:直觉 —— 尽管它并不总是可靠的 —— 告诉我,这事可能出了些问题。\n```\n\n#### 连接号\n\n(1)连接号用于连接两个类似的词。\n\n(2)以下场合应该使用直线连接号(`-`),占一个半角字符的位置。\n\n- 两个名词的复合\n- 图表编号\n\n```\n例句:氧化-还原反应\n \n例句:图 1-1\n```\n\n(3)数值范围(例如日期、时间或数字)应该使用波浪连接号(`~`)或一字号(`—`),占一个全角字符的位置。\n\n```\n例句:2009 年~2011 年\n\n \n \n \n```\n\n注意,波浪连接号前后两个值都建议加上单位。\n\n(4)波浪连接号也可以用汉字“至”代替。\n\n```\n例句:周围温度:-20 °C 至 -10 °C\n\n \n \n \n```\n\n------\n\n### 文档体系\n\n#### 结构\n\n软件手册是一部完整的书,建议采用下面的结构。\n\n- **简介**(Introduction): [必备] [文件] 提供对产品和文档本身的总体的、扼要的说明\n\n- **快速上手**(Getting Started):[可选] [文件] 如何最快速地使用产品\n\n- 入门篇\n\n (Basics): [必备] [目录] 又称”使用篇“,提供初级的使用教程\n\n - **环境准备**(Prerequisite):[必备] [文件] 软件使用需要满足的前置条件\n - **安装**(Installation):[可选] [文件] 软件的安装方法\n - **设置**(Configuration):[必备] [文件] 软件的设置\n\n- **进阶篇**(Advanced):[可选] [目录] 又称”开发篇“,提供中高级的开发教程\n\n- **API**(Reference):[可选] [目录|文件] 软件 API 的逐一介绍\n\n- **FAQ**:[可选] [文件] 常见问题解答\n\n- 附录\n\n (Appendix):[可选] [目录] 不属于教程本身、但对阅读教程有帮助的内容\n\n - **Glossary**:[可选] [文件] 名词解释\n - **Recipes**:[可选] [文件] 最佳实践\n - **Troubleshooting**:[可选] [文件] 故障处理\n - **ChangeLog**:[可选] [文件] 版本说明\n - **Feedback**:[可选] [文件] 反馈方式\n\n下面是两个真实范例,可参考。\n\n- [Redux 手册](https://redux.js.org/introduction/getting-started)\n- [Atom 手册](http://flight-manual.atom.io/)\n\n#### 文件名\n\n文档的文件名不得含有空格。\n\n文件名必须使用半角字符,不得使用全角字符。这也意味着,中文不能用于文件名。\n\n```\n错误:名词解释.md\n \n正确:glossary.md\n```\n\n文件名建议只使用小写字母,不使用大写字母。\n\n```\n错误:TroubleShooting.md\n \n正确:troubleshooting.md \n```\n\n为了醒目,某些说明文件的文件名,可以使用大写字母,比如`README`、`LICENSE`。\n\n文件名包含多个单词时,单词之间建议使用半角的连词线(`-`)分隔。\n\n```\n不佳:advanced_usage.md\n \n正确:advanced-usage.md\n```\n\n------\n\n### 参考链接\n\n- [产品手册中文写作规范](https://www.taodocs.com/p-51273.html), by 华为\n- [写作规范和格式规范](http://guide.daocloud.io/dcs/写作规范和格式规范-9153803.html), by DaoCloud\n- [技术写作技巧在日汉翻译中的应用](http://www.hitachi-tc.co.jp/company/thesis/thesis.pdf), by 刘方\n- [简体中文规范指南](https://www.lengoo.de/documents/styleguides/lengoo_styleguide_ZH.pdf), by lengoo\n- [文档风格指南](https://open.leancloud.cn/copywriting-style-guide.html), by LeanCloud\n- [豌豆荚文案风格指南](https://docs.google.com/document/d/1R8lMCPf6zCD5KEA8ekZ5knK77iw9J-vJ6vEopPemqZM/edit), by 豌豆荚\n- [中文文案排版指北](https://github.com/sparanoid/chinese-copywriting-guidelines), by sparanoid\n- [中文排版需求](http://w3c.github.io/clreq/), by W3C\n- [为什么文件名要小写?](http://www.ruanyifeng.com/blog/2017/02/filename-should-be-lowercase.html), by 阮一峰\n- [Google Developer Documentation Style Guide](https://developers.google.com/style/), by Google\n- [出版物上数字用法的规定(国家标准GBT15835-2011)](http://www.moe.gov.cn/ewebeditor/uploadfile/2015/01/13/20150113091154536.pdf)\n- [GB 3100-1993 国际单位制及其应用](https://zh.wikisource.org/zh-hans/GB_3100-1993_国际单位制及其应用)\n\n\n\n","tags":["GitHub","转载","学习","习惯"],"categories":["转载"]},{"title":"04_转载-提问的智慧","url":"/posts/beb8baf2.html","content":"\n\n具体版权见原文。原文:https://github.com/tvvocold/How-To-Ask-Questions-The-Smart-Way\n\n\n\n### 弃权申明\n\n许多项目的网站在如何取得帮助的部分链接了本文,这没有关系,也正是我们想要的。但如果你是该项目生成此链接的网管,请在链接附近显著位置注明:我们不提供该项目的服务支持!\n\n我们已经领教了没有此说明带来的痛苦,我们将不停地被一些白痴纠缠,他们认为既然我们发布了本文,那么我们就有责任解决世上所有的技术问题。\n\n如果你是因为需要帮助正在阅读本文,然后就带着可以直接从作者那取得帮助的印象离开,那么 你 就不幸成了我们所说的白痴之一。 别向 我们 提问,我们不会理睬的。 我们只是在这教你如何从那些真正懂得你软硬件问题的人那里取得帮助,但 99.9% 的时间我们不会是那些人。除非你非常地 确定 本文的作者是你遇到问题方面的专家,请不要打搅,这样大家都更开心一点。\n\n### 引言\n\n在 黑客 的世界里,你所提技术问题的解答很大程度上取决于你提问的方式与解决此问题的难度,本文将教你如何提问才更有可能得到满意的答复。\n\n开源程序的应用已经很广,你通常可以从其他更有经验的用户而不是黑客那里得到解答。这是好事,他们一般对新手常有的毛病更容忍一点。然尔,使用我们推荐的方法,象对待黑客那样对待这些有经验的用户,通常能最有效地得到问题的解答。\n\n第一件需要明白的事是黑客喜欢难题和激发思考的好问题。假如不是这样,我们也不会写本文了。如果你能提出一个有趣的问题让我们咀嚼玩味,我们会感激你。好问题是种激励与礼物,帮助我们发展认知,揭示没有注意或想到的问题。在黑客中,“好问题!” 是非常热烈而真挚的赞许。\n\n此外,黑客还有遇到简单问题就表现出敌视或傲慢的名声。有时,我们看起来还对新手和愚蠢的家伙有条件反射式的无礼,但事情并不真是这样。\n\n我们只是毫无歉意地敌视那些提问前不愿思考、不做自己家庭作业的人。这种人就象时间无底洞──他们只知道索取,不愿意付出,他们浪费了时间,这些时间本可用于其它更有趣的问题或更值得回答的人。我们将这种人叫做 “失败者(loser)” (由于历史原因,我们有时将“loser”拼写为“lusers” 。)\n\n我们意识到许多人只是想使用我们写的软件,他们对学习技术细节没有兴趣。对大多数人而言,计算机只是种工具,是种达到目的的手段而已。他们有自己的生活并且有更要紧的事要做,我们承认这点,也从不指望每个人都对这些让我们着迷的技术问题感兴趣。不过,我们回答问题的风格是为了适应那些真正对此有兴趣并愿意主动参与解决问题的人,这一点不会变,也不该变。如果连这都变了,我们就会在自己能做得最好的事情上不再那么犀利。\n\n我们(大多数)是自愿者, 从自己繁忙的生活中抽时间来回答问题,有时会力不从心。因此,我们会毫不留情地滤除问题,特别是那些看起来象是失败者提的,以便更有效地把回答问题的时间留给那些胜利者。\n\n如果你认为这种态度令人反感、以施惠者自居或傲慢自大,请检查你的假设,我们并未要求你屈服──事实上,假如你做了该做的努力,我们中的大多数将非常乐意平等地与你交流,并欢迎你接纳我们的文化。试图去帮助那些不愿自救的人对我们简直没有效率。不懂没有关系,但愚蠢地做事不行。\n\n所以,你不必在技术上很在行才能吸引我们的注意,但你 必须 表现出能引导你在行的姿态──机 敏、有想法、善于观察、乐于主动参与问题的解决。如果你做不到这些使你与众不同的事情,我们建议你付钱跟别人签商业服务合同,而不是要求黑客无偿帮助。\n\n如果你决定向我们求助,你不会想成为一名失败者,你也不想被看成一个失败者。得到快速有效回答的最好方法是使提问者看起来象个聪明、自信和有想法的人,并且暗示只是碰巧在某一特别问题上需要帮助。\n\n(欢迎对本文指正,可以将建议发至 esr@thyrsus.com 或 respond-auto@linuxmafia.com。 请注意,本文不想成为一般性的 网络礼仪 指南,我一般会拒绝那些与引出技术论坛中有用的回答不特别相关的建议。)\n\n### 提问前\n\n在通过电邮、新闻组或论坛提技术问题以前,做以下事情:\n\n* 尝试在你准备提问论坛的历史文档中搜索答案\n* 尝试搜索互联网以找到答案\n* 尝试阅读手册以找到答案\n* 尝试阅读“常见问题文档”(FAQ)以找到答案\n* 尝试自己检查或试验以找到答案\n* 尝试请教懂行的朋友以找到答案\n* 如果你是程序员,尝试阅读源代码以找到答案\n\n提问时,请先表明你已做了上述事情,这将有助于建立你不是寄生虫与浪费别人时间的印象。最好再表述你从中 学到的东西 ,我们喜欢回答那些表现出能从答案中学习的人。\n\n运用某些策略,比如用谷歌(Google)搜索你遇到的各种错误提示(既搜索 谷歌论坛,也搜索网页), 这样很可能直接就找到了解决问题的文档或邮件列表线索。 即使没有结果,在邮件列表或新闻组寻求帮助时提一句“我在谷歌中搜过下列句子但没有找到什么有用的东西” 也是件好事,至少它表明了搜索引擎不能提供哪些帮助。将搜索关键词与你的问题及可能的解决方案联系起来,还有助于引导其他有类似问题的人。\n\n别着急,不要指望几秒钟的谷歌搜索就能解决一个复杂的问题。读一下常见问题文档。在向专家提问之前,先向后靠靠放松一下,再思考一下问题。相信我们,他们能从你的提问看出你做了多少阅读与思考,如果你是有备而来,将更有可能得到解答。不要将所有问题一股脑抛出,只因你的第一次搜索没有结果(或者结果太多)。\n\n认真地思考,准备好你的问题。轻率的提问只能得到轻率的回答,或者压根没有。在提问时,你越是表现出在此前做过思考与努力去解决自己的问题,你越有可能得到真正的帮助。\n\n注意别提错问题。如果提问基于错误的假设,某黑客多半会一边想 “愚蠢的问题……”,一边按将错就错的答案回复你,并且希望这种只是得到你自己“问的问题”而非真正所需的解答,给你一个教训。\n\n永远不要假设你 有资格 得到解答。你没有这种资格,毕竟你没有为此服务付费。如果你能够提出有内容、有趣和激励思考的问题──那种毫无疑问能够向社区贡献经验,而不仅仅是消极地要求从别人那获取知识的问题,你将“挣到”答案。\n\n另一方面,表明你有能力也乐意参与问题的解决是个很好的开端。“有没有人能指个方向?”,我这还差点什么?”,“我应该查哪个网站?”,通常要比 “请给出我可以用的完整步骤”更容易得到回复,因为你表明了只要有人能指个方向,你就很乐意完成剩下的过程。\n\n### 提问时\n\n#### 仔细挑选论坛\n\n要对在哪提问留心,如果你做了下述事情,多半会被一笔勾销或被看成“失败者”:\n\n* 张贴与论坛主题无关的问题\n* 在面向高级技术问题的论坛上张贴肤浅的问题,或者反之。\n* 在太多不同的新闻组同时张贴\n* 给既非熟人也没有义务解决你问题的人发送你私人的电邮\n\n为保护通信的渠道不被无关的东西淹没,黑客会除掉那些没有找对地方的问题,你不会想让这种事落到自己头上的。\n\n因此,第一步是找对论坛。谷歌和其它搜索引擎还是你的朋友,可以用它们搜索你遇到困难的软硬件问题最相关的项目网站。那里通常都有项目的常见问题(FAQ)、邮件列表及文档的链接。如果你的努力(包括 阅读 FAQ)都没有结果,这些邮件列表就是最后能取得帮助的地方。项目的网站也许还有报告Bug的流程或链接,如果是这样,去看看。\n\n向陌生的人或论坛发送邮件极有可能是在冒险。譬如,不要假设一个内容丰富的网页的作者想充当你的免费顾问,不要对你的问题是否会受到欢迎做太乐观的估计──如果你不确定,向别处发或者压根别发。\n\n在选择论坛、新闻组或邮件列表时,别太相信名字,先看看 FAQ 或者许可书以明确你的问题是否切题。发贴前先翻翻已有的帖子,这样可以让你感受一下那里行事的方式。事实上,张贴前在新闻组或邮件列表的历史文档中搜索与你问题相关的关键词是个极好的主意,也许就找到答案了。即使没有,也能帮助你归纳出更好的问题。\n\n别象机关枪似的一次性“扫射”所有的帮助渠道,这就象大喊大叫一样会令人不快,温柔地一个一个来。\n\n弄懂主题!最典型的错误之一是在某种致立于跨平台可移植的语言、库或工具的论坛中提关于 Unix 或 Windows 操作系统程序接口的问题。如果你不明白为什么这是大错,最好在搞清楚概念前什么也别问。\n\n一般来说,在仔细挑选的公共论坛中提问比在私有论坛中提同样的问题更容易得到有用的回答。有几个道理支持这点,一是看潜在的回复者有多少,二是看论坛的参与者有多少,黑客更愿回答能启发多数人的问题。\n\n可以理解,老练的黑客和一些流行软件的作者正在承受过多的不当消息。就象那根最后压垮骆驼背的稻草一样,你的加入也有可能使情况走向极端──已经好几次了,一些流行软件的作者退出了对自己软件的支持,因为伴随而来的涌入其私人邮箱的垃圾邮件变得无法忍受。\n\n#### 面向新手的论坛和互联网中继聊天(IRC)通常响应最快\n\n本地的用户组织或者你所用的 Linux 发行版也许正在宣传新手取得帮助的论坛或 IRC 通道(在一些非英语国家,新手论坛很可能还是邮件列表),这些地方是开始提问的好去处,特别是当你觉得遇到的也许只是相对简单或者很普通的问题时。经过宣传的 IRC 通道是公开邀请提问的地方,通常可以得到实时的回复。\n\n事实上,如果出问题的程序来自某发行版(这很常见),最好先去该发行版的论坛或邮件列表中提问,再到程序本身的项目论坛或邮件列表,(否则)该项目的黑客可能仅仅回复“用 我们的 代码”。\n\n在任何论坛发贴以前,先看看有没有搜索功能。如果有,就试着用问题的几个关键词搜索一下,也许就有帮助。如果在此之前你已做过全面的网页搜索(你应该这样去做),还是再搜索一下论坛,搜索引擎有可能没来得及索引此论坛的全部内容。\n\n通过论坛或 IRC 通道提供项目的用户支持有增长的趋势,电子邮件交流则更多地为项目开发者保留。所以先在论坛或 IRC 中寻求与该项目相关的帮助。\n\n#### 第二步,使用项目的邮件列表\n\n当某个项目存在开发者邮件列表时,要向列表而不是其中的个别成员提问,即使你确信他能最好地回答你的问题。查一查项目的文档和主页,找到项目的邮件列表并使用它。采用这种办法有几个很好的理由:\n\n* 向个别开发者提的问题(如果)足够好,也将对整个项目组有益。相反,如果你认为自己的问题对整个项目组来说太愚蠢,这也不能成为骚扰个别开发者的理由。\n* 向列表提问可以分散开发者的负担,个别开发者(尤其是项目领导)也许太忙以至于没法回答你的问题。\n* 大多数邮件列表都要存档,那些存档将被搜索引擎索引,如果你向列表提问并得到解答,将来其它人可以通过网页搜索找到你的问题和答案,也就不用再次发问了。\n* 如果某些问题经常被问到,开发者可以利用此信息改进文档或软件本身,以使其更清楚。如果只是私下提问,就没有人能看到最常见问题的完整场景。\n\n如果一个项目既有 “用户” 也有“开发者”(或 “黑客”)邮件列表或论坛,而你又不摆弄那些代码,向“用户”列表或论坛提问。不要假设自己会在开发者列表中受到欢迎,那些人多半会遭受你的噪音干扰。\n\n然尔,如果你 确信 你的问题不一般,而且在“用户” 列表或论坛中几天都没有回复,可以试试“开发者”列表或论坛。建议你在张贴前最好先暗暗地观察几天,至少看看最近几天保存的帖子,以了解那的行事方式(事实上这是参与任何私有或半私有列表的好主意)\n\n如果你找不到一个项目的邮件列表,而只能查到项目维护者的地址,只管向其发信。即便在这种情况下,也别假设(项目)邮件列表不存在。在你的电子邮件中陈述你已经试过但没有找到合适的邮件列表,也提及你不反对将自己的邮件转发给他人(许多人认为,即使没什么秘密,私人电子邮件也不应该被公开。通过允许将你的电子邮件转发他人,你给了相应人员处置你邮件的选择)。\n\n#### 使用有意义且明确的主题\n\n在邮件列表、新闻组或论坛中,主题是你在五十个或更少的字以内吸引有资格专家注意的黄金机会,不要用诸如 “请帮我” (更别提大写的 “请帮我!!!!”,这种主题的消息会被条件反射式地删掉)之类的唠叨浪费机会。不要用你痛苦的深度来打动我们,相反,要在这点空间中使用超级简明扼要的问题描述。\n\n使用主题的好惯例是“对象──偏差”(式的描述),许多技术支持组织就是这样做的。在“对象”部分指明是哪一个或哪一组东西有问题,在“偏差”部分则描述与期望的行为不一致的地方。\n\n愚蠢:\n>救命啊!我的笔记本视频工作不正常!\n\n明智:\n>X.org 6.8.1 扭曲鼠标光标,MV1005 型号的某显卡芯片组\n\n更明智:\n>使用 MV1005 型号的某显卡芯片组在 X.org 6.8.1 的鼠标光标被扭曲\n\n编写 “对象──偏差”式描述的过程有助于你组织对问题的细致思考。是什么被影响了?仅仅是鼠标光标或者还有其它图形?只在 X.org 中出现?或只是在其 6.8.1 版中?是针对某显卡芯片组?或者只是其中的 MV1005 型号?一个黑客只需描一眼就能够立即明白什么是你遇到的问题,什么是你自己的问题。\n\n更一般地,想象一下在一个只显示主题的文档索引中查找。让你的主题更好地反映问题,可以使下一个搜索类似问题的人能够在文档中直接就找到答案的线索,而不用再次发贴提问。\n\n如果你想在回复中提问,确保改变主题以表明你是在问一个问题,一个主题象 `Re: 测试` 或者 `Re: 新Bug` 的消息不太可能引起足够的注意。同时,将回复中与新主题不甚相关的引用内容尽量删除。\n\n对于列表消息,不要直接点击回复(按钮)来开始一个全新的线索,这将限制你的观众。有些邮件阅读程序,比如 mutt,允许用户按线索排序并通过折叠线索来隐藏消息,这样做的人永远看不到你发的消息。\n\n仅仅改变主题还不够。mutt 和其它一些邮件阅读程序还要检查邮件头主题以外的其它信息,以便为其指定线索,所以宁可发一个全新的邮件。\n\n在论坛,因为消息与特定的线索紧密结合,并且通常在线索之外不可见,好的提问方式略有不同,通过回复提问并不要紧。不是所有论坛都允许在回复中出现分离的主题,而且这样做了基本上没有人会去看。不过,通过回复提问本身就是令人怀疑的做法,因为它们只会被正在查看该线索的人读到。所以,除非你 只想 在该线索当前活跃的人群中提问,还是另起炉灶比较好。\n\n#### 使问题容易回复\n\n以`请向……回复`来结束问题多半会使你得不到回答。如果你觉得花几秒钟在邮件客户端设置一下回复地址都麻烦,我们也觉得花几秒钟考虑你的问题更麻烦。如果你的邮件客户端程序不支持这样做,换个好点的;如果是操作系统不支持所有这种邮件客户端程序,也换个好点的。\n\n在论坛,要求通过电子邮件回复是完全无礼的,除非你确信回复的信息也许是敏感的(而且有人会为了某些未知的原因,只让你而不是整个论坛知道答案)。如果你只是想在有人回复线索时得到电子邮件提醒,可以要求论坛发送。几乎所有论坛都支持诸如`留意本线索`、`有回复发送邮件`等功能。\n\n#### 用清晰、语法、拼写正确的语句书写\n\n经验告诉我们,粗心与草率的作者通常也粗心与草率地思考和编程(我敢打赌)。为这些粗心与草率的思考者回答问题没有什么好处,我们宁可将时间花在其它地方。\n\n清楚、良好地表达你的问题非常重要。如果你觉得这样做麻烦,我们也觉得注意(你的问题)麻烦。花点额外的精力斟酌一下字句,用不着太僵硬与正式──事实上,黑客文化很看重能准确地使用非正式、俚语和幽默的语句。但它 必须 很准确,而且有迹象表明你是在思考和关注问题。\n\n正确地拼写、使用标点和大小写,不要将 `its` 混淆为 `it's`,`loose` 搞成 `lose` 或者将 “discrete” 弄成 “discreet”。不要全部用大写,这会被视为无礼的大声嚷嚷 (全部小写也好不到哪去,因为不易阅读。Alan Cox [注:著名黑客,Linux 内核的重要参与者] 也许可以这样做,但你不行。)\n\n一般而言,如果你写得象个半文盲似的傻子,多半得不到理睬。也不要使用即时通讯中的简写,如将 `you` 简化为 `u` 会使你看起来象一个为了节约二次击键的半文盲式的傻子。更糟的是,如果象个小孩似地鬼画桃符那绝对是在找死,可以肯定没人会理你(或者最多是给你一大堆指责与挖苦)。\n\n如果在非母语论坛提问,你的拼写与语法错误会得到有限的宽容,但懒惰完全不会被容忍(是的,我们通常看得出其中的差别)。同时,除非你知道回复者使用的语言,请使用英语书写。繁忙的黑客一般会直接删除用他们看不懂语言写的消息。在互联网上英语是工作语言,用英语书写可以将你的问题不被阅读就被直接删除的可能性降到最低。\n\n如果你用英语书写但它是你的第二语言,最好提醒潜在的回复者语言上可能的困难以便绕过这个问题,比如:\n\n* 英语不是我的母语,请谅解拼写错误。\n* 如果您使用某某语言,请电邮/私聊我,也许我需要您的协助翻译我的问题。\n* 对于这个技术术语本身我很熟悉,但对于它的一些俚语或习惯表达方式就不太明白了。\n* 我已经同时用某某语及英语提问,如果您使用两者之一回复,我很乐意翻译。\n\n#### 使用易于读取且标准的文件格式发送问题\n\n如果你人为地将问题搞得难以阅读,它多半会被忽略,人们更愿读易懂的问题,所以:\n\n* 使用纯文本而不是 HTML(超文本标注语言)( 关闭HTML 并不难)\n\n* 使用 MIME(多用途互联网邮件扩展)附件通常没有问题,前提是真正有内容(譬如附带的源文件或补丁),而不仅仅是邮件客户端程序生成的模板(譬如只是消息内容的拷贝)。\n* 不要发送整段只是单行句子但多次折回的邮件(这使得回复部分内容非常困难)。设想你的读者是在80个字符宽的文本终端阅读邮件,设置你的行折回点小于 80 列。\n* 但是,也 不要 用任何固定列折回数据(譬如日志文件拷贝或会话记录)。数据应该原样包含,使回复者确信他们看到的是与你看到的一样的东西。\n* 在英语论坛中,不要使用'Quoted-Printable' MIME 编码发送消息。这种编码对于张贴非 ASCII 语言可能是必须的,但很多邮件程序并不支持。当它们分断时,那些文本中四处散布的 “=20”符号既难看也分散注意力,甚至有可能破坏内容的语意。\n* 永远不要 指望黑客们阅读使用封闭的专用格式编写的文档,诸如微软公司的 Word 或 Excel 文件等。大多数黑客对此的反应就象有人将还在冒热气的猪粪倒在你门口时你的反应一样。即使他们能够处理,也很厌恶这么做。\n* 如果你从使用视窗的电脑发送电子邮件,关闭问题颇多的微软“聪明引用”功能(在“工具” -> “自动纠正选项”的“输入时自动格式化”下去掉聪明引用的选框),以免在你的邮件中到处散布垃圾字符。\n* 在论坛,勿滥用“表情符号”和“HTML”功能(当它们提供时)。一两个表情符号通常没有问题,但花哨的彩色文本倾向于使人认为你是个无能之辈。过滥地使用表情符号、色彩和字体会使你看来象个傻笑的小姑娘。这通常不是个好主意,除非你只是对性而不是有用的回复更有兴趣。\n* 如果你使用图形用户界面的邮件客户端程序(如网景公司的 Messenger、微软公司的 Outlook 或者其它类似的),注意它们的缺省配置不一定满足这些要求。大多数这类程序有基于菜单的`查看源码`命令,用它来检查发送文件夹中的消息,以确保发送的是没有多余杂质的纯文本文件。\n\n#### 描述问题应准确且有内容\n\n* 仔细、清楚地描述问题的症状\n* 描述问题发生的环境(主机、操作系统、应用程序,任何相关的),提供销售商的发行版和版本号(如:“Fedora Core 7”、“Slackware 9.1”等)\n* 描述提问前做过的研究及其理解。\n* 描述提问前为确定问题而采取的诊断步骤。\n* 描述最近对计算机或软件配置的任何相关改变。\n* 如果可能,提供在可控环境下重现问题的方法。\n* 尽最大努力预测黑客会提到的问题,并提前备好答案。\n\n如果你认为是代码有问题,向黑客提供在可控环境下重现问题的方法尤其重要。当你这么做时,得到有用且及时回复的可能性将大大增加。\n\n[西蒙.泰瑟姆(Simon Tatham)](http://www.chiark.greenend.org.uk/%7Esgtatham/)写过一篇《[如何有效报告Bug》](http://www.chiark.greenend.org.uk/%7Esgtatham/bugs-tw.html)的文章,我强烈推荐各位阅读。\n\n#### 量不在多,精炼则灵\n\n你应该(写得)精炼且有内容,简单地将一大堆代码或数据罗列在求助消息中达不到目的。如果你有一个很大且复杂的测试样例让程序崩溃,尝试将其裁剪得越小越好。\n\n至少有三个理由支持这点。第一,让别人看到你在努力简化问题使你更有可能得到回复。第二,简化问题使你更有可能得到 `有用的` 回复。第三,在提纯Bug报告的过程中,你可能自己就找到了解决办法或权宜之计。\n\n#### 别急于宣称找到Bug\n\n当你在一个软件中遇到问题,除非你 非常、非常 的有根据,不要动辄声称找到了Bug。提示:除非你能提供解决问题的源代码补丁,或者对前一版本的回归测试表现出不正确的行为,否则你都多半不够完全确信。对于网页和文档也如此,如果你(声称)发现了文档的“Bug”,你应该能提供相应位置的替代文本。\n\n记住,还有许多其它用户并未经历你遇到的问题,否则你在阅读文档或搜索网页时就应该发现了([你在报怨前已经做了这些,是吧 ?](#你在报怨前已经做了这些,是吧 ?))。这也意味着很有可能是你弄错了而不是软件本身有问题。\n\n编写软件的人总是非常辛苦地使它尽可能完美。如果你声称找到了Bug,也就置疑了他们的能力,即使你是对的,也有可能会使其中的部分人感到不快。(此外,)在主题中嚷嚷“Bug”也是特别不老练的。\n\n提问时,即使你私下非常确信已经发现一个真正的Bug,最好写得象是 你 做错了什么。如果真的有Bug,你会在回复中看到这点。这样做的话,如果真有虫子,维护者就会向你道歉,这总比你弄砸了然后欠别人一个道歉要强。\n\n#### 低声下气代替不了做自己的家庭作业\n\n有些人明白他们不应该粗鲁或傲慢地行事并要求得到答复,但他们退到相反的低声下气的极端:“我知道我只是个可怜的新丁,一个失败者,但……”。这既使人困扰,也没有用,当伴随着对实际问题含糊的描述时还特别令人反感。\n\n别用低级灵长类动物的办法浪费你我的时间,相反,尽可能清楚地描述背景情况和你的问题,这比低声下气更好地摆正了你的位置。\n\n有时,论坛设有单独的初学者提问版面,如果你真的认为遇到了肤浅的问题,到那去就是了,但一样别低声下气。\n\n#### 描述问题症状而不是猜测\n\n告诉黑客是什么导致了问题是没用的(如果你的诊断理论是了不起的东西,你还会向别人咨询求助吗?)。所以,确保只是告诉他们问题的原始症状,而不是你的解释和理论,让他们来解释和诊断。如果你认为陈述自己的猜测很重要,应清楚地说明这只是你的猜测并描述为什么它们不起作用。\n\n愚蠢:\n>我在编译内核时接连遇到 SIG11 错误,怀疑主板上的某根电路丝断了,找到它们的最好办法是什么?\n\n明智:\n> 我组装的电脑(K6/233 CPU、FIC-PA2007 主板[威盛 Apollo VP2 芯片组]、Corsair PC133 SDRAM 256Mb 内存)最近在开机 20 分钟左右、做内核编译时频繁地报 SIG11 错,但在头 20 分钟内从不出问题。重启动不会复位时钟,但整夜关机会。更换所有内存未解决问题,相关的典型编译会话日志附后。\n\n由于以上这点许多人似乎难以掌握,这里有句话可以提醒你:“所有的诊断专家都来自密苏里州”。美国国务院的官方座右铭则是“让我看看”(出自国会议员威勒德.D.范迪弗[Willard D. Vandiver]在1899年时的讲话:“我来自一个出产玉米、棉花、牛蒡和民主党人的国家,滔滔雄辩既不能说服我,也不会让我满意。我来自密苏里州,你必须让我看看。”)针对诊断者而言,这并不是怀疑,而只是一种真实而有用的需求,以便让他们看到与你看到的原始证据尽可能一致的东西,而不是你的猜测与总结。(所以,)让我们看看。\n\n#### 按时间先后罗列问题症状\n\n刚出问题之前发生的事情通常包含有解决问题最有效的线索。所以,记录中应准确地描述你、电脑和软件在崩溃前都做了什么。在命令行处理的情况下,有会话日志(如运行脚本工具生成的)并引用相关的若干(如20)行记录会非常有帮助。\n\n如果崩溃的程序有诊断选项(如-v详述开关),试着选择这些能在记录中增加排错信息的选项。记住,“多”不等于“好”。试着选取适当的排错级别以便提供有用的信息而不是将阅读者淹没在垃圾中。\n\n如果你的记录很长(如超过四段),在开头简述问题随后按时间先后罗列详细过程也许更有用。这样,黑客在读你的记录时就知道该注意哪些内容了。\n\n#### 描述目标而不是过程\n\n如果你想弄清楚如何做某事(而不是报告一个Bug),在开头就描述你的目标,然后才陈述遇到问题的特定步骤。\n\n经常出现这种情况,寻求技术帮助的人在脑袋里有个更高层次的目标,他们在自以为能达到目标的特定道路上被卡住了,然后跑来问该怎么走,但没有意识到这条路本身有问题,结果要费很大的劲才能通过。\n\n愚蠢:\n> 我怎样才能让某图形程序的颜色拾取器取得十六进制的 RGB 值?\n\n明智:\n> 我正试着用自己选定数值的颜色替换一幅图片的色表,我现在知道的唯一方法是编辑每个表槽,但却无法让某图形程序的颜色拾取器取得十六进制的 RGB 值。\n\n第二种提法是明智的,它使得建议采用更合适的工具以完成任务的回复成为可能。\n\n#### 别要求私下回复电邮\n\n黑客们认为问题的解决过程应该公开、透明,此过程中如果更有才能的人注意到不完整或者不当之处,最初的回复才能够、也应该被纠正。同时,作为回复者也因为能力和学识被其它同行看到而得到某种回报。\n\n当你要求私下回复时,此过程和回报都被中止。别这样做,让 回复者 来决定是否私下回答──如果他真这么做了,通常是因为他认为问题编写太差或者太肤浅,以至于对其它人毫无意义。\n\n对这条规则存在一条有限的例外,如果你确信提问可能会引来大量雷同的回复时,那么“向我发电邮,我将为论坛归纳这些回复”将是神奇的句子。试着将邮件列表或新闻组从洪水般雷同的回复中解救出来是非常有礼貌的──但你必须信守诺言。\n\n#### 提问应明确\n\n漫无边际的问题通常也被视为没有明确限制的时间无底洞。最有可能给你有用答案的人通常也是最忙的人(假如只是因为他们承担了太多工作的话),这些人对于没有止境的时间无底洞极其敏感,所以他们也倾向于讨厌那些漫无边际的问题。\n\n如果你明确了想让回复者做的事(如指点方向、发送代码、检查补丁或其它),你更有可能得到有用的回复。(因为)这样可以让他们集中精力并间接地设定了他们为帮助你需要花费的时间和精力上限,这很好。\n\n要想理解专家生活的世界,可以这样设想:那里有丰富的专长资源但稀缺的响应时间。你暗中要求他们奉献的时间越少,你越有可能从这些真正懂行也真正很忙的专家那里得到解答。\n\n所以限定你的问题以使专家回答时需要付出的时间最少──这通常与简化问题还不太一样。举个例,“请问可否指点一下哪有好一点的 X 解释?”通常要比“请解释一下 X”明智。如果你的代码不运行了,通常请别人看看哪有问题比叫他们帮你改正更明智。\n\n#### 关于代码的问题\n\n别要求他人给你出问题的代码排错而不提及应该从何入手。张贴几百行的代码,然后说一声“它不能运行”会让你得不到理睬。只贴几十行代码,然后说一句“在第七行以后,本应该显示<x>,但实际出现的是<y>”非常有可能让你得到回复。\n\n最精确描述代码问题的方法是提供一个能展示问题的最小测试样例。什么是最小测试样例?它是对问题的展现,只需要刚好能够重现非预期行为的代码即可。如何生成一个最小测试样例?如果你知道哪一行或哪一段代码会产生问题,将其复制并提供刚好够用的外围支撑代码以构成一个完整的样例(够用是指源码刚好能被编译器、解释器或任何处理它的程序所接受)。如果你不能将问题缩小到特定的段落,复制源码并去除那些与问题无关的代码段。你能提供的最小测试样例越小越好(参见 量不在多,精炼则灵 )。\n\n生成一个非常小的最小测试样例并不总是可能,但尽力去做是很好的锻练,这有可能帮助你找到需要自己解决的问题。即使你找不到,黑客们喜欢看到你努力过,这将使他们更合作。\n\n如果你只是想让别人帮忙审一下代码,在最开头就要说出来,并且一定要提到你认为哪一部分特别需要关注以及为什么。\n\n#### 别张贴家庭作业式问题\n\n黑客们善于发现“家庭作业”式的问题。我们中的大多数人已经做了自己的家庭作业,那是该 你 做的,以便从中学到东西。问一下提示没有关系,但不是要求完整的解决方案。\n\n如果你怀疑自己碰到了一个家庭作业式的问题,但仍然无法解决,试试在用户组、论坛或(作为最后一招)在项目的“用户”邮件列表或论坛中提问。尽管黑客们 会 看出来,一些老用户也许仍会给你提示。\n\n#### 删除无意义的要求\n\n抵制这种诱惑,即在求助消息末尾加上诸如“有人能帮我吗?”或“有没有答案?”之类在语义上毫无意义的东西。第一,如果问题描述还不完整,这些附加的东西最多也只能是多余的。第二,因为它们是多余的,黑客们会认为这些东西烦人──就很有可能用逻辑上无误但打发人的回复,诸如“是的,你可以得到帮助”和“不,没有给你的帮助”。\n\n一般来说,避免提“是或否”类型的问题,除非你想得到 “是或否”类型的回答。\n\n#### 不要把问题标记为“紧急”,即使对你而言的确如此\n\n这是你的问题,不要我们的。宣称“紧急”极有可能事与愿违:大多数黑客会直接删除这种消息,他们认为这是无礼和自私地企图得到即时与特殊的关照。而且“紧急”或其它有类似含义的主题有可能触发垃圾过滤规则,潜在的回复者可能永远看不到你的问题!\n\n有一点点局部的例外,如果你是在一些知名度很高、会使黑客们激动的地方使用程序,也许值得这样去做。在这种情况下,如果你有期限压力,也很有礼貌地提到这点,人们也许会有足够的兴趣快一点回答。\n\n当然,这是非常冒险的,因为黑客们对什么是令人激动的标准多半与你的不同。譬如从国际空间站这样张贴没有问题,但代表感觉良好的慈善或政治原因这样做几乎肯定不行。事实上,张贴诸如“紧急:帮我救救这个毛绒绒的小海豹!”肯定会被黑客回避或光火,即使他们认为毛绒绒的小海豹很重要。\n\n如果你觉得这不可思议,再把剩下的内容多读几遍,直到弄懂了再发贴也不迟。\n\n#### 礼貌总是有益的\n\n礼貌一点,使用 `请` 和 `谢谢你的关注` 或者 `谢谢你的关照`,让别人明白你感谢他们无偿花时间帮助你。\n\n坦率地讲,这一点没有语法正确、文字清晰、准确、有内容和避免使用专用格式重要(同时也不能替代它们)。黑客们一般宁可读有点唐突但技术鲜明的Bug报告,而不是那种有礼但含糊的报告。(如果这点让你不解,记住我们是按问题能教我们什么来评价它的)\n\n然尔,如果你已经谈清楚了技术问题,客气一点肯定会增加你得到有用回复的机会。\n\n(我们必须指出,本文唯一受到一些老黑客认真反对的地方是以前曾经推荐过的“提前谢了”,一些黑客认为这隐含着事后不用再感谢任何人的暗示。我们的建议是要么先说 `提前谢了`,事后 再 对回复者表示感谢,要么换种方式表达,譬如用 `谢谢你的关注` 或 `谢谢你的关照`)。\n\n#### 问题解决后追加一条简要说明\n\n问题解决后向所有帮助过的人追加一条消息,让他们知道问题是如何解决的并再次感谢。如果问题在邮件列表或新闻组中受到广泛关注,在那里追加此消息比较恰当。\n\n最理想的方式是向最初提问的线索回复此消息,并在主题中包含 `已解决`、`已搞定` 或其它同等含义的明显标记。在人来人往的邮件列表里,一个看见线索 `问题 X` 和 `问题 X-已解决` 的潜在回复者就明白不用再浪费时间了(除非他个人觉得“问题 X”有趣),因此可以利用此时间去解决其它问题。\n\n追加的消息用不着太长或太复杂,一句简单的“你好──是网线坏了!谢谢大家──比尔”就比什么都没有要强。事实上,除非解决问题的技术真正高深,一条简短而亲切的总结比长篇大论要好。说明是什么行动解决了问题,用不着重演整个排错的故事。\n\n对于有深度的问题,张贴排错历史的摘要是恰当的。描述问题的最终状态,说明是什么解决了问题,在此之后 才指明可以避免的弯路。应避免的弯路部分应放在正确的解决方案和其它总结材料之后,而不要将此消息搞成侦探推理小说。列出那些帮助过你的名字,那样你会交到朋友的。\n\n除了有礼貌、有内容以外,这种类型的追帖将帮助其他人在邮件列表、新闻组或论坛文档中搜索到真正解决你问题的方案,从而也让他们受益。\n\n最后,此类追帖还让每位参与协助的人因问题的解决而产生一种满足感。如果你自己不是技术专家或黑客,相信我们,这种感觉对于你寻求帮助的老手和专家是非常重要的。问题叙述到最后不知所终总是令人沮丧的,黑客们痒痒地渴望它们被解决。`挠痒痒` 为你挣到的信誉将对你下次再次张贴提问非常非常的有帮助。\n\n考虑一下怎样才能避免他人将来也遇到类似的问题,问问自己编一份文档或 FAQ 补丁会不会有帮助,如果是的话就将补丁发给维护者。\n\n在黑客中,这种良好的后继行动实际上比传统的礼貌更重要,也是你善待他人而赢得声誉的方式,这是非常有价值的财富。\n\n### 如何解读回答\n\n#### “读读该死的手册”(RTFM)和“搜搜该死的网络”(STFW):如何明白你已完全搞砸\n\n有一个古老而神圣的传统:如果你收到 `读读该死的手册`(RTFM) 的回复,发信人认为你应该去“读读该死的手册”。他或她多半是对的,去读一下吧。\n\n“读读该死的手册”(RTFM)有个年轻一点的亲戚,如果你收到“搜搜该死的网络”(STFW)的回复,发信人认为你应该“搜搜该死的网络”。那人多半也是对的,去搜一下吧。(更温和一点的说法是“[谷歌是你的朋友!](http://lmgtfy.com/)”)\n\n在论坛,你也可能被要求去搜索论坛的文档。事实上,有人甚至可能热心地为你提供以前解决此问题的线索。但不要依赖这种关照,提问前应该先搜索一下文档。\n\n通常,叫你搜索的人已经打开了能解决你问题的手册或网页,正在一边看一边敲键盘。这些回复意味着他认为:\n\n* 第一,你要的信息很容易找到。\n* 第二,自已找要比别人喂到嘴里能学得更多。\n\n你不应该觉得这样就被冒犯了,按黑客的标准,回复者没有不理你就是在向你表示某种尊敬,你反而应该感谢他热切地想帮助你。\n\n#### 如果还不明白……\n\n如果你看不懂回答,不要马上回复一个要求说明的消息,先试试那些最初提问时用过的相同工具(如手册、FAQ、网页、懂行的朋友等)试着搞懂回答。如果还是需要说明,展现你已经明白的。\n\n譬如,假如我告诉你:“看起来象是某输入项有问题,你需要清除它”,接着是个 不好 的回帖:“什么是某输入项?”。而这是一个 很好 的跟帖:“是的,我读了手册,某某输入项只在 -z 和 -p 开关中被提到,但都没有涉及到如何清除它们,你指的是哪一个还是我弄错了什么?”\n\n#### 对待无礼\n\n很多黑客圈子中看似无礼的行为并不是存心冒犯。相反,它是直接了当、一针见血式的交流风格,这种风格对于更关注解决问题而不是使别人感觉舒服而混乱的人是很自然的。\n\n如果你觉得被冒犯了,试着平静地反应。如果有人真的做了过格的事,邮件列表、新闻组或论坛中的前辈多半会招呼他。如果这 没有 发生而你却光火了,那么你发火对象的言语可能在黑客社区中看起来是正常的,而 你 将被视为有错的一方,这将伤害到你获取信息或帮助的机会。\n\n另一方面,你会偶而真的碰到无礼和无聊的言行。与上述相反,对真正的冒犯者狠狠地打击、用犀利的语言将其驳得体无完肤都是可以接受的。然尔,在行事之前一定要非常非常的有根据。纠正无礼的言论与开始一场毫无意义的口水战仅一线之隔,黑客们自己莽撞地越线的情况并不鲜见。如果你是新手或外来者,避开这种莽撞的机会并不高。如果你想得到的是信息而不是消磨时光,这时最好不要把手放在键盘上以免冒险。\n\n(有些人断言很多黑客都有轻度的自闭症或阿斯伯格综合症,缺少用于润滑人类社会“正常”交往所需的脑电路。这既可能是真也可能是假。如果你自己不是黑客,兴许你认为我们脑袋有问题还能帮助你应付我们的古怪行为。只管这么干好了,我们不在乎。我们 喜欢 现在这个样子,并且一般都对病号标记有站得住脚的怀疑。)\n\n在下一节,我们会谈到另一个问题,当 你 行为不当时会受到的“冒犯”。\n\n### 别象失败者那样反应\n\n在黑客社区的论坛中有那么几次你可能会搞砸──以本文描述或类似的方式。你会被示众是如何搞砸的,也许言语中还会带点颜色。\n\n这种事发生以后,你能做的最糟糕的事莫过于哀嚎你的遭遇、宣称被口头攻击、要求道歉、高声尖叫、憋闷气、威胁诉诸法律、向其雇主报怨、忘了关马桶盖等等。相反,你该这样去做:\n\n熬过去,这很正常。事实上,它是有益健康与恰当的。\n\n社区的标准不会自己维持,它们是通过参与者积极而 公开 地执行来维持的。不要哭嚎所有的批评都应该通过私下的邮件传送,这不是事情运作的方式。当有人评论你的一个说法有误或者提出不同看法时,坚持声称受到个人攻击也毫无益处,这些都是失败者的态度。\n\n也有其它的黑客论坛,受过高礼节要求的误导,禁止参与者张贴任何对别人帖子挑毛病的消息,并声称“如果你不想帮助用户就闭嘴”。有思路的参与者纷纷离开的结果只会使它们变成了毫无意义的唠叨与无用的技术论坛。\n\n是夸张的“友谊”(以上述方式)还是有用?挑一个。\n\n记着:当黑客说你搞砸了,并且(无论多么刺耳地)告诉你别再这样做时,他正在为关心你和他的社区而行动。对他而言,不理你并将你从他的生活中滤除要容易得多。如果你无法做到感谢,至少要有点尊严,别大声哀嚎,也别因为自己是个有戏剧性超级敏感的灵魂和自以为有资格的新来者,就指望别人象对待脆弱的洋娃娃那样对你。\n\n有时候,即使你没有搞砸(或者只是别人想象你搞砸了), 有些人也会无缘无故地攻击你本人。在这种情况下,报怨倒是 真的 会把问题搞砸。\n\n这些找茬者要么是毫无办法但自以为是专家的不中用家伙,要么就是测试你是否真会搞砸的心理专家。其它读者要么不理睬,要么用自己的方式对付他们。这些找茬者在给自己找麻烦,这点你不用操心。\n\n也别让自己卷入口水战,大多数口水战最好不要理睬──当然,是在你核实它们只是口水战、没有指出你搞砸的地方,而且没有巧妙地将问题真正的答案藏于其中之后(这也是可能的)。\n\n### 提问禁忌\n\n下面是些典型的愚蠢问题和黑客不回答它们时的想法。\n\n问:我到哪可以找到某程序或 X 资源?\n\n问:我怎样用 X 做 Y?\n\n问:如何配置我的 shell 提示?\n\n问:我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文档转为 TeX 格式吗?\n\n问:我的{程序、配置、SQL 语句}不运行了\n\n问:我的视窗电脑出问题了,你能帮忙吗?\n\n问:我的程序不运行了,我认为系统工具X有问题\n\n问:我安装 Linux 或 X 遇到困难,你能帮忙吗?\n\n问:我如何才能破解超级用户口令/盗取通道操作员的特权/查看某人的电子邮件?\n\n---\n\n问:\t\n> 我到哪可以找到某程序或 X 资源?\n\n答:\t\n> 在我找到它的同样地方,笨旦──在网页搜索引擎上。上帝啊,难道还有人不知道如何使用 谷歌 吗?\n\n问:\t\n> 我怎样用 X 做 Y?\n\n答:\t\n> 如果你想解决的是 Y,提问时别给出可能并不恰当的方法。这种问题说明提问者不但对 X 完全无知,也对要解决的 Y 问题糊涂,还被特定形势禁锢了思维。等他们把问题弄好再说。\n\n问:\t\n> 如何配置我的 shell 提示?\n\n答:\t\n> 如果你有足够的智慧提这个问题,你也该有足够的智慧去 “读读该死的手册”(RTFM),然后自己去找出来。\n\n问:\t\n> 我可以用 Bass-o-matic 文件转换工具将 AcmeCorp 文档转为 TeX 格式吗?\n\n答:\t\n> 试试就知道了。如果你试过,你既知道了答案,又不用浪费我的时间了。\n\n问:\t\n> 我的{程序、配置、SQL 语句}不运行了\n\n答:\t\n> 这不是一个问题,我也没有兴趣去猜你有什么问题──我有更要紧的事要做。看到这种东西,我的反应一般如下:\n\n* 你还有什么补充吗?\n* 噢,太糟了,希望你能搞定。\n* 这跟我究竟有什么关系?\n\n问:\t\n> 我的视窗电脑出问题了,你能帮忙吗?\n\n答:\t\n> 是的,把视窗垃圾删了,装个象 Linux 或 BSD 的开源操作系统吧。\n\n注意:如果程序有官方的视窗版或者与视窗有交互(如 Samba),你 可以 问与视窗相关的问题,只是别对问题是由视窗操作系统而不是程序本身造成的回复感到惊讶,因为视窗一般来说太差,这种说法一般都成立。\n\n问:\t\n> 我的程序不运行了,我认为系统工具 X 有问题\n\n答:\t\n> 你完全有可能是第一个注意到被成千上万用户反复使用的系统调用与库文件有明显缺陷的人,更有可能的是你完全没有根据。不同凡响的说法需要不同凡响的证据,当你这样声称时,你必须有清楚而详尽的缺陷说明文档作后盾。\n\n问:\t\n> 我安装 Linux 或 X 遇到困难,你能帮忙吗?\n\n答:\t\n> 不行,我需要亲手操作你的电脑才能帮你排错,去向当地的 Linux 用户组寻求方便的帮助(你可以在 这里 找到用户组列表)\n\n注意:如果安装问题与某 Linux 发行版有关,在针对 它 的邮件列表、论坛或本地用户组织中提问也许是恰当的。此时,应描述问题的准确细节。在此之前,先用 “linux”和 所有 被怀疑的硬件 [作关键词] 仔细搜索。\n\n问:\t\n> 我如何才能破解超级用户口令/盗取通道操作员的特权/查看某人的电子邮件?\n\n答:\t\n> 想做这种事情说明你是个卑劣的家伙,想让黑客教你做这种事情说明你是个白痴。\n\n#### 好问题与坏问题\n\n最后,我将通过举例来演示提问的智慧。同样的问题两种提法,一种愚蠢,另一种明智。\n\n愚蠢:我在哪能找到关于 Foonly Flurbamatic 设备的东西?\n> 这个问题在乞求得到 “搜搜该死的网络”(STFW) 式的回复。\n\n明智: 我用谷歌搜索过“Foonly Flurbamatic 2600”,但没有找到什么有用的,有谁知道在哪能找到这种设备的编程信息?\n> 这个人已经搜索过网络了,而且听起来他可能真的遇到了问题。\n\n愚蠢: 我不能编译某项目的源代码,它为什么这么破?\n> 提问者假设是别人搞砸了,太自大了。\n\n明智: 某项目的源代码不能在某 Linux 6.2 版下编译。我读了常见问题文档,但其中没有与某 Linux 相关的内容。这是编译时的记录,我做错了什么吗?\n> 提问者已经指明了运行环境,读了常见问题文档(FAQ),列出了错误,也没有假设问题是别人的过错,这家伙值得注意。\n\n愚蠢: 我的主板有问题,谁能帮我?\n> 某黑客对此的反应可能是:“是的,还需要帮你拍背和换尿布吗?”,然后是敲下删除键。\n\n明智: 我在 S2464 主板上试过 X、Y 和 Z,当它们都失败后,又试了 A、B 和 C。注意我试 C 时的奇怪症状,显然某某东西正在做某某事情,这不是期望的行为。通常在 Athlon MP 主板上导致某某事情的原因是什么?有谁知道我还能再试点什么以确定问题?\n> 相反地,这个人看来值得回答。他或她展现了解决问题的能力而不是坐等天上掉馅饼。\n\n在最后那个问题中,注意“给我一个回答”与“请帮我看看我还能再做点什么测试以得到启发”之间细微但重要的差别。\n\n事实上,最后那个问题基本上源于 2001 年 8 月 Linux 内核邮件列表(lkml)上的真实事件,是我(Eric)当时提了那个问题,我发现 Tyan S2462 主板有神秘的死机现象,邮件列表成员给我提供了解决此问题的关键信息。\n\n通过这种提问方式,我给了别人可以咀嚼玩味的东西。我设法使之对参与者既轻松又有吸引力,也表明了对同行能力的尊敬并邀请他们与我一起协商。通过告诉他们我已经走过的弯路,我还表明了对他们宝贵时间的尊重。\n\n事后,当我感谢大家并评论这次良好的经历时,一个 Linux 内核邮件列表的成员谈到,他认为我得到答案并不是因为我的名字挂在列表上,而只是因为我正确的提问方式。\n\n黑客们在某种方面是非常不留情面的精英分子。我想在这事上他是对的,如果我 表现得 象个不劳而获的寄生虫,不管我是谁都会被忽略或斥责。他建议将整个事件作为对其它人提问的指导,这直接导致了本文的编写。\n\n### 如果得不到回答\n\n如果得不到回答,请不要认为我们不想帮你,有时只是因为被问到的小组成员的确不知道答案。没有回复不等于不被理睬,当然必须承认从外面很难看出两者的差别。\n\n一般而言,直接将问题再张贴一次不好,这会被视为毫无意义的骚扰。耐心一点,知道你问题答案的人可能生活在不同的时区,有可能正在睡觉,也有可能你的问题一开始就没有组织好。\n\n还有其它资源可以寻求帮助,通常是在一些面向新手的资源中。\n\n有许多在线与本地的用户组织,虽然它们自己不编写任何软件,但是对软件很热心。这些用户组通常因互助和帮助新手而形成。\n\n还有众多大小商业公司提供签约支持服务,别因为要付点钱才有支持就感到沮丧!毕竟,如果你车子的汽缸垫烧了,你多半还得花钱找个修理店把它弄好。即使软件没花你一分钱,你总不能指望服务支持都是免费的。\n\n象 Linux 这样流行的软件,每个开发者至少有一万个以上的用户,一个人不可能应付这么多用户的服务要求。记住,即使你必须付费才能得到支持,也比你还得额外花钱买软件要少得多(而且对封闭源代码软件的服务支持与开源软件相比通常还要贵一点,也要差一点)。\n\n### 如何更好地回答\n\n态度和善一点。问题带来的压力常使人显得无礼或愚蠢,其实并不是这样。\n\n对初犯者私下回复。 对那些坦诚犯错之人没有必要当众羞辱,一个真正的新手也许连怎么搜索或在哪找 FAQ 都不知道。\n\n如果你不确定,一定要说出来! 一个听起来权威的错误回复比没有还要糟,别因为听起来象个专家好玩就给别人乱指路。要谦虚和诚实,给提问者与同行都树个好榜样。\n\n如果帮不了忙,别妨碍。 不要在具体步骤上开玩笑,那样也许会毁了用户的安装──有些可怜的呆瓜会把它当成真的指令。\n\n探索性的反问以引出更多的细节。 如果你做得好,提问者可以学到点东西──你也可以。试试将很差的问题转变成好问题,别忘了我们都曾是新手。\n\n尽管对那些懒虫报怨一声“读读该死的手册”(RTFM)是正当的,指出文档的位置(即使只是建议做个谷歌关键词搜索)会更好\n\n如果你决意回答,给出好的答案。 当别人正在用错误的工具或方法时别建议笨拙的权宜之计,应推荐更好的工具,重新组织问题。\n\n请回答真正的问题!如果提问者已经做了自己该做的研究,并且说明尝试过` X,Y,Z,A,B 与 C` 都没有得到想要的結果,那么回复 `试试 A 或 B` 或者给出一个内容为 `试一下 X,Y,Z,A,B 或 C` 的链接将极其无益!\n\n帮助你的社区从中学习。当回复一个好问题时,问问自己 `如何修改相关文件或 FAQ 文档以免再次解答同样的问题?`,接着再向文档维护者发一份补丁。\n\n如果你是在研究一番后才做出的回答,展现你的技巧而不是直接端出结果。毕竟“授人以鱼,不如授人以渔”。\n\n### 相关资源\n\n如果需要个人电脑、Unix 和互联网如何工作的基础知识,参阅 [Unix 和互联网工作的基本原理](http://en.tldp.org/HOWTO/Unix-and-Internet-Fundamentals-HOWTO/)。\n\n当你发布软件或补丁时,试着按 [软件发布实践](http://en.tldp.org/HOWTO/Software-Release-Practice-HOWTO/index.html) 操作。\n\n### 鸣谢\n\n伊夫林.米切尔(Evelyn Mitchell)贡献了一些愚蠢问题例子并启发了编写`如何更好地回答问题`这一节,米哈伊尔.罗门迪克(Mikhail Ramendik)贡献了一些特别有价值的建议和改进。\n\n","tags":["GitHub","转载","学习"],"categories":["转载"]},{"title":"03_转载-中文文案排版指北","url":"/posts/3e42a4ef.html","content":"\n\n原文:[https://github.com/sparanoid/chinese-copywriting-guidelines](https://github.com/sparanoid/chinese-copywriting-guidelines/blob/master/README.zh-Hans.md#%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%88%E6%8E%92%E7%89%88%E6%8C%87%E5%8C%97)\n\n\n统一中文文案、排版的相关用法,降低团队成员之间的沟通成本,增强网站气质。\n\n\n## 空格\n\n> 「有研究显示,打字的时候不喜欢在中文和英文之间加空格的人,感情路都走得很辛苦,有七成的比例会在 34 岁的时候跟自己不爱的人结婚,而其余三成的人最后只能把遗产留给自己的猫。毕竟爱情跟书写都需要适时地留白。\n>\n> 与大家共勉之。」——[vinta/paranoid-auto-spacing](https://github.com/vinta/pangu.js)\n\n### 中英文之间需要增加空格\n\n正确:\n\n> 在 LeanCloud 上,数据存储是围绕 `AVObject` 进行的。\n\n错误:\n\n> 在LeanCloud上,数据存储是围绕`AVObject`进行的。\n>\n> 在 LeanCloud上,数据存储是围绕`AVObject` 进行的。\n\n完整的正确用法:\n\n> 在 LeanCloud 上,数据存储是围绕 `AVObject` 进行的。每个 `AVObject` 都包含了与 JSON 兼容的 key-value 对应的数据。数据是 schema-free 的,你不需要在每个 `AVObject` 上提前指定存在哪些键,只要直接设定对应的 key-value 即可。\n\n例外:「豆瓣FM」等产品名词,按照官方所定义的格式书写。\n\n### 中文与数字之间需要增加空格\n\n正确:\n\n> 今天出去买菜花了 5000 元。\n\n错误:\n\n> 今天出去买菜花了 5000元。\n>\n> 今天出去买菜花了5000元。\n\n### 数字与单位之间需要增加空格\n\n正确:\n\n> 我家的光纤入屋宽带有 10 Gbps,SSD 一共有 20 TB\n\n错误:\n\n> 我家的光纤入屋宽带有 10Gbps,SSD 一共有 20TB\n\n例外:度数/百分比与数字之间不需要增加空格:\n\n正确:\n\n> 角度为 90° 的角,就是直角。\n>\n> 新 MacBook Pro 有 15% 的 CPU 性能提升。\n\n错误:\n\n> 角度为 90 ° 的角,就是直角。\n>\n> 新 MacBook Pro 有 15 % 的 CPU 性能提升。\n\n### 全角标点与其他字符之间不加空格\n\n正确:\n\n> 刚刚买了一部 iPhone,好开心!\n\n错误:\n\n> 刚刚买了一部 iPhone ,好开心!\n>\n> 刚刚买了一部 iPhone, 好开心!\n\n### 用 `text-spacing` 来挽救?\n\nCSS Text Module Level 4 的 [`text-spacing`](https://www.w3.org/TR/css-text-4/#text-spacing-property) 和 Microsoft 的 [`-ms-text-autospace`](https://msdn.microsoft.com/library/ms531164(v=vs.85).aspx) 可以实现自动为中英文之间增加空白。不过目前并未普及,另外在其他应用场景,例如 macOS、iOS、Windows 等用户界面目前并不存在这个特性,所以请继续保持随手加空格的习惯。\n\n## 标点符号\n\n### 不重复使用标点符号\n\n虽然中国大陆的标点符号用法允许重复使用标点符号,但是这么做会破坏句子的美观性。\n\n正确:\n\n> 德国队竟然战胜了巴西队!\n>\n> 她竟然对你说「喵」?!\n\n错误:\n\n> 德国队竟然战胜了巴西队!!\n>\n> 德国队竟然战胜了巴西队!!!!!!!!\n>\n> 她竟然对你说「喵」??!!\n>\n> 她竟然对你说「喵」?!?!??!!\n\n## 全角和半角\n\n不明白什么是全角(全形)与半角(半形)符号?请查看维基百科条目『[全角和半角](https://zh.wikipedia.org/wiki/%E5%85%A8%E5%BD%A2%E5%92%8C%E5%8D%8A%E5%BD%A2)』。\n\n### 使用全角中文标点\n\n正确:\n\n> 嗨!你知道嘛?今天前台的小妹跟我说「喵」了哎!\n>\n> 核磁共振成像(NMRI)是什么原理都不知道?JFGI!\n\n错误:\n\n> 嗨! 你知道嘛? 今天前台的小妹跟我说 \"喵\" 了哎!\n>\n> 嗨!你知道嘛?今天前台的小妹跟我说\"喵\"了哎!\n>\n> 核磁共振成像 (NMRI) 是什么原理都不知道? JFGI!\n>\n> 核磁共振成像(NMRI)是什么原理都不知道?JFGI!\n\n例外:中文句子内夹有英文书籍名、报刊名时,不应借用中文书名号,应以英文斜体表示。\n\n### 数字使用半角字符\n\n正确:\n\n> 这个蛋糕只卖 1000 元。\n\n错误:\n\n> 这个蛋糕只卖 1000 元。\n\n例外:在设计稿、宣传海报中如出现极少量数字的情形时,为方便文字对齐,是可以使用全角数字的。\n\n### 遇到完整的英文整句、特殊名词,其内容使用半角标点\n\n正确:\n\n> 乔布斯那句话是怎么说的?「Stay hungry, stay foolish.」\n>\n> 推荐你阅读 *Hackers & Painters: Big Ideas from the Computer Age*,非常地有趣。\n\n错误:\n\n> 乔布斯那句话是怎么说的?「Stay hungry,stay foolish。」\n>\n> 推荐你阅读《Hackers&Painters:Big Ideas from the Computer Age》,非常的有趣。\n\n## 名词\n\n### 专有名词使用正确的大小写\n\n大小写相关用法原属于英文书写范畴,不属于本 wiki 讨论内容,在这里只对部分易错用法进行简述。\n\n正确:\n\n> 使用 GitHub 登录\n>\n> 我们的客户有 GitHub、Foursquare、Microsoft Corporation、Google、Facebook, Inc.。\n\n错误:\n\n> 使用 github 登录\n>\n> 使用 GITHUB 登录\n>\n> 使用 Github 登录\n>\n> 使用 gitHub 登录\n>\n> 使用 gイんĤЦ8 登录\n>\n> 我们的客户有 github、foursquare、microsoft corporation、google、facebook, inc.。\n>\n> 我们的客户有 GITHUB、FOURSQUARE、MICROSOFT CORPORATION、GOOGLE、FACEBOOK, INC.。\n>\n> 我们的客户有 Github、FourSquare、MicroSoft Corporation、Google、FaceBook, Inc.。\n>\n> 我们的客户有 gitHub、fourSquare、microSoft Corporation、google、faceBook, Inc.。\n>\n> 我们的客户有 gイんĤЦ8、キouЯƧquムгє、๓เςг๏ร๏Ŧt ς๏гק๏гคtเ๏ภn、900913、ƒ4ᄃëв๏๏к, IПᄃ.。\n\n注意:当网页中需要配合整体视觉风格而出现全部大写/小写的情形,HTML 中请使用标淮的大小写规范进行书写;并通过 `text-transform: uppercase;`/`text-transform: lowercase;` 对表现形式进行定义。\n\n### 不要使用不地道的缩写\n\n正确:\n\n> 我们需要一位熟悉 TypeScript、HTML5,至少理解一种框架(如 React、Next.js)的前端开发者。\n\n错误:\n\n> 我们需要一位熟悉 Ts、h5,至少理解一种框架(如 RJS、nextjs)的 FED。\n\n## 争议\n\n以下用法略带有个人色彩,即:无论是否遵循下述规则,从语法的角度来讲都是**正确**的。\n\n### 链接之间增加空格\n\n用法:\n\n> 请 [提交一个 issue](#) 并分配给相关同事。\n>\n> 访问我们网站的最新动态,请 [点击这里](#) 进行订阅!\n\n对比用法:\n\n> 请[提交一个 issue](#)并分配给相关同事。\n>\n> 访问我们网站的最新动态,请[点击这里](#)进行订阅!\n\n### 简体中文使用直角引号\n\n用法:\n\n> 「老师,『有条不紊』的『紊』是什么意思?」\n\n对比用法:\n\n> “老师,‘有条不紊’的‘紊’是什么意思?”\n\n## 工具\n\n仓库 | 系列 | 语言\n--- | ---- | ---\n[pangu.js](https://github.com/vinta/pangu.js) | pangu | JavaScript\n[pangu-go](https://github.com/vinta/pangu) | pangu | Go\n[pangu.java](https://github.com/vinta/pangu.java) | pangu | Java\n[pangu.py](https://github.com/vinta/pangu.py) | pangu | Python\n[pangu.rb](https://github.com/dlackty/pangu.rb) | pangu | Ruby\n[pangu.php](https://github.com/cchlorine/pangu.php) | pangu | PHP\n[pangu.vim](https://github.com/hotoo/pangu.vim) | pangu | Vim\n[vue-pangu](https://github.com/serkodev/vue-pangu) | pangu | Vue.js (Web Converter)\n[intellij-pangu](https://plugins.jetbrains.com/plugin/19665-pangu) | pangu | Intellij Platform Plugin\n[autocorrect](https://github.com/huacnlee/autocorrect) | autocorrect | Rust, WASM, CLI tool\n[autocorrect-node](https://github.com/huacnlee/autocorrect/tree/main/autocorrect-node) | autocorrect | Node.js\n[autocorrect-py](https://github.com/huacnlee/autocorrect/tree/main/autocorrect-py) | autocorrect | Python\n[autocorrect-rb](https://github.com/huacnlee/autocorrect/tree/main/autocorrect-rb) | autocorrect | Ruby\n[autocorrect-java](https://github.com/huacnlee/autocorrect/tree/main/autocorrect-java) | autocorrect | Java\n[autocorrect-go](https://github.com/longbridgeapp/autocorrect) | autocorrect | Go\n[autocorrect-php](https://github.com/NauxLiu/auto-correct) | autocorrect | PHP\n[autocorrect-vscode](https://marketplace.visualstudio.com/items?itemName=huacnlee.autocorrect) | autocorrect | VS Code Extension\n[autocorrect-idea-plugin](https://plugins.jetbrains.com/plugin/20244-autocorrect) | autocorrect | Intellij Platform Plugin\n[jxlwqq/chinese-typesetting](https://github.com/jxlwqq/chinese-typesetting) | other | PHP\n[sparanoid/space-lover](https://github.com/sparanoid/space-lover) | other | PHP (WordPress)\n[sparanoid/grunt-auto-spacing](https://github.com/sparanoid/grunt-auto-spacing) | other | Node.js (Grunt)\n[hjiang/scripts/add-space-between-latin-and-cjk](https://github.com/hjiang/scripts/blob/master/add-space-between-latin-and-cjk) | other | Python\n[hustcc/hint](https://github.com/hustcc/hint) | other | Python\n[n0vad3v/Tekorrect](https://github.com/n0vad3v/Tekorrect) | other | Python\n\n## 谁在这样做?\n\n网站 | 文案 | UGC\n--- | --- | ---\n[Apple 中国](https://www.apple.com/cn/) | 是 | N/A\n[Apple 香港](https://www.apple.com/hk/) | 是 | N/A\n[Apple 台湾](https://www.apple.com/tw/) | 是 | N/A\n[Microsoft 中国](https://www.microsoft.com/zh-cn/) | 是 | N/A\n[Microsoft 香港](https://www.microsoft.com/zh-hk/) | 是 | N/A\n[Microsoft 台湾](https://www.microsoft.com/zh-tw/) | 是 | N/A\n[LeanCloud](https://leancloud.cn/) | 是 | N/A\n[V2EX](https://www.v2ex.com/) | 是 | 是\n[Apple4us](https://apple4us.com/) | 是 | N/A\n[Ruby China](https://ruby-china.org/) | 是 | 是\n[少数派](https://sspai.com/) | 是 | N/A\n\n## 参考文献\n\n- [Guidelines for Using Capital Letters - ThoughtCo.](https://www.thoughtco.com/guidelines-for-using-capital-letters-1691724)\n- [Letter case - Wikipedia](https://en.wikipedia.org/wiki/Letter_case)\n- [Punctuation - Oxford Dictionaries](https://en.oxforddictionaries.com/grammar/punctuation)\n- [Punctuation - The Purdue OWL](https://owl.english.purdue.edu/owl/section/1/6/)\n- [How to Use English Punctuation Correctly - wikiHow](https://www.wikihow.com/Use-English-Punctuation-Correctly)\n- [格式 - openSUSE](https://zh.opensuse.org/index.php?title=Help:%E6%A0%BC%E5%BC%8F)\n- [全形和半形 - 维基百科](https://zh.wikipedia.org/wiki/%E5%85%A8%E5%BD%A2%E5%92%8C%E5%8D%8A%E5%BD%A2)\n- [引号 - 维基百科](https://zh.wikipedia.org/wiki/%E5%BC%95%E8%99%9F)\n- [疑问惊叹号 - 维基百科](https://zh.wikipedia.org/wiki/%E7%96%91%E5%95%8F%E9%A9%9A%E5%98%86%E8%99%9F)\n\n## Forks\n\n衍生项目的用法可能与本项目存在差异。\n\n- [mzlogin/chinese-copywriting-guidelines](https://github.com/mzlogin/chinese-copywriting-guidelines)\n","tags":["GitHub","转载","学习"],"categories":["转载"]},{"title":"11_Hexo-GitHub Actions 自动部署博客","url":"/posts/8b765f7a.html","content":"\n\n\n简单记录,步骤潦草\n\n## 示例\n\n### 1. .gitignore\n\n根路径 `.gitignore` 内容\n\n```x86asm\n.DS_Store\n#/Thumbs.db\n/db.json\n*.log\nnode_modules/\npublic/\n.deploy*/\n.deploy_git/\n.deploy_git*/\n.idea\nthemes/butterfly/.git\n```\n\n\n\n### 2. workflows\n\n根路径 `.github/workflows/autodeploy.yml` 内容\n\n```yaml\nname: Auto deploy\n# 当有改动推送到master分支时,启动Action\non:\n workflow_dispatch:\n push:\n branches:\n - main\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n steps:\n - name: 检查分支\n uses: actions/checkout@v2\n with:\n ref: main\n\n - uses: szenius/set-timezone@v1.0 # 设置执行环境的时区\n with:\n timezoneLinux: \"Asia/Shanghai\"\n\n - name: 安装 Node\n uses: actions/setup-node@v1\n with:\n node-version: \"18.x\"\n\n - name: 安装 Hexo\n run: |\n export TZ='Asia/Shanghai'\n npm install hexo-cli -g\n\n - name: 缓存 Hexo\n uses: actions/cache@v1\n id: cache\n with:\n path: node_modules\n key: ${{runner.OS}}-${{hashFiles('**/package-lock.json')}}\n\n - name: 安装依赖\n if: steps.cache.outputs.cache-hit != 'true'\n run: |\n npm install gulp-cli -g #全局安装gulp\n npm install --save\n\n - name: Generate static file\n run: |\n hexo clean ; hexo generate ; gulp\n\n - name: 推送百度 url\n run: |\n hexo deploy\n\n - name: Deploy static file\n run: |\n cd ./public\n git init\n git config --global user.email 'github-actions[bot]@users.noreply.github.com'\n git config --global user.name 'github-actions[bot]'\n git add .\n git commit -m \"$(date +'%Y/%m/%d')\"\n git push --force --quiet \"https://mycpen:${{ secrets.GH_TOKEN }}@github.com/mycpen/blog.git\" master:main\n\n - name: Delete workflow runs\n uses: Mattraks/delete-workflow-runs@v2\n with:\n token: ${{ secrets.GH_TOKEN }}\n repository: ${{ github.repository }}\n retain_days: 30\n keep_minimum_runs: 6\n\n```\n\nActions Secrets 变量含义\n\n| Secrets 变量 | 释义 |\n| :----------- | :------------------------------------------------- |\n| GH_TOKEN | [GitHub Token](https://github.com/settings/tokens) |\n\n\n\n### 3. 插件\n\nhexo-baidu-url-submit:https://github.com/huiwang/hexo-baidu-url-submit\n\n根路径 `_config.yml` 配置文件\n\n```yaml\n# Deployment\n## Docs: https://hexo.io/docs/one-command-deployment\ndeploy:\n - type: baidu_url_submitter # 这是新加的百度主动推送\n\n# 百度主动推送\n# https://github.com/huiwang/hexo-baidu-url-submit\nbaidu_url_submit:\n count: 1000 # 提交最新的多少个链接\n host: blog.xxx.com # 在百度站长平台中添加的域名\n token: xxxxxx # 秘钥\n path: baidu_urls.txt # 文本文档的地址, 新链接会保存在此文本文档里\n```\n\n\n\n## 参考\n\n1. [Akilar | 使用Github Action实现全自动部署](https://akilar.top/posts/f752c86d/)\n2. [安知鱼 | hexo博客工作流CI(一键部署的快乐)](https://blog.anheyu.com/posts/b228.html)\n3. [CCKNBC | 工作流示例](https://github.com/ccknbc-actions/blog-butterfly/tree/master/.github/workflows)\n4. https://github.com/Mattraks/delete-workflow-runs\n5. https://github.com/dmego/home.github.io/blob/gh-pages/.github/workflows/auto-bing.yml\n","tags":["Hexo","GitHub"],"categories":["Hexo"]},{"title":"10_Hexo-GitHub Actions 自动刷新多吉云 CDN 缓存","url":"/posts/6f7759e0.html","content":"\n\n\n## 前言\n\n之前一直通过 [多吉云控制台](https://console.dogecloud.com/cdn/refresh) 手动刷新博客全站 CDN 缓存,CDN 源站为 Vercel 部署的网址\n\n由 [空梦:全自动博客部署方案](https://kmar.top/posts/a427ed12/) 这篇文章萌生了自动化的念头,且这些 CDN 服务商都提供了相应的 API 文档和代码样例,开箱即用\n\n~~仓库示例:[https://github.com/mycpen/blog/tree/main/.github](https://github.com/mycpen/blog/tree/main/.github)~~\n\n\n\n## 个人示例\n\n### 1. 新增 Workflow 文件\n\n以我为例,新增 `source/.github/workflows/refresh-dogecloud.yml` 文件,内容如下:\n\n```yaml\n# This workflow will install Python dependencies, run tests and lint with a single version of Python\n# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python\n\nname: Refresh dogecloud CDN\n\non:\n push:\n branches:\n - main\n workflow_dispatch:\n\njobs:\n build:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v3\n - uses: szenius/set-timezone@v1.0 # 设置执行环境的时区\n with:\n timezoneLinux: \"Asia/Shanghai\"\n - name: Set up Python 3.10\n uses: actions/setup-python@v3\n with:\n python-version: \"3.10\"\n - name: Wait for 3 minutes\n run: sleep 180 # 等待 3 分钟,单位为秒\n - name: Run refresh script\n env:\n ACCESS_KEY: ${{ secrets.ACCESS_KEY }}\n SECRET_KEY: ${{ secrets.SECRET_KEY }}\n run: |\n pip install requests\n python .github/refresh-dogecloud.py\n\n```\n\n\n\n### 2. 新增 PY 脚本:刷新缓存\n\n以我为例,新增 `source/.github/refresh-dogecloud.py` 文件,内容如下:\n\n脚本里的 `url_list` 为需要刷新的目录,需手动修改为自己的。代码来自多吉云 [API 验证](https://docs.dogecloud.com/cdn/api-access-token?id=python)、[刷新目录任务](https://docs.dogecloud.com/cdn/sdk-full-python?id=%e5%88%9b%e5%bb%ba%e5%88%b7%e6%96%b0%e7%9b%ae%e5%bd%95%e4%bb%bb%e5%8a%a1)\n\n\n\n```python\nfrom hashlib import sha1\nimport hmac\nimport requests\nimport json\nimport urllib\nimport os\n\ndef dogecloud_api(api_path, data={}, json_mode=False):\n \"\"\"\n 调用多吉云API\n\n :param api_path: 调用的 API 接口地址,包含 URL 请求参数 QueryString,例如:/console/vfetch/add.json?url=xxx&a=1&b=2\n :param data: POST 的数据,字典,例如 {'a': 1, 'b': 2},传递此参数表示不是 GET 请求而是 POST 请求\n :param json_mode: 数据 data 是否以 JSON 格式请求,默认为 false 则使用表单形式(a=1&b=2)\n\n :type api_path: string\n :type data: dict\n :type json_mode bool\n\n :return dict: 返回的数据\n \"\"\"\n\n # 这里替换为你的多吉云永久 AccessKey 和 SecretKey,可在用户中心 - 密钥管理中查看\n # 请勿在客户端暴露 AccessKey 和 SecretKey,否则恶意用户将获得账号完全控制权\n access_key = os.environ[\"ACCESS_KEY\"]\n secret_key = os.environ[\"SECRET_KEY\"]\n\n body = ''\n mime = ''\n if json_mode:\n body = json.dumps(data)\n mime = 'application/json'\n else:\n body = urllib.parse.urlencode(data) # Python 2 可以直接用 urllib.urlencode\n mime = 'application/x-www-form-urlencoded'\n sign_str = api_path + \"\\n\" + body\n signed_data = hmac.new(secret_key.encode('utf-8'), sign_str.encode('utf-8'), sha1)\n sign = signed_data.digest().hex()\n authorization = 'TOKEN ' + access_key + ':' + sign\n response = requests.post('https://api.dogecloud.com' + api_path, data=body, headers = {\n 'Authorization': authorization,\n 'Content-Type': mime\n })\n return response.json()\n\n\nurl_list = [\n \"https://cpen.top/\",\n]\n\napi = dogecloud_api('/cdn/refresh/add.json', {\n 'rtype': 'path',\n 'urls': json.dumps(url_list)\n})\nif api['code'] == 200:\n print(api['data']['task_id'])\nelse:\n print(\"api failed: \" + api['msg']) # 失败\n\n```\n\n\n\n### 3. 新增 Secrets 变量\n\nActions 新增 2 个 Secrets 变量,`ACCESS_KEY`、`SECRET_KEY`,对应的值在 多吉云 [用户中心 - 密钥管理](https://console.dogecloud.com/user/keys) 中查看。[link](https://docs.dogecloud.com/cdn/api-access-token?id=python)\n\n\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202305022253516.png\" alt=\"image-20230502225346425\" style=\"zoom: 33%;\" />\n\n\n\n避免因权限问题导致工作流执行失败,也可以设置下 Actions 读写权限\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202305022259686.png\" alt=\"image-20230502225900571\" style=\"zoom: 33%;\" />\n\n\n\n### 4. 新增 JS 代码:复制 .github\n\n前言:`source/.github` 这类 . 开头的隐藏文件默认是不会被 hexo generate 渲染生成到 public 目录下的。网上和 ChatGPT 给出的解决办法大多试了(如 `skip_render`),没有生效,打算直接用 JS 代码将 `source/.github` 目录复制到 `public/.github` 目录下。以下代码每次 hexo generate 之后能实现复制的效果\n\n以我为例,新增 `scripts/before_generate.js` 文件,内容如下:\n\n```javascript\nconst fs = require('fs-extra');\nconst path = require('path');\n\nfunction copyFolder(source, target) {\n // Create the target folder if it doesn't exist\n fs.ensureDirSync(target);\n\n // Get the list of files in the source folder\n const files = fs.readdirSync(source);\n\n // Loop through each file and copy it to the target folder\n files.forEach((file) => {\n const sourcePath = path.join(source, file);\n const targetPath = path.join(target, file);\n\n if (fs.statSync(sourcePath).isDirectory()) {\n // Recursively copy subfolders\n copyFolder(sourcePath, targetPath);\n } else {\n // Copy the file\n fs.copyFileSync(sourcePath, targetPath);\n }\n });\n}\n\ncopyFolder('./source/.github', './public/.github');\n\n```\n\n\n\n### 5. 更新 _config.yml 配置\n\n> 当 hexo deploy 将渲染后的静态仓库推送到 Github 时,默认会取消推送 . 开头的隐藏文件,具体如下:\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202305022249331.png\" alt=\"image-20230502224949276\" style=\"zoom: 67%;\" />\n\n\n\n在 Hexo 配置文件 `_config.yml` 进行修改,新增 git 部署器 `ignore_hidden` 配置项,样例如下:\n\n```diff\n# Deployment\n## Docs: https://hexo.io/docs/one-command-deployment\ndeploy:\n - type: git\n repository: git@github.com:mycpen/blog.git\n branch: main\n commit: Site updated\n message: \"{{ now('YYYY/MM/DD') }}\"\n+ ignore_hidden: false\n\n```\n\n\n\n## 参考链接\n\n1. [多吉云:API 验证机制(Python)](https://docs.dogecloud.com/cdn/api-access-token?id=python)\n2. [多吉云:SDK 文档 - 刷新预热](https://docs.dogecloud.com/cdn/sdk-full-python?id=%e5%88%9b%e5%bb%ba%e5%88%b7%e6%96%b0%e7%9b%ae%e5%bd%95%e4%bb%bb%e5%8a%a1)\n3. ChatGPT(deploy.ignore_hidden、js 代码 复制目录、sleep)\n\n\n\n\n\n","tags":["Hexo","GitHub"],"categories":["Hexo"]},{"title":"08_Other-GitHub Actions 定时执行脚本,备份又拍云云存储","url":"/posts/acb8c062.html","content":"\n## 前言\n\n使用 GitHub Acitons,定时跑 Python FTP 脚本,达到 [又拍云云存储](https://help.upyun.com/knowledge-base/object_storage_index/) 与 GitHub 仓库间的备份\n\n仓库示例:https://github.com/mycpen/image_bed/tree/main/.github\n\n\n\n## 个人示例\n\n### 1. 新增 Workflow YML 文件\n\n复制以下我的 yml 示例;或是按照 [这篇文章](https://blog.csdn.net/weixin_44786530/article/details/127890033),选择想要的 workflow 模板,再自定义修改内容(Actions => New workflow = Choose a workflow)\n\n我的文件路径为 `.github/workflows/python-app.yml`,内容如下:\n\n\n\n```yaml\n# This workflow will install Python dependencies, run tests and lint with a single version of Python\n# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python\n\nname: Python application\n\non:\n schedule:\n - cron: \"0 17 * * 5\" # 周六 1:00\n workflow_dispatch:\n\njobs:\n build:\n\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v3\n - uses: szenius/set-timezone@v1.0 # 设置执行环境的时区\n with:\n timezoneLinux: \"Asia/Shanghai\"\n - name: Set up Python 3.10\n uses: actions/setup-python@v3\n with:\n python-version: \"3.10\"\n - name: Run sync script\n env:\n UPYUNUSERNAME: ${{ secrets.UPYUNUSERNAME }}\n UPYUNPASSWORD: ${{ secrets.UPYUNPASSWORD }}\n run: |\n git config --global user.name ${{ secrets.GITHUBUSERNAME }}\n git config --global user.email ${{ secrets.GITHUBEMAIL }}\n python .github/ftp.py\n bash git.sh\n\n```\n\n\n\n参数解释:\n\n- `cron`:定义工作流的时间表(有延迟),为格林尼治时间(UTC),换算为北京时间需在该基础上增加 8 小时,参考:[Actions 中的 cron 格式和设置](http://blog.ynxiu.com/aixiu/f9ec3873.html)、[Actions 时区及缓存问题处理](https://blog.csdn.net/u010214511/article/details/127079323)\n\n- `UPYUNUSERNAME`, `UPYUNPASSWORD`, `GITHUBUSERNAME`, `GITHUBEMAIL`,为自定义的 Secrets 变量\n \n | 变量名 | 释义 |\n | -------------- | ------------------------------------------------------------ |\n | UPYUNUSERNAME | 又拍云 FTP 用户名,格式「操作员名/服务名」,参考 [又拍云视频教程](https://techs.upyun.com/videos/cdnpage/creating_storage.html)、[又拍云文档](https://help.upyun.com/2015/12/28/%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-ftp%e3%80%81api-%e4%b8%8a%e4%bc%a0%e6%96%87%e4%bb%b6/) |\n | UPYUNPASSWORD | 又拍云 FTP 密码,参考同上 |\n | GITHUBUSERNAME | GitHub 账号,如 mycpen |\n | GITHUBEMAIL | GitHub 账号绑定的主邮箱 |\n \n- `ftp.py`:Python 脚本,使用 FTP 同步云存储与仓库的文件内容\n\n- `git.sh`:将本地变更推送至远端的脚本,git add, git commit, git push 这类\n\n\n\n### 2. 新增 Secrets 变量\n\n新增 4 个 Secrets 变量,UPYUNUSERNAME、UPYUNPASSWORD、GITHUBUSERNAME、GITHUBEMAIL,具体含义同上\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304170942576.png\" alt=\"image-20230417094207479\" style=\"zoom: 33%;\" />\n\n\n\n### 3. 授予 Workflow 读写权限\n\n参考:https://blog.csdn.net/jj89929665/article/details/129817011\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304170956642.png\" alt=\"image-20230417095659542\" style=\"zoom:33%;\" />\n\n\n\n### 4. 新建 Python 同步脚本\n\n脚本内容来自:[Python实现的FTP上传和下载功能](https://blog.csdn.net/ouyang_peng/article/details/79271113)\n\n脚本最后的 if 语句中声明了相关路径和参数\n\n我的脚本路径为 `.github/ftp.py`,作用是同步仓库 image/ 目录与又拍云云存储 /image/ 目录,内容如下:\n\n```python\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\n\n\nfrom cmath import log\nfrom ftplib import FTP\nimport os\nimport sys\nimport time\nimport socket\nimport subprocess\n\nclass MyFTP:\n \"\"\"\n ftp自动下载、自动上传脚本,可以递归目录操作\n 作者:欧阳鹏\n 博客地址:http://blog.csdn.net/ouyang_peng/article/details/79271113\n \"\"\"\n\n def __init__(self, host, port=21):\n \"\"\" 初始化 FTP 客户端\n 参数:\n host:ip地址\n\n port:端口号\n \"\"\"\n # print(\"__init__()---> host = %s ,port = %s\" % (host, port))\n\n self.host = host\n self.port = port\n self.ftp = FTP()\n # 重新设置下编码方式\n #self.ftp.encoding = 'gbk'\n self.ftp.encoding = 'utf8'\n # 获取脚本路径\n path = os.path.dirname(os.path.realpath(__file__))\n # self.log_file = open(path + \"/log.txt\", \"a\", encoding='utf-8')\n self.file_list = []\n\n def login(self, username, password):\n \"\"\" 初始化 FTP 客户端\n 参数:\n username: 用户名\n\n password: 密码\n \"\"\"\n try:\n timeout = 60\n socket.setdefaulttimeout(timeout)\n # 0主动模式 1 #被动模式\n self.ftp.set_pasv(True)\n # 打开调试级别2,显示详细信息\n # self.ftp.set_debuglevel(2)\n\n self.debug_print('开始尝试连接到 %s' % self.host)\n self.ftp.connect(self.host, self.port)\n self.debug_print('成功连接到 %s' % self.host)\n\n self.debug_print('开始尝试登录到 %s' % self.host)\n self.ftp.login(username, password)\n self.debug_print('成功登录到 %s' % self.host)\n\n self.debug_print(self.ftp.welcome)\n except Exception as err:\n self.deal_error(\"FTP 连接或登录失败 ,错误描述为:%s\" % err)\n pass\n\n def is_same_size(self, local_file, remote_file):\n \"\"\"判断远程文件和本地文件大小是否一致\n\n 参数:\n local_file: 本地文件\n\n remote_file: 远程文件\n \"\"\"\n try:\n remote_file_size = self.ftp.size(remote_file)\n except Exception as err:\n # self.debug_print(\"is_same_size() 错误描述为:%s\" % err)\n remote_file_size = -1\n\n try:\n local_file_size = os.path.getsize(local_file)\n except Exception as err:\n # self.debug_print(\"is_same_size() 错误描述为:%s\" % err)\n local_file_size = -1\n\n self.debug_print('local_file_size:%d , remote_file_size:%d' % (local_file_size, remote_file_size))\n if remote_file_size == local_file_size:\n return 1\n else:\n return 0\n\n def download_file(self, local_file, remote_file):\n \"\"\"从ftp下载文件\n 参数:\n local_file: 本地文件\n\n remote_file: 远程文件\n \"\"\"\n self.debug_print(\"download_file()---> local_path = %s ,remote_path = %s\" % (local_file, remote_file))\n\n if self.is_same_size(local_file, remote_file):\n self.debug_print('%s 文件大小相同,无需下载' % local_file)\n return\n else:\n try:\n self.debug_print('>>>>>>>>>>>>下载文件 %s ... ...' % local_file)\n buf_size = 1024\n file_handler = open(local_file, 'wb')\n self.ftp.retrbinary('RETR %s' % remote_file, file_handler.write, buf_size)\n file_handler.close()\n except Exception as err:\n self.debug_print('下载文件出错,出现异常:%s ' % err)\n return\n\n def download_file_tree(self, local_path, remote_path):\n \"\"\"从远程目录下载多个文件到本地目录\n 参数:\n local_path: 本地路径\n\n remote_path: 远程路径\n \"\"\"\n print(\"download_file_tree()---> local_path = %s ,remote_path = %s\" % (local_path, remote_path))\n try:\n self.ftp.cwd(remote_path)\n except Exception as err:\n self.debug_print('远程目录%s不存在,继续...' % remote_path + \" ,具体错误描述为:%s\" % err)\n return\n\n if not os.path.isdir(local_path):\n self.debug_print('本地目录%s不存在,先创建本地目录' % local_path)\n os.makedirs(local_path)\n\n self.debug_print('切换至目录: %s' % self.ftp.pwd())\n\n self.file_list = []\n # 方法回调\n self.ftp.dir(self.get_file_list)\n\n remote_names = self.file_list\n self.debug_print('远程目录 列表: %s' % remote_names)\n for item in remote_names:\n file_type = item[0]\n file_name = item[1]\n local = os.path.join(local_path, file_name)\n if file_type == 'd':\n print(\"download_file_tree()---> 下载目录: %s\" % file_name)\n self.download_file_tree(local, file_name)\n elif file_type == '-':\n print(\"download_file()---> 下载文件: %s\" % file_name)\n self.download_file(local, file_name)\n self.ftp.cwd(\"..\")\n self.debug_print('返回上层目录 %s' % self.ftp.pwd())\n return True\n\n def upload_file(self, local_file, remote_file):\n \"\"\"从本地上传文件到ftp\n\n 参数:\n local_path: 本地文件\n\n remote_path: 远程文件\n \"\"\"\n if not os.path.isfile(local_file):\n self.debug_print('%s 不存在' % local_file)\n return\n\n if self.is_same_size(local_file, remote_file):\n self.debug_print('跳过相等的文件: %s' % local_file)\n return\n\n buf_size = 1024\n file_handler = open(local_file, 'rb')\n self.ftp.storbinary('STOR %s' % remote_file, file_handler, buf_size)\n file_handler.close()\n self.debug_print('上传: %s' % local_file + \"成功!\")\n\n def upload_file_tree(self, local_path, remote_path):\n \"\"\"从本地上传目录下多个文件到ftp\n 参数:\n\n local_path: 本地路径\n\n remote_path: 远程路径\n \"\"\"\n if not os.path.isdir(local_path):\n self.debug_print('本地目录 %s 不存在' % local_path)\n return\n\n self.ftp.cwd(remote_path)\n self.debug_print('切换至远程目录: %s' % self.ftp.pwd())\n\n local_name_list = os.listdir(local_path)\n for local_name in local_name_list:\n src = os.path.join(local_path, local_name)\n if os.path.isdir(src):\n try:\n self.ftp.mkd(local_name)\n except Exception as err:\n self.debug_print(\"目录已存在 %s ,具体错误描述为:%s\" % (local_name, err))\n self.debug_print(\"upload_file_tree()---> 上传目录: %s\" % local_name)\n self.upload_file_tree(src, local_name)\n else:\n self.debug_print(\"upload_file_tree()---> 上传文件: %s\" % local_name)\n self.upload_file(src, local_name)\n self.ftp.cwd(\"..\")\n\n def close(self):\n \"\"\" 退出ftp\n \"\"\"\n self.debug_print(\"close()---> FTP退出\")\n self.ftp.quit()\n # self.log_file.close()\n\n def debug_print(self, s):\n \"\"\" 打印日志\n \"\"\"\n self.write_log(s)\n\n def deal_error(self, e):\n \"\"\" 处理错误异常\n 参数:\n e:异常\n \"\"\"\n log_str = '发生错误: %s' % e\n self.write_log(log_str)\n sys.exit()\n\n def write_log(self, log_str):\n \"\"\" 记录日志\n 参数:\n log_str:日志\n \"\"\"\n time_now = time.localtime()\n date_now = time.strftime('%Y-%m-%d', time_now)\n format_log_str = \"%s ---> %s \\n \" % (date_now, log_str)\n print(format_log_str)\n # self.log_file.write(format_log_str)\n\n def get_file_list(self, line):\n \"\"\" 获取文件列表\n 参数:\n line:\n \"\"\"\n file_arr = self.get_file_name(line)\n # 去除 . 和 ..\n if file_arr[1] not in ['.', '..']:\n self.file_list.append(file_arr)\n\n def get_file_name(self, line):\n \"\"\" 获取文件名\n 参数:\n line:\n \"\"\"\n pos = line.rfind(':')\n while (line[pos] != ' '):\n pos += 1\n while (line[pos] == ' '):\n pos += 1\n file_arr = [line[0], line[pos:]]\n return file_arr\n\n\nif __name__ == \"__main__\":\n # 清除日志\n path = os.path.dirname(os.path.realpath(__file__)) # 脚本路径\n # if os.path.exists(path + '/log.txt'):\n # log_file = path + '/log.txt 'if os.sep == \"/\" else path + '\\\\' + 'log.txt'\n # subprocess.Popen(f'rm -rf {log_file}', shell=True)\n # time.sleep(1)\n\n # 获取 Actions Secrets 变量\n upyunUsername = os.environ[\"UPYUNUSERNAME\"]\n upyunPassword = os.environ[\"UPYUNPASSWORD\"]\n\n my_ftp = MyFTP(\"v0.ftp.upyun.com\")\n my_ftp.login(upyunUsername, upyunPassword)\n\n # 下载目录\n # 又拍云云存储 → 本地 image/\n if os.sep == \"\\\\\": # Windows\n pass\n elif os.sep == \"/\": # Unix\n my_ftp.download_file_tree(\"image/\", \"/image/\") # image/ 仓库目录; /image/ 又拍云云存储目录\n\n # 上传目录\n # 本地 image/ → 又拍云云存储\n if os.sep == \"\\\\\":\n pass\n elif os.sep == \"/\":\n my_ftp.upload_file_tree(\"image/\", \"/image/\") # image/ 仓库目录; /image/ 又拍云云存储目录\n my_ftp.close()\n\n```\n\n\n\n### 5. git.sh 推送变更\n\n个人习惯将 push 命令写在一个文件里,放在仓库根目录下\n\n```bash\n#!/usr/bin/bash\n\n# 远端同步至本地\ngit pull\n\n# 推送变更\ngit add .\ngit commit -m \"$(date +'%Y/%m/%d')\"\ngit push\n```\n\n\n\n## 参考文章\n\n1. [\\* GitHub Actions 中 python 脚本获取仓库 secrets](https://blog.csdn.net/sculpta/article/details/106474324)\n2. [\\* 使用github仓库创建定时任务,定时签到等服务](https://blog.csdn.net/weixin_44786530/article/details/127890033)\n3. [\\* Python实现的FTP上传和下载功能](https://blog.csdn.net/ouyang_peng/article/details/79271113)\n4. [\\* 使用Github Action实现全自动部署](http://akilar.top/posts/f752c86d/)\n5. [\\* 又拍云:如何使用 FTP、API 上传文件](https://help.upyun.com/2015/12/28/%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-ftp%e3%80%81api-%e4%b8%8a%e4%bc%a0%e6%96%87%e4%bb%b6/)\n6. [\\* 又拍云:创建存储服务和使用 FTP 上传](https://techs.upyun.com/videos/cdnpage/creating_storage.html)\n7. [\\* Github/Gitlab Actions 中的 cron 格式和设置方法](http://blog.ynxiu.com/aixiu/f9ec3873.html)\n8. [\\* Github Actions 执行Python定时任务(时区及缓存问题处理)](https://blog.csdn.net/u010214511/article/details/127079323)\n9. [\\* 运行Github Actions unable to access ‘https://github.com/x/‘: The requested URL returned error: 403](https://blog.csdn.net/jj89929665/article/details/129817011)\n10. [\\* workflow_dispatch](https://docs.github.com/zh/actions/using-workflows/events-that-trigger-workflows#workflow_dispatch)\n11. [白嫖github的Action做定时任务](https://www.ngui.cc/article/show-1024687.html?action=onClick)\n12. [Github+Action实现自动定时推送](https://www.xiaohongshu.com/explore/62ff387d000000001b01e535)\n13. [基于github中action服务的自动化打包部署](https://blog.wandhi.com/pages/bbd4b7/)\n14. [基于GITHUB ACTION的定时任务,真香!](https://blog.csdn.net/qq_40748336/article/details/110749375)\n15. [GitHub Actions 定时运行代码:每天定时百度链接推送](http://chart.zhenglinglu.cn/pages/f44d2f9ad04ab8d3/)\n\n\n\n","tags":["GitHub","Other","Python","FTP"],"categories":["Other"]},{"title":"07_Other-文章记录-sshpass","url":"/posts/cee83196.html","content":"\n\n\n## 前言\n\n记录一些小知识点、工具、文章收藏\n\n\n\n## 01. 链接收藏\n\n| 地址 | 地址 | 地址 |\n| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| [MyFreeMP3](https://tools.liumingye.cn/music/#/) | [Typora入门](https://www.cnblogs.com/hider/p/11614688.html) | [Typora页面美化](https://zhuanlan.zhihu.com/p/193101244) |\n| [Microsoft Store](https://apps.microsoft.com/store/apps) | [中文文案排版指北](https://github.com/sparanoid/chinese-copywriting-guidelines/blob/master/README.zh-Hans.md) | [Git常见用法总结](https://blog.csdn.net/m0_37624402/article/details/108960118) |\n| [ProcessOn](https://www.processon.com/) | [牛客网-面经-运开资料](https://www.nowcoder.com/discuss/353154816606150656) | [JavaScript日期格式化,不足两位数补0](https://www.cnblogs.com/blogkui/p/12900655.html) |\n| [Molunerfinn 大佬面经](https://molunerfinn.com/my-2019-interview-of-summer-internship/) | [Akilar:Github Action自动部署](https://akilar.top/posts/f752c86d/#%E9%85%8D%E7%BD%AEGithub-Action) | [AutoPlan.哔哩升级](https://auto.oldwu.top/) |\n| [Jetbrains 激活方法](https://www.cnblogs.com/xxhxs-21/p/17151813.html) | [公众号二维码.下载](https://mp.weixin.qq.com/cgi-bin/settingpage?t=setting/index&action=index&token=168808346&lang=zh_CN) | [GitHub: BiliBiliToolPro](https://github.com/RayWangQvQ/BiliBiliToolPro) |\n| [Snipaste JPG 截图格式](https://jingyan.baidu.com/article/25648fc14b3276d091fd00c3.html) | [倚栏听风.2023计算机保研经历总结](https://www.yilantingfeng.site/%e5%ad%a6%e4%b8%9a%e7%9b%b8%e5%85%b3/1503/) | [Veen Zhao.南师大.考研](https://blog.zwying.com/archives/93.html) |\n| [批量删除微博博文](https://github.com/dxhuii/delWeibo) | [chatgpt账号-key购买](https://xedu.me/) | |\n| | | |\n\n其他:\n\n1. [03_Other-PC端环境记录](https://blog.cpen.top/posts/583c5c34.html)\n\n非技术:\n\n| 地址 | 地址 | 地址 |\n| ------------------------------------------------------------ | ---- | ---- |\n| [酷壳:别让自己“墙”了自己](http://coolshell.cn/articles/20276.html) | | |\n| | | |\n\n云服务器:\n\n- 阿里云 ECS 99/年,活动期内(活动时间: ==2023年10月31日0点0分0秒至2026年3月31日23点59分59秒==。)续费同价,新老用户同享:https://www.aliyun.com/lowcode/promotion/allinaliyun/99program\n- 阿里云在校学生300无门券/合作高校3折券领取:https://university.aliyun.com/\n\n\n\n## 02. sshpass 非交互登录\n\nssh 不能在命令行中指定密码\n\nsshpass:\n\n1. 用于非交互的 ssh 密码验证,允许用 -p 参数指定明文密码\n2. 支持密码从命令行,文件,环境变量中读取\n\n\n\n> Ubuntu 报错 `E: Unable to locate package sshpass`\n>\n> `apt-get update` ; sudo apt-get install sshpass\n>\n> 参考文章:[ssh快捷登录 sshpass+alias](https://www.cnblogs.com/itsfei/p/15014277.html)\n>\n\n\n\n登录脚本(第一次需 SSH 登录)\n\n```bash\n$ cat ali.sh\n#!/bin/bash\n\nsshpass -p 密码 ssh -o ServerAliveinterval=60 root@IP\n# sshpass -p 密码 ssh root@IP\n\n$ chmod +x ali.sh\n\n```\n\n- -o option => Can be used to give options in the format used in the configuration file.\n- `ServerAliveinterval=60` client每隔60秒发送一次请求给server,然后server响应,从而保持连接(防止连接空闲超时)\n\n\n\n定义别名 alias\n\n```bash\n$ cat ~/.bashrc\n# User specific aliases and functions\nalias ali='bash /home/peng/sh_file/ali.sh'\n```\n\n\n\n参考文章:\n\n1. [Shell 脚本 ssh免密码 登录 远程服务器 sshpass用法示例](https://blog.csdn.net/u013288190/article/details/116921994)\n2. [Shell脚本免密码登录远程服务器(方法一)](https://blog.csdn.net/liao392781/article/details/79220395)\n3. [ssh快捷登录 sshpass+alias](https://www.cnblogs.com/itsfei/p/15014277.html)\n4. [Linux -- 将自己的shell脚本设置成命令](https://blog.csdn.net/weixin_48693408/article/details/125961472)\n5. [配置SSH服务远程连接空闲超时退出时间(包括SSH无法登录、登录缓慢)](https://blog.csdn.net/qq_44895681/article/details/124841145)\n\n\n\n## 03. Xftp 显示隐藏文件\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304042240000.png\" alt=\"image-20230404224047926\" style=\"zoom: 33%;\" />\n\n参考文章:[Xftp显示隐藏文件的方法](http://www.nndssk.com/xtjc/287647HVA4sC.html)\n\n\n\n## 04. Github 多账户 SSH 配置\n\n> ```bash\n> ssh-keygen -f ~/.ssh/id_rsa_gh -C user_gh@gmail.com\n> ```\n>\n> - -b:指定 key 的 bit 数,对于 RSA key 而言,默认是 3072 bits\n> - -f:指定 key 的文件名,若需要指定路径,则文件名需要和路径一直,如 ~/.ssh/id_rsa_gh\n> - -C:指定新的 comment,即公钥末尾的字符串,一般是邮箱地址,若不指定会是 \"username@hostname\" 的形式\n> - -t:指定私钥类型,一般有 \"dsa\", \"ecdsa\", \"ecdsa-sk\", \"ed25519\", \"ed25519-sk\" 和 \"rsa\" 等几种,若指定为 rsa 还可以指定签名类型,默认为 \"rsa-sha2-512\"\n\n\n\n> Github 不同账户,类似配置\n>\n> ```bash\n> $ cat ~/.ssh/config\n> Host github.com\n> HostName github.com\n> PreferredAuthentications publickey\n> IdentityFile ~/.ssh/user1_rsa\n> User user1\n> Host github.com\n> HostName github.com\n> PreferredAuthentications publickey\n> IdentityFile ~/.ssh/user2_rsa\n> User user2\n> ------\n> Host user_gh.github.com\n> HostName github.com\n> User user_gh\n> IdentityFile ~/.ssh/id_rsa_gh\n> Host github-qileq.com\n> HostName github.com\n> User qileq\n> IdentityFile ~/.ssh/id_rsa_qileq\n> Host gitlab.com\n> HostName gitlab.com\n> User user_gl\n> IdentityFile ~/.ssh/id_rsa_gl\n> \n> ```\n>\n> - Host 类型昵称,可以简化登录的输入地址,比如`Host ccl`,则可以用`ssh ccl`直接连接\n> - HostName 表示连接的远程主机地址\n> - IdentityFile 表示指定私钥文件路径\n> - Port 指定端口\n> - User 指定用户名\n>\n> 修改仓库的 git 信息,将仓库配置 url 的 [http://github.com](https://link.zhihu.com/?target=http%3A//github.com) 替换为 ssh config 中设置的 Host 值。\n>\n> 笔者以 [java-roam-guide](https://link.zhihu.com/?target=https%3A//github.com/qileq/java-roam-guide) 为例,使用如下两种方式来修改仓库地址:\n>\n> 1. 执行命令 git remote set-url origin git@github-qileq.com:qileq/java-roam-guid.git\n> 2. 将该仓库 .git/config 中的 url = [git@github.com](mailto:git@github.com):qileq/java-roam-guide.git 修改为 url = git@github-qileq.com:qileq/java-roam-guide.git\n>\n> 修改完成后,执行 git remote -v 查看仓库地址是否正确。\n\n\n\n> ```bash\n> # 当使用<user1.github.com>替换<github.com>进行访问时,ssh会自动识别为user1\n> # 配置用户1\n> Host user1.github.com\t# 别名,可以随便写一个url。\n> \tHostname github.com\t# 网站真实的域名,如果是GitHub就不用改了\n> \tPreferredAuthentications publickey\n> \tIdentityFile ~/.ssh/id_rsa_user1\t# 指向user1的私钥路径,似乎只能在~/.ssh下,不要随便放\n> \tUser user1\t# 填写user1的Github用户名,不过似乎最后获取的还是真实的Github用户名\n> \n> # 配置用户2\n> Host user1.github.com\n> \tHostname github.com\t\t\t\t\t\n> \tPreferredAuthentications publickey\n> \tIdentityFile ~/.ssh/id_rsa_user2\t# 指向user2的私钥路径,似乎只能在~/.ssh下,不要随便放\n> \tUser user2\t# 填写user2的GitHub用户名,不过似乎最后获取的还是真实的Github用户名\n> \n> ```\n>\n> \n>\n> 如果是直接使用 `git@github.com`,那么ssh将自动识别为config列表的第一个用户,可以认为是单用户模式\n>\n> 由于是多用户,所以在第一次clone一个GitHub地址的时候,需要简单的修改一下对应的域名,此时SSH将可以识别使用哪个用户进行操作,并建立配置记录\n>\n> ```bash\n> # 原始要clone的仓库命令\n> git clone git@github.com:oneflyingfish/WebServer_C.git\n> \n> # 对应修改一下<github.com>,user1修改为上面配置的<user1.github.com>即可\n> git clone git@user1.github.com:oneflyingfish/WebServer_C.git\n> \n> ```\n>\n> \n>\n> 多用户共用情况下,如果提示设置用户名,一定要设置为`局部信息`,而不是`global`。命令应修改为\n>\n> ```bash\n> # git默认提示的命令\n> git config --global user.name \"your_name\"\n> git config --global user.email \"your_eamil\"\n> \n> # 我们应该使用的命令\n> git config user.name \"your_name\"\n> git config user.email \"your_eamil\"\n> \n> ```\n>\n> \n\n\n\n参考文章:\n\n1. [* SSH 多账号的配置](https://zhuanlan.zhihu.com/p/521768041)\n2. [ssh config多账户/多域名配置](https://cloud.tencent.com/developer/article/2121948)\n3. [SSH Config 使用](https://blog.csdn.net/senlin1202/article/details/122081089)\n4. [Mac上配置多个SSH](https://blog.anheyu.com/posts/443e.html)\n5. [* 配置SSH keys连接GitHub(支持多用户)](https://oneflyingfish.gitee.io/articles/20c7aea41283/)\n6. [解决 Git 同时部署到 GitHub 和 Gitee 时,密钥 SSH 冲突问题](https://happyleecode.gitee.io/2023/04/05/SSH/)\n\n\n\n## 05. APICloud 打包网页\n\n==未成功==\n\n[APICloud](https://www.apicloud.com/portal-web/console) => Web App 创建\n\n图标\thttps://dlvr.cpen.top/gh/mycpen/image_bed/image/202304061700919.png\n\n启动页\thttps://dlvr.cpen.top/gh/mycpen/image_bed/image/202304061700867.png\n\n\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304061613612.png\" alt=\"image-20230406161352487\" style=\"zoom:33%;\" />\n\n安装后的 APP 因无法开启存储空间权限,未能成功(个人原因,[Fomalhaut🥝](https://www.fomal.cc/) 的 [APP](https://lskypro.acozycotage.net/Fomalhaut/Fomalhaut.apk) 能设置)\n\n参考教程:[将网站 / 博客打包成桌面 APP](https://naokuoteng.cn/posts/2afd210.html)、[Fomalhaut🥝.留言](https://www.fomal.cc/comments/#9392fccc60784238be439c910336af0b)\n\n\n\n## 06. Hexo 渲染脚注\n\n下文采用 hexo-renderer-markdown-it 渲染器(渲染脚注效果一般,不打算用脚注了)\n\n\n\n> 尽管标准 Markdown 不支持脚注,但很多 Markdown 变种都支持。一般来说,大多数 Markdown 方言和编辑器支持行内脚注和引用式脚注这两种方式,而后者使用更为普遍(原文:[在 Markdown 中使用引用式链接和脚注](https://sspai.com/post/77513))\n\n> ```bash\n> npm uninstall --save hexo-renderer-marked\n> npm install --save hexo-renderer-markdown-it\n> ```\n>\n> ```yaml\n> markdown:\n> plugins:\n> - markdown-it-footnote\n> ```\n>\n> 原文:[我的博客的诞生(二)](https://blog.imql.life/2020/01/24/My_HexoBlog_with_NexT(2)/#%E6%9B%B4%E6%8D%A2%E9%BB%98%E8%AE%A4%E7%9A%84-Markdown-%E6%B8%B2%E6%9F%93%E5%99%A8-1)\n\n\n\n> ```markdown\n> Here is a footnote reference,[^1] and another.[^longnote]\n> \n> [^1]: Here is the footnote.\n> \n> [^longnote]: Here's one with multiple blocks.\n> \n> Subsequent paragraphs are indented to show that they\n> belong to the previous footnote.\n> ```\n>\n> ```markdown\n> Here is an inline note.^[Inlines notes are easier to write, since\n> you don't have to pick an identifier and move down to type the\n> note.]\n> ```\n>\n> 来源:[markdown-it/markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote)\n\n\n\n个人配置:\n\n```diff\n# https://butterfly.js.org/posts/ceeb73f/#Math-%E6%95%B8%E5%AD%B8\n# https://www.nickxu.top/2022/04/17/Hexo-Butterfly-建站指南(八)使用-KaTeX-数学公式/\n# https://github.com/hexojs/hexo-renderer-markdown-it\n# https://ezgx.tk/posts/65320/\nmarkdown:\n preset: 'default'\n render:\n html: true\n xhtmlOut: false\n langPrefix: 'language-'\n breaks: true\n linkify: true\n typographer: true\n quotes: '“”‘’'\n enable_rules:\n disable_rules:\n plugins:\n - markdown-it-abbr\n # installed external plugins also can be enabled\n - markdown-it-table-of-contents\n - markdown-it-attrs\n # - markdown-it-cjk-breaks\n - markdown-it-container\n - markdown-it-deflist\n - markdown-it-emoji\n+ - markdown-it-footnote\n - markdown-it-ins\n - markdown-it-mark\n - markdown-it-sub\n - markdown-it-sup\n - markdown-it-checkbox\n - markdown-it-imsize\n - markdown-it-expandable\n - markdown-it-merge-cells\n - '@renbaoshuo/markdown-it-katex'\n # - @iktakahiro/markdown-it-katex\n # - name: '@neilsustc/markdown-it-katex'\n # enable: true\n # options:\n # strict: false\n # - markdown-it-toc-and-anchor\n - name: markdown-it-container\n options: success\n - name: markdown-it-container\n options: tips\n - name: markdown-it-container\n options: warning\n - name: markdown-it-container\n options: danger\n anchors:\n level: 1\n collisionSuffix: ''\n permalink: false\n permalinkClass: 'header-anchor'\n permalinkSide: 'left'\n permalinkSymbol: '¶'\n case: 0\n separator: '-'\n images:\n lazyload: false\n prepend_root: false\n post_asset: false\n```\n\n\n\n参考文章:\n\n1. [在 Markdown 中使用引用式链接和脚注](https://sspai.com/post/77513)\n2. [Markdown 脚注](https://markdown.com.cn/extended-syntax/footnotes.html)\n3. [百里飞洋 Barry-Flynn(得知脚注)](https://blog.meta-code.top/2023/03/21/2023-53/)\n4. [hexojs/hexo-renderer-markdown-it](https://github.com/hexojs/hexo-renderer-markdown-it)\n5. [* markdown-it/markdown-it-footnote](https://github.com/markdown-it/markdown-it-footnote)\n6. [* 我的博客的诞生(二)](https://blog.imql.life/2020/01/24/My_HexoBlog_with_NexT(2)/#%E6%9B%B4%E6%8D%A2%E9%BB%98%E8%AE%A4%E7%9A%84-Markdown-%E6%B8%B2%E6%9F%93%E5%99%A8-1)\n\n\n\n## 07. Base64 加密邮箱 解密\n\n加密的邮箱地址,使用 base64 加密。在线加密:https://encode.chahuo.com/\n\n解密 `javascript:decryptEmail(...)`,代码示例:https://www.mycpen.cn/\n\n```html\n<a href=\"javascript:decryptEmail('bXljcGVuQHFxLmNvbQ==');\" title=\"email\"></a>\n```\n\n\n\n## 08. Word 转 MD(Pandoc)\n\n```bash\npandoc -xxx.docx -o xxx.md\n```\n\n> 一、下载pandoc\n> 建议使用msi直接安装,而不是下载安装包直接使用,msi的下载方法:安装方法。\n>\n> 二、pandoc转换\n> 1、cmd进入文件夹\n> 打开cmd。\n> 转换到文件所在的路径中。d:进入D盘的路径下,CD D:\\Program Files\\OneDrive\\桌面\\temp\n>\n> 2、代码实现\n>\n> ```bash\n> pandoc -xxx.docx -o xxx.md # docx 文件转换为 md 文件\n> ```\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304162143719.png\" alt=\"image-20230416214320662\" style=\"zoom: 33%;\" />\n\n参考文章:[word文件转md文件](http://www.taodudu.cc/news/show-3860696.html)\n\n\n\n## 09. GitHub 删除历史记录\n\n```bash\ngit reset <上一步复制到的字符串>\ngit push -f\n```\n\n参考文章:[GITHUB删除历史记录](https://blog.csdn.net/sunzequan888/article/details/125738176)\n\n\n\n## 10. ChatGPT API Key 个人站\n\n项目地址:\n\n1. https://github.com/Chanzhaoyu/chatgpt-web\n2. https://github.com/Yidadaa/ChatGPT-Next-Web\n\n参考文章:\n\n1. [无服务器部署自己的chatGPT](https://www.fomal.cc/posts/74ac8dc8.html)\n\n\n\n## 11. 字符画 consolo.log()\n\n**推荐**:http://patorjk.com/software/taag\n\n文字生成字符画:\nhttp://patorjk.com/software/taag\nhttp://www.network-science.de/ascii/\n\n图片生成字符画:\nhttp://www.degraeve.com/img2txt.php\nhttp://life.chacuo.net/convertphoto2char\n\n流程图生成字符画:\nhttp://asciiflow.com/\n\nVSCode 插件:\nhttps://github.com/OBKoro1/koro1FileHeader\n\n参考:https://blog.saop.cc/p/c9df/\n\n\n\n## 12. ERR_HTTP2_PROTOCOL_ERROR 关闭 HSTS\n\n访问网站,偶然性报错:ERR_HTTP2_PROTOCOL_ERROR。试着关闭 HSTS\n\nCDN HTTPS 配置 关闭 `HSTS`,[多吉云个人链接](https://console.dogecloud.com/cdn/domain/https?domainId=6667)\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304191935126.png\" alt=\"image-20230419193555012\" style=\"zoom: 33%;\" />\n\n以下内容来自 ChatGPT:\n\n> 问:`ERR_HTTP2_PROTOCOL_ERROR 和 HSTS 有什么联系`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304191946818.png\" alt=\"image-20230419194615758\" style=\"zoom: 50%;\" />\n>\n> 问:`HSTS 会导致 ERR_HTTP2_PROTOCOL_ERROR 报错吗`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304191946462.png\" alt=\"image-20230419194650417\" style=\"zoom: 50%;\" />\n\n\n\n## 13. Clash Parsers\n\n设置 => 配置 => 配置文件预处理\n\n```yaml\nparsers: # array\n - url: https://xxx.xxx/xxx\n yaml:\n prepend-rules:\n - DOMAIN-SUFFIX,xxx.com,香港Az-优化3\n - DOMAIN-SUFFIX,xxx.com,GLOBAL\n - DOMAIN-SUFFIX,xxx.com,DIRECT\n\n```\n\n\n\n参考链接:\n\n1. [* Clash for Windows:配置文件预处理](https://docs.cfw.lbyczf.com/contents/parser.html)\n2. [* Clash利用parsers进行规则预处理](https://zhuanlan.zhihu.com/p/600564111)\n3. [* Clash使用Parser添加自定义规则并防止更新覆盖](https://blog.csdn.net/u013559309/article/details/129437063)\n4. [clash for windows自定义规则(不会被更新覆盖)](https://www.wangpc.cc/software/clash-for-windows-paarsers-rules/)\n5. [clash for windows如何设置指定IP或者网站才走xx?](https://www.zhihu.com/question/507810862)\n\n\n\n## 14. Replit 部署 Typecho.TimePlus\n\n> 步骤:https://github.com/zhheo/TimePlus/wiki/\n>\n> Demo:https://plog.zhheo.com/\n>\n> 在 Typecho 后台导航栏点击【撰写】,在自定义字段中填写图片地址。并填写文章标题和内容,即对应为图片的标题和简介。\n\n搭建步骤:\n\n1. [Replit](https://replit.com/) Create a Repl,环境选 SQLite;参照 [@valetzx/typechonreplit](https://github.com/valetzx/typechonreplit) 执行 `git clone https://github.com/valetzx/typechonreplit && mv -b typechonreplit/* ./ && mv -b typechonreplit/.[^.]* ./ && rm -rf *~ && rm -rf typechonreplit`;注释 `main.sh` butterfly 相关行,`bash main.sh`;Run 运行;设置 Typecho 时选择 SQLite 数据库\n2. 按照 [TimePlus.Wiki](https://github.com/zhheo/TimePlus/wiki/%E7%AC%AC%E4%B8%80%E6%AC%A1%E4%B8%8A%E6%89%8B) 设置,将 [Source code](https://github.com/zhheo/TimePlus/releases) 解压上传 Replit Repl 对应路径,按步骤设置\n3. 图片仓库批量获取图片 URL `ls ./bj |awk '{print \"https://mycpen.gitee.io/cdn2/image/bj/\"$1\"\"}' > C:/Users/Administrator/Desktop/TimePlus.txt`\n4. Replit Repl 绑自定义域名,需先 TXT 记录认证(因验证问题无法使用 https)\n\n\n\n相关链接:\n\n1. https://github.com/zhheo/TimePlus/wiki/\n2. https://github.com/zhheo/TimePlus\n3. https://github.com/valetzx/typechonreplit\n4. https://blog.zhheo.com/p/bed74f41.html\n5. [Replit](https://replit.com/)\n6. [阿里云.DNS](https://dns.console.aliyun.com/)\n\n\n\n## 15. Git 修改提交信息\n\n**2023-12-13 更新**\n\n使用 `git rebase -i HEAD~<n>` 修改最近某一次的提交信息,以下来自 chatgpt\n\n> 当您执行 `git rebase -i HEAD~<n>` 命令时,会打开一个交互式的编辑器界面,列出最近 `<n>` 个提交。下面是一个示例,假设您要修改最近的前三次提交的提交信息:\n>\n> ```\n> pick 1a2b3c4 Commit message 1\n> pick 5d6e7f8 Commit message 2\n> pick 9g0h1i2 Commit message 3\n> ```\n>\n> 要修改提交信息,将每个提交的行的开头的 `pick` 改为 `reword` 或 `r`,然后保存并关闭编辑器。修改后的示例如下:\n>\n> ```\n> reword 1a2b3c4 Commit message 1\n> reword 5d6e7f8 Commit message 2\n> reword 9g0h1i2 Commit message 3\n> ```\n>\n> 保存并关闭编辑器后,Git 会逐个应用这些提交,并在每个提交之前暂停并等待您编辑提交信息。对于每个提交,Git 会打开一个新的编辑器窗口,允许您修改提交信息。完成修改后,保存并关闭编辑器。\n>\n> 请注意,如果在 rebase 过程中出现冲突,您需要解决冲突并使用 `git add` 命令将解决后的文件标记为已解决。然后,继续进行 rebase,直到所有提交都被处理完毕。\n>\n> 完成 rebase 后,您可以使用 `git log` 命令验证提交信息是否已成功修改。\n>\n> ```\n> $ git log\n> ```\n>\n> 如果要将修改的提交信息推送到远程仓库,您需要使用 `git push --force` 命令,因为您已经修改了历史提交。\n>\n> ```\n> $ git push --force\n> ```\n>\n> 请确保在进行此操作之前备份您的代码,并与团队成员进行沟通,以免影响其他人的工作。\n\n---\n\n\n\n> ```bash\n> git commit --amend\n> git push --force <remote-name> <branch-name>\n> \n> ```\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202305131749192.png\" alt=\"image-20230513174958143\" style=\"zoom: 80%;\" />\n\n\n\n> ```bash\n> git log --oneline\n> git commit --amend -m \"新的提交信息\"\n> git push --force origin master\n> \n> ```\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202305131751216.png\" alt=\"image-20230513175153157\" style=\"zoom: 67%;\" />\n\n\n\n\n## 16. GitHub: BiliBiliToolPro\n\n地址:https://github.com/RayWangQvQ/BiliBiliToolPro\n\n[本地部署](https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docs/runInLocal.md#3-linux):\n\n```bash\n$ pwd\n/root/sh_file/BiliBiliToolPro\n\n$ wget https://github.com/RayWangQvQ/BiliBiliToolPro/releases/download/1.0.3/bilibili-tool-pro-v1.0.3-linux-x64.zip\n$ unzip bilibili-tool-pro-v1.0.3-linux-x64.zip\n$ cd ./linux-x64/\n$ ./Ray.BiliBiliTool.Console --runTasks=Login\n\n```\n\n```bash\n$ crontab -l\n0 1 * * * cd /root/sh_file/BiliBiliToolPro/linux-x64; ./Ray.BiliBiliTool.Console --runTasks=VipBigPoint\n0 8 * * * cd /root/sh_file/BiliBiliToolPro/linux-x64; ./Ray.BiliBiliTool.Console --runTasks=Daily\n* */12 * * * cd /root/sh_file/BiliBiliToolPro/linux-x64; ./Ray.BiliBiliTool.Console --runTasks=LiveLottery\n0 16 * * * cd /root/sh_file/BiliBiliToolPro/linux-x64; ./Ray.BiliBiliTool.Console --runTasks=UnfollowBatched\n0 20 * * * cd /root/sh_file/BiliBiliToolPro/linux-x64; ./Ray.BiliBiliTool.Console --runTasks=LiveFansMedal\n\n```\n\n\n\n\n\n## 17. GitHub Compare\n\n原文:https://akilar.top/posts/bbf68ad4/\n\n示例:https://github.com/jerryc127/hexo-theme-butterfly/compare/4.8.5...4.9.0\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202309161502336.png\" alt=\"image-20230916150258235\" style=\"zoom:50%;\" />\n\n\n\n## 18. new Date().getFullYear();\n\nJavaScript 获取当前年份\n\n```JavaScript\n// 要以自动方式获取明年的年份并将其用于创建日期对象,您可以按如下方式修改代码:\nconst currentYear = new Date().getFullYear();\nconst nextYear = currentYear + 1;\nconst newYearTimestamp = new Date(`${nextYear}-01-01 00:00:00`).getTime() / 1000;\n\n```\n\n\n\n## 19. JavaScript 解码 Base64\n\n在线加密:https://encode.chahuo.com/\n\n以下来自 [ChatGPT](https://chat-shared2.zhile.io/)\n\n> 在 JavaScript 中解码 Base64 编码的数据,你可以使用 `atob()` 函数。该函数可以将 Base64 编码的字符串解码为原始的文本数据。示例代码如下:\n>\n> ```javascript\n> const base64String = \"SGVsbG8gd29ybGQ=\"; // Base64 编码的字符串\n> const decodedString = atob(base64String); // 解码\n> console.log(decodedString); // 输出解码后的字符串\n> ```\n>\n> 在这个例子中,`base64String` 你要解码Base64编码的字符串。使用`atob()`函数对它进行解码,然后你就可以处理解码后的原始字符串了。\n\n\n\n## 20. JavaScript 取绝对值\n\n来自 [ChatGPT](https://chat-shared2.zhile.io/)\n\n> 在 JavaScript 中,你可以使用 `Math.abs()` 函数来获取一个数的绝对值,从而去除负号。例如:\n>\n> ```javascript\n> let num = -5;\n> let absNum = Math.abs(num); // absNum将是5\n> ```\n>\n> 这样,`absNum` 将会取得 `num` 的绝对值,而不考虑其正负。\n\n\n\n## 21. JavaScript 三元运算\n\n来自 [ChatGPT](https://chat-shared2.zhile.io/)\n\n> 你可以使用条件运算符(三元运算符)来判断 `e - now1` 是否大于 0,然后决定是否执行 +1。下面是优化后的代码:\n>\n> ```javascript\n> let daysDifference = Math.floor(((e - now1) / 1e3 / 60 / 60 / 24) + (e - now1 > 0 ? 1 : 0));\n> ```\n>\n> 这行代码首先计算 `(e - now1) / 1e3 / 60 / 60 / 24` 得到天数差,然后根据 `(e - now1 > 0)` 条件判断天数差是否大于 0,如果是则加 1,否则加 0。最后使用 `Math.floor` 向下取整。\n\n\n\n## 22. Snipaste 截图格式改 JPG\n\n参考:https://jingyan.baidu.com/article/25648fc14b3276d091fd00c3.html\n\n右键 → 首选项 → 输出 → 文件名.后缀\n\n实测大大减少图片体积,500 KB (PNG) → 70KB (JPG)\n\n仅适用于保存为本地文件,从剪贴板中粘贴到 typora 里还是 PNG 格式的\n\n本人格式:`image-$yyyyMMddHHmmsszzz$.jpg`,目的 与 typora 剪贴板 上场时的 alt 命名保持一致\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202310070313815.jpg\" alt=\"image-20231007031301508\" style=\"zoom: 25%;\" />\n\n\n\n## 23. CSS 视口单位 dvh, svh, lvh\n\n参考:\n\n1. https://blog.anheyu.com/posts/e644.html\n2. https://blog.csdn.net/LuckyWinty/article/details/128962918\n\n\n\n## 24. CSS 旋转 rotate(90deg)\n\n来自 [ChatGPT](https://chat-shared2.zhile.io/)\n\n> `rotate(90deg)` 是CSS中的旋转变换指令,用于将元素顺时针旋转90度。这可以应用于任何HTML元素,使其在页面上以指定角度旋转。\n>\n> 逆时针旋转一个元素90度,`rotate(-90deg)`\n>\n> ```css\n> .about-page-chicken-soup details[open]>summary:after {\n> transform: rotate(-90deg);\n> }\n> ```\n\n\n\n## 25. Markdown 折叠语法\n\n参考:https://blog.csdn.net/ybb_ymm/article/details/128508243\n\n```markdown\n<details> \n <summary>指示标题</summary>\n 内容\n</details>\n```\n\n```markdown\n<details> \n <summary>展开查看</summary>\n <pre><code>\n 此处为代码的块具体内容\n </code></pre> \n</details>\n```\n\n\n\n## 26. PicGo 图片压缩插件\n\n插件名:[picgo-plugin-compress-tinypng](https://github.com/liujinpen/picgo-plugin-compress-tinypng)\n\nNPM 包:[picgo-plugin-tinypng](https://www.npmjs.com/package/picgo-plugin-tinypng)\n\nTinyPNG\n\n- 官网:https://tinify.cn/\n- 获取 Key 参考:https://bearcai.com/index.php/archives/44/\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202310070421963.jpg\" alt=\"image-20231007042117896\" style=\"zoom:25%;\" />\n- Key 限额 500 次/月:https://tinify.cn/dashboard/api\n\n起因:[picgo-plugin-compress](https://github.com/juzisang/picgo-plugin-compress) 长久失修,picgo 2.3.1 报错 `TypeError: req.end is not a function`。 [issue#64](https://github.com/juzisang/picgo-plugin-compress/issues/64#issuecomment-1504939740) 获知此插件\n\n\n\n## 27. JavaScript copy 事件\n\n来自 ChatGPT\n\n要检测用户是否复制内容,你可以使用JavaScript中的`copy`事件来捕获复制操作。你可以将事件监听器绑定到`copy`事件上,然后在该事件触发时执行相应的操作,以获知用户是否复制了内容。\n\n```javascript\ndocument.addEventListener('copy', function(event) {\n // 在这里执行你想要的操作,例如记录复制操作或发送数据到服务器\n console.log('用户复制了内容');\n});\n```\n\n```javascript\ndocument.addEventListener('copy', function(event) {\n // 获取复制的内容\n var copiedText = window.getSelection().toString().trim();\n \n // 检查复制的内容是否为空\n if (copiedText.length > 0) {\n // 在这里执行你想要的操作,例如记录复制操作或发送数据到服务器\n console.log('用户复制了内容:', copiedText);\n } else {\n // 复制的内容为空,可以选择不执行任何操作或者执行相应处理\n console.log('用户尝试复制空内容');\n }\n});\n```\n\n\n\n## 28. JavaScript window.onresize\n\n来自:ChatGPT\n\n`window.onresize` 是 JavaScript 中的一个事件处理属性,它用于指定在浏览器窗口大小改变时要执行的函数。当用户调整浏览器窗口的大小时,就会触发 `resize` 事件,如果你将一个函数分配给 `window.onresize`,那么这个函数将在窗口大小改变时被调用。\n\n例如,你可以使用以下方式监听窗口大小改变事件并执行相应的操作:\n\n```javascript\nwindow.onresize = function() {\n // 在窗口大小改变时执行的代码\n console.log(\"窗口大小已改变\");\n};\n```\n\n这对于创建响应式设计或根据窗口大小进行布局调整等任务非常有用。当窗口大小发生变化时,你可以根据需要更新页面内容、样式或执行其他自定义操作。\n\n\n\n## 29. Git 指定远端\n\n参考:http://www.mobiletrain.org/about/BBS/161969.html\n\n```bash\ngit remote add origin <远程仓库URL>\n\ngit push <远程仓库别名> <本地分支名>:<远程分支名>\n\ngit push origin master:main\n```\n\n\n\n## 30. Git 删除文件历史提交记录\n\n参考:ChatGPT\n\n```bash\ngit filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch node_modules' --prune-empty --tag-name-filter cat -- --all\ngit rm --cached node_modules -r\n\ngit reflog expire --expire=now --all && git gc --prune=now --aggressive\n```\n\nChatGPT 还提供了 `git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD` 命令删除,运行时间过长,不采用,给出的解释:命令1 使用了 `--index-filter` 和 `--cached`,这些参数可以更快地处理 Git 的索引而不需要检查和修改实际的工作树文件\n\n> 1. `git filter-branch --tree-filter 'rm -rf node_modules' --prune-empty HEAD`:\n> - 使用 `--tree-filter` 参数,它会在每个提交上执行指定的 shell 命令。在这种情况下,它会执行 `rm -rf node_modules` 命令来删除 `node_modules` 目录。\n> - 使用 `--prune-empty` 选项以删除空提交。\n> - 只作用于当前分支 `HEAD`。\n> 2. `git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch node_modules' --prune-empty --tag-name-filter cat -- --all`:\n> - 使用 `--index-filter` 参数,它会在 Git 索引上执行指定的命令。在这种情况下,它会执行 `git rm -r --cached --ignore-unmatch node_modules` 命令,以将 `node_modules` 从索引中删除。\n> - 使用 `--prune-empty` 选项以删除空提交。\n> - 使用 `--tag-name-filter cat` 选项,以保留提交的标签(tags)。\n> - 使用 `--all` 来指定作用于所有分支。\n>\n> ---\n>\n> 之前上传 github 时提交了无需提交的 node_modules,如何缩小 .git 的大小\n>\n> ChatGPT:要缩小.git目录的大小,可以采取以下步骤:\n>\n> 1. 清理历史提交中的node_modules:首先,你需要清理历史提交中的不必要的node_modules目录。你可以使用`git filter-branch`命令或`git filter-repo`工具来重写历史提交以删除node_modules。确保在删除之前备份你的仓库,以防发生问题。\n> 2. 使用.gitignore:在项目根目录下创建一个名为`.gitignore`的文件,并将`node_modules/`添加到其中,以确保不再将该目录包括在提交中。\n> 3. 执行`git rm --cached node_modules -r`:这将删除当前暂存区中的node_modules目录,但不会删除物理文件。然后,提交这一变更。\n> 4. 执行`git reflog expire --expire=now --all`:这将清理Git的reflog,以确保不再保留对不必要历史提交的引用。\n> 5. 执行`git gc --prune=now`:这将触发垃圾收集,清理不必要的数据,从而缩小.git目录的大小。\n> 6. 推送到远程仓库:如果你使用远程仓库(如GitHub),确保将这些更改推送到远程仓库以同步它们。\n>\n> 请注意,这些步骤会修改你的Git历史,因此在执行它们之前务必小心,确保已备份你的仓库数据。\n\n\n\n## 31. 洛雪音乐导入三方音源\n\n官方源因 TX 警告而报废,详见 issue:https://github.com/lyswhut/lx-music-desktop/issues/1643\n\n详见 issue:https://github.com/lyswhut/lx-music-desktop/issues/1649#issuecomment-1774536022\n\n仓库:https://github.com/OneCodeMonkey/music-sources\n\n\n\n## 32. Clash GUI\n\n起因:[Clash for Windows](https://github.com/Fndroid/clash_for_windows_pkg) 删库\n\nClash Verge:https://github.com/zzzgydi/clash-verge/\n\nClash for Android 存档:https://github.com/Z-Siqi/Clash-for-Windows_Chinese/releases/tag/CFA\n\nClash for Windows 存档:https://github.com/Z-Siqi/Clash-for-Windows_Chinese\n\n\n\n## 33. GitHub SSH 超时\n\n`git pull` 报超时、`ping github.com` 报超时\n\n解决方案\n\n```bash\n# git bash 终端\nvim ~/.ssh/config\n```\n\n内容如下,第一次 `git pull` 时输入 `yes`\n\n```bash\n# GitHub Start\nHost github.com\n Hostname ssh.github.com\n# GitHub End\n```\n\n参考\n\n1. https://blog.ttiee.tech/posts/2024/71e1/\n2. https://ww-rm.github.io/posts/2024/01/17/githubssh-timeout/\n3. github [Using SSH over the HTTPS port](https://docs.github.com/en/authentication/troubleshooting-ssh/using-ssh-over-the-https-port)\n4. github [About GitHub's IP addresses](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/about-githubs-ip-addresses)\n\n","tags":["Git","Hexo","SSH","Other"],"categories":["Other"]},{"title":"03_Error-问题记录-winpty-.gitignore","url":"/posts/fe8dbc73.html","content":"\n\n\n## 前言\n\n记录一些遇到的问题\n\n\n\n## 01. Python 中文乱码 (Git Bash)\n\nwin终端正常运行但是在git bash 终端运行py文件中文乱码\n在python命令前加 `winpty` 之后则可以正常显示中文\n\n> winpty:一个 Windows 软件包,提供类似于 Unix pty-master 的接口,用于与 Windows 控制台程序通信。\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202303310016695.png\" alt=\"image-20230331001601640\" style=\"zoom: 25%;\" />\n\n参考文章:\n\n1. [【python中文乱码】git bash终端运行python文件中文乱码的问题](https://blog.csdn.net/sinat_42414027/article/details/127787059)\n2. https://github.com/rprichard/winpty\n\n\n\n## 02. .gitignore 测试规则\n\n.gitignore 配置\n\n> ```\n> *.a 表示忽略所有 .a 结尾的文件\n> !lib.a 表示但lib.a除外\n> doc/*.txt 表示会忽略doc/notes.txt但不包括 doc/server/arch.txt\n> /TODO 表示仅仅忽略项目根目录下的 TODO 文件,不包括 subdir/TODO\n> bin/ 表示忽略当前路径下的bin文件夹,该文件夹下的所有内容都会被忽略,不忽略 bin 文件\n> **/foo: 表示忽略/foo,a/foo,a/b/foo等\n> a/**/b: 表示忽略a/b, a/x/b,a/x/y/b等\n> *.log: 表示忽略所有 .log 文件\n> /mtk/ 表示过滤整个文件夹\n> *.zip 表示过滤所有.zip文件\n> --- 需要注意的是,gitignore还可以指定要将哪些文件添加到版本管理中,如下: ---\n> !*.zip\n> !/mtk/one.txt\n> 唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。为什么要有两种规则呢?\n> 想象一个场景:假如我们只需要管理/mtk/目录中的one.txt文件,\n> 这个目录中的其他文件都不需要管理,那么.gitignore规则应写为:\n> /mtk/*\n> !/mtk/one.txt\n> 假设我们只有过滤规则,而没有添加规则,\n> 那么我们就需要把/mtk/目录下除了one.txt以外的所有文件都写出来!\n> 注意上面的/mtk/*不能写为/mtk/,否则父目录被前面的规则排除掉了,\n> one.txt文件虽然加了!过滤规则,也不会生效!\n> --- 还有一些规则如下: ---\n> fd1/*\n> 说明:忽略目录 fd1 下的全部内容;\n> 注意,不管是根目录下的 /fd1/ 目录,还是某个子目录 /child/fd1/ 目录,都会被忽略;\n> /fd1/*\n> 说明:忽略根目录下的 /fd1/ 目录的全部内容;\n> ------\n> /*\n> !.gitignore\n> !/fw/ \n> /fw/*\n> !/fw/bin/\n> !/fw/sf/\n> 说明:忽略全部内容,但是不忽略 .gitignore 文件、根目录下的 /fw/bin/ 和 /fw/sf/ 目录;\n> 注意要先对bin/的父目录使用!规则,使其不被排除。\n> \n> ```\n\n==*== .gitignor 忽略规则查看\n\n> 有时候,确定为什么要忽略特定文件可能会很困难,尤其是当你使用多个.gitignore文件或复杂格式时。这是git check-ignore命令的用处,告诉git显示匹配模式的详细信息。\n>\n> 例如,要检查为什么忽略www/yarn.lock文件,可以运行:\n>\n> `git check-ignore -v www/yarn.lock`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202304041447156.png\" alt=\"image-20230404144757129\" style=\"zoom: 67%;\" />\n\n显示所有被忽略的文件\n\n> 带有--ignored选项的git status命令显示所有被忽略文件的列表:\n>\n> `git status --ignored`\n\n参考文章:\n\n1. [Git忽略提交规则 - .gitignore配置【学习】](https://blog.csdn.net/stephenbruce/article/details/127355631)\n2. [如何使用.gitignore忽略Git中的文件和目录](https://blog.csdn.net/m0_49448331/article/details/128655710)\n\n\n\n## 03. Windows 显示\"无Internet\"\n\n情况:网络显示 “无Internet”,但是可以上网。以下措施没根本解决,最终用微软诊断工具,重置了 `以太网` 网络(万能的重装大法)......\n\n\n\n> 1. 向 dns.msftncsi.com 发送 DNS 查找请求,DNS 解析为 131.107.255.255\n> 2. 请求 http://www.msftconnecttest.com/connecttest.txt,如果网络正常,则此文件是纯文本文件,仅包含文本 Microsoft Connect Test\n>\n> 如果过程1不正常,则提示“无法访问Internet”,如果1正常2不正常,则提示需要进行身份验证\n\n\n\n==以下措施没解决问题==\n\n估计 DHCP 分配的 DNS 服务器(指向网关)有问题,[SwitchHosts](https://github.com/oldj/SwitchHosts) 追加本地记录\n\n```bash\n# Microsoft\ndns.msftncsi.com 131.107.255.255\n```\n\n开机自启 SwitchHosts(Win):\n\n- 快捷方式 复制到 => C:\\Users\\Administrator\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup\\\n- 设置 => 选项 => 启动时隐藏 √\n\n参考文章:\n\n1. [解决Windows有网络连接但是显示“无Internet”的问题](https://blog.csdn.net/wangpeng246300/article/details/120230220)\n2. [SwitchHosts/issues/646](https://github.com/oldj/SwitchHosts/issues/646#issuecomment-945391940)\n\n\n\n## 04. Replit Repl ERR_SSL_PROTOCOL_ERROR\n\n未解决,绑自定义域名后,未分配 SSL 证书\n\nReplit 官方论坛:\n\n1. https://ask.replit.com/t/err-ssl-protocol-error-for-all-sites/27775\n2. 问题搜索:https://ask.replit.com/search?q=ERR_SSL_PROTOCOL_ERROR\n\nReplit 官方服务状态:\n\n1. [SSL 证书问题](https://status.replit.com/notices/ggj8gbnshk50a6yz-ssl-certificates-issues)\n2. [部署的新自定义域遇到 SSL 错误](https://status.replit.com/notices/5pcyvknbltq1mrmg-new-custom-domains-with-deployments-are-experiencing-ssl-errors)\n\n临时方案:\n\n1. https://ask.replit.com/t/err-ssl-protocol-error-for-all-sites/27775/4\n\n > 现在,更改“。” 在 url 中的 repl 名称和用户名之间添加到“–”就可以了。\n >\n > 例如,[https://score-analyzer--enderparakeet.repl.co/ 3个](https://score-analyzer--enderparakeet.repl.co/)作品。\n\n教程:\n\n1. [Replit 绑自定义域名(官方)](https://docs.replit.com/tutorials/html-css-js/building-a-nineties-inspired-website#custom-domain)\n\n\n\n## 05. Terminal 报错: 4294967295\n\nwsl2 报错: `[已退出进程,代码为 4294967295 (0xffffffff)]`,终端无法打开\n\n```bash\n# 管理员身份 PowerShell\nnetsh winsock reset\n\n# 重新打开 terminal,无效则尝试重启后再打开\n```\n\n参考:[打开wsl,显示 [已退出进程,代码为 4294967295] 的解决方案](https://blog.csdn.net/weixin_53347816/article/details/123637289)\n\n后记:未根本解决,根本错误 wsl `Error: 0x80040326`,如下\n\n\n\n## 06. wsl2 Error: 0x80040326\n\n无法打开终端,报错:\n\n`Error: 0x80040326\nError code: Wsl/Service/0x80040326`\n\n解决方法:powershell 管理员模式:`wsl --update`\n\n参考:\n\n1. https://blog.csdn.net/minibirder/article/details/129863725\n2. https://blog.csdn.net/qq_37932051/article/details/129873314\n\n\n\n## 07. crond 致 sendmail 大量进程\n\n阿里云服务器监控显示 CPU 长期高负载,原因:`定时任务 crond 引发大量 sendmail 进程`\n\n参考:\n\n1. https://blog.csdn.net/LQzhang_11/article/details/114323700\n2. https://blog.51cto.com/ning235/2661806\n\n处理方法:\n\n1. cron 后面添加 `&> /dev/null` 或 `> /dev/null 2>&1`\n\n2. 禁止 cron 发用户邮件(未操作)\n\n ![image-20230905154616545](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202309051546612.png)\n\n\n\n## 08. Netlify 自动转换小写 URI\n\n现象:原 URI `/tags/Error/` 转为 `/tags/error/`\n\n解决:配置中取消 `Pretty URLs` 美化 URL 的功能\n\n- `Site configuration` → `Post processing` → `Pretty URLs` → □ `Enable Pretty URLs`\n\n示例:https://app.netlify.com/sites/mycpen-blog/configuration/deploys#pretty-urls\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202310042038361.png\" alt=\"image-20231004203836279\" style=\"zoom:25%;\" />\n\n","tags":["Error","Git"],"categories":["Error"]},{"title":"02_转载-Replit 部署 Memos & Butterfly 基于 Memos 实现清单功能","url":"/posts/10d5063.html","content":"\n\n\n## 2023/06/01 更新\n\n最近 Replit 的 Repl 出现回档现象,导致最新变更操作丢失,正如 [uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit#readme) 仓库管理者提到的 `Replit有点拉,似乎会回档,会导致数据库很多对不上。随便用用吧20220430`,回档现象我暂未找到解决办法\n\n\n\n## 参考链接\n\n- [Atticus:replit免费部署memos](https://www.iweec.cn/30.htm)(`本文转载`)\n- [Leonus:基于Memos实现说说和清单功能](https://blog.leonus.cn/2023/memeos.html#%E5%85%AD%E3%80%81%E6%B8%85%E5%8D%95%E5%8A%9F%E8%83%BD)(`本文转载 清单部分`)\n- [Leonus:基于memos实现动态相册](https://blog.leonus.cn/2023/photos.html)\n- [Atticus B站视频:replit免费部署memos](https://www.bilibili.com/video/BV1sA411679Q/)\n- [usememos/memos](https://github.com/usememos/memos)\n- [Atticus6/memos-on-replit](https://github.com/Atticus6/memos-on-replit)\n\n\n\n\n\n以下内容全文摘自 [Atticus](https://www.iweec.cn/30.htm)、[Leonus](https://blog.leonus.cn/2023/memeos.html#%E5%85%AD%E3%80%81%E6%B8%85%E5%8D%95%E5%8A%9F%E8%83%BD) 的文章\n\n\n\n## 文章1. Atticus:replit免费部署memos\n\n### 部署\n\n使用默认项目名称 `memos-on-replit`,否则会无法部署\n\n- [Run On Replit.io](https://replit.com/github/Atticus6/memos-on-replit)\n- 备用地址:https://github.com/mycpen/memos-on-replit\n\n\n\n语言必须为Go\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202302080127653.png\" alt=\"image-20230208012722551\" style=\"zoom:50%;\" />\n\n\n\n### 许可\n\n`memos-replit` 是在 AGPL-3.0 许可下许可的开源软件。\n\n\n\n### 免责声明\n\n> - 本程序为免费开源项目,旨在分享网盘文件,方便下载以及学习golang,使用时请遵守相关法律法规,请勿滥用;\n> - 本程序通过调用官方sdk/接口实现,无破坏官方接口行为;\n> - 本程序仅做302重定向/流量转发,不拦截、存储、篡改任何用户数据;\n> - 在使用本程序之前,你应了解并承担相应的风险,包括但不限于账号被ban,下载限速等,与本程序无关;\n> - 如有侵权,请通过[邮件](mailto:a@iweec.cn)与我联系,会及时处理。[@博客](https://www.iweec.cn/) · [@GitHub](https://github.com/Atticus6) · [@Telegram群](https://t.me/+z76QXxWq23U3NTU9)\n>\n> 版权属于: atticus\n> 本文链接: https://www.iweec.cn/30.htm\n\n\n\n\n\n## 文章2. Leonus:基于Memos实现说说和清单功能\n\n相关链接\n\n1. [Leonus:基于Memos实现说说和清单功能](https://blog.leonus.cn/2023/memeos.html#%E5%85%AD%E3%80%81%E6%B8%85%E5%8D%95%E5%8A%9F%E8%83%BD)\n2. [Leonus:基于memos实现动态相册](https://blog.leonus.cn/2023/photos.html)\n\n\n\n以下内容全文摘自 [Leonus:基于Memos实现说说和清单功能](https://blog.leonus.cn/2023/memeos.html#%E5%85%AD%E3%80%81%E6%B8%85%E5%8D%95%E5%8A%9F%E8%83%BD) `清单功能` 部分\n\n\n\n**清单功能**\n\n> 再次说明,这一切只是我定的规则而已,你可以随意修改代码来实现你想实现的效果。\n\n\n\n### 实现\n\n还是先使用`hexo n page xxx`创建页面。\n然后粘贴如下代码并按照注释修改内容。\n\n\n\n```markdown\n<style>\n/* 页面初始化 */\ndiv#page {\n background: none;\n border: 0;\n padding: 0;\n}\n[data-theme=dark] #twikoo .tk-content,\n#twikoo .tk-content {\n padding: 0;\n background: transparent;\n}\n\n.tk-comments-container>.tk-comment,\n.tk-submit:nth-child(1){\n background: var(--card-bg);\n border: 1px rgba(188, 188, 188, 0.8) solid;\n box-shadow: 0 5px 10px rgb(189 189 189 / 10%);\n transition: all .3s ease-in-out;\n border-radius: 12px;\n}\n\n.tk-comments-container>.tk-comment:hover,\n.tk-submit:nth-child(1):hover {\n border-color: #6dc3fd;\n}\n\n.tk-submit {\n padding: 20px 10px 0;\n}\n\n.tk-comments-container>.tk-comment {\n padding: 15px;\n}\n\n/* 页面初始化结束 */\ndiv#todolist {\n display: flex;\n flex-wrap: wrap;\n margin-top: 1rem;\n}\n.list_item {\n display: inline-block;\n width: calc(50% - .4rem);\n background: #ffe3dd;\n border-radius: 12px;\n padding: 10px 1rem 1.2rem;\n border: 2px dashed #f7a796;\n --todo-border: 1px solid #f7a796;\n margin-right: 1rem;\n margin-bottom: 1rem;\n}\n.list_item h3 {\n margin: 0;\n border-bottom: var(--todo-border);\n}\n.list_item ul {\n font-size: 17px;\n padding: 0 !important;\n margin: 0;\n}\n .list_item li{\n margin: 0 !important;\n border-bottom: var(--todo-border);\n }\n.list_item li::marker {\n content: none;\n}\nli.achieve {\n opacity: .8;\n text-decoration: line-through;\n}\n@media screen and (max-width: 900px) {\n div#todolist {\n margin: 1rem 5px 0;\n }\n}\n@media screen and (max-width: 768px) {\n .list_item{\n width: 100%;\n }\n}\n</style>\n\n\n<div id=\"todolist\"></div>\n\n\n<script>\n// 瀑布流函数,不用管\nfunction waterfall(t){function e(t,e){var n=window.getComputedStyle(e);return parseFloat(n[\"margin\"+t])||0}function n(t){return t+\"px\"}function r(t){return parseFloat(t.style.left)}function o(t){return t.clientWidth}function l(t){return function(t){return parseFloat(t.style.top)}(t)+function(t){return t.clientHeight}(t)+e(\"Bottom\",t)}function i(t){return r(t)+o(t)+e(\"Right\",t)}function u(t){t=t.sort((function(t,e){return l(t)===l(e)?r(e)-r(t):l(e)-l(t)}))}function a(e){o(t)!=h&&(e.target.removeEventListener(e.type,arguments.callee),waterfall(t))}\"string\"==typeof t&&(t=document.querySelector(t));var s=[].map.call(t.children,(function(t){return t.style.position=\"absolute\",t}));t.style.position=\"relative\";var f=[];s.length&&(s[0].style.top=\"0px\",s[0].style.left=n(e(\"Left\",s[0])),f.push(s[0]));for(var p=1;p<s.length;p++){var c=s[p-1],y=s[p];if(!(i(c)+o(y)<=o(t)))break;y.style.top=c.style.top,y.style.left=n(i(c)+e(\"Left\",y)),f.push(y)}for(;p<s.length;p++){u(f);y=s[p];var d=f.pop();y.style.top=n(l(d)+e(\"Top\",y)),y.style.left=n(r(d)),f.push(y)}u(f);var v=f[0];t.style.height=n(l(v));var h=o(t);window.addEventListener?window.addEventListener(\"resize\",a):document.body.onresize=a}\n\n// 清单函数\ntodolist();\nfunction todolist() {\n fetch('https://你的memos地址/api/memo?creatorId=1&tag=清单').then(res => res.json()).then(data => { // 注意替换链接\n // 获取并处理数据\n data = data.data\n let box = document.getElementById('todolist')\n data.forEach(item => {\n // 处理数据\n let content = item.content,\n title = content.match(/\\[(.*?)\\]/g)[0].replace(/\\[(.*?)\\]/,'$1');\n // 去掉多余内容,替换清单内容\n content = content.replace(/#.*\\s/g, '').replace(/(-\\s\\[\\s\\]\\s)(.*)/g, `<li><i style=\"margin-right: 5px;\" class=\"fa-regular fa-circle\"></i>$2</li>`).replace(/(-\\s\\[x\\]\\s)(.*)/g, `<li class=\"achieve\"><i style=\"margin-right: 5px;\" class=\"fa-regular fa-circle-check\"></i>$2</li>`);\n // 渲染数据\n let div = document.createElement('div');\n div.className = 'list_item';\n div.innerHTML = `<h3>${title}</h3><ul>${content}</ul>`;\n box.appendChild(div);\n });\n waterfall('#todolist');\n }).catch()\n}\n</script>\n```\n\n\n\n### 使用\n\n使用的格式如下:\n\n\n\n```markdown\n#清单 [想去的地方]\n- [ ] 轻笑的米奇妙妙屋(轻笑让我加的)\n- [x] 已完成的清单\n```\n\n\n\n注意,前面的`#清单 `是固定的。标题用中括号包起来。已完成的将括号内的空格改成x即可。\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202302080138164.png\" alt=\"image-20230208013833064\" style=\"zoom: 50%;\" />\n\n\n\n> 文章作者: [Leonus](https://blog.leonus.cn/)\n> 文章链接: https://blog.leonus.cn/2023/memeos.html\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n","tags":["Replit","转载","Memos"],"categories":["转载"]},{"title":"09_Hexo-Replit 搭建 Uptime Kuma 监控服务","url":"/posts/27addd89.html","content":"\n\n\n## 2023/10/01 更新\n\nReplit 上的 Repl 报错,重新搭建 Uptime Kuma\n\n参考自 [梦念逍遥:使用Replit平台免费搭建站点监控工具——Uptime-Kuma](https://blog.mnxy.eu.org/posts/uptime)\n\n1. [Replit](https://replit.com/) 导入仓库 `louislam/uptime-kuma`,语言 `Bash`\n\n2. .replit 即首次配置弹出的输入框 Configure the Run Command 输入 `node server/server.js`\n\n3. Shell 终端输入 `node`,选择 nodejs-16_x.out\n\n4. Shell 终端输入以下内容,指定版本 1.21.3\n\n ```bash\n git fetch --all\n git checkout 1.21.3 --force\n npm run setup\n ```\n\n5. 点击 Run\n\n\n\n## 2023/06/01 更新\n\n最近 Replit 的 Repl 出现回档现象,导致最新变更操作丢失,正如 [uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit#readme) 仓库管理者提到的 `Replit有点拉,似乎会回档,会导致数据库很多对不上。随便用用吧20220430`,回档现象我暂未找到解决办法\n\n\n\n## 1. 前言\n\n打算监控博客友链的存活情况(不太礼貌的行为<img class=\"inline-img\" src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/blog/link/blog.zhheo.com/sticker-heo/Sticker-100/%E8%A2%AB%E6%89%93.png\" style=\"height:30px; border: unset;\">),因 [UptimeRobot](https://uptimerobot.com/) 免费版有 50 monitors 的限制,转而使用 [Uptime Kuma](https://github.com/louislam/uptime-kuma),[官方 readme](https://github.com/louislam/uptime-kuma#-how-to-install) 介绍了 Docker、Non-Docker 两者安装方式\n\n由 [uptime-kuma/issues/1472](https://github.com/louislam/uptime-kuma/issues/1472) 及 [butterfly 魔改群](https://jq.qq.com/?_wv=1027&k=5o4Iga8D) 群友获知 [Replit](https://replit.com/) 可以搭建 Uptime Kuma;根据 [issues #1472](https://github.com/louislam/uptime-kuma/issues/1472) 给出的步骤并未顺利搭建(体质问题吧),进而继续百度\n\n由 [B站视频:Uptime Kuma…replit…](https://www.bilibili.com/video/BV16P4y197FN/) 获知仓库 [valetzx/uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit)(Replit 下搭建的很顺利)\n\n由 [B站视频:Replit…绑定…域名](https://www.bilibili.com/video/BV1aP411K7b3/) 获知 Replit 下服务绑定自定义域名\n\n搭建效果见 [Mycpenの友链检测](http://status1.cpen.top/status/link)\n\n\n\n## 2. 搭建步骤\n\n**主要步骤**:Replit 导入 [valetzx/uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit) 项目\n\n搭建步骤:\n\n1. 注册 [Replit](https://replit.com/)\n\n2. Replit 导入 [valetzx/uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit) 仓库\n\n - 按 [valetzx/uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit) readme 操作:\n\n - Replit 个人版:点击 [Run on Replit](https://repl.it/github/valetzx/uptimekumaonreplit) 导入 Replit\n\n - 当加载完 Loading Nix environment... 后点击绿色 ▶ Run\n\n3. Replit 服务绑定自定义域名\n\n 按 [B站视频:Replit…绑定…域名](https://www.bilibili.com/video/BV1aP411K7b3/) 操作:在 Replit Webview 窗口右侧按钮下(如下图),绑定自定义域名,并按提示在域名服务商 DNS 控制台进行解析\n\n <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202301311404922.png\" alt=\"image-20230131122911248\" style=\"zoom: 25%;\" />\n\n\n\n至此,搭建结束。可以通过 自定义域名 前往 Uptime Kuma 仪表盘进行 注册、设置、新增状态页、添加监控项、状态页分组绑定监控项\n\n\n\n## 3. 注意点\n\n1. 监控类型为 `HTTP(s)` 时,`HTTP 选项 - 方法` 选择 `HEAD` 验证存活(不要使用默认的 GET,GET 会对对应服务造成 `大量无意义的流量`)\n\n2. 心跳间隔 (检测频率) 建议`拉长`(不要使用默认的 60s,会对对应服务造成 `大量无意义的流量`)。以我为例,设置了 `86400 秒`(即 1 天监控 1 次)\n\n以我为例 `监控项` 变动了 4 处值,如下图\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202301311243386.png\" alt=\"image-20230131124355253\" style=\"zoom: 33%;\" />\n\n\n\n<br>\n\n若网站屏蔽了 Uptime Kuma 的 UA,例如此文 [如何禁止 Uptime Kuma 监控网站](https://blog.zhheo.com/p/9540801e.html),可以配置 `请求头` 来解决,参考自 [张洪Heo.评论区](https://blog.zhheo.com/p/9540801e.html#d102f6ee4dbe4242a1a545d6ce8b9654)\n\n\n\n```json\n{\n \"User-Agent\": \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36\"\n}\n```\n\n\n\n## 4. 参考链接\n\n[louislam/uptime-kuma](https://github.com/louislam/uptime-kuma)\n\n[* valetzx/uptimekumaonreplit](https://github.com/valetzx/uptimekumaonreplit)\n\n[louislam/uptime-kuma/issues/1472](https://github.com/louislam/uptime-kuma/issues/1472)\n\n[B站视频:Uptime Kuma…replit…](https://www.bilibili.com/video/BV16P4y197FN/)\n\n[B站视频:Replit…绑定…域名](https://www.bilibili.com/video/BV1aP411K7b3/)\n\n[valetzx:在Replit中自建监控网站(未参考)](https://blog.learnonly.xyz/p/c99d.html)(uptimekumaonreplit 仓库作者的文章,介绍了些监控报警通知。个人未配置)\n\n\n\n\n\n","tags":["Hexo","Replit"],"categories":["Hexo"]},{"title":"08_Hexo-博客引用 B站鸿蒙字体","url":"/posts/df249111.html","content":"\n## 2022/12/31 更新\n\n在 [butterfly.zhheo.com](https://butterfly.zhheo.com/docs/font.html) 上看到下面这篇文章,介绍了很多其他字体(包括本文B站鸿蒙字体),写的很好\n\n[免费引入**黑体字体系列整理及 CSS 字体](https://www.thyuu.com/word/tips/62610)\n\n\n\n## 1. 前言\n\n在 [Eurkon](https://blog.eurkon.com/) 那发现了B站使用的 `harmonyOS_Regular` 字体,[B站网页端](https://www.bilibili.com/) 打开开发者工具能看到字体由 [regular.css](https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css) 引入\n\n计划用一段时间该字体,如有明显限速再停止使用\n\n\n\n## 2. 引用步骤\n\n1. 自定义css 引入 [regular.css](https://s1.hdslb.com/bfs/static/jinkela/long/font/regular.css) 内容\n\n2. 自定义css 追加使用该字体的 css,以我的站点为示例(`Butterfly 主题可跳过,直接步骤 3`)\n\n ```css\n /* 字体样式 */\n body {\n font-family: HarmonyOS_Regular,-apple-system,BlinkMacSystemFont,'Segoe UI','Helvetica Neue',Lato,Roboto,'PingFang SC','Microsoft YaHei',sans-serif;\n }\n ```\n\n3. Butterfly 主题内置了自定义字体的配置,参见 [官方文档_自定义字体和字体大小](https://butterfly.js.org/posts/ceeb73f/#%E8%87%AA%E5%AE%9A%E7%BE%A9%E5%AD%97%E9%AB%94%E5%92%8C%E5%AD%97%E9%AB%94%E5%A4%A7%E5%B0%8F)\n\n 示例:修改主题配置文件,如 [Blogroot]/_config.butterfly.yml\n\n ```diff\n # Don't modify the following settings unless you know how they work (非必要不要修改)\n font:\n global-font-size:\n code-font-size:\n - font-family: \n + font-family: HarmonyOS_Regular,-apple-system,BlinkMacSystemFont,'Segoe UI','Helvetica Neue',Lato,Roboto,'PingFang SC','Microsoft YaHei',sans-serif\n code-font-family:\n ```\n\n 个人建议:代码字体不建议使用 HarmonyOS_Regular,主题原生的 consolas 字体更好看\n\n\n\n## 3. 后记\n\n手机上唯二浏览器之一的 某浏览器 出现站内跳转时,页面长时间加载不出来的情况,考虑到 B站 对外站限速的可能性(排除法,大概率浏览器问题,同机的另一个浏览器不会复现🤔),备用方案:字体放 Github 个人仓库中,通过 [staticaly](https://statically.io/) CDN 进行免费加速使用\n\n该字体已同步至 [个人仓库](https://github.com/mycpen/CDN/tree/main/font/s1.hdslb.com/bfs/static/jinkela/long/font)\n\n由 [Fomalhaut🥝](https://www.fomal.cc/posts/b48804d5.html#4-1-%E5%8F%AF%E7%94%A8%E7%9A%84%E5%85%8D%E8%B4%B9CDN%E9%80%89%E6%8B%A9) 获知 staticaly CDN 的使用,引用内容如下\n\n> 原文地址:[https://www.fomal.cc/](https://www.fomal.cc/posts/b48804d5.html#4-1-%E5%8F%AF%E7%94%A8%E7%9A%84%E5%85%8D%E8%B4%B9CDN%E9%80%89%E6%8B%A9)\n>\n> 官网地址:https://www.staticaly.com\n> 轻松地从GitHub / GitLab / Bitbucket等加载您的项目 没有流量限制或限制。\n>\n> 文件通过超快速全球CDN提供。 在URL(不是分支)中使用特定标记或提交哈希。\n> 根据URL永久缓存文件。 除master分支外,文件在浏览器中缓存1年。 具体用法:\n\n```\n# GitHub CDN\nhttps://cdn.staticaly.com/gh/:user/:repo/:tag/:file\nhttps://cdn.staticaly.com/gh/growvv/growvv.github.io/master/README.md\n\n# GitLab CDN\nhttps://cdn.staticaly.com/gl/:user/:repo/:tag/:file\n\n# Bitbucket CDN\nhttps://cdn.staticaly.com/bb/:user/:repo/:tag/:file\n\n# WordPress CDN\nhttps://cdn.staticaly.com/wp/c/:version/wp-includes/:file \nhttps://cdn.staticaly.com/wp/p/:plugin_name/:version/:file \nhttps://cdn.staticaly.com/wp/t/:theme_name/:version/:file\n\n# Imgpx CDN\nhttps://cdn.staticaly.com/img/:image_url\n\n# Favicons CDN\nhttps://cdn.staticaly.com/favicons/:favicon_url\n```\n\n\n\n总结:staticaly CDN 作为免费 CDN,速度勉强还行\n\n![image-20221228131708176](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212281317244.png)\n\n\n\n## 4. 字体样式总结\n\n相较于 [Butterfly](https://butterfly.js.org/) 主题原字体,harmonyOS_Regular 字体左右间距略变大,字母略变明显,汉字略细密\n\n总结:感知不强,徒增功耗 😂\n\n`主题原字体(Segoe UI)`\n\n![image-20221228133644745](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212281336799.png)\n\n`harmonyOS_Regular 字体`\n\n![image-20221228133740948](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212281337989.png)\n","tags":["Hexo","字体"],"categories":["Hexo"]},{"title":"07_Hexo-插件整理","url":"/posts/4c16ee73.html","content":"**目录3 为转载内容**,原文:[Justlovesmile_Hexo博客 | 插件推荐](https://blog.justlovesmile.top/posts/86111745.html)\n\n## 1. 较为关注\n\n### 1.1 hexo-blog-encrypt\n- 博客文章加密,由 [Justlovesmile文章](https://blog.justlovesmile.top/posts/43010.html) 获知\n- [Github地址](https://github.com/D0n9X1n/hexo-blog-encrypt)\n\n\n\n### 1.2 hexo-hide-posts\n- 隐藏 Hexo 文章,由 [Butterfly issue#1122](https://github.com/jerryc127/hexo-theme-butterfly/pull/1122)、[issue#1119](https://github.com/jerryc127/hexo-theme-butterfly/issues/1119) 获知\n- [Github地址](https://github.com/prinsss/hexo-hide-posts)\n\n\n\n### 1.3 hexo-renderer-markdown-it\n- 渲染引擎,由 [Butterfly文档](https://butterfly.js.org/posts/ceeb73f/#Math-%E6%95%B8%E5%AD%B8) 获知,由 [Echocbx](https://ezgx.tk/posts/65320/) 获知 plugins 配置项\n- [Github地址](https://github.com/hexojs/hexo-renderer-markdown-it)\n\n\n\n### 1.4 @upupming/hexo-renderer-markdown-it-plus\n- 渲染引擎,由 [Butterfly文档](https://butterfly.js.org/posts/ceeb73f/#Math-%E6%95%B8%E5%AD%B8) 获知\n- [Github地址](https://github.com/upupming/hexo-renderer-markdown-it-plus)\n\n\n\n### 1.5 hexo-renderer-markdown-it-katex\n- 渲染引擎,由 [Nick Xu](https://www.nickxu.top/2022/04/17/Hexo-Butterfly-%E5%BB%BA%E7%AB%99%E6%8C%87%E5%8D%97%EF%BC%88%E5%85%AB%EF%BC%89%E4%BD%BF%E7%94%A8-KaTeX-%E6%95%B0%E5%AD%A6%E5%85%AC%E5%BC%8F/) 获知\n- [Github地址](https://github.com/Abreto/hexo-renderer-markdown-it-katex)\n\n\n\n## 2. Butterfly主题\n\n### 2.1 hexo-butterfly-swiper\n- 轮播图,作者:[Akilar](https://akilar.top/posts/8e1264d1/);二创:[安知鱼](https://blog.anheyu.com/posts/sdxhu.html#hexo-butterfly-swiper-anzhiyu-%E6%8F%92%E4%BB%B6%E5%AE%89%E8%A3%85)\n\n### 2.2 hexo-butterfly-categories-card\n- 分类磁铁,[Akilar](https://akilar.top/posts/a9131002/)\n\n### 2.3 hexo-circle-of-friends\n- 友链朋友圈,https://fcircle-doc.js.cool/#/\n- 非插件\n\n### 2.4 hexo-butterfly-article-double-row\n- 文章双栏,[小冰](https://zfe.space/post/hexo-butterfly-article-double-row.html)\n\n### 2.5 hexo-butterfly-charts\n- 统计图表,[Guo Le](https://guole.fun/posts/18158/)\n\n\n## 3. 以下内容摘自 Justlovesmile\n\n原文:[Justlovesmile_Hexo博客 | 插件推荐](https://blog.justlovesmile.top/posts/86111745.html)\n\n\n\n| 插件 | 功能 | 文档链接 |\n| ---------------------------- | -------------------------------------------------------- | ------------------------------------------------------------ |\n| hexo-generator-index-pin-top | 文章置顶 | https://github.com/netcan/hexo-generator-index-pin-top |\n| hexo-wordcount | 文章字数统计和阅读时长统计 | https://github.com/willin/hexo-wordcount |\n| hexo-abbrlink | 生成URL短链接 | https://github.com/rozbo/hexo-abbrlink |\n| hexo-lazyload-image | 图片懒加载 | https://github.com/Troy-Yang/hexo-lazyload-image |\n| hexo-generator-baidu-sitemap | 生成baidusitemap.xml | https://github.com/coneycode/hexo-generator-baidu-sitemap |\n| hexo-generator-sitemap | 生成sitemap.xml | https://github.com/hexojs/hexo-generator-sitemap |\n| hexo-generator-feed | 生成RSS文件 | https://github.com/hexojs/hexo-generator-feed |\n| hexo-external-link | 外链跳转 | https://github.com/hvnobug/hexo-external-link |\n| hexo-autonofollow | 自动对外部链接增加nofollow属性 | https://github.com/liuzc/hexo-autonofollow |\n| hexo-filter-nofollow | 为外链添加 `rel=\"noopener external nofollow noreferrer\"` | https://github.com/hexojs/hexo-filter-nofollow |\n| hexo-prism-plugin | 代码高亮 | https://github.com/ele828/hexo-prism-plugin |\n| hexo-neat | 博客压缩 | https://github.com/rozbo/hexo-neat |\n| hexo-allminifier | 博客压缩 | https://developer.aliyun.com/mirror/npm/package/hexo-all-minifier |\n| hexo-tag-aplayer | aplayer音乐播放器 | https://github.com/MoePlayer/hexo-tag-aplayer |\n| hexo-tag-dplayer | dplayer视频播放器 | https://github.com/MoePlayer/hexo-tag-dplayer |\n| hexo-douban | 添加豆瓣读书,电影,游戏页面 | https://github.com/mythsman/hexo-douban |\n| hexo-generator-searchdb | 本地搜索,生成search.xml | https://github.com/theme-next/hexo-generator-searchdb |\n| hexo-algoliasearch | 搜索系统 | https://github.com/LouisBarranqueiro/hexo-algoliasearch |\n| hexo-algolia | 搜索系统 | https://github.com/oncletom/hexo-algolia |\n| hexo-generator-search | 本地搜索系统 | https://github.com/wzpan/hexo-generator-search |\n| hexo-baidu-url-submit | 百度站长主动推送 | https://github.com/huiwang/hexo-baidu-url-submit |\n| hexo-offline | 开启PWA | https://github.com/JLHwung/hexo-offline |\n| hexo-pwa | 开启PWA | https://github.com/lavas-project/hexo-pwa |\n| hexo-helper-live2d | 看板娘 | https://github.com/EYHN/hexo-helper-live2d |\n| hexo-addlink | 文末添加当前文章链接和版权声明 | https://github.com/acwong00/hexo-addlink |\n| hexo-blog-encrypt | 博客文章加密 | https://github.com/MikeCoder/hexo-blog-encrypt |\n| hexo-simple-mindmap | 博客添加脑图 | https://github.com/HunterXuan/hexo-simple-mindmap |\n| hexo-pdf | 博客展示pdf | https://github.com/superalsrk/hexo-pdf |\n| hexo-tag-echarts | 博客添加图表 | https://github.com/zhoulvjun/hexo-tag-echarts |\n| hexo-steam-games | 添加Steam游戏界面 | https://github.com/HCLonely/hexo-steam-games |\n| hexo-bilibili-bangumi | 添加bilibili番剧页面 | https://github.com/HCLonely/hexo-bilibili-bangumi |\n| hexo-generator-random | 生成随机文章页面 | https://github.com/Drew233/hexo-generator-random |\n| hexo-web-push-notification | web推送插件 | https://github.com/glazec/hexo-web-push-notification |\n\n","tags":["Hexo","插件"],"categories":["Hexo"]},{"title":"06_Other-Windows 图片批量压缩工具 ultra-tinypng","url":"/posts/b7f58a40.html","content":"\n\n## 2023-07-11 作者更新\n\n> fix:修复了tinypng官方修改了校验策略导致批量上传会报错为问题,解决方法是降低频率到单线程5秒一次\n> 详见issue:[#1](https://github.com/libudu/ultra-tinypng/issues/1)\n>\n> 引自:https://github.com/libudu/ultra-tinypng/releases/tag/v0.4\n\n\n\n## 1. 前言\n\n在 [B站](https://www.bilibili.com/video/BV1ve4y1C7im/) 上发现了这款 Win 平台图片压缩工具\n\n优点:\n\n1. 作者:本项目基于[super-tinypng](https://github.com/zhanyuzhang/super-tinypng),在原项目基础上加入了打包开箱即用、递归目录、线程池、重复跳过的功能。 项目的原理是程序化处理文件,调用[tinypng](https://tinypng.com/)的接口进行文件压缩。\n\n遗憾点:\n\n1. 图片后缀需为 PNG或JPG\n2. 需小于5MB\n3. Windows 平台工具(exe)\n\n\n\n## 2. 下载地址\n\n视频介绍:[B站:【开源工具】图片素材一键批量压缩 untra-tinypng](https://www.bilibili.com/video/BV1ve4y1C7im/)\n\n项目源码:[Github](https://github.com/libudu/ultra-tinypng)\n\n工具下载:[Release](https://github.com/libudu/ultra-tinypng/releases)\n\n\n\n## 3. 相关及其他压缩工具\n\n[TinyPNG](https://tinypng.com/)\n\n[Imagine](https://github.com/meowtec/Imagine/releases)\n\n\n\n## 4. 鸣谢\n\n开发者:[linpicio](https://github.com/libudu)\n\n","tags":["Other","TinyPNG"],"categories":["Other"]},{"title":"01_转载-图床搭建 Backblaze B2 + Cloudflare CDN","url":"/posts/16589f92.html","content":"\n\n\n## 相关链接\n\n1. [BlazeB2 - 基于 BackBlazeB2 和 Cloudflare 的图床工具(未使用)](https://blazeb2.js.org/)\n\n\n\n## 转载文章\n\n1. [Backblaze B2 + Cloudflare CDN可自定义域名的10G高速免费外链图床](https://www.coca.cc/mf/37.html)\n\n2. [使用Backblaze B2 + Cloudflare CDN + PicGo实现可自定义域名的10G免费图床解决方案](https://blog.winer.website/archives/use_blackblaze_b2_and_cloudflare_cdn_to_bulid_a_free_oss.html)\n\n3. [使用Backblaze B2和Cloudflare作为免费图床](https://blog.bloade.com/2022/06/20/%E4%BD%BF%E7%94%A8backblaze-b2%E5%92%8Ccloudflare%E4%BD%9C%E4%B8%BA%E5%85%8D%E8%B4%B9%E5%9B%BE%E5%BA%8A/)\n\n\n感谢 [ReCreyed](https://recreyed.tk/) 的分享。以下内容全文摘自上面 3 篇文章\n\n\n\n## 文章1:Backblaze B2 + Cloudflare CDN\n\n本博客其他文章使用的都是github图床,无意中发现了B2+CF+ShareX的自建图床方案,而且还可以自定义域名,所以就有了这篇文章,本文所有图片全部来自这种方法的图床。\n\n图床指的就是储存图片的服务器,网站管理员为了方便维护和管理,会将图片存放在专门的服务器集群里,通常还会在外层套层 CDN 做分发。市面上的公开图床很多,例如 imgur、sm.ms、imgbox 等等,这些图床都开放了 API 方便开发者调用。不过由于运营成本问题,也有不少图床相继倒闭或者转入收费。\n\n怎么自建图床?如果是有VPS主机服务器,安装个Chevereto 开源图床网站程序即可。但这是VPS单纯用来做图床给博客外链图片用,有点浪费且不易长久。图片存储最好是放在大公司的云服务平台上, Backblaze B2 是一个云存储解决方案,类似于Amazon AWS S3, 但是价格稍微便宜一些. Backblaze的云存储每个注册用户拥有10G免费空间以及每天1G的下载流量,上传流量不限。超过免费额度后的价格以及与其他几家主流商家的对比见下图。\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234175.png)\n\n\n\n\n\n在backblaze存储1T的内容也仅需$5/月,不过流量费还是比较贵的 ,上传流量不限。 由于 [Bandwidth Alliance(带宽联盟)](https://www.cloudflare.com/bandwidth-alliance/),Backblaze 到 Cloudflare 之间的出口是完全免费的, 所以Backblaze B2可以配合cloudflare CDN来使用达到无限免费下载流量。\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234730.png)\n\n\n\n\nBackblaze宣布与Cloudflare合作,免除掉Backblaze到Cloudflare的流量费用。\n\n\n\n因此我们得到如下网盘/图床产品:\n\n- 10G存储空间免费, 全球最可靠的云存储服务\n\n- 上行免费\n\n- 下行免费\n\n- 可自定义域名\n\n- 全球最强CDN加速\n\n \n\n### 搭建自定义域名图床教程开始\n\n首先,你需要有一个域名,选择一个子域名作为图床的域名。 关于图床的二级域名命名,一般有以下几种:\n\n- img\n- images\n- assets\n- static (不仅存放图片,还有存放 css、js)\n\n然后,创建 Backblaze B2 Bucket(存储桶) 。\n\n在[Backblaze’s B2 storage](https://www.backblaze.com/) 注册一个账号,注册好了后,在后台面板选择 “Buckets”(存储桶),然后点击 “Create a Bucket”,创建一个存储桶。选Public,以便所有人可访问。\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234897.png)\n\n\n\n\n\n然后,回到 “Buckets(存储桶)” , 在你刚刚创建的存储桶上,点击 “Upload/Download(上传/下载)”. 上传一个临时的测试文件到存储桶中,然后在你刚上传的文件处,点击 “i(information,信息)”. 这是为了获取下一步需要的信息,你的存储桶处于哪台服务器上.\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234770.png)\n\n\n\n\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234174.png)\n\n\n\n\n\n在上面的截图中,可以看到,我的文件是放在 https://f000.backblazeb2.com/ – 记住这个域名\n最后,获取到地址之后就登录cloudflare,给你的域名添加一个子域名,并新增一条cname记录,指向文件地址中的域名,例如将img.coca.cc通过cname到f000.backblazeb2.com,效果便是https://img.coca.cc/file/imgsgj/img.jpg 指向 https://f001.backblazeb2.com/file/imgsgj/img.jpg\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234496.png)\n\n\n\n\n\n根据上面截图中的记录, 我使用这个子域名 img.coca.cc作为图床的域名, 并且指向 f000.backblazeb2.com. 确保 Cloudflare 橙色保护盾是开启的状态, 这代表请求是通过了 Cloudflare 的 CDN 代理层. Cloudflare 默认的 TTL 将被设置为 auto(自动).\n\n虽然启用了CloudFlare CDN,但发现缓存永远不能命中(MISS),我们需要对添加一个缓存指令(默认是不缓存),打开存储桶设置,桶信息设置为{\"cache-control\":\"max-age=43200\"},其中43200单位为秒(s),意思就是说43200秒内CF不会去从源站重新获取资源。\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234558.png)\n\n\n\n\n\nCloudfalre的ssl设置需要使用full,因为backblaze仅提供https访问地址。\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234323.png)\n\n\n\n\n\n当然你如果觉得文件链接不好看太长了,你也可以使用cloudflare自带的页面规则301 ,缩短链接地址,比如通过 https://img.coca.cc/img.jpg 直接访问 https://f001.backblazeb2.com/file/imgsgj/img.jpg 。\n例:\n匹配规则 https://img.coca.cc/*\n重定向网址到 https://f001.backblazeb2.com/file/imgsgj/$1\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234511.png)\n\n\n\n\n\n加一条页面缓存规则\n\n![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262234756.png)\n\n\n\n\n\n最后,请注意:Backblaze B2 流出到 Cloudflare 的流量是免费的,也就是说就算 CF 回源 B2 也没有 $0.01/GB 的流出流量费,相当于免费无限流量。不过这并不能阻止坏蛋直接用 B2 的域名(而不是套了 CF 的域名)刷流量。\n\n\n\n最后修改:2021 年 03 月 01 日\n\n\n\n## 文章2:Backblaze B2 + Cloudflare CDN + PicGo\n\n### 前言\n\n近期,由于服务器需要扩展功能,以及阿里云推送日志时有所不便决定重新购买服务器并部署相关网站和服务。决定趁此机会对图片存储进行规范,由于网站未备案,国内的阿里云OSS+阿里云CDN、又拍云、七牛云等厂家提供的服务无法享受,只能将目光转向国外。\n\n原本使用Github+JSDelivr是一个很好的免费图床解决方案,且网上教程也很多,但2020年8月9日JSDelivr发布的新使用政策中第四条引起讨论\n\n```text\n4. Prohibited Use\n\nThe following behavior is prohibited:\n\n 1. Hosting or accessing content that:\n - contains malware or harmful code in any form,\n - violates proprietary rights of others,\n - is sexually explicit,\n - is potentially illegal in the EU or the USA.\n\n 2. Abusing the service and its resources, or using jsDelivr as a general-purpose\n file or media hosting service. This includes, for example:\n - running an image hosting website and using jsDelivr as a storage for all\n uploaded images,\n - hosting videos, file backups, or other files in large quantities.\n\n We recognize that there are legitimate projects that consist of a large number\n of files, and these are not considered abuse. For example: icons packs, apps,\n or games with a large number of assets.Copy\n```\n\n`running an image hosting website and using jsDelivr as a storage for all uploaded images`这句话有所歧义,因为无法判断个人博客和文章上传的图片数量和访问量是否会被判定为图片存储站,导致封禁或删除数据,只能寻求其余解决方案。\n\n此时发现[Cloudflare Bandwidth Alliance宽带联盟宽带联盟](https://www.cloudflare.com/zh-cn/bandwidth-alliance/)中包含Backblaze,Backblaze到Cloudflare的所有出口流量完全免费。再加上Backblaze对个人用户提供10G的免费存储额度,每天1G的下载量与无限上传量。我们可以同时使用两者达到10G免费额度与不限量上传下载。\n\n![3961390e212619b300d72abb1c6d7467-NyquapNRbB](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262252472.png)\n\n\n\n在超过免费存储额度之后,相比其他几家国外主流OSS服务提供商,Backblaze的价格也较为低廉,唯一的缺点是目前只支持信用卡支付。\n\n![92f663d63338db8becab34b40760b0c3-i5xUgrOY5D](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262253539.png)\n\n### 前置条件\n\n1. 一个域名~ 最好是一级域名,即xxx.xxx这种类型的。搜索任意域名供应商即可购买,比较推荐NameSlio,支持支付宝付款,免费的Whois隐私保护,同时价格便宜。`.com`域名每年仅需要9.95美金,如果不是很在乎可以买其他后缀只买首年,2美金一年。免费域名也有一些可以申请,比较出名的就是freenom的域名了,不过听说今年Cloudflare的免费服务不再支持免费域名,所以只能自己试试是否能够成功。\n\n### Backblaze OSS部分\n\n1. 从[此处](https://www.backblaze.com/b2/cloud-storage.html)进入,创建Backblaze账号并完善相关信息,直接从首页进入可能没有Sing Up选项\n2. 从[此处](https://secure.backblaze.com/b2_buckets.htm)进入控制台,创建Buckets存储桶存储桶\n3. 给存储桶起一个名字方便识别且不易被猜测即可,无需在意生成的图片链接长短,后续可以进行重定向方便识别且不易被猜测即可,无需在意生成的图片链接长短,后续可以进行301重定向,并将`Files in Bucket are`修改为`Public`\n **注意:给存储桶起名时尽量起不易被别人猜测的名字,可在其中增加部分随机字符,如`c42rx71-example-winer-website`,因为在存储桶的模式为Public时,别人只需知道你的OSS服务提供商+存储桶名称+其中一个文件名,即可拼凑出文件真实链接,从而绕过CDN刷空你的免费流量,如果有绑定支付方式还会扣费。**\n\n![80ddd93eafadbb256b763fa1ae4e0757-image-20210914161619618](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262253084.png)\n\n\n\n1. 点击`Upload/Download`上传一张图片或临时文件,用于后续获取存储桶所在的服务器地址\n2. 从左侧菜单栏的`Browse Files`进入刚刚的存储桶并找到上传的文件,点击查看详细信息,记住`Friendly URL`行的链接内容\n\n\n\n![a875ac31d761acd0f2d4e23a2c4d500d-image-20210914161911330](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262254668.png)\n\n\n\n3. 从`Friendly URL`的链接可以看到我们的存储桶位于`https://f002.backblazeb2.com/`,而`/file/example-winer-website`则是存放文件目录的相对路径,记住这两个值后登陆Cloudflare进行设置。\n\n \n\n### Cloudflare部分\n\n1. 打开[Cloudflare官网](https://www.cloudflare.com/zh-cn/)并进行注册\n2. 根据提示前往域名注册商修改DNS解析服务器到Cloudflare提供给你的服务器地址不同用户地址不同不同用户地址不同,个人使用选择免费计划即可\n\n\n\n![c4693f6f0580b728b9315b2754d10d7d-image-20210911163637613](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262255445.png)\n\n\n\n\n\n\n\n3. 添加一条CNAME记录到你刚刚得到的存储桶服务器,二级域名可以根据喜好选择,但一般使用这几种\n\n ```text\n oss\n img\n images\n assets\n static(不仅存放图片,还存放网站加载时的css、js文件)\n ```\n\n\n\n![669afcbfe869f4fb67cee2a9132a87bc-image-20210914162453761](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262256761.png)\n\n\n\n\n\n1. 此时等待DNS解析完成后我们就完成了通过Cloudflare访问Backblaze的设置,可以使用浏览器的开发者工具,访问二级域名下对应网址来查看是否命中CDN缓存。`cf-cache-status`行HIT代表命中缓存,MISS代表没有命中CDN缓存,回源到Backblaze,此时会消耗下载流量。\n\n![9dab9b8dededc833583c61fb9615aaa5-image-20210911165431297](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262257026.png)\n\n\n\n2. 为了避免无法命中缓存或回源次数过多导致加载速度低下,我们需要回到Backblaze进行桶信息设置,添加`{\"cache-control\":\"max-age=86400\"}`,意味86400秒内Cloudflare不再返回源站重新获取信息。\n **注意,回源时为CDN节点回源站重新拉去数据,然后再传递给用户,并不是将源站地址直接转给用户,所以无需担心回源过多导致的免费流量配额消耗完毕。max-age可以不用太长,太长的话若源文件发生更改,且站点没有主动推送到CDN节点时会导致用户不能及时得到最新版本。(书写本文时发现BackBlaze也存在免费请求次数显示,B类C类请求每天各2500次,暂时未确定Cloudflare访问是否计算请求次数,故也不建议太短)**\n\n![c5aa7f1948a64ce3cd9391ad316ac951-image-20210914162745460](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262258762.png)\n\n\n\n\n\n1. 可选可选**不建议使用的重定向方式不建议使用的重定向方式**通过cloudflare自带的页面规则301,对于文件连接进行重定向缩短链接地址。按照下图选项根据喜好进行创建即可,*用于匹配所有的图片路径及名称,`$1`代表使用星号部分的内容对网址进行补全。\n **注意:**\n\n**1.匹配URL时,地址中的`/img`是必须的否则被转发过的URL会再次匹配到转发规则,造成重定向次数过多或其他位置错误,但是`/img`可以替换为任意不为`/file/example-winer-website(你的存储桶名)`的字符串**\n**2.经过测试后发现,使用该方式进行的重定向在开发者工具Network页面可以抓取到重定向后的链接直接新标签打开图片也可以获取直接新标签打开图片也可以获取,从而得到你的存储桶名称以及真是文件名,配合服务器提供商即可拼凑真实地址进行恶意刷流量攻击。故建议使用第8步的第二种创建方式。**\n\n![da954ad89387900fa24ea3a96a9255da-image-20210914163315660](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262258597.png)\n\n\n\n1. 可选可选在查找资料时,见到有些地方建议在进行URL重定向后增加一条页面缓存规则来防止缓存失效。按照下图进行配置即可。但是在我进行测试时发现不增加这条内容,也可以命中Cloudflare的CDN缓存,故暂时未添加。也可以在此处增加安全级别选项,并设置为`本质上为关`,来保证主站被攻击在CDN环节增加验证时,写在本地的Markdown文档能够正常加载图片。\n 猜测存在此步骤的可能原因是将缓存级别设置`无查询字符串`时仅在图片后不跟随参数时使用缓存的内容,部分OSS供应商提供追加参数对图片进行处理(如压缩、剪裁、缩放)后发送的功能,若主站缓存级别设置为标准,此处修改部分内容设置后就可以使用那些功能。但Backblaze的免费服务并不包含这些,所以暂时用不到。若以后发现在问题或真正的原因会进行补充说明。\n\n![5e57fe3d244d67a57ba0e6f1b0b9256b-image-20210914164221363](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262259760.png)\n\n\n\n8.可选可选**建议使用的重定向方式建议使用的重定向方式**由于不使用链接重定向和使用页面规则重定向均会暴露桶名称,我们选择通过重写的方式进行解决。这种方式可以在链接不变的情况下改写其中的内容。这次我们使用规则中的转换规则进行页面重写。匹配主机名用于确定请求来源需要进行重写,且再次匹配完整URI确认不包含已经重写过的链接,避免出现反复重写的错误。重写路径的concat含义为将两字符串拼接,在请求的文件路径前添加存储桶路径,而主机名example.winer.website在使用concat函数时无需书写,会自动添加为传入请求的主机名。(如一定要在concat函数内添加主机名,请不要带`http://`或`https://`开头,而是在前面添加`/`进行替代,例如`concat(\"/example.winer.website/file/example-winer-website\", http.request.uri.path)`)\n注:如果页面规则剩余不足或不想使用本方法,也可以[参考本文](https://help.backblaze.com/hc/en-us/articles/360010017893-How-to-allow-Cloudflare-to-fetch-content-from-a-Backblaze-B2-private-bucket)创建私有存储桶并使用Cloudflare Workers来进行访问。鉴于Workers访问方法已存在很久,且有众多其他博主教程,不再进行书写。但Workers同样有免费限额,请注意。\n\n\n\n![de64d3a53e203c221c0969806ad58aa6-image-20210914164843797](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262259217.png)\n\n\n\n### 搭配PicGo更好的进行图床食用\n\n首先恭喜你,至此你已经完成了图床基本搭建工作!下面是拓展部分\n\n1. 图床搭建完毕后,若不进行其他操作,每次上传图片都需要打开Backblaze的网站并在完成身份验证后进入桶设置页面进行上传,即不便捷也不友好。因此介绍一款跨平台且同时支持命令行与可视化界面的图片上传工具——PicGo\n 主要功能即为上传图片到你指定的位置,并获取图片链接,搭配typora编辑器可以直接在粘贴图片时就自动上传并将链接写入Markdown文档,避免图片在其它网站或放在本地后移动文档导致的图片丢失。\n2. 进入[项目主页](https://github.com/Molunerfinn/PicGo),下载并安装PicGo\n3. 选择插件设置,搜索`s3`或进入[插件项目主页](https://github.com/wayjam/picgo-plugin-s3)下载并安装该插件\n4. 安装完毕后左侧的图床设置会多出“Amazon S3”,对于所有与S3 API兼容的云存储均可使用\n5. 打开的[Backblaze官网的AppKeys设置页面](https://secure.backblaze.com/app_keys.htm),添加一个新的Key建议不要使用建议不要使用MasterApplicationKey,按照如下格式设置并申请Key\n **注意:Key的最长有效时间为1000天,即86400000秒,过期后请重新申请**\n\n![209573ceb1bfacd10cfc6d61ae7b43fc-image-20210911203404570](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202212262300765.png)\n\n\n\n1. 记录得到的`Key ID、applicationKey、桶名称、桶的Endpoint地址`分别填写到对应位置。同时将301跳转或页面重写的网址填写到自定义域名。其余设置无需变更。保存后即可上传图片,也可以修改文件的命名方式或通过修改配置文件进行设置,详见[此页面](https://github.com/wayjam/picgo-plugin-s3/blob/main/README.md)。\n\n### 注意事项\n\n到此为止所有工作都已完成,但是有一点需要注意:\n\n1. 通过这种方式上传文件,文件路径中如果包含空格,在Backblaze存储时会将空格换为加号,所以路径中包含空格的文件PicGo上传后生成的链接并不正确。\n2. 通过此方法搭建的图床或书写的教程,切记不要泄露存储桶名称,避免刷流量,且建议给所有上传文件的命名规则添加哈希值,使其不可猜测,避免存储桶名称暴露时获取其他文件。\n\n**同时本文内建立的存储桶并未使用,教程书写完毕后立刻删除,并创建了及其难以猜测的存储桶名称更改了相关地址,无需尝试使用文中或图中的信息进行访问测试。**\n\n 最后修改:2022 年 08 月 28 日 10 : 37 AM\n\n\n\n\n\n评论区\n\n**刚下飞机的道士** May 24th, 2022 at 11:48 am\n\n感谢大佬文章,现在cloudflare提供了transform rules,可以不用worker进行路径重写了。\n\n\n\n**sakuya** April 9th, 2022 at 02:44 pm\n\n友情提示:\n第8步的concat\"/example.winer.website/file/example−winer−website\",http.requrst.uri.paht),似乎多了个括号,以及request、path写错了\n\n\n\n**[winer](https://blog.winer.website/)** August 28th, 2022 at 10:36 am\n\n**[@sakuya](https://blog.winer.website/archives/use_blackblaze_b2_and_cloudflare_cdn_to_bulid_a_free_oss.html#comment-10)**\n\n谢谢提醒,括号多的那个其实是因为外面有个中文的括号,只看有代码标记的里面就行\n不过request和path确实是打错了hhhhh图片里还没错,这就改掉\n\n\n\n\n\n## 文章3:Backblaze B2 + Cloudflare\n\nB2是Backblaze提供的一个OSS存储服务,有着10G的免费容量以及每天1G的免费流量。而且他还是Cloudflare带宽联盟的成员,通过Cloudflare传输Backblaze中的内容是完全免费的。即使在超出免费额度的情况下,$0.005 GB/Mo的的容量和$0.01 GB/Mo的流量价格比起其他存储服务的价格也十分便宜。\n\n有许多其他文章也介绍了如何使用B2和CF作为免费图床,但现在CF有了新的转换规则功能,和其他文章使用的Worker和页面规则比起来,转换规则提供了更多的免费条目,也更易于使用。\n\n当然用来作为网盘也可以,不过10G就不太够用了。\n\n### 要求\n\n首先需要注册Backblaze B2和Cloudflare的账号,其次需要一个域名,现在Cloudflare就提供域名购买,也可以从namesilo或者其他地方购买后给Cloudflare解析。Backblaze注册之后需要进行邮箱验证,不然无法创建公开存储桶。\n\n### 创建存储桶\n\n进入Backblaze的用户管理界面,选择B2云存储下面的桶选项,然后点击创建存储桶,创建时需要输入桶的名称,这个名称会包含在URL中,所以不能与其他人的桶活着自己的其他桶有同样的名字。创建时需要选中公众选项,将其设置为公开的,其他选项不需要修改。\n\n在创建完成后可以在里面上传一张图片,点击上传后的图片,其中友好URL就是要使用的地址,接下来记录下友好URL的主机名,例如`f00x.backblaze2.com`。\n\n刚创建的存储桶默认不会被Cloudflare缓存,而是每次都要回源,对于图床来说,缓存下来才更方便。点击桶选项,回到刚才创建存储桶的地方,可以看到已经创建好的存储桶,点击桶设定,将桶信息修改为`{\"cache-control\":\"max-age=43200\"}`,其中`max-age=`后面的数字为Cloudflare的缓存时长,单位为秒。\n\n### 配置Cloudflare\n\n在Cloudflare中为图床要使用的子域名创建一个CNAME记录,将其指向刚才记录下的主机名f00x.bckblze2.com,由于要使用Cloudflare的CDN进行缓存,所以要将代理状态设置为已代理。\n\n在创建CNAME记录之后,将友好URL的主机名换成刚创建的域名就可以访问文件了。如果测试时Cloudflare提示错误522,这是因为Backblaze只允许使用Https访问,需要在Cloudflare的SSL/TLS中改成完全(严格)。此外,如果是Cloudflare的Pro付费用户的话,还需要关闭自动签名交换(SXG),他在速度-优化选项中。\n\n直接使用CNAME域名修改URL的话的话会暴露存储桶的名称,也显得URL十分啰嗦,这时候就需要使用Cloudflare的转换规则来将URL缩短。\n\n选择规则-转换规则,然后点击创建转换规则-重写URL创建一个重写URL的规则,首先为规则取一个名字。如果使用单独的子域名作为专用的图床域名的话,可以直接在字段中选择主机名,在运算符中选择等于,然后在值当中输入子域名。\n\n如果图床并不是使用专门的子域名,需要点击编写表达式,并参照[Cloudflare文档](https://developers.cloudflare.com/ruleset-engine/rules-language)来编写如何匹配图床的URL地址。\n\n匹配表达式配置完成后,在下面的重写-路径中选择重写到,在选项中选择Dynamic,如果只想在URL中删去`/file/存储桶`名称的话,在后面填写`concat(\"/file/存储桶名称\", http.request.uri.path)`,如果有其他要求,也可以参照上面的Cloudflare文档来修改。设置完成后点击部署即可启用该规则。现在输入`https://img.example.com/桶中的文件路径`或是自定义的地址即可加载存储桶中的图片。\n\n以下是用这种方式上传的图片,另外如果有人认得作者是谁可以在评论里回复一下。\n\n图片略...\n\n\n\n### 参考\n\n[Free Image Hosting With Cloudflare Transform Rules and Backblaze B2](https://www.backblaze.com/blog/free-image-hosting-with-cloudflare-transform-rules-and-backblaze-b2/)\n\n[Backblaze B2 + Cloudflare CDN可自定义域名的10G高速免费外链图床](https://www.coca.cc/mf/37.html)\n\n[Backblaze+CloudFlare实现0成本简单图床](https://233.al/archives/b2-cf.html)\n\n\n\n","tags":["转载","图床"],"categories":["转载"]},{"title":"05_Other-使用 Python open 函数批量替换文件内容","url":"/posts/3ffec809.html","content":"\n\n## 2023/02/06 更新\n\nVSCode 集成了 `某路径下的文件批量替换指定内容` 的功能,更方便\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202302061839251.png\" alt=\"image-20230206183933193\" style=\"zoom:50%;\" />\n\n\n\n## 1. 前言\n\n在 [jsd](https://www.jsdelivr.com/) 失效之后,博主使用了新的图床方案,需将文章的原 jsd 图片链接替换为新的图片地址\n\n这类脚本在网上有很多,都很推荐,如 \n\n- [批量修改文件内容(Python版)](https://blog.csdn.net/qq_38150250/article/details/118026219)\n- [张洪Heo:用 Python 批量替换 md 文件内容](https://blog.zhheo.com/p/369dbf41.html)\n- [Justlovesmile:如何自动下载、压缩并批量替换文章中的外链图片](https://blog.justlovesmile.top/posts/7a5857a0.html)\n\n\n\n## 2. 脚本内容\n\n源码来自:[批量修改文件内容(Python版)](https://blog.csdn.net/qq_38150250/article/details/118026219)\n\n脚本采用递归的方式,遍历 43~46 行 目录下的所有文件,进行批量替换\n\n说明:\n\n1. 根据自身情况修改 43~46 行 需遍历的目录;修改 47、48 行 需要替换的内容\n2. 脚本第 24 行 限制了只筛选出 Markdown 类型的文本文件进行修改,如需修改其他类型的文本文件 需自行更改后缀进行匹配\n3. 执行前请先备份源文件,以防出错后无法还原\n\n\n\n```python\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\n\n# 源码参考 https://blog.csdn.net/qq_38150250/article/details/118026219\n\nimport os\nimport re\n\n# 文件查找 find . -name file_name -type f\n# 查找函数:search_path 查找根路径 \n\n# 获取文章路径\ndef search(search_path, search_result):\n # 获取当前路径下地所有文件\n all_file = os.listdir(search_path)\n # 对于每一个文件\n for each_file in all_file:\n # 若文件为一个文件夹\n if os.path.isdir(search_path + each_file):\n # 递归查找\n search(search_path + each_file + '/', search_result)\n # 如果是需要被查找的文件\n else:\n if re.findall('.*\\.md$', each_file) == [each_file]:\n # 输出路径\n search_result.append(search_path + each_file)\n\n\n# 替换 sed -i 's/old_str/new_str/'\n# 文本替换 replace_file_name 需要替换的文件路径,replace_old_str 要替换的字符,replace_new_str 替换的字符\ndef replace(replace_file_name, replace_old_str, replace_new_str):\n with open(replace_file_name, \"r\", encoding = \"UTF-8\") as f1: \n content = f1.read()\n f1.close()\n t = content.replace(replace_old_str, replace_new_str)\n with open(replace_file_name, \"w\", encoding = \"UTF-8\") as f2:\n f2.write(t)\n f2.close()\n\n\n# 需要改的地方\n#path = 'E:/code_zone/.history/20220831_blog/source/_posts/'\npath_list = [\n 'E:/code_zone/hexo-source/source/_posts/',\n 'E:/code_zone/hexo-source-butterfly/source/_posts/',\n]\nold_str = 'https://dlvr.cpen.top/gh/mycpen/image_bed/image/'\nnew_str = 'https://dlvr.cpen.top/gh/mycpen/image_bed/image/'\n\nsearch_result = []\n\nif __name__ == '__main__':\n result = [] # 存放文件路径\n # 默认当前目录\n # path = os.getcwd()\n for path in path_list:\n search(path, result) # 获取文章路径\n count = 0\n for file_name in result:\n replace(file_name, old_str, new_str)\n count += 1\n print(\"{} done {}\".format(file_name, count))\n\n# 命令\n# python E:/code_zone/tools/python-replace/replace.py\n\n```\n\n\n\n## 3. 参考文章\n\n源码来自:[批量修改文件内容(Python版)](https://blog.csdn.net/qq_38150250/article/details/118026219)\n","tags":["Other","Python","Open"],"categories":["Other"]},{"title":"04_Other-使用 Python ftplib 模块同步又拍云云存储数据至本地","url":"/posts/4f5c6419.html","content":"## 1. 前言\n\n在 [jsd](https://www.jsdelivr.com/) 失效之后,博主将图床资源从 github 迁移至又拍云云存储上\n\n[qiniuClient](https://github.com/willnewii/qiniuClient) 是我所知的 云存储管理客户端,有需要的朋友可以下载使用\n\n目前的图床方案是写文章时利用 picgo 上传图片,再通过 Python 脚本同步又拍云上的图片至本地,再将本地图片 push 到 github,通过云服务器(CentOS)计划任务 每天凌晨1点执行以上备份操作\n\n\n## 2. 脚本内容\n\n源码来自:https://blog.csdn.net/ouyang_peng/article/details/79271113\n\n又拍云官方教程:[创建存储服务和使用 FTP 上传](https://techs.upyun.com/videos/cdnpage/creating_storage.html)\n\n说明:\n\n1. 脚本执行顺序是先下载云存储资源至本地,再将本地资源上传至云存储,所以云存储上的资源优先级更大,当本地出现同名资源时 会被覆盖\n2. 根据自身情况修改 273、274 行 路线、操作员/服务名、token(参考 [创建存储服务和使用 FTP 上传](https://techs.upyun.com/videos/cdnpage/creating_storage.html)),和 290~297 行本地、云存储的资源路径\n\n\n\n```python\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\n\n\nfrom cmath import log\nfrom ftplib import FTP\nimport os\nimport sys\nimport time\nimport socket\nimport subprocess\n\nclass MyFTP:\n \"\"\"\n ftp自动下载、自动上传脚本,可以递归目录操作\n 作者:欧阳鹏\n 博客地址:http://blog.csdn.net/ouyang_peng/article/details/79271113\n \"\"\"\n\n def __init__(self, host, port=21):\n \"\"\" 初始化 FTP 客户端\n 参数:\n host:ip地址\n\n port:端口号\n \"\"\"\n # print(\"__init__()---> host = %s ,port = %s\" % (host, port))\n\n self.host = host\n self.port = port\n self.ftp = FTP()\n # 重新设置下编码方式\n #self.ftp.encoding = 'gbk'\n self.ftp.encoding = 'utf8'\n # 获取脚本路径\n path = os.path.dirname(os.path.realpath(__file__))\n self.log_file = open(path + \"/log.txt\", \"a\", encoding='utf-8')\n self.file_list = []\n\n def login(self, username, password):\n \"\"\" 初始化 FTP 客户端\n 参数:\n username: 用户名\n\n password: 密码\n \"\"\"\n try:\n timeout = 60\n socket.setdefaulttimeout(timeout)\n # 0主动模式 1 #被动模式\n self.ftp.set_pasv(True)\n # 打开调试级别2,显示详细信息\n # self.ftp.set_debuglevel(2)\n\n self.debug_print('开始尝试连接到 %s' % self.host)\n self.ftp.connect(self.host, self.port)\n self.debug_print('成功连接到 %s' % self.host)\n\n self.debug_print('开始尝试登录到 %s' % self.host)\n self.ftp.login(username, password)\n self.debug_print('成功登录到 %s' % self.host)\n\n self.debug_print(self.ftp.welcome)\n except Exception as err:\n self.deal_error(\"FTP 连接或登录失败 ,错误描述为:%s\" % err)\n pass\n\n def is_same_size(self, local_file, remote_file):\n \"\"\"判断远程文件和本地文件大小是否一致\n\n 参数:\n local_file: 本地文件\n\n remote_file: 远程文件\n \"\"\"\n try:\n remote_file_size = self.ftp.size(remote_file)\n except Exception as err:\n # self.debug_print(\"is_same_size() 错误描述为:%s\" % err)\n remote_file_size = -1\n\n try:\n local_file_size = os.path.getsize(local_file)\n except Exception as err:\n # self.debug_print(\"is_same_size() 错误描述为:%s\" % err)\n local_file_size = -1\n\n self.debug_print('local_file_size:%d , remote_file_size:%d' % (local_file_size, remote_file_size))\n if remote_file_size == local_file_size:\n return 1\n else:\n return 0\n\n def download_file(self, local_file, remote_file):\n \"\"\"从ftp下载文件\n 参数:\n local_file: 本地文件\n\n remote_file: 远程文件\n \"\"\"\n self.debug_print(\"download_file()---> local_path = %s ,remote_path = %s\" % (local_file, remote_file))\n\n if self.is_same_size(local_file, remote_file):\n self.debug_print('%s 文件大小相同,无需下载' % local_file)\n return\n else:\n try:\n self.debug_print('>>>>>>>>>>>>下载文件 %s ... ...' % local_file)\n buf_size = 1024\n file_handler = open(local_file, 'wb')\n self.ftp.retrbinary('RETR %s' % remote_file, file_handler.write, buf_size)\n file_handler.close()\n except Exception as err:\n self.debug_print('下载文件出错,出现异常:%s ' % err)\n return\n\n def download_file_tree(self, local_path, remote_path):\n \"\"\"从远程目录下载多个文件到本地目录\n 参数:\n local_path: 本地路径\n\n remote_path: 远程路径\n \"\"\"\n print(\"download_file_tree()---> local_path = %s ,remote_path = %s\" % (local_path, remote_path))\n try:\n self.ftp.cwd(remote_path)\n except Exception as err:\n self.debug_print('远程目录%s不存在,继续...' % remote_path + \" ,具体错误描述为:%s\" % err)\n return\n\n if not os.path.isdir(local_path):\n self.debug_print('本地目录%s不存在,先创建本地目录' % local_path)\n os.makedirs(local_path)\n\n self.debug_print('切换至目录: %s' % self.ftp.pwd())\n\n self.file_list = []\n # 方法回调\n self.ftp.dir(self.get_file_list)\n\n remote_names = self.file_list\n self.debug_print('远程目录 列表: %s' % remote_names)\n for item in remote_names:\n file_type = item[0]\n file_name = item[1]\n local = os.path.join(local_path, file_name)\n if file_type == 'd':\n print(\"download_file_tree()---> 下载目录: %s\" % file_name)\n self.download_file_tree(local, file_name)\n elif file_type == '-':\n print(\"download_file()---> 下载文件: %s\" % file_name)\n self.download_file(local, file_name)\n self.ftp.cwd(\"..\")\n self.debug_print('返回上层目录 %s' % self.ftp.pwd())\n return True\n\n def upload_file(self, local_file, remote_file):\n \"\"\"从本地上传文件到ftp\n\n 参数:\n local_path: 本地文件\n\n remote_path: 远程文件\n \"\"\"\n if not os.path.isfile(local_file):\n self.debug_print('%s 不存在' % local_file)\n return\n\n if self.is_same_size(local_file, remote_file):\n self.debug_print('跳过相等的文件: %s' % local_file)\n return\n\n buf_size = 1024\n file_handler = open(local_file, 'rb')\n self.ftp.storbinary('STOR %s' % remote_file, file_handler, buf_size)\n file_handler.close()\n self.debug_print('上传: %s' % local_file + \"成功!\")\n\n def upload_file_tree(self, local_path, remote_path):\n \"\"\"从本地上传目录下多个文件到ftp\n 参数:\n\n local_path: 本地路径\n\n remote_path: 远程路径\n \"\"\"\n if not os.path.isdir(local_path):\n self.debug_print('本地目录 %s 不存在' % local_path)\n return\n\n self.ftp.cwd(remote_path)\n self.debug_print('切换至远程目录: %s' % self.ftp.pwd())\n\n local_name_list = os.listdir(local_path)\n for local_name in local_name_list:\n src = os.path.join(local_path, local_name)\n if os.path.isdir(src):\n try:\n self.ftp.mkd(local_name)\n except Exception as err:\n self.debug_print(\"目录已存在 %s ,具体错误描述为:%s\" % (local_name, err))\n self.debug_print(\"upload_file_tree()---> 上传目录: %s\" % local_name)\n self.upload_file_tree(src, local_name)\n else:\n self.debug_print(\"upload_file_tree()---> 上传文件: %s\" % local_name)\n self.upload_file(src, local_name)\n self.ftp.cwd(\"..\")\n\n def close(self):\n \"\"\" 退出ftp\n \"\"\"\n self.debug_print(\"close()---> FTP退出\")\n self.ftp.quit()\n self.log_file.close()\n\n def debug_print(self, s):\n \"\"\" 打印日志\n \"\"\"\n self.write_log(s)\n\n def deal_error(self, e):\n \"\"\" 处理错误异常\n 参数:\n e:异常\n \"\"\"\n log_str = '发生错误: %s' % e\n self.write_log(log_str)\n sys.exit()\n\n def write_log(self, log_str):\n \"\"\" 记录日志\n 参数:\n log_str:日志\n \"\"\"\n time_now = time.localtime()\n date_now = time.strftime('%Y-%m-%d', time_now)\n format_log_str = \"%s ---> %s \\n \" % (date_now, log_str)\n print(format_log_str)\n self.log_file.write(format_log_str)\n\n def get_file_list(self, line):\n \"\"\" 获取文件列表\n 参数:\n line:\n \"\"\"\n file_arr = self.get_file_name(line)\n # 去除 . 和 ..\n if file_arr[1] not in ['.', '..']:\n self.file_list.append(file_arr)\n\n def get_file_name(self, line):\n \"\"\" 获取文件名\n 参数:\n line:\n \"\"\"\n pos = line.rfind(':')\n while (line[pos] != ' '):\n pos += 1\n while (line[pos] == ' '):\n pos += 1\n file_arr = [line[0], line[pos:]]\n return file_arr\n\n\nif __name__ == \"__main__\":\n # 清除日志\n path = os.path.dirname(os.path.realpath(__file__)) # 脚本路径\n if os.path.exists(path + '/log.txt'):\n log_file = path + '/log.txt 'if os.sep == \"/\" else path + '\\\\' + 'log.txt'\n subprocess.Popen(f'rm -rf {log_file}', shell=True)\n time.sleep(1)\n\n my_ftp = MyFTP(\"v0.ftp.upyun.com\")\n my_ftp.login(\"xxx/xxx\", \"tokenxxxxxxxxx\")\n\n\n # 下载单个文件\n # my_ftp.download_file(\"E:/code_zone/image_bed/image/wallpaper/1.jpg\", \"/image/wallpaper/1.jpg\")\n\n # 上传单个文件\n # my_ftp.upload_file(\"G:/ftp_test/Release/XTCLauncher.apk\", \"/App/AutoUpload/ouyangpeng/I12/Release/XTCLauncher.apk\")\n\n # 下载目录\n # image.cpen.top/image/ → 本地 E:/code_zone/image_bed/image/ (本地图床目录, 又拍云路径)\n if os.sep == \"\\\\\":\n my_ftp.download_file_tree(\"E:/code_zone/image_bed/image/\", \"/image/\")\n elif os.sep == \"/\": # aliyun\n my_ftp.download_file_tree(\"/root/code_zone/image_bed/image/\", \"/image/\")\n\n # 上传目录\n # 本地 E:/code_zone/image_bed/image/ → image.cpen.top/image/ (本地图床目录, 又拍云路径)\n if os.sep == \"\\\\\": # Windows\n my_ftp.upload_file_tree(\"E:/code_zone/image_bed/image/\", \"/image/\") \n my_ftp.close()\n elif os.sep == \"/\": # aliyun\n my_ftp.upload_file_tree(\"/root/code_zone/image_bed/image/\", \"/image/\") \n my_ftp.close()\n\n\n# 命令\n# python E:/code_zone/tools/python-ftp/ftp.py\n# python3 /root/code_zone/tools/python-ftp/ftp.py\n\n```\n\n\n\n执行命令\n\n```bash\n# Windows 终端\npython E:/code_zone/tools/python-ftp/ftp.py\n\n# 类 Unix 终端\npython3 /root/code_zone/tools/python-ftp/ftp.py\n```\n\n\n\n## 3. 参考文章\n\n源码来自:[Python实现的FTP上传和下载功能](https://blog.csdn.net/ouyang_peng/article/details/79271113)\n\n又拍云官方教程:[创建存储服务和使用 FTP 上传](https://techs.upyun.com/videos/cdnpage/creating_storage.html)\n","tags":["Other","Python","FTP"],"categories":["Other"]},{"title":"03_Other-PC端环境记录","url":"/posts/583c5c34.html","content":"## 前言\n\n记录个人电脑环境\n\n更新时间:2023.03.10\n\n\n\n## Windows\n\n### 202303\n\n系统重置记录\n\n\n\n| 软件 | 软件 | 软件 |\n| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| 联想电脑管家 | 联想应用商店 | QQ |\n| Clash for Windows | Typora | WeGame |\n| Google Chrome | Microsoft Edge | Firefox |\n| Logitech G HUB | 搜狗输入法 | 网易邮箱大师 |\n| 网易有道词典 | [滴答清单](https://www.ghxi.com/ddqdpc.html) | 微信 |\n| 腾讯会议 | 百度网盘 | 阿里云盘 |\n| 哔哩哔哩 | PotPlayer | [~~Sublime Text~~](https://www.sublimetext.com/) |\n| [~~Sublime Text 汉化教程~~](https://www.w3cschool.cn/sublimetext/sublimetext-mdc13bbj.html) | [Sublime Text](https://www.ghxi.com/sublimetext4.html) | WPS Office |\n| 腾讯文档 | XMind ZEN(本地安装包) | [XMind 8](https://www.zjh336.cn/?id=280) |\n| WinRAR | Git | Windows Terminal |\n| [WSL 2](https://www.bilibili.com/video/BV1n14y1x7Y7) | [VMware Workstation Pro](https://www.ghxi.com/vmware17.html) | [CentOS](https://zhuanlan.zhihu.com/p/104118123)、[安装教程](https://blog.cpen.top/posts/48860.html) |\n| Xshell、Xftp | Visual Studio Code | SwitchHosts |\n| PicGo、[教程](https://blog.csdn.net/jiangjianzhong00/article/details/128256073)、[密钥](https://github.com/mycpen/tools/tree/main/python-ftp) | uTools | Snipaste |\n| Python | PyCharm | [Navicat](https://www.ghxi.com/navicat16.html) |\n| [Node.js](https://www.runoob.com/nodejs/nodejs-install-setup.html) | [联想软件:关闭Win10系统自动更新](https://iknow.lenovo.com.cn/detail/dc_178562.html) | [~~联想软件:网络图标叹号修复工具~~](https://iknow.lenovo.com.cn/detail/dc_184411_1.html) |\n| [Listen 1](https://github.com/listen1/listen1_desktop) | [LX Music](https://github.com/lyswhut/lx-music-desktop) | [Telegram](https://desktop.telegram.org/)、[汉化](https://t.me/setlanguage/classic-zh-cn) |\n| [赛尔号](https://seer.61.com/) | [Tai](https://github.com/Planshit/Tai) | |\n| | | |\n\n\n| GitHub | GitHub | GitHub |\n| ------------------------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------ |\n| [image_bed](https://github.com/mycpen/image_bed) | [ultra-tinypng](https://github.com/mycpen/ultra-tinypng) | [tools](https://github.com/mycpen/tools) |\n| [hexo-source-butterfly](https://github.com/mycpen/hexo-source-butterfly) | [hexo-source](https://github.com/mycpen/hexo-source) | [hexo-source-diary](https://github.com/mycpen/hexo-source-diary) |\n| [nav](https://github.com/mycpen/nav) | [dino](https://github.com/mycpen/dino) | |\n| | | |\n| | | |\n\n| VSCode | VSCode | VSCode |\n| ------------------------------------------------------------ | ------- | ------------------------------------------------------------ |\n| 简中插件 | GitLens | [Material Icon Theme](https://marketplace.visualstudio.com/items?itemName=PKief.material-icon-theme) |\n| [Git History](https://marketplace.visualstudio.com/items?itemName=donjayamanne.githistory) | | |\n| | | |\n\n\n| 参考教程 | 参考教程 | 参考教程 |\n| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |\n| [本文](https://blog.cpen.top/posts/583c5c34.html) | [GIT SSH 密钥认证教程](https://mp.weixin.qq.com/s?__biz=MjM5MDA2MTI1MA==&mid=2649092080&idx=3&sn=124abf24a463486deaf380e710a31822&chksm=be5bc85d892c414b2f52e7d7d58a3a6dc987324ded0ed749295a480ce0cb86df1eaefd7fb3c7&scene=27) | [PyCharm 汉化](https://baijiahao.baidu.com/s?id=1742306839397588676) |\n| [果壳剥壳](https://www.ghxi.com/) | [vscode 配置 gitbash 终端](https://blog.csdn.net/qq_44498977/article/details/124204347) | [Hexo 官网](https://hexo.io/zh-cn/) |\n| [npm 淘宝源](https://blog.anheyu.com/posts/sdxhu.html#npm-%E9%95%9C%E5%83%8F) | [Typora 页面美化](https://juejin.cn/post/7078155627305893925) | [~~PicGo安装插件compress~~](https://bearcai.com/index.php/archives/44/) |\n| [安装 Node.js](https://zhuanlan.zhihu.com/p/618663612) | | |\n| | | |\n\n\n\n### 202211\n\n\n第三方分享网站:[果壳剥壳](https://www.ghxi.com/)\n\n| name | description |\n| ------------------------------------------------------------ | ------------------------------------------------------------ |\n| 联想电脑管家、联想应用商店、Legion Zone、Logitech G HUB、小米云服务、金山打字通、搜狗输入法、网易邮箱大师、网易有道词典、滴答清单 | |\n| 腾讯QQ、微信、腾讯会议、向日葵 | |\n| 网易云音乐、酷我音乐、QQ音乐 | |\n| 百度网盘、阿里云盘、迅雷 | 网盘 |\n| 哔哩、哔哩哔哩 UWP | 哔哩哔哩uwp |\n| draw.io | 流程拓扑图 |\n| PotPlayer 64 bit | 视频播放 |\n| Typora、Sublime Text、WPS Office、XMind 8、XMind 2021、腾讯文档、MarkdownPad 2 | 文本编辑 |\n| WSA Toolbox | WSA |\n| Chrome、Firefox、Edge | 浏览器 |\n| Windows Terminal、PowerShell 7、Git bash | 终端 |\n| WSL2、Ubuntu 20.04 LTS、WSA | 虚拟机 |\n| VMware Workstation Pro、Xshell 7、Xftp 7 | 虚拟机 |\n| Clash for Windows、Steam++ | 代理客户端 |\n| PyCharm、Visual Studio Code、HBuilder X、CodeBlocks、Visual C++ 6.0 | 开发工具 |\n| Postman | 接口调试 |\n| SwitchHosts | 本地解析 |\n| Navicat Premium 15、SQLyog、QuickRedis、Another Redis Desktop Manager | 数据库客户端 |\n| PicGo | 图片上传 |\n| uTools、Everything | 剪贴板,取色 |\n| Snipaste | 截图 |\n| [mycpen/ultra-tinypng](https://github.com/mycpen/ultra-tinypng) | 图片压缩。原地址:[libudu/ultra-tinypng](https://github.com/libudu/ultra-tinypng) |\n| [mycpen/tools](https://github.com/mycpen/tools) | 私有仓库。ftp图床同步、内容替换 |\n| | |\n\n\n\n## 软件备份\n\n- bilibili下载助手 (谷歌插件)\n\n 引导页:[csser.top](https://csser.top/)、[docs.qq.com](https://docs.qq.com/doc/DQ2lhaWRpS0tubVVF)\n\n crx文件备份 (v3.0.0):[gitee.com/mycpen/cdn3](https://gitee.com/mycpen/cdn3/blob/master/download/bilibili-helper-3.0.0.crx)\n\n\n\n\n\n\n\n","tags":["Other","工具"],"categories":["Other"]},{"title":"06_Hexo-elemecdn 加速 Butterfly 第三方资源","url":"/posts/9b5a2768.html","content":"\n\n\n## 2023/01/09 更新\n\n今天发现 [Butterfly 文档](https://butterfly.js.org/posts/ceeb73f/#CDN) 有介绍自定义 CDN 的配置项,只需简单配置即可完成需求,`所以之前写的东西 属于是 ` **`画蛇添足`**,参考价值不高\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202301100050094.png\" alt=\"image-20230110005050004\" style=\"zoom:50%;\" />\n\n官方样例中的 `cdn.staticfile.org` CDN 加速由七牛云提供,技术社区掘金支持,可以直接填入使用\n\n个人示例如下(主题配置文件)\n\n```yaml\n# CDN\n# Don't modify the following settings unless you know how they work\n# 非必要請不要修改\nCDN:\n # The CDN provider of internal scripts (主題內部 js 的 cdn 配置)\n # option: local/jsdelivr/unpkg/cdnjs/custom\n # Dev version can only choose. ( dev版的主題只能設置為 local )\n internal_provider: local\n\n # The CDN provider of third party scripts (第三方 js 的 cdn 配置)\n # option: local/jsdelivr/unpkg/cdnjs/custom\n # when set it to local, you need to install hexo-butterfly-extjs\n # third_party_provider: jsdelivr\n third_party_provider: custom\n\n # Add version number to CDN, true or false \n version: false\n\n # Custom format\n # For example: https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file}\n custom_format: https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file}\n\n```\n\n~~想用 elemecdn 的话,custom_format 配置项该怎么写 我也不清楚。尝试写 `https://npm.elemecdn.com/${name}${verType}/${file}` 或 `https://npm.elemecdn.com/${cdnjs_name}/${version}/${min_cdnjs_file}` 都失败了~~\n\n想用 elemecdn 的话,[Butterfly 文档](https://butterfly.js.org/posts/ceeb73f/#custom-format) 给出了格式:\n\n![image-20230125233819686](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202301252338749.png)\n\n\n\n**`以下步骤已过时`**\n\n## 前言\n\n博客异常加载,f12发现 https://unpkg.com/swiper/swiper-bundle.min.js (主因)和 https://unpkg.com/@fancyapps/ui/dist/fancybox.umd.js 报 520(520,当源站服务器向 [CDN](https://baike.baidu.com/item/CDN/420951?fromModule=lemma_inlink) 返回空白、未知或意外响应时,会发生 520 错误),日常都返的 200\n\n基于此有了换 cdn 的想法。[butterfly 官方教程](https://butterfly.js.org/posts/ceeb73f/#CDN) 介绍了 local/jsdelivr/unpkg/cdnjs/custom 这些选择,都不是想要的,看到别人用的 Element cdn,学习一下\n\n\n\n## 步骤\n\n参考文章:[butterfly官方教程#CDN](https://butterfly.js.org/posts/ceeb73f/#CDN)、[安知鱼 - 可用cdn整理](https://blog.anheyu.com/posts/fe76.html)、[张洪 Heo - Butterfly CDN链接更改指南](https://blog.zhheo.com/p/790087d9.html#%E9%93%BE%E6%8E%A5)\n\n修改源码:\n\n1. 修改 themes/butterfly/scripts/events/cdn.js,新增 elemecdn 字段\n\n <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221028222132106.png\" alt=\"image-20221028222132106\" style=\"zoom: 67%;\" />\n\n ```javascript\n elemecdn: `https://npm.elemecdn.com/${name}${verType}/${file}`,\n ```\n\n \n\n2. 修改 _config.butterfly.yml,CDN.third_party_provider\n\n <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221029143047143.png\" alt=\"image-20221029143047143\" style=\"zoom: 67%;\" />\n\n f12 看了下 网络,替换后没异常\n\n <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221028223148954.png\" alt=\"image-20221028223148954\" style=\"zoom:50%;\" />\n\n \n\n3. 根据 [张洪Heo:Butterfly CDN链接更改指南](https://blog.zhheo.com/p/790087d9.html#%E9%93%BE%E6%8E%A5) 按需替换 cdn链接(~~需注意变量名,比如butterfly v4.4.0 fontawesome 写成 fontawesomeV6 似乎才会生效~~ [Butterfly v4.8.0](https://github.com/jerryc127/hexo-theme-butterfly/releases/tag/4.8.0) 变量名已改为 fontawesome)\n\n <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221028223928594.png\" alt=\"image-20221028223928594\" style=\"zoom:50%;\" />\n\n \n\n ```yaml\n CDN:\n option:\n # 张洪Heo https://blog.zhheo.com/p/790087d9.html\n jquery: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/jquery/3.6.0/jquery.min.js\n pjax: https://npm.elemecdn.com/pjax@latest/pjax.min.js\n sharejs: https://lib.baomitu.com/social-share.js/1.0.16/js/social-share.min.js\n sharejs_css: https://lib.baomitu.com/social-share.js/1.0.16/css/share.min.css\n gitalk: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/gitalk/1.7.2/gitalk.min.js\n gitalk_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/gitalk/1.7.2/gitalk.min.css\n valine: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/valine/1.4.16/Valine.min.js\n disqusjs: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/disqusjs/1.3.0/disqus.js\n disqusjs_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/disqusjs/1.3.0/disqusjs.css\n waline: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/waline/1.5.4/Waline.min.js\n lazyload: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/vanilla-lazyload/17.3.1/lazyload.iife.min.js\n instantpage: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/instant.page/5.1.0/instantpage.min.js\n typed: https://lf9-cdn-tos.bytecdntp.com/cdn/expire-1-M/typed.js/2.0.12/typed.min.js\n # fancybox_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/fancybox/3.5.7/jquery.fancybox.min.css\n # fancybox: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/fancybox/3.5.7/jquery.fancybox.min.js\n medium_zoom: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/medium-zoom/1.0.6/medium-zoom.min.js\n snackbar_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/node-snackbar/0.1.16/snackbar.min.css\n snackbar: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/node-snackbar/0.1.16/snackbar.min.js\n fontawesome: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css\n # fontawesomeV6: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/font-awesome/6.0.0/css/all.min.css\n # translate: https://npm.elemecdn.com/js-heo@1.0.6/translate/tw_cn.js # 与主题原文件不符\n aplayer_css: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.css\n aplayer_js: https://lf6-cdn-tos.bytecdntp.com/cdn/expire-1-M/aplayer/1.10.1/APlayer.min.js\n meting_js: https://npm.elemecdn.com/js-heo@1.0.12/metingjs/Meting.min.js\n prismjs_js: https://npm.elemecdn.com/prismjs@1.1.0/prism.js\n prismjs_lineNumber_js: https://npm.elemecdn.com/prismjs/plugins/line-numbers/prism-line-numbers.min.js\n prismjs_autoloader: https://npm.elemecdn.com/prismjs/plugins/autoloader/prism-autoloader.min.js\n justifiedGallery_js: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/justifiedGallery/3.8.1/js/jquery.justifiedGallery.min.js\n justifiedGallery_css: https://lf3-cdn-tos.bytecdntp.com/cdn/expire-1-M/justifiedGallery/3.8.1/css/justifiedGallery.min.css\n #twikoo: https://npm.elemecdn.com/twikoo@1.6.8/dist/twikoo.all.min.js\n \n ```\n\n \n\n\n\n\n\n\n\n","tags":["Hexo","Element"],"categories":["Hexo"]},{"title":"05_Hexo-twikoo数据从MongoDB导出-js适配pjax","url":"/posts/51a9ee30.html","content":"# 一. Twikoo数据从MongoDB导出\n\n## 前言\n\n1. **参考文章** [iMaeGoo](https://www.imaegoo.com/2022/twikoo-data-export/)、[张时贰](https://zhangshier.vip/posts/41646/#%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%87%BA)\n\n2. 记录 [twikoo](https://twikoo.js.org/) 由 [vercel](https://vercel.com/dashboard) + [mongodb](https://www.mongodb.com/) 改为 [私有部署](https://twikoo.js.org/quick-start.html#%E7%A7%81%E6%9C%89%E9%83%A8%E7%BD%B2),数据导出过程\n\n3. Win 下使用 `mongoexport` 和客户端工具 失败(个人原因,[作者的样例](https://www.imaegoo.com/2022/twikoo-data-export/#%E5%AF%BC%E5%87%BA-Twikoo-%E5%9C%A8-Vercel-%E7%9A%84%E6%95%B0%E6%8D%AE) 是成功的),转而用云主机(CentOS 8.2)导出数据\n\n\n\n## 步骤\n\n参考自 [iMaeGoo](https://www.imaegoo.com/2022/twikoo-data-export/)、[张时贰](https://zhangshier.vip/posts/41646/#%E6%95%B0%E6%8D%AE%E5%AF%BC%E5%87%BA)\n\n1. MongoDB官网下载 [Database Tools](https://www.mongodb.com/try/download/database-tools),解压安装\n\n2. \n\n```bash\n# 登录 Vercel 管理后台,点开 Twikoo 的环境,点击上方的 Settings,点击左侧的 Environment Variables,在页面下方找到 MONGODB_URI,点击对应的小眼睛图标,会出现数据库连接地址,点击以复制这串地址;\n# 如果地址中包含参数,请先删去参数,参数即 “?” 和 “?” 后面的部分,例如 ?journal=true&w=majority;\n# 打开一个命令行窗口,粘贴以下命令:\nmongoexport --uri 这里换成刚才复制的地址 --collection comment --type json --out twikoo-comments.json\n\n```\n\n\n\n\n\n---\n\n# 二. js文件适配 PJAX\n\n**参考文章**:\n\n[张洪Hexo - pjax无法生效解决办法,butterfly主题维护你的pjax](https://blog.zhheo.com/p/3e567fa7.html)\n\n[Leonus - 评论区](https://blog.leonus.cn/2022/owo-big.html#post-comment)\n\n[心流 - 记录一次因为pjax导致js无法生效以及解决方案](https://blog.panghai.top/posts/6e665e82/)\n\n\n\n1. butterfly主题下\n\n > butterfly的话就使用data-pjax属性来让js文件重载,因为这个是butterfly中写好的规则:\n >\n > ```javascript\n > <script src=\"https://cdn.zhheo.com/JS-Heo/bb/showbb_in_index.js\" data-pjax=\"\" defer=\"\"></script>\n > ```\n\n2. 在自定义js文件按照下面这样写即可,可以把代码弄成一个函数,然后把函数名放在下面的函数里面\n\n > ```javascript\n > function whenDOMReady() {\n > //此处填写需要执行的代码,如:\n > //leonus.demo()\n > }\n > \n > whenDOMReady() //打开网站之后先执行一次函数\n > document.addEventListener(\"pjax:complete\", whenDOMReady) //pjax加载完成之后执行上面函数\n > ```\n\n\n\n","tags":["Hexo","Twikoo","PJAX"],"categories":["Hexo"]},{"title":"04_Hexo-多平台部署-云服务器-GitHub-Gitee","url":"/posts/38874.html","content":"## 一. 开篇词\n\n### 1.1 前言\n\n- 官方文档介绍了 Hexo 可以同时`一键部署`到多个平台,只需要同时使用多个 `deployer`。\n\n> [中文官方文档](https://hexo.io/zh-cn/docs/one-command-deployment)\n>\n> Hexo 提供了快速方便的一键部署功能,让您只需一条命令就能将网站部署到服务器上。\n>\n> ```bash\n> $ hexo deploy\n> ```\n>\n> 在开始之前,您必须先在 `_config.yml` 中修改参数,一个正确的部署配置中至少要有 `type` 参数,例如:\n>\n> ```bash\n> deploy:\n> type: git\n> ```\n>\n> 您可同时使用多个 deployer,Hexo 会依照顺序执行每个 deployer。\n>\n> ```bash\n> deploy:\n> - type: git\n> repo:\n> - type: heroku\n> repo:\n> ```\n\n\n\n### 1.2. 说明\n\n- 使用 `Git Hooks` 同步 Hexo 生成的静态文件。(后期我弃用 git,改用 rsync 了)\n\n\n\n## 二. 步骤\n\n### 2.1 云服务器创建 Git 仓库\n\n```\n$ cd /opt/git/\n\n$ git init --bare hexo.git\t\t\t# 创建 Hexo 远程仓库\tgit init --bare 仓库名.git\n\n$ cd /opt/git/hexo.git/hooks/ \n\n$ vim post-receive \n#!/bin/bash\ngit --work-tree=/opt/www/hexo --git-dir=/opt/git/hexo.git checkout -f\n\n# --work-tree=/opt/www/hexo 设置工作树的路径\n# --git-dir=/opt/git/hexo.git 设置存储库的路径\n\n$ chmod +x post-receive\t\t\t\t# 给钩子文件添加执行权限\n\n$ mkdir /opt/www/hexo\t\t\t\t# 创建工作树路径\n\n$ chmod -R 777 /opt/www/hexo\t\t# 授权,否则到后面访问报 403\n```\n\n\n\n#### 2.1.2 deployer 使用 rsync 进行部署\n\n前言:后面发现使用 git 上传至云服务器速度太慢了(不清楚啥原因),改用 rsync。\n\n> git 上传速度如下图\n>\n> ![image-20220906115955982](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220906115955982.png)\n\n1. 使 git bash 支持 rsync(Windows)\n\n 参考 \n \t\t[https://blog.csdn.net/m0_48613893/article/details/124104757](https://blog.csdn.net/m0_48613893/article/details/124104757)\n \t\t[https://blog.csdn.net/qq_38689395/article/details/125758842](https://blog.csdn.net/qq_38689395/article/details/125758842)\n 如果文件重复,就跳过\n 如果出错就修改文件名 `.\\usr\\bin\\msys-xxhash-0.8.0.dll → msys-xxhash-0.dll`\n\n\n\n2. `./_config.yml` 文件\n\n ```\n deploy:\n - type: rsync\n host: IP地址\n user: 使用者名称\n root: 远程主机的根目录\n port: 22\n delete: true\n verbose: true\n ignore_errors: false\n ```\n\n 参考 [https://hexo.io/zh-cn/docs/one-command-deployment#Rsync](https://hexo.io/zh-cn/docs/one-command-deployment#Rsync)\n \n\n在传大文件(也就10M)时依旧很慢,但比前者速度快些。\n\n\n\n### 2.2 配置本地Hexo _config.yml\n\n- `./_config.yml` 文件,同步部署 `GitHub、Gitee、云服务器`\n\n```bash\n# Deployment - 部署\n## Docs: https://hexo.io/zh-cn/docs/one-command-deployment.html\ndeploy:\n- type: git\n repository: root@IP地址:/opt/git/hexo.git\n branch: master\n commit: Site updated\n message: hexo {{ now('YYYYMMDD') }}\n- type: git\n repository: git@github.com:mycpen/mycpen.github.io.git\n branch: main\n commit: Site updated\n message: hexo {{ now('YYYYMMDD') }} # message为自定义提交信息,默认为 Site updated: YYYY-MM-DD HH:mm:ss\n- type: git\n repository: git@gitee.com:mycpen/mycpen.gitee.io.git\n branch: master\n commit: Site updated\n message: hexo {{ now('YYYYMMDD') }}\n```\n\n\n\n### 2.3 配置 SSH 免密登录\n\n- 本地 SSH 公钥 如`~/.ssh/id_rsa.pub` 内容添加至云服务器 `~/.ssh/authorized_keys` 中\n\n\n\n### 2.4 部署\n\n- 本地 Hexo 源文件项目下敲\n\n```\nhexo clean ; hexo g ; hexo d\n```\n\n\n\n### 2.5 使用 NGINX 做 Web 服务器\n\n- 新增虚拟主机配置\n\n```bash\n$ cat /usr/local/nginx/conf/conf.d/blog.cpen.top.conf\nserver {\n listen 80;\n listen 443 ssl;\n\n server_name blog.cpen.top;\n\n error_page 404 /404.html;\n\n # 强制HTTPS跳转\n if ($scheme = \"http\") {\n return 307 https://$host$request_uri;\n }\n\n root /opt/www/hexo;\n\n ssl_certificate /usr/local/nginx/ssl/blog.cpen.top.pem;\n ssl_certificate_key /usr/local/nginx/ssl/blog.cpen.top.key;\n\n access_log /data/service_logs/nginx/blog.cpen.top_access.log misc;\n error_log /data/service_logs/nginx/blog.cpen.top_error.log;\n}\n```\n\n\n\n- 最后浏览器访问 [https://blog.cpen.top/](https://blog.cpen.top/)\n\n\n\n## 三. 注意点\n\n1. 配置 SSH `免密`;\n\n2. 存储目录`授权`;\n\n 给工作树路径 /opt/www/hexo 777 权限,~~一开始没授权 访问报 403,环境为 CentOS 8.2;~~原因找到了,第 5 点。\n\n3. 开放端口。注意是否需要在云服务器新增`安全组策略`,80、443 端口需要打开;\n\n4. SELinux 等原因。\n\n5. `403 权限问题`\n 后面查询发现了 `403` 的原因,Nginx 编译安装时我指定了启动用户为 普通用户(默认为 nobody),导致起的工作进程权限不够。而 Hexo 上传的新的静态文件权限不为 777。\n\n 所以修改 Nginx 的启动用户为 root。\n\n ```bash\n $ vim /usr/local/nginx/conf/nginx.conf\n user root;\n \n $ nginx -s reload\n ```\n\n\n\n## 四. 参考文章\n\n[官方文档 一键部署](https://hexo.io/zh-cn/docs/one-command-deployment)\n\n`*` [使用 Git Hooks 部署至云服务器](https://blog.csdn.net/wangjienull/article/details/109227984)\n\n[使用 Git Hooks 部署至云服务器](https://blog.csdn.net/qq_38679881/article/details/122730065)\n\n[使用 Git Hooks 部署至云服务器 新增 git 用户、授权目录](https://blog.csdn.net/Y_Ace/article/details/121764537)\n\n`*` [访问403 修改 Nginx 启动用户为 root](https://www.idczone.net/news/3261.html/)\n\n`*` [访问403 授权 777 目录](https://blog.csdn.net/alexis7/article/details/109569218)\n\n[访问 403 CentOS 8 环境](https://www.likecs.com/show-204450505.html)\n\n[访问 403 SELinux 未关闭](http://www.wjhsh.net/reblue520-p-6239733.html)\n\n\n\n---\n","tags":["Troubleshooting","Git","Hexo"],"categories":["Hexo"]},{"title":"03_Hexo-Github Pages 个人博客源文件备份迁移","url":"/posts/43907.html","content":"# Github Pages 个人博客源文件\n\n## 1. 起因\n\n1. **源文件保存问题**:[Hexo](https://hexo.io/) 搭建的个人博客,其远程仓库只保存 [Hexo](https://hexo.io/) 发布后的 Html 静态文件,博客的源 Markdown 文件、主题配置等资源还在本地;\n\n2. **源文件隐私**:考虑到源文件的隐秘性,放弃了新建分支存放源文件,而采用新建项目来存放。\n\n\n\n\n\n## 2. 作用\n\n1. 源文件**备份**;\n2. 博客的可移植性。\n\n\n\n\n\n## 3. 注意点\n\n- 删除 `themes` 文件下 clone 的主题文件下的 `.git` 文件;\n\n- `node-modules/` 中,自定义了一些配置,改动了源码,需要同步,.gitignore 中不写入;\n\n .gitignore 配置如下\n\n```bash\n.DS_Store\ndb.json\n*.log\npublic/\n.deploy*/\n```\n\n\n\n\n\n## 4. 配置步骤\n\n1. 将仓库克隆至本地;\n\n\n\n2. 安装 [Node.js](https://nodejs.org/en/) 和 [GIt](https://git-scm.com/);[官方中文文档](https://hexo.io/zh-cn/docs/#%E5%AE%89%E8%A3%85)\n\n\n\n3. 安装 [Hexo](https://hexo.io/zh-cn/docs/#%E5%AE%89%E8%A3%85-Hexo);\n\n ```bash\n $ npm install -g hexo-cli\n ```\n\n\n\n4. 如之前未配置 Git 信息,则需配置下;\n\n ```bash\n git config --global user.email \"you@example.com\"\n git config --global user.name \"Your Name\"\n ```\n\n > ![image-20220830155020917](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830155020917.png)\n\n\n\n5. 执行 [Hexo 命令](https://hexo.io/zh-cn/docs/commands),生成静态文件、部署网站等。例如:\n\n ```bash\n hexo clean ; hexo g ; hexo d ; hexo s\n ```\n\n > 过程顺利。\n >\n > ![image-20220830155418809](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830155418809.png)\n\n\n\n5. 提交本地源文件变更。\n\n ```bash\n git pull ; git add . ; git commit -m 'backup' ; git push\n ```\n \n 命令组合\t`git pull ; hexo clean ; hexo g ; hexo d ; git add . ; git commit -m 'backup' ; git push`\n\n\n\n\n\n## 5. 参考文章\n\n[Hexo 和博客源文件之间的关系](https://www.jianshu.com/p/a04d75ee9ab6)\n\n[官方文档分支示例为 gh-pages](https://hexo.io/zh-cn/docs/github-pages)\n\n[新建仓库样例1](https://zhuanlan.zhihu.com/p/127027266)\n\n[新建仓库样例2](https://blog.csdn.net/weixin_39961522/article/details/112096073)\n\n[新建仓库样例3](https://blog.csdn.net/stringwinder/article/details/126287503)\n\n[新建分支样例1](https://zhuanlan.zhihu.com/p/71544809)\n\n[新建分支样例2](https://zhuanlan.zhihu.com/p/476603074)\n\n\n\n---\n","tags":["Hexo"],"categories":["Hexo"]},{"title":"02_Hexo-出错排查-Nunjucks Error","url":"/posts/5162.html","content":"# Hexo 出错排查\n\n## 一. Nunjucks Error\n\n**现象描述**\n\n> Unhandled rejection Nunjucks Error: _posts/xxx.md [Line 84, Column 13] `unknown block tag: 标签`\n>\n> ![image-20220829151147643](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220829151147643.png)\n\n\n\n**解决办法**\n\n> 参考\t[https://hexo.io/docs/troubleshooting.html#Escape-Contents](https://hexo.io/docs/troubleshooting.html#Escape-Contents)\n> \t\t\t[https://blog.csdn.net/Calvin_zhou/article/details/109303640](https://blog.csdn.net/Calvin_zhou/article/details/109303640)\n>\n> 泄露(Escape)内容\n>\n> Hexo 使用 [Nunjucks](https://mozilla.github.io/nunjucks/) 来解析文章(旧版本使用 [Swig](http://paularmstrong.github.io/swig/),两者语法类似),内容若包含 `{{ }}` 或 `{% %}` 可能导致解析错误,您可以用 [`raw`](https://hexo.io/docs/tag-plugins#Raw) 标签包裹,single backtick ``{{ }}`` 或 triple backtick 来避免潜在问题发生。\n> Alternatively, Nunjucks tags can be disabled through the renderer’s option (if supported), [API](https://hexo.io/api/renderer#Disable-Nunjucks-tags) or [front-matter](https://hexo.io/docs/front-matter).\n>\n> ```\n> {% raw %}\n> Hello {{ world }}\n> {% endraw %}\n> ```\n>\n> ````\n> ```\n> Hello {{ world }}\n> ```\n> ````\n\n\n\n\n---\n\n","tags":["Troubleshooting","Hexo"],"categories":["Hexo"]},{"title":"02_Error-记 Win下 Git 忘加入 PATH","url":"/posts/cb0ae693.html","content":"# 1. 问题描述\n\n右键 vscode 打开项目,使用 git bash 作为终端 敲命令,有些仓库出现 `bash: xxx: command not found`\n\n原因:git 下的 bin 目录未加入环境变量,基础命令找不到\n\n\n\n# 2. 加入环境变量\n\nxxx/git/bin 加入 PATH 变量\n\n> 参考自:https://blog.csdn.net/u012724595/article/details/114740935\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221026212837312.png\" alt=\"image-20221026212837312\" style=\"zoom:50%;\" />\n>\n> 后话:xxx/bin/cmd 应该是安装 git 的时候选勾加上的。直接右键 git bash 是能查找到命令的,先前 用 vscode 打开经常用的仓库也能找到命令(为啥没报 not found 不确定原因)\n\n","tags":["Error","Git"],"categories":["Error"]},{"title":"02_Other-AList 搭建云盘","url":"/posts/6a2caa19.html","content":"# 1. 参考链接\n\n> [作者 Xhofe](https://nn.ci/)\n>\n> [AList 官方文档](https://alist.nn.ci/zh/)\n>\n> - [官方文档.指南](https://alist.nn.ci/zh/guide/)\n> - [官方文档.指南.添加存储](https://alist.nn.ci/zh/guide/drivers/)\n> - [官方文档.配置](https://alist.nn.ci/zh/config/)\n>\n> [Github 地址](https://github.com/alist-org/alist/blob/main/README_cn.md)\n>\n> - [Special sponsors](https://github.com/alist-org/alist/blob/main/README_cn.md#special-sponsors)\n> - [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.la/)\n> - [KinhDown 百度云盘不限速下载!永久免费!已稳定运行3年!非常可靠!](https://kinhdown.com/?Type=Tutorials)\n>\n> \n>\n> > **AList**:🗂️ 一个支持多种存储的文件列表程序,使用 Gin 和 Solidjs。\n> >\n> > ```\n> > 使用简单\n> > AList 从一开始就设计为易于安装,并且可以在所有平台上使用。\n> > \n> > 多种存储\n> > AList 支持多个存储提供商,包括本地存储、阿里云盘、OneDrive、Google Drive 等,且易于拓展。\n> > \n> > 支持 WebDAV\n> > AList 支持所有 WebDAV 存储,这是一种用于访问文件的标准。\n> > \n> > 黑暗模式\n> > 自由切换明暗模式\n> > \n> > 受保护的路由\n> > 为特定路径添加密码保护和身份验证\n> > \n> > 文件预览\n> > 支持视频、音频、文档、PDF、图片预览等,甚至支持 ipa 安装\n> > \n> > 打包下载\n> > 使用浏览器的 stream api 支持打包下载,无需使用服务器\n> > \n> > 更多新功能\n> > 包括文本编辑器、README/HTML 渲染、文件永久链接、Cloudflare Workers 代理等\n> > ```\n> >\n> > \n>\n> \n>\n> ```bash\n> # 一键脚本\n> curl -fsSL \"https://alist.nn.ci/v3.sh\" | bash -s install\n> \n> ```\n>\n> \n>\n> ```nginx\n> # 反向代理\n> location / {\n> proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n> proxy_set_header Host $http_host;\n> proxy_set_header X-Real-IP $remote_addr;\n> proxy_set_header Range $http_range;\n> \tproxy_set_header If-Range $http_if_range;\n> proxy_redirect off;\n> proxy_pass http://127.0.0.1:5244;\n> # the max size of file to upload\n> client_max_body_size 20000m;\n> }\n> \n> ```\n>\n> \n>\n> ```bash\n> # 命令\n> 启动: systemctl start alist\n> 关闭: systemctl stop alist\n> 配置开机自启: systemctl enable alist\n> 取消开机自启: systemctl disable alist\n> 状态: systemctl status alist\n> 重启: systemctl restart alist\n> \n> cd /opt/alist\n> # 运行程序\n> ./alist server\n> # 获得管理员信息\n> ./alist admin\n> \n> ```\n>\n> \n\n\n\n---\n\n# 2. 个人样例\n\n## 反向代理\n\n```nginx\n# root @ CentOS in /usr/local/nginx/conf/conf.d\n$ cat cpen.top.conf\n...\n\n# AList 个人云盘\n# https://github.com/alist-org/alist/blob/main/README_cn.md\nserver {\n listen 8004 ssl;\n\n server_name cpen.top;\n\n location / {\n proxy_pass http://127.0.0.1:5244;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Host $http_host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header Range $http_range;\n proxy_set_header If-Range $http_if_range;\n proxy_redirect off;\n # the max size of file to upload\n client_max_body_size 20000m;\n proxy_connect_timeout 120; # 加大120\n proxy_send_timeout 120; # 加大120\n proxy_read_timeout 120; # 加大120\n proxy_http_version 1.1; # 开启后端,长连接\n proxy_set_header Connection \"\"; # 开启后端,长连接\n }\n\n ssl_certificate /usr/local/nginx/ssl/cpen.top.pem;\n ssl_certificate_key /usr/local/nginx/ssl/cpen.top.key;\n\n access_log /data/service_logs/nginx/cpen.top_access.log misc;\n error_log /data/service_logs/nginx/cpen.top_error.log;\n}\n\n```\n\n\n\n## 设置.全局.自定义内容\n\n```html\n<div style=\"display: flex; flex-direction: column; align-items: center;\"><a target=\"_blank\" rel=\"noopener noreferrer\" class=\"chakra-link line1 css-f4h6uy\" href=\"http://beian.miit.gov.cn\" style=\"\">苏ICP备xxx号</a></div>\n\n```\n\n\n\n","tags":["Other","AList"],"categories":["Other"]},{"title":"30_Linux基础-shell编程-sed","url":"/posts/4cb758ea.html","content":"# 一. sed的整行替换 c\n\n> ```bash\n> #示例:sed的整行替换 c\n> [root@cPen_A 10]# cp /etc/sysconfig/selinux .\n> [root@cPen_A 10]# sed -i '/^SELINUX=/c SELINUX=disabled' selinux \n> [root@cPen_A 10]# cp /etc/ssh/sshd_config .\n> [root@cPen_A 10]# sed -i '/^#Port/c Port 2233' sshd_config \n> [root@cPen_A 10]# cat sshd_config |grep Port\n> Port 2233\n> ```\n>\n> ![image-20221011221851457](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011221851457.png)\n\n\n\n---\n\n```bash\n#注:对文件的修改 用sed比较好\n\n[root@cPen_A 10]# cp /etc/sysconfig/network-scripts/ifcfg-ens33 .\t\t#注:网卡配置文件\n[root@cPen_A 10]# vim ifcfg-ens33 \nBOOTPROTO=\"none\"\t\t\t\t\t#注:none 静态配置ip地址\tdhcp动态获得ip\nNAME=\"ens33\"\t\t\t\t\t\t#注:网卡连接的名字\nUUID=\"831f1350-14c2-46db-bf53-1937c5feb8f5\"\t#注:网卡的设备编号的唯一值\nDEVICE=\"ens33\"\t\t\t\t\t#注:网卡设备的名字\nONBOOT=\"yes\"\t\t\t\t\t\t#注:开机的时候是否激活 yes表示激活启动 no禁用\nIPADDR=\"192.168.0.38\"\t\t\t\t#注:ip地址\nNETMASK=255.255.255.0\t\t\t\t#注:子网掩码\nGATEWAY=192.168.0.1\t\t\t\t#注:默认网关\t\t路由器的接口地址\nDNS1=192.168.0.1\t\t\t\t\t#注:首选dns服务器\nDNS2=114.114.114.114\t\t\t\t#注:备用dns服务器\n\n#示例:将ip地址替换,使用sed 整行替换\n\n#注:光猫/调制解调器(modem)\n```\n\n> ![image-20221011221926041](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011221926041.png)\n\n\n\n> ![image-20221011221940988](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011221940988.png)\n>\n> 需求分析:\n>\n> 1. read或者位置变量\n>\n> 2. 修改配置文件 sed\t\t(整行替换 或 局部替换)\n>\n> 3. ip合法判断 --> 正则\n\n\n\n---\n\n# 二. sed的w命令 写入文件\n\n> ```bash\n> sed的w命令 写入文件\n> #示例:把以#开头的行 不写到文件里\n> [root@cPen_A 10]# sed '/^#/!w a.txt' selinux \n> [root@cPen_A 10]# cat selinux |sed '/^#/!w abc.txt'\n> [root@cPen_A 10]# cat a.txt \n> SELINUX=disabled\n> SELINUXTYPE=targeted \n> \n> ```\n>\n> ![image-20221011222050156](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011222050156.png)\n\n\n\n---\n\n# 三. sed的替换 -->核心功能\n\n> ![image-20221011222143284](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011222143284.png)\n>\n> ```bash\n> [root@cPen_A 10]# sed -i 's/xiaomi/redmi/' phone.txt \t#注:替换每一行的第1个xiaomi替换为redmi\n> [root@cPen_A 10]# sed -i 's/vivo/nokia/2' phone.txt \t#注:替换每一行的第2个vivo替换为nokia\n> [root@cPen_A 10]# sed -i 's/oppo/meizu/g' phone.txt \t#注:每一行所有的oppo替换为meizu\n> [root@cPen_A 10]# sed -i 's/xiaomi/redmi/2g' phone.txt #注:替换每一行的第2个后所有xiaomi全部替换为redmi\n> \n> [root@cPen_A 10]# sed -i '/^ONBOOT/ s/yes/no/' ifcfg-ens33 \t#注:查找替换 (局部替换)\n> [root@cPen_A 10]# sed -i '8 s/192.168.0.1/192.168.0.2/' ifcfg-ens33 \t#注:根据 行号替换 (局部替换)\n> [root@cPen_A 10]# sed -i '8 s/GATEWAY.*/GATEWAY=192.168.0.2/' ifcfg-ens33 \t#注:整行替换\n> \n> #示例:把所有apple删除 --> 删除部分字符串\n> [root@cPen_A 10]# sed -i 's/apple//g' phone.txt \t\t#注:拿空的去替换它\n> \n> \\n 换行\n> \\t tab\n> [root@cPen_A 10]# sed -i 's/s/\\t/g' phone.txt \n> \n> ---------------------------------------------------------\n> [root@cPen_A 10]# sed -i '1c sanchuang' /etc/hostname \n> \n> [root@cPen_A 10]# sed -i '3,5s/^/#/' phone.txt \t#注:3-5行加注释\n> \n> [root@cPen_A 10]# sed -i '3,5s/$/ sanchuang/' phone.txt \t#注:3-5行 末尾加sanchuang\n> \n> [root@cPen_A 10]# sed -i '/^DNS2/ s/^/#/' ifcfg-ens33 \t\t#注:注释\n> #DNS2=114.114.114.114\n> ```\n>\n> \n\n\n\n---\n\n> ![image-20221011222225313](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011222225313.png)\n>\n> ```bash\n> #示例:\n> [root@cPen_A 10]# sed -i 's#/sbin/nologin#/bin/bash#' passwd \n> ```\n>\n> \n\n---\n\n> ![image-20221011222251704](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011222251704.png)\n>\n> ```bash\n> #示例:\n> [root@cPen_A 10]# cat c.txt \n> 0.0.0.0\n> 1.1.1.1\n> 2.2.2.2\n> [root@cPen_A 10]# cat c.txt|sed -n 's/$/:80/;H;${x;s/\\n/,/2g;p}'\n> \n> 0.0.0.0:80,1.1.1.1:80,2.2.2.2:80\n> \n> h H Copy/append pattern space to hold space.\n> \n> g G Copy/append hold space to pattern space.\n> \n> x Exchange the contents of the hold and pattern spaces.\n> ---------------------------------------------------------------------\n> [root@localhost 10]# cat c.txt |tr '\\n' ','|sed -n 's/,/:80&/g;p'|awk -F, 'OFS=\",\"{print $1,$2,$3}'\n> 0.0.0.0:80,1.1.1.1:80,2.2.2.2:80\n> ```\n>\n> ![image-20221011222324095](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011222324095.png)\n\n\n\n---\n\n```bash\nsed的命令中&的用法\n&用于表示替换命令中的匹配模式\n```\n\n\n\n---\n\n> ![image-20221011222349210](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011222349210.png)\n>\n> (正则) --》对应一个标签--》分组\n>\n> 从左到右 1开始\n>\n> \\3 引用第3个分组(标签)\n>\n> ```bash\n> 示例:\n> [root@cPen_A 10]# echo aaa bbb 123456 ccc | sed -r 's/([a-z]+) ([a-z]+) ([0-9]+) ([a-z]+)/\\3/'\n> 123456\n> ```\n>\n> \n\n---\n\n# 四. 模式空间(pattern space)和暂存空间(hold space)相关的命令\n\n> 模式空间(pattern space)和暂存空间(hold space)相关的命令:\n>\n> \n>\n> n 输出模式空间行,读取下一行替换当前模式空间的行,执行下一条处理命令而非第一条命令。\n>\n> N 读入下一行,追加到模式空间行后面,此时模式空间有两行。\n>\n> h 把模式空间里的行拷贝到暂存空间。\n>\n> H 把模式空间里的行追加到暂存空间。\n>\n> g 用暂存空间的内容替换模式空间的行。\n>\n> G 把暂存空间的内容追加到模式空间的行后。\n>\n> x 将暂存空间的内容于模式空间里的当前行互换。\n>\n> ! 对所选行以外的所有行应用命令。\n>\n> \n>\n> http://blog.csdn.net/itsenlin/article/details/21129405\n>\n> \n\n---\n\n# 五. 练习\n\n```markdown\n练习:\n1.编写一个修改ip地址的脚本\n提醒用户输入ip、子网掩码、网关、dns服务器地址\n直接修改网卡配置文件,然后刷新服务让输入的ip地址信息生效\n需要检查输入ip地址是否合法,不能输入空的内容或者字母,如果ip地址不合法或者输入空内容、字母都给予提醒\n提醒:空的内容包括回车和空格,可以是多个空格\n\n需求分析:\n\t1.read或者位置变量\n\t2.修改配置文件 sed\n\t3.ip合法判断--》正则\n\n2.请将所有的非root用户的uid后面加一个0,gid前面加一个1\n\t复制/etc/passwd 到当前目录下操作\n\n3给下列含有大写字母的行,在数字后追加sanchuang --》sed\n   abcd6Sdd9dde\n   islHishbxld\n   goBke8fji\n   daa5nshXxge\n\n\n4.自己编辑一个文件test.txt,内容如下:\n\t\t0.0.0.0\n\t\t1.1.1.1\n\t\t2.2.2.2\n\t\t输出以下形式:\n\t\t\t0.0.0.0:80,1.1.1.1:80,2.2.2.2:80\n5.sed取出/etc/passwd文件的第一列\n6.sed将PATH环境变量中的冒号换成换行\n7.sed将PATH环境变量斜杠/换成斜杠\\\n8.sed修改SELINUX配置文件从开启(enforcing)变成禁用(disabled)\n/etc/sysconfig/selinux\n9.去掉/etc/passwd文件中第二个字段的x\n10.将/etc/sysconfig/network-scripts/ifcfg-ens33里的ONBOOT=no修改为yes或者修改下IPADDR后面的ip地址\n只显示ip add的ip地址\n11.复制/etc/ssh/sshd_config 到当前目录,然后操作。将sshd_config里的端口号修改为8899\n```\n\n\n\n","tags":["Linux","Shell","Sed"],"categories":["Linux"]},{"title":"29_Linux基础-shell编程-awk-sed","url":"/posts/3ae7567f.html","content":"**awk**\n\n输入分隔符(-F、FS)、输出分隔符(OFS)\n\n\n\n---\n\nawk里引用shell变量\n\n\n\n# 一. awk和shell变量交换的问题\n\n**awk和shell变量交换的问题**\n\n1、使用 -v选项\n\n2、使用双引号,但是awk内部的$0 $1等$符号前需要使用\\转义\n\n3、使用单引号,将变量引起来,然后前面加一个$符号再次引用变量的值,相当于取2次值\n\n```bash\n#示例:使用 -v选项\n[root@cPen_A ~]# sg=\"panjinhao\"\n[root@cPen_A ~]# echo $sg\npanjinhao\n[root@cPen_A ~]# echo|awk '{print $sg}'\n\n[root@cPen_A ~]# echo|awk -v bsg=$sg '{print bsg}'\npanjinhao\n[root@cPen_A ~]# ls|awk -v bsg=$sg '{print bsg}'\npanjinhao\t\t\t#注:ls 输出多行\npanjinhao\n……\npanjinhao\n\n[root@cPen_A lianxi]# vim test2.sh \nawk -v var=$1 -F: '$1==var{print NR,$0}' /etc/passwd\n[root@cPen_A lianxi]# bash test2.sh root\n1 root:x:0:0:root:/root:/bin/bash\n[root@cPen_A lianxi]# bash test2.sh sanchuang\n21 sanchuang:x:1000:1000::/home/sanchuang:/bin/bash\n#注:第1个$1 位置变量,第2个$1 第1个字段\n\n#示例:使用双引号,但是awk内部的$0 $1等$符号前需要使用\\转义\n[root@cPen_A lianxi]# mv=\"zhangjie\"\n[root@cPen_A lianxi]# useradd zhangjie_123\n[root@cPen_A lianxi]# cat /etc/passwd|awk -F: \"/^$mv/{print \\$1,\\$3}\"\nzhangjie_123 12358\n\n#示例:使用单引号,将变量引起来,然后前面加一个$符号再次引用变量的值,相当于取2次值\n[root@cPen_A lianxi]# sg=3\n[root@cPen_A lianxi]# awk -F: '/root/{print $1,$'$sg'}' /etc/passwd\nroot 0\noperator 11\n```\n\n\n\n---\n\n# 二. 进程和进程之间通信的方式\n\n1、共享内存\n\n2、信号量\n\n3、信号\n\n4、管道\n\n5、队列\n\n6、Socket\n\n\n\n---\n\n```bash\n[root@cPen_A lianxi]# cat /etc/shadow\n第2个字段:密码字段\n*操作系统自带的,没有密码的\n!!用户建的,没有密码的\n提示:密码字段为*、!!表示没有设置密码;密码字段为空说明密码被清除。\n#示例:没有设置密码的用户\n[root@cPen_A lianxi]# cat /etc/shadow|awk -F: 'BEGIN{i=0}length($2)<=2{print $1,\"没有设置密码\";i++}END{print \"一共有\"i\"个用户\"}'\n```\n\n\n\n---\n\n# 三. awk内置函数\n\nawk内置的函数:\n\n​\t\tlength()\n\n​\t\tint()\n\n​\t\tsqrt()\n\n​\t\tsystem()\n\nString Functions\n\n​\t\tsub()\n\n​\t\tindex()\n\n​\t\tlength()\n\n​\t\tsplit()\n\n\nNumeric Functions\n\nyum install python3\t安装python3\n\n```bash\n#示例:生成0-1之间随机数\n[root@cPen_A lianxi]# echo |awk '{print rand()}'\n0.237788\n#示例:产生0-100之间随机数\n[root@cPen_A lianxi]# echo |awk '{print rand()*100}'\n23.7788\n[root@cPen_A lianxi]# echo |awk '{print int(rand()*100)}'\n23\n```\n\n\n\n---\n\n# 四. 流控\n\n流控:流程控制\tcontrol flow\n\nfor\n\nwhile\n\ncase\n\nif\n\n\n\n```bash\nif语句\n单分支\n[root@cPen_A lianxi]# awk -F: '{if($1 ~ /\\<...\\>/)print $0}' /etc/passwd\nbin:x:1:1:bin:/bin:/sbin/nologin\n[root@cPen_A lianxi]# awk -F: '$1 ~ /\\<.{3}\\>/{print $0}' /etc/passwd\nbin:x:1:1:bin:/bin:/sbin/nologin\n\n双分支\n[root@cPen_A lianxi]# awk -F: '{if($1 ~ /\\<...\\>/)print $0;else print \"不符合要求\"}' /etc/passwd\n不符合要求\nbin:x:1:1:bin:/bin:/sbin/nologin\n```\n\n> ![image-20221011220439733](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220439733.png)\n\n\n\n```bash\n#练习\n/etc/passwd\n$3是uid 用户的编号\n如果用户的编号是0 --> 管理员\n1~999 --> 程序用户\n大于1000 --> 普通用户\n最后统计出有多少管理员,多少程序用户,多少普通用户?\n-----------------------------------------------------\n[root@cPen_A ~]# awk -F: 'BEGIN{x=0;y=0;z=0}{if($3==\"0\") {print $1,\"管理员\";x++} else if($3>=1 && $3<=999) {print $1,\"程序用户\";y++} else {print $1,\"普通用户\";z++}}END{print \"管理员\"x,\"程序用户\"y,\"普通用户\"z}' /etc/passwd\nroot 管理员\nbin 程序用户\n……\n管理员1 程序用户25 普通用户40\n```\n\n\n\n---\n\n# 五. awk的for循环、数组\n\n> ![image-20221011220532360](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220532360.png)\n>\n> ![image-20221011220538243](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220538243.png)\n>\n> ![image-20221011220551647](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220551647.png)\n>\n> ![image-20221011220605574](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220605574.png)\n>\n> ![image-20221011220614623](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220614623.png)\n>\n> \n\n\n\n---\n\nawk难点:\n\n1. 正则表达\n\n2. if\n\n3. 内置函数\n\n4. 内置变量\n\n5. for,数组array\n\n\n\n---\n\n# 六. sed\n\nsed是什么?what --> text stream editor\n\t\t有什么用?where how --> 修改和替换文本 --> modify and substitute\n\n\n\nsed是一种支持正则表达式的非交互式流编工具(stream editor)\n\n​\t\t脚本中修改文本或者文本替换的最佳工具\n\n\n\n交互式:一问一答。比如python3里敲命令\n\n> ![image-20221011220732396](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220732396.png)\n\n\n\n**2个空间**\n\t\t**pattern space --> 处理数据的地方 --> 处理一行数据后,模式空间会清空**\n\t\t**hold space --> 临时存放数据的地方**\n\n\n把pattern space放到hold space 命令:h、H\n\n把hold space放到pattern space 命令:g、G\n\n\n\\#注:性能意识,sed在内存里运行,比磁盘速度快\n\n\\#注:容量意识\n\n\n\n---\n\n```bash\n#示例:-i选项 直接在文件里进行修改,不输出到屏幕\n[root@cPen_A lianxi]# sed -i 's/xiaomi/redmi/g' test.txt \n#示例:通过管道传过来\n[root@cPen_A lianxi]# cat chen |sed 's/xiaomi/redmi/g'\n```\n\n> ![image-20221011220845338](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220845338.png)\n\n\n\n---\n\n```bash\n[root@cPen_A lianxi]# cat -n /etc/passwd|head |tail -6\n 5\tlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n 6\tsync:x:5:0:sync:/sbin:/bin/sync\n 7\tshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n 8\thalt:x:7:0:halt:/sbin:/sbin/halt\n 9\tmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n 10\toperator:x:11:0:operator:/root:/sbin/nologin\n#示例:-n选项 值显示匹配处理的行 (否则会输出所有)\n[root@cPen_A lianxi]# cat -n /etc/passwd|sed -n '5,10p'\n 5\tlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n 6\tsync:x:5:0:sync:/sbin:/bin/sync\n 7\tshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n 8\thalt:x:7:0:halt:/sbin:/sbin/halt\n 9\tmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n 10\toperator:x:11:0:operator:/root:/sbin/nologin\n```\n\n\n\n---\n\n> ![image-20221011220928234](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011220928234.png)\n\n\n\n## sed的p命令示例\n\n```bash\n= :输出行号\n\np命令输出的时候:\n连续的行\n[root@localhost lianxi]# cat /etc/passwd|sed -n '1,5p'\n不连续的行\n[root@localhost lianxi]# cat /etc/passwd|sed -n '10p;20p'\n\n示例:sed的p命令示例\nsed -n ‘行号1,行号2p’ 输出文件\n[root@localhost lianxi]# cat /etc/passwd|sed -n '1,5p'\t\t\t#注:连续用,号\nroot:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n[root@localhost lianxi]# cat /etc/passwd|sed -n '=;1,5p'\t\t#注:=;输出行号\n1\nroot:x:0:0:root:/root:/bin/bash\n2\nbin:x:1:1:bin:/bin:/sbin/nologin\n3\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\n4\nadm:x:3:4:adm:/var/adm:/sbin/nologin\n5\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n6\n7\n……\n14\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n '1,$p'\t\t#注:$p最后一行\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n '5,+5p'\t\t#注:第5行开始 往后加5行\n 5\tlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n 6\tsync:x:5:0:sync:/sbin:/bin/sync\n 7\tshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n 8\thalt:x:7:0:halt:/sbin:/sbin/halt\n 9\tmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n 10\toperator:x:11:0:operator:/root:/sbin/nologin\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n '5,100!p'\t\t#注:取反,取1到4行\n 1\troot:x:0:0:root:/root:/bin/bash\n 2\tbin:x:1:1:bin:/bin:/sbin/nologin\n 3\tdaemon:x:2:2:daemon:/sbin:/sbin/nologin\n 4\tadm:x:3:4:adm:/var/adm:/sbin/nologin\n#示例:步长值\n\t# cat -n /etc/passwd|sed -n '1~2p'\n\t# cat -n /etc/passwd|sed -n '2~2p'\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n '1~2p'\t#注:单数行,1开始每次往后2行\n 1\troot:x:0:0:root:/root:/bin/bash\n 3\tdaemon:x:2:2:daemon:/sbin:/sbin/nologin\n 5\tlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n 7\tshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n 9\tmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n 11\tgames:x:12:100:games:/usr/games:/sbin/nologin\n 13\tnobody:x:99:99:Nobody:/:/sbin/nologin\n 15\tdbus:x:81:81:System message bus:/:/sbin/nologin\n 17\tsshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin\n 19\tchrony:x:998:996::/var/lib/chrony:/sbin/nologin\n 21\tchenpeng:x:1001:1001::/home/chenpeng:/bin/bash\n 23\tnginx:x:996:994:Nginx web server:/var/lib/nginx:/sbin/nologin\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n '2~2p'\t\t#注:双数行\n 2\tbin:x:1:1:bin:/bin:/sbin/nologin\n 4\tadm:x:3:4:adm:/var/adm:/sbin/nologin\n 6\tsync:x:5:0:sync:/sbin:/bin/sync\n 8\thalt:x:7:0:halt:/sbin:/sbin/halt\n 10\toperator:x:11:0:operator:/root:/sbin/nologin\n 12\tftp:x:14:50:FTP User:/var/ftp:/sbin/nologin\n 14\tsystemd-network:x:192:192:systemd Network Management:/:/sbin/nologin\n 16\tpolkitd:x:999:998:User for polkitd:/:/sbin/nologin\n 18\tpostfix:x:89:89::/var/spool/postfix:/sbin/nologin\n 20\tmysql:x:1000:1000::/home/mysql:/sbin/nologin\n 22\tredis:x:997:995:Redis Database Server:/var/lib/redis:/sbin/nologin\n#示例:shell变量传到sed里\n#双引号 推荐\n[root@localhost lianxi]# num1=6\n[root@localhost lianxi]# num2=10\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n \"${num1},${num2}p\"\n 6\tsync:x:5:0:sync:/sbin:/bin/sync\n 7\tshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n 8\thalt:x:7:0:halt:/sbin:/sbin/halt\n 9\tmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n 10\toperator:x:11:0:operator:/root:/sbin/nologin\n#单引号\n[root@localhost lianxi]# cat -n /etc/passwd|sed -n ''${num1},${num2}'p'\n 6\tsync:x:5:0:sync:/sbin:/bin/sync\n 7\tshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\n 8\thalt:x:7:0:halt:/sbin:/sbin/halt\n 9\tmail:x:8:12:mail:/var/spool/mail:/sbin/nologin\n 10\toperator:x:11:0:operator:/root:/sbin/nologin\n\n----------------------------------------------------------\n#示例:显示包含bash的行\n[root@localhost lianxi]# cat /etc/passwd|sed -n '/bash/p'\nroot:x:0:0:root:/root:/bin/bash\nchenpeng:x:1001:1001::/home/chenpeng:/bin/bash\n[root@localhost lianxi]# cat /etc/passwd|egrep \"bash\"\nroot:x:0:0:root:/root:/bin/bash\nchenpeng:x:1001:1001::/home/chenpeng:/bin/bash\n[root@localhost lianxi]# cat /etc/passwd|awk '/bash/'\nroot:x:0:0:root:/root:/bin/bash\nchenpeng:x:1001:1001::/home/chenpeng:/bin/bash\n\n#示例:输出#号开头的行\n[root@localhost lianxi]# cat /etc/ssh/ssh_config |sed -n '/^#/p'\n#示例:输出不是#号开头的行\n[root@localhost lianxi]# cat /etc/ssh/ssh_config |sed -n '/^#/!p'\n#示例:显示 不是#号和!号开头的行\n[root@localhost lianxi]# cat /etc/ssh/ssh_config |sed -r -n '/^#|^$/!p'\t#注:-r支持更多正则\n[root@localhost lianxi]# cat /etc/ssh/ssh_config |egrep -v '^#|^$'\n#示例:显示 以/结尾的行\n[root@localhost lianxi]# df -h|egrep \"/$\"\n/dev/mapper/centos-root 17G 9.9G 7.2G 58% /\n[root@localhost lianxi]# df -h|sed -n '/\\/$/p'\n/dev/mapper/centos-root 17G 9.9G 7.2G 58% /\n\n#示例:以a-Z开头的行\n[root@localhost lianxi]# cat /etc/passwd|sed -n '/^[a-Z]/p'\n#示例:不以a-Z开头的行\n[root@localhost lianxi]# cat /etc/passwd|sed -n '/^[^a-Z]/p'\n```\n\n\n\n---\n\n```bash\n题目:截取nginx的access.log文件里3月18号15:30:00 -- 16:48:10时间段内的所有访问日志\n\n[root@cPen_A lianxi]# service firewalld stop\t#注:立马停止firewalld服务\n[root@cPen_A lianxi]# systemctl disable firewalld\t#注:设置firewalld服务开机不启动-->下次重启机器的时候不启动\n\n[root@cPen_A nginx]# tail -f access.log\t\t#注:动态监控最后一行\n192.168.0.17 - - [09/Jan/2021:16:36:03 +0800] \"GET /favicon.ico HTTP/1.1\" 404 3650 \"http://192.168.0.118/\" \"Mozilla/5.0 (Linux; Android 10; PCT-AL10; HMSCore 5.1.0.300; GMSCore 20.26.14) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.106 HuaweiBrowser/11.0.5.304 Mobile Safari/537.36\" \"-\"\n[root@cPen_A nginx]# pwd\n/var/log/nginx\t\t\t\t#注:nginx的日志文件的路径\n[root@cPen_A nginx]# ls\naccess.log access.log-20201202.gz error.log error.log-20201202.gz\n#注:access.log是nginx的访问日志文件,记录访问过我们的网站的信息\n[root@cPen_A nginx]# cat access.log | awk -F'[()]' '{print $2}'|sort|uniq -c|sort -nr\n 13 Windows NT 10.0; WOW64\t\t\t#注:排序去重 再降序排序 显示数量\n 4 Linux; Android 10; PCT-AL10; HMSCore 5.1.0.300; GMSCore 20.26.14\n---------------------------------------------------------------------------\n[09/Jan/2021:16:32:46 +0800] --> 09/Jan/2021:16:32:46\n[09/Jan/2021:16:33:07 +0800] --> 09/Jan/2021:16:32:46\n#示例:查找该时间段的所有访问日志\n[root@cPen_A nginx]# cat access.log|sed -n '/09\\/Jan\\/2021:16:32:46/,/09\\/Jan\\/2021:16:33:07/p'\n#示例:正则写法\n[root@cPen_A nginx]# cat access.log|sed -r -n '/09\\/Jan\\/2021:16:(3[789]|4[0-9]|5[01]):(0[1-9]|[1-5][0-9])/p'\n#注:分钟的范围37~51 秒的范围01~59\n#37~51\n#37~39\n#40~49\n#50~51\n\n#01~59\n0[1-9]|[1-5][0-9]\n```\n\n\n\n---\n\n## sed的d命令示例\n\n```bash\nsed的d命令示例\n删除操作可以根据行号和匹配模式进行操作\n#示例:删除有denghui的行\n[root@cPen_A nginx]# cat /etc/passwd|sed '/denghui/d'\n#示例:-i动原文件 删除有redmi这行\n[root@cPen_A lianxi]# sed -i '/redmi/d' test.txt \n#示例:根据行删除\n[root@cPen_A lianxi]# sed -i '2d' test.txt \t#注:删除第2行\nsed查找方式:\n\t1、根据行号\n\t2、根据模式 -->正则表达式=字符+特殊符号\n\t3、根据字符串\n\n#示例:在第4行后面追加huawei\n[root@cPen_A lianxi]# sed -i '4a huawei' test.txt \n#示例:在第4行前面插入apple\n[root@cPen_A lianxi]# sed -i '4i apple' test.txt \n#示例:在VIVO这行前一行插入OPPO\n[root@cPen_A lianxi]# sed -i '/VIVO/i OPPO' test.txt \n#示例:在VIVO同行后面添加APPLE.&表示前面全部\n[root@cPen_A lianxi]# sed -i 's/VIVO/& APPLE/' test.txt \n#示例:将所有为huawei都替换成sanchuang\n[root@cPen_A lianxi]# sed -i 's/huawei/sanchuang/g' test.txt \nsed的命令:\n\tp\n\td\n\ta\n\ti\n\ts\n\tc\n\tr\n\tw\n```\n\n\n\n","tags":["Linux","Shell","Awk","Sed"],"categories":["Linux"]},{"title":"28_Linux基础-shell编程-awk","url":"/posts/29e2641c.html","content":"> /bin下面放二进制文件\n> lib 放系统的公共模块、公共库、公共工具\n> /dev设备文件\n>\n> #标准输入、标准输出\n>\n> /usr 安装的命令安装的模块 编译安装、rpm安装的程序\n>\n> /boot 系统启动会到这里来找\n>\n> /proc 保留正在运行的程序\n>\n> /proc/sys 正在运行的内核参数进行修改 \n> /etc/sysctl.conf 永久修改\n> [root@localhost net]# sysctl -p 生效\n>\n> /run 保存pid文件\n>\n> /var/log 系统日志\n\n---\n\n# 一. 脚本调试 -x\n\n```bash\n#示例:脚本的调试 -x\n[root@cPen_A lianxi]# bash -x test.sh \n+ ls\naaa2 aaa.py d.md5 mod1.py __pycache__ test_class2.py test_class.py test.sh \n+ echo ok\nok\n+ echo err\nerr\n```\n\n\n\n---\n\n# 二. 小数计算\n\n```bash\n#示例:小数计算\n[root@cPen_A lianxi]# echo \"scale=2;5/3\" |bc\n1.66\n[root@cPen_A lianxi]# echo \"5 3\" |awk '{print $1/$2}'\n1.66667\n[root@cPen_A lianxi]# echo \"5 3\" |awk '{printf \"%.2f\",$1/$2}'\n1.67\n```\n\n\n\n---\n\n# 三. 打印奇数\n\n```bash\n#示例:打印奇数\n[root@cPen_A lianxi]# for i in `seq 1 2 100` ;do echo $i;done\n\n#注:或者类似C语言for循环写法\n```\n\n\n\n---\n\n# 四. 合并文件\n\n```bash\n#示例:合并文件\n把用户名字和用户金额统一在一起\n#注:把2个文件按照列合并\n\n[root@cPen_A shell_test]# cat user.txt \n100 cp1\n200 cp2\n300 cp3\n[root@cPen_A shell_test]# cat money.txt \n100 $500\n300 $600\n200 $400\n-----------------------------------------------------\n[root@cPen_A shell_test]# cat money.txt |sort -t \" \" -n >money2.txt\n[root@cPen_A shell_test]# cat user.txt |sort -t \" \" -n >user2.txt \n[root@cPen_A shell_test]# cat user2.txt \n100 cp1\n200 cp2\n300 cp3\n[root@cPen_A shell_test]# cat money2.txt \n100 $500\n200 $400\n300 $600\n[root@cPen_A shell_test]# join user2.txt money2.txt \n100 cp1 $500\n200 cp2 $400\n300 cp3 $600\n\n[root@cPen_A shell_test]# paste user2.txt money2.txt \n100 cp1 100 $500\n200 cp2 200 $400\n300 cp3 300 $600\n\n-----------------------------------------------------\nwhile read user_id user_name\ndo\n while read user_id2 user_money\n do\n if [[ $user_id == $user_id2 ]]\n then\n echo $user_id $user_name $user_money >> user_money.txt\n fi\n done < money.txt\ndone < user.txt\n\n```\n\n\n\n---\n\n> sed处理文本\n>\n> vim替换文本,用替换模式 按r\n>\n> sed在文本外部操作文本里面的内容。做更新替换和删除(比如修改一键化安装脚本 配置文件 用sed去修改)\n>\n> http://c.biancheng.net/linux/sed.html\n>\n> ```bash\n> [root@cPen_A shell_test]# vim test.txt\n> aa\n> bb\n> cc\n> abc\n> def\n> [root@cPen_A shell_test]# sed '/a/d' test.txt \n> bb\n> cc\n> def\n> [root@cPen_A shell_test]# cat test.txt \n> aa\n> bb\n> cc\n> abc\n> def\n> [root@cPen_A shell_test]# sed -i '/a/d' test.txt \t#注:真正删除成功\n> [root@cPen_A shell_test]# cat test.txt \n> bb\n> cc\n> def\n> ```\n>\n> \n\n\n\n---\n\n# 五. 文本处理\n\n> **1.文本处理(请使用shell脚本让其满足下列特性):**\n>\n> (1)给下列含有大写字母的行,在大写字母后追加数字2020 --》sed\n>\n> abcdSdddde\n>\n> islHishbxld\n>\n> goBkefji\n>\n> daanshXxge\n>\n> ```bash\n> sed -i‘s/oldword/newword/g’ c.txt\n> #注:s substitute替换\n> &代表前面匹配的oldword\n> \n> [root@cPen_A ~]# cat c.txt |sed 's/[A-Z]/&2020/g'\n> [root@cPen_A ~]# sed -i 's/[A-Z]/&2020/g' c.txt\t\t#注:对源文件做修改\n> ```\n>\n> \n\n> ```bash\n> (2)请取出下列以逗号分割符最后一个字段不为0的行,并对最后一个字段以100为最小单位取整取正\n>    000001,2,115\n>    000002,2,1,0\n>    000002,2,1,-200\n> \tawk,tr\n> \n> [root@cPen_A ~]# vim c.txt\n> ? ?000001,2,115\n> ? ?000002,2,1,0\n> ? ?000002,2,1,-200\n> [root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $1,int($NF/100)}'\n> ? ?000001 1\n> ? ?000002 -2\n> [root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $0,int($NF/100)}'|tr -d \"-\"\n> ? ?000001,2,115 1\n> ? ?000002,2,1,200 2\n> [root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $0,sqrt(int($NF/100)*int($NF/100))}'\n> ? ?000001,2,115 1\n> ? ?000002,2,1,-200 2\n> [root@cPen_A ~]# cat c.txt |tail -3|awk -F, '$NF != 0{print $0,sqrt(int($NF/100)*int($NF/100)),length($1)}'\n> ? ?000001,2,115 1 9\n> ? ?000002,2,1,-200 2 9\n> #注:$NF != 0 最后一项不为0\n> #注:$0 指全部。sqrt开平方\n> \n> AWK 里有很多的内置函数\n> int()\n> sqrt() 开根号\n> length()\n> \n> [root@cPen_A ~]# a=-488\n> [root@cPen_A ~]# echo ${a#-}\t\t\t\t#注:删除-号\n> 488\n> ```\n>\n> \n\n\n\n---\n\n# 六. awk\n\n> awk 是什么?\n>\n> ​\t\tawk是linux里的一个文本处理的命令(工具) --> 程序 --> c语言\n>\n> unix --> awk\n>\n> ​\t\t为什么要使用awk?\n>\n> ​\t\t\t\t截取内容\n>\n> \n>\n> bc进行小数运算\n>\n> awk也可以\n>\n> \n\n\n\n> 字段:field --> 列 column\n> \n>\n> name age sex grade\n>\n> cali 18 M 70\n>\n> rose 19 F 90\n>\n> \n>\n> \\#注:CSV文件 以,作为分割的文件\n>\n> \n>\n> $0 存储的是整行数据\n>\n> 每个数据存入$1-$7中\n\n\n\n> AWK 默认的分隔符是空白(空格、tab)\n>\n> 输入分隔符\n>\n> ​\t\t-F\n>\n> 输出分隔符\n>\n> ​\t\t,\n\n\n\n> ```bash\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F\":\" '{print $1$3$7}'\n> root0/bin/bash\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F\":\" '{print $1,$3,$7}'\n> root 0 /bin/bash\n> ```\n>\n> ![image-20221011213436007](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011213436007.png)\n\n\n\n> ```bash\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: 'BEGIN{print \"######start######\"} /bash$/{print $1,$7}END{print \"######end######\"}'\n> ######start######\n> root /bin/bash\n> sanchuang /bin/bash\n> ……\n> chen223344 /bin/bash\n> ######end######\n> #注:/bash$ 以bash结尾的行\n> \n> #示例:统计有多少行\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: 'BEGIN{i=0} {i++} END{print i}'\n> 65\n> #注:不需要用$,因为引用的不是变量\n> #注:多条命令使用,在{花括号}里放;号\n> #注:~波浪符号 模糊匹配 ~/feng/; || 或;&& 且\n> ```\n>\n> \n\n\n\n## AWK内置变量\n\n> **AWK内置变量**\n>\n> NR 代表行号 number of record --> record 记录 --> 行\n>\n> NF 代表一行的字段数量 number of field\n>\n> $NF 表示最后一个字段;$(NF-1)倒数第一个字段\n\n\n\n```bash\n[root@cPen_A lianxi]# cat /etc/passwd |awk -F: 'BEGIN{num=0;print \"开始统计/etc/passwd文件\"} $1 ~ /feng/ || $3 > 1005 {print NR,NF,$1,length($1),$(NF-1),$NF,$3;num++}END{print \"统计结束\",num}'\n开始统计/etc/passwd文件\n24 7 chenpeng1 9 /home/chenpeng1 /bin/bash 1100\n25 7 chenpeng2 9 /home/chenpeng2 /bin/bash 1200\n……\n65 7 nfsnobody 9 /var/lib/nfs /sbin/nologin 65534\n统计结束 37\n\n-------------------------------------------------------------------\n#示例:AWK过滤功能\n[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/xiexy/'\n[root@cPen_A lianxi]# cat /etc/passwd|egrep \"xiexy\"\n#示例:AWK截取功能\n[root@cPen_A lianxi]# who |awk '{print $2}'\ntty1\npts/2\n[root@cPen_A lianxi]# who |awk '{print $2,$4}'\ntty1 11:23\npts/2 09:38\n#示例:自定义的字符串和字段拼接\n[root@cPen_A lianxi]# who |awk '{print \"time:\"$4,\"name:\"$2}'\ntime:11:23 name:tty1\ntime:09:38 name:pts/2\n\n-------------------------------------------------------------------\n#示例:/^[^abcdefg]/ 不是以abcdefg开头的行\n[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/^[^abcdefg]/{print $1,$7}'\n#示例:/^[^A-z]/ 不是A-z字母开头的行\n[root@cPen_A lianxi]# cat /etc/passwd|awk -F: '/^[^A-z]/{print $1,$7}'\n#示例:指定2个分割符\n[root@cPen_A lianxi]# cat /etc/passwd|tail -1|awk -F[:/] '{print $8}'\nlib\n```\n\n\n\n## awk命令的操作符\n\n> awk命令的操作符\n> 比较操作符:匹配符号 ~ !~\n>\n> ```bash\n> #示例:\n> [root@cPen_A lianxi]# who\n> root tty1 2020-12-23 11:23\n> root pts/2 2021-01-08 09:38 (192.168.0.119)\n> [root@cPen_A lianxi]# who|awk '$2 ~ /pts/{print $0}'\n> root pts/2 2021-01-08 09:38 (192.168.0.119)\n> \n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: '$1 ~/deng/ && $3>1058 && $NF ~/bash$/'\n> ```\n>\n> \n\n\n\n## 文本数据表达式\n\n> 文本数据表达式:\n> == 精确匹配\n> ~ 模糊匹配\n>\n> ```bash\n> [root@cPen_A lianxi]# awk -F: '$3 ~ /\\<...\\>/ {print $1,$3}' /etc/passwd\n> systemd-network 192\n> polkitd 999\n> chrony 998\n> nginx 997\n> [root@cPen_A lianxi]# awk -F: '$3 ~ /\\<.{3}\\>/ {print $1,$3}' /etc/passwd\n> systemd-network 192\n> polkitd 999\n> chrony 998\n> nginx 997\n> \n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: '$1 ~ /deng/ {print $1}'\n> ```\n>\n> \n\n## awk 内置变量和函数\n\n> **awk 内置变量和函数?**\n> NF\t每行$0的字段数\n> NR\t当前处理的行号\n> FS 当前的输入分隔符,默认是空白字符(空格和tab) field separator\n> OFS 当前的输出分隔符,默认是空格字符(空格) output field separator\n>\n> \n>\n> ```bash\n> 示例:\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0}'\n> 1 root:x:0:0:root:/root:/bin/bash\t\t\t#注:NR行号\n> 2 bin:x:1:1:bin:/bin:/sbin/nologin\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0,NF}'\n> 1 root:x:0:0:root:/root:/bin/bash 7\n> 2 bin:x:1:1:bin:/bin:/sbin/nologin 7\n> [root@cPen_A lianxi]# cat /etc/passwd|awk -F: '{print NR,$0,$NF}'\n> 1 root:x:0:0:root:/root:/bin/bash /bin/bash\n> 2 bin:x:1:1:bin:/bin:/sbin/nologin /sbin/nologin\n> \n> [root@cPen_A lianxi]# cat /etc/passwd|awk 'FS=\":\";OFS=\"#\"{print NR,$0,$NF}'\n> root:x:0:0:root:/root:/bin/bash\n> 1#root:x:0:0:root:/root:/bin/bash#root:x:0:0:root:/root:/bin/bash\n> bin:x:1:1:bin:/bin:/sbin/nologin\n> 2#bin:x:1:1:bin:/bin:/sbin/nologin#/sbin/nologin\n> daemon:x:2:2:daemon:/sbin:/sbin/nologin\n> #推荐使用-F指定输入分隔符\n> \n> ===========================================================================================\n> 使用NF变量显示passwd文件倒数第二列的内容\n> [root@cPen_A ~]# cat /etc/passwd|awk -F: '{print $(NF-1)}'\n> \n> ----------------------------------------------------------\n> 显示passwd文件中第5到第10行的用户名\n> [root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR >= 5 && NR <= 10 {print $1}'\n> [root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR >= 5 && NR <= 10 {print NR,$1}'\n> \n> ----------------------------------------------------------\n> 显示passwd文件中第7列不是bash的用户名\n> [root@cPen_A ~]# cat /etc/passwd|awk -F: '$7 ~ /bash/ {print NR,$1}'\n> \n> ----------------------------------------------------------\n> 显示passwd文件中行号是5结尾的行号和行\n> [root@cPen_A ~]# cat /etc/passwd|awk -F: 'NR ~ /5$/ {print NR,$1}'\n> \n> ----------------------------------------------------------\n> 用ip add只显示ip(不能使用tr或者cut命令)\n> [root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $0}'\n> inet 192.168.0.118/24 brd 192.168.0.255 scope global noprefixroute dynamic ens33\n> [root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $2}'\n> 192.168.0.118/24\n> [root@cPen_A ~]# ip add|awk '$NF ~ /ens33/ {print $2}'|awk -F/ '{print $1}'\n> 192.168.0.118\n> \n> ----------------------------------------------------------\n> [root@localhost lianxi]# yum install net-tools -y\n> 先使用ifconfig,使用awk显示eth0的入站流量和出站流量(字节)\n> [root@cPen_A ~]# ifconfig|head -8|awk '$1 ~ /RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $0}'\n> RX packets 494598 bytes 38344433 (36.5 MiB)\n> TX packets 17025 bytes 1718505 (1.6 MiB)\n> [root@cPen_A ~]# ifconfig|head -8|awk '$1 ~ /RX/ && $4 ~ /bytes/ || $1 ~ /TX/ && $4 ~ /bytes/ {print $5}'\n> 38372669\n> 1719743\n> [root@cPen_A ~]# ifconfig|head -8|awk '$0 ~ /RX.*bytes|TX.*bytes/ {print $5}'\n> 38476866\n> 1744541\n> \n> #注:当有&&或者||,&&(and)的优先级高\n> \n> ----------------------------------------------------------\n> 使用awk命令统计以r开头的用户数目,显示如下效果\n> [root@cPen_A ~]# cat /etc/passwd|awk -F: 'BEGIN{i=0} $1 ~ /^r/ {print $1;i++} END{print i}'\n> root\n> rpc\n> rpcuser\n> 3\n> \n> ```\n>\n> \n\n\n\n","tags":["Linux","Shell","Awk"],"categories":["Linux"]},{"title":"27_Linux基础-nginx","url":"/posts/45562d6f.html","content":"web方向\n\n​\t\t经典提问:\n\n​\t\t\t\t在浏览器里输入一个www.baidu.com回车,到显示出内容,背后发生哪些事情?\n\n​\t\t\t\t应用层 --> 传输层 --> 网络层 --> 数据链路层 --> 物理层\n\n​\t\tnginx --> 详细的使用\n\n​\t\t\t\tflask --> web服务器 --> python写的 --> 自己写的web服务器软件\n\n​\t\t\t\t\t\tmvc, usgi等\n\n​\t\t\t\tnginx --> web服务器 --> C语言\n\n​\t\t\t\tgo语言 --> bingo\n\n​\t\t\t\thttp/https协议\n\n---\n\nnginx\n\n​\t\t1.安装 --> 最新版本 --> 编写脚本 --> 一键安装\n\n​\t\t2.nginx的配置文件深入讲解 --> 经典的功能实现\n\n​\t\t3.一定要使用一个云服务器 --> 购买域名 --> 备案 --> 上线\n\n​\t\t4.http协议\n\n---\n\n# 1. nginx是什么?\n\nnginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP/UDP proxy server, originally written by Igor Sysoev. \n\n​\t\thttp://nginx.org/\n\n​\t\thttp是什么?\n\n​\t\tHTTP是Hyper Text Transfer Protocol(超文本传输协议)的缩写\n\n​\t\t工作:应用层\n\n​\t\twww --> World Wide Web 万维网\n\n​\t\t协议:其实就规矩,方便双方沟通使用\n\n​\t\thttp协议是:浏览器和web服务器之间使用的\n\n​\t\t谁能读懂http协议?\n\n​\t\t\t\t所有的浏览器,所有web服务器,爬虫库(requests)等其他\n\n\n\n---\n\n# 2. nginx的安装\n\ncentos8.2\t\tnginx-1.19.5\n\nnginx最新的\tnginx-1.19.5\n\n```bash\n[root@cPen ~]# cat /etc/centos-release\t#注:查看版本\nCentOS Linux release 7.6.1810 (Core) \n\t1.下载\n\tmkdir -p /nginx\n\tcd /nginx\n\tcurl -O http://nginx.org/download/nginx-1.19.5.tar.gz\n\t2.解压\n\t[root@cPen_B nginx]# tar xf nginx-1.19.5.tar.gz \n\t[root@cPen_B nginx]# cd nginx-1.19.5\n\t[root@cPen_B nginx-1.19.5]# \n编译安装经典3步:\n\t1.编译前的配置:配置安装到哪里,启用哪些功能等\n\t\t./configure\n\t2.编译,将c的代码编译成二进制文件\n\t\tmake\n\t3.编译安装,将编译好的二进制文件复制到第一步里我们指定的路径\n\t\tmake install\n\n```\n\n```bash\n[root@cPen_B nginx-1.19.5]# ./configure --help 查看哪些功能可以开启,哪些功能可以禁用\nprefix 前缀\n\n--prefix=/usr/local/nginx 指定安装路径\n--with-select_module 启用,默认没有启用\n--without-select_module 禁用,默认是启用\n\n--with-http_ssl_module 启用https功能\n--with-http_realip_module --》修改http协议,里面增加一个字段realip-->nginx服务器做反向代理服务器的时候使用\n\n============\n解决依赖关系\nyum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ autoconf automake make \n\n编译前的配置\n[root@cPen_B nginx-1.19.5]# ./configure --prefix=/usr/local/nginx --user=cPen_nginx --group=cPen_nginx --build=scweb_server --with-threads --with-file-aio --with-http_v2_module --with-http_ssl_module --with-stream\n\n编译\nmake -j 2\n\n编译安装\nmake install\n\n启动nginx\n[root@cPen_B nginx-1.19.5]# cd /usr/local/nginx\n[root@cPen_B nginx]# ls\nconf html logs sbin\nconf 存放配置文件\nhtml 存放网页文件\nlogs 存放日志\nsbin 存放启动nginx的程序\n[root@cPen_B nginx]# cd sbin/\n[root@cPen_B sbin]# ls\nnginx\n[root@cPen_B sbin]# ./nginx\n[root@cPen_B sbin]# lsof -i:80\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nnginx 23548 root 9u IPv4 66009 0t0 TCP *:http (LISTEN)\nnginx 23549 cPen_nginx 9u IPv4 66009 0t0 TCP *:http (LISTEN)\n[root@cPen_B sbin]# ps aux|grep nginx\nroot 23548 0.0 0.0 41072 836 ? Ss 19:09 0:00 nginx: master process ./nginx\ncPen_ng+ 23549 0.0 0.2 74636 4852 ? S 19:09 0:00 nginx: worker process\n#注:master是领导,worker真正干活的\nmaster process 父进程:管理进程\nworker process 子进程:被管理的进程\n\n#注:pstree 查看进程树 -p选项看到进程号\n\n#修改PATH变量,方便启动nginx和停止nginx\n[root@cPen_B sbin]# PATH=/usr/local/nginx/sbin/:$PATH\n[root@cPen_B sbin]# echo $PATH\n/usr/local/nginx/sbin/:/lianxi/sc:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/nginx/sbin:/root/bin:/usr/local/nginx5/sbin:/root/bin\n\n#关闭防火墙和selinux\n[root@cPen nginx]# service firewalld stop\t\t\t#注:立马关闭防火墙\nRedirecting to /bin/systemctl stop firewalld.service\n[root@cPen nginx]# systemctl disable firewalld\t\t#注:设置防火墙开机不要启动\n#关闭selinux\nsetenforce 0 #临时关闭\nsed -i '/^SELINUX/ s/enforcing/disabled/' /etc/sysconfig/selinux\nsed -i '/^SELINUX/ s/enforcing/disabled/' /etc/selinux/config\n\n```\n\n```bash\n开机启动nginx的问题\n\t脚本的方式\n\t思考:如何让编译安装的nginx开机启动?\n\t1./etc/rc.local\n\t[root@sc-nginx sbin]# echo \"/usr/local/nginx/sbin/nginx\" >>/etc/rc.local \n\t[root@sc-nginx sbin]# chmod +x /etc/rc.d/rc.local \n\t# Please note that you must run 'chmod +x /etc/rc.d/rc.local' to ensure\n ------------------------------------------------------------------------\n [root@cPen_B ~]# chmod +x /etc/rc.d/rc.local \n #注:这是给源文件可执行权限\n [root@cPen_B ~]# chmod +x /usr/local/nginx/sbin/nginx\n [root@cPen_B ~]# vim /etc/rc.local #注:启动的时候会执行这个文件里的脚本\n #注:添加 /usr/local/nginx/sbin/nginx (最好是绝对路径)\n#on boot\necho \"/usr/local/nginx/sbin/nginx\" >>/etc/rc.local\nchmod +x /etc/rc.d/rc.local\n```\n\n\n\n---\n\n**配置文件**\n\n​\t\t路径 /usr/local/nginx/conf/\n\n​\t\tnginx.conf #注:主配置文件\n\n面试:请你说说nginx配置文件里有哪些常见的配置 (讲它的结构)\n\n​\t\t日志\n\n​\t\t\t\taccess.log 记录正常的访问\n\n​\t\t\t\terror.log 访问出错的信息\n\n​\t\tlisten\n\n```nginx\n[root@cPen conf]# cat nginx.conf\n#user nobody;\t\t\t\t\t#注:指定启动nginx的用户\nworker_processes 1;\t\t\t\t#注:工作进程的数量 需要和cpu核心的数量一致\n\n#error_log logs/error.log;\t\t\t#注:日志文件放在哪里,日志级别\n#error_log logs/error.log notice;\n#error_log logs/error.log info;\n\n#pid logs/nginx.pid;\t\n\n#注:块 {}\nevents {\n worker_connections 1024;\t\t#注:表示nginx可以同时支持的并发数,同时支持多少人访问,具体需要考虑机器的cpu,内存,磁盘IO,网络带宽 --》压力测试\n}\n\n\nhttp {\t\t\t\t\t\t\t\t#注:与http协议相关的\n include mime.types;\n default_type application/octet-stream;\n\n #log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n # '$status $body_bytes_sent \"$http_referer\" '\n # '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n\n #access_log logs/access.log main;\n\n sendfile on;\n #tcp_nopush on;\n\n #keepalive_timeout 0;\n keepalive_timeout 65;\n\n #gzip on;\n\n server {\t\t\t\t\t\t\t#注:提供http服务的,一个server对应一个网站\n #listen 80;\t\t\t\t#注:监听的端口\n listen 8080;\n #server_name localhost;\t\t#注:为哪个网站(域名)提供网站的\n server_name www.cpen.top;\n\n #charset koi8-r;\n charset utf-8;\n\n #access_log logs/host.access.log main;\n\n location / {\t\t\t\t\t#注:访问网页的根\n root html;\t\t\t\t#注:存放网页的位置\n index index.html index.htm;\t#注:指定首页,其他页面通过链接过去\n }\n\n #error_page 404 /404.html;\n\n # redirect server error pages to the static page /50x.html\n #\n error_page 500 502 503 504 /50x.html;\n location = /50x.html {\n root html;\n }\n\n # proxy the PHP scripts to Apache listening on 127.0.0.1:80\n #\n #location ~ \\.php$ {\n # proxy_pass http://127.0.0.1;\n #}\n\n # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000\n #\n #location ~ \\.php$ {\n # root html;\n # fastcgi_pass 127.0.0.1:9000;\n # fastcgi_index index.php;\n # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;\n # include fastcgi_params;\n #}\n\n # deny access to .htaccess files, if Apache's document root\n # concurs with nginx's one\n #\n #location ~ /\\.ht {\n # deny all;\n #}\n }\n\n\n # another virtual host using mix of IP-, name-, and port-based configuration\n #\n #server {\n # listen 8000;\n # listen somename:8080;\n # server_name somename alias another.alias;\n\n # location / {\n # root html;\n # index index.html index.htm;\n # }\n #}\n\n\n # HTTPS server\n #\n #server {\n # listen 443 ssl;\n # server_name localhost;\n\n # ssl_certificate cert.pem;\n # ssl_certificate_key cert.key;\n\n # ssl_session_cache shared:SSL:1m;\n # ssl_session_timeout 5m;\n\n # ssl_ciphers HIGH:!aNULL:!MD5;\n # ssl_prefer_server_ciphers on;\n\n # location / {\t\t\t\t\t\t\t\t#注:和路由相关的\n # root html;\n # index index.html index.htm;\n # }\n #}\n\n}\n\n```\n\n**配置文件里相关配置**\n\n> ![image-20221011201523665](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011201523665.png)\n\n\n\n---\n\n**防火墙**\n\n```bash\niptables -A INPUT -p tcp --dport 8099 -j ACCEPT\n```\n\n\n\n---\n\nnginx的首页文件\n\n[root@cPen html]# cd /usr/local/nginx/html/\n\n[root@cPen html]# vim index.html \t\t#注:修改首页\n\n\\#注:修改内容自己定义\n\n \n\n\\#注:修改网页内容不需要刷新nginx服务\n\n​\t\t只有修改nginx的配置文件才需要刷新nginx服务\n\n---\n\n**使用域名访问:**\n\n​\t\t阿里云:没有备案的域名不允许访问\n\n​\t\t腾讯云:没有备案的域名不允许访问\n\n购买域名--》绑定公网ip--》搞一个首页--》去备案\n\n---\n\n# 3. shell编程语法\n\n**shell编程语法**\n\n```bash\n\\ 续行\ncmd1 && cmd2\ncmd1 || cmd2\ncmd1 && cmd2 || cmd3\n\ntest -d '/usr/local/nginx8/logs'\n[ -d /usr/local/nginx8/logs ] 判断/usr/local/nginx8/logs这个目录是否存在\n\ntest -f '/usr/local/nginx8/conf/nginx.conf' \n[ -f /usr/local/nginx8/conf/nginx.conf ] 判断/usr/local/nginx8/conf/nginx.conf这个文件是否存在\n```\n\n\n\n---\n\n```bash\n[root@sc-nginx nginx-1.19.5]# which killall\n/usr/bin/killall\n[root@sc-nginx nginx-1.19.5]# rpm -qf /usr/bin/killall \npsmisc-23.1-5.el8.x86_64\n#注:killall -9 nginx 杀死所有nginx进程\n```\n\n\n\n---\n\n```bash\n#注:vim编辑器 全部替换\n:%s/nginx8/nginx18/\n```\n\n\n\n---\n\n# 4. web\n\n```\nnginx\n\t官方网站 http://nginx.org/en/\n \t\t\t http://nginx.org/en/docs/\n\n\t安装 编译\n\n\t网站\n\t\t静态页面 纯html,css,js(没有和数据库交互)\n\t\t\t\t nginx的强项是解析静态页面\n\t\t动态页面 需要使用动态编程语言:python,go,java,c#,php等\n\t\t\t\t 和数据库交互 --> 读写数据\n\t\t图解\n\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011202103199.png\" alt=\"image-20221011202103199\" style=\"zoom:150%;\" />\n\n\n\n```bash\n模块\n --with-http_realip_module\n --with-http_ssl_module\n --with-stream 让nginx具有负载均衡,支持4层\n \t\t\t\t enables building the stream module for generic TCP/UDP proxying and load balancing.\n启动nginx\n ./nginx\n \t启动\n ./nginx -s stop 停止\n nginx -s reload 重启\n kill\n killall\n pstree\tyum install psmisc\n lsof -i:80\n netstat -anplut\n PATH变量的修改 PATH=/usr/local/nginx/sbin/:$PATH 临时修改\n 永久修改 \n vim /etc/profile 在末尾添加 PATH=/usr/local/nginx/sbin:$PATH\n \n```\n\n---\n\nhttp协议\n\n​\t\t1.0\n\n​\t\t1.1\n\n​\t\t2.0\n\n​\t\thttp2.0比http1.1好在哪里?\n\n​\t\thttp和https的区别\n\n---\n\n**设置xshell小键盘可用**\n\n> ![image-20221011202303724](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011202303724.png)\n>\n> \\#注:属性 --》 终端 --》 VT模式 --》 设置为普通\n\n---\n\n--with-http_realip_module --》修改http协议,里面增加一个字段realip-->nginx服务器做反向代理服务器的时候使用\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011202334741.png\" alt=\"image-20221011202334741\" style=\"zoom:150%;\" />\n\n\n\n---\n\n# 5. nginx安装脚本\n\n```bash\n[root@cPen nginx]# cat onekey_install_nginx.sh \n#!/bin/bash\n\n#time:2020-12-12\n#author: cPen\n#company: cPen\n#mail:1533431376@qq.com\n\n#新建用户,用来启动nginx\nuseradd -s /sbin/nologin cPen_nginx\n#解决依赖关系\nyum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ autoconf automake make psmisc lsof net-tools vim\n\n#download file\nmkdir -p /nginx\ncd /nginx\ncurl -O http://nginx.org/download/nginx-1.19.5.tar.gz\n#解压文件\ntar xf nginx-1.19.5.tar.gz\ncd nginx-1.19.5\n#编译前的配置\n./configure --prefix=/usr/local/nginx --user=cPen_nginx --group=cPen_nginx --build=scweb_server --with-threads --with-file-aio --with-http_v2_module --with-http_ssl_module --with-stream\n\n#编译,-j 2 启动2个进程去编译,需要你有2个核心的cpu\nmake -j 2\n\n#编译安装\nmake install\n\n#修改PATH变量\nPATH=/usr/local/nginx/sbin:$PATH\necho 'PATH=/usr/local/nginx/sbin:$PATH' >>/etc/profile\n\n#关闭防火墙\nservice firewalld stop\nsystemctl disable firewalld\n\n#关闭selinux\nsetenforce 0 #临时关闭\nsed -i '/^SELINUX/ s/enforcing/disabled/' /etc/sysconfig/selinux\nsed -i '/^SELINUX/ s/enforcing/disabled/' /etc/selinux/config\n\n#启动nginx\nnginx\n\n#on boot\necho \"/usr/local/nginx/sbin/nginx\" >>/etc/rc.local\nchmod +x /etc/rc.d/rc.local\n\n```\n\n\n\n","tags":["Nginx","Linux"],"categories":["Linux"]},{"title":"26_Linux基础-项目轮廓-回顾ansible-dns-nfs-nginx","url":"/posts/dd4b1092.html","content":"# 一. ansible\n\n**ansible**\n\n​\t\t是什么?由哪些组成?\n​\t\t有什么作用?\n​\t\tparamiko\t\t--> 这个库/模块 ansible实现ssh功能\n\n---\n\n是什么?\n\nansible是一个自动化运维工具的名称\n\n---\n\n由哪些组成?\n\n**ansible组成:**\n\n​\t1、host inventory\t--#定义客户机,可以对客户机进行分类:db类,web类...等等\n\n​\t2、playbook\t\t\t --#剧本 让主机按照我给定的剧本去完成一些事情\n\n​\t3、module\t\t\t\t--#模块 实现一个个功能的程序\n\n​\t4、pluging\t\t\t\t --#插件 实现一些额外的小功能\n\n\\---------------------------------------\n\n有什么作用?\n\n装软件、卸软件、改配置、打补丁、做备份、跑脚本(运维工作)\n\n\\---------------------------------------\n\nansible是python写的,底层是ssh\n\n\\---------------------------------------\n\nparamiko\t\t--》 这个库/模块 ansible实现ssh功能\n\n\\---------------------------------------\n\nsshpass 模块 --》linux命令 实现ssh登录\n\n\\---------------------------------------\n\n[root@cPen_A ~]# ansible --version\t#注:查看版本\nansible 2.9.15\n\n\n\n---\n\n# 二. grep\n\n```bash\n#grep相关命令\n[root@cPen_B network-scripts]# cat /etc/passwd|grep -B 5 mail\t#注:查看前5行\n[root@cPen_B network-scripts]# cat /etc/passwd|grep -A 5 mail\t#注:查看后5行\n[root@cPen_B network-scripts]# cat /etc/passwd|grep -C 5 mail\t#注:中间 查看前后5行\n```\n\n\n\n---\n\n```bash\n[root@cPen_A ~]# vim /etc/ansible/ansible.cfg \t#注:ansible配置文件\nforks = 5\t\t\t\t\t\t#注:起5个进程去处理\t -f 选项\n```\n\n\n\n---\n\n```bash\nip地址显示不出来\nservice NetworkManager stop\t\t#注:这个服务影响的\nservice network restart\n```\n\n\n\n---\n\n```bash\ntemplate\t模板\t--> 绝大部分固定的,有几个是变量,根据ansible取机器上的值\n\n[root@cPen_A ansible]# ansible web -m setup\t\t#注:查看节点服务器的信息 以字典形式展示\n192.168.0.79 | SUCCESS => {\n \"ansible_facts\": {\n……\n}\n[root@cPen_A ansible]# ansible web -m setup -a \"filter=ansible_all_ipv4_addresses\"\n#注:过滤获得指定信息\n#注:获取 ansible-demo3 主机的 IPV4 地址\n192.168.0.79 | SUCCESS => {\n \"ansible_facts\": {\t\t\t\t#注:ansible_事实\n \"ansible_all_ipv4_addresses\": [\n \"192.168.0.79\"\n ], \n \"discovered_interpreter_python\": \"/usr/bin/python\"\n }, \n \"changed\": false\n}\n\n==========================================================\nssh = paramiko.SSHClient()\nssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())\nssh.connect(\"某IP地址\",22,\"用户名\", \"口令\")\n==========================================================\n解决使用密码连接,第一ssh过去的时候,需要输入yes的问题\n\n[root@C ansible]# vim hosts \n[web]\n192.168.0.77\n[db]\n192.168.0.35 ansible_ssh_user=root ansible_ssh_pass=123456\n\n[root@C ansible]# vim ansible.cfg \n# uncomment this to disable SSH key host checking\nhost_key_checking = False\n```\n\n\n\n---\n\n```bash\napi\t接口 --> application interface\n#注:写接口\njson\t有什么用?轻量级的数据交换格式\n```\n\n\n\n---\n\n```bash\n[root@cPen_A ansible]# ansible-doc -l\t\t#注:查看ansible的模块\n#注:doc 文档,l list\n```\n\n\n\n---\n\n```bash\nlastest表示安装 不是指最新的\n```\n\n\n\n---\n\n```markdown\n项目\nansible\n\n项目名称:使用ansible批量部署nginx集群和mysql集群\n项目环境:centos8.2,ansible2.9.15,nginx1.19.5,mysql5.7.31\n项目描述:\n\t使用ansible去批量部署6台nginx服务器,1台NFS文件服务器,3台MySQL服务器,其中nginx采用源码编译安装,MySQL采用二进制安装,NFS采用yum安装方法。nginx的编译安装和MySQL的二进制安装过程提前编写好脚本,通过ansible下发到nginx和MySQL服务器上执行,全程采用playbook来实现批量自动化部署\n项目步骤:\n\t1.部署好11台linux虚拟机,全部的配置,采用1核2G的内存的配置,安装好centos8.2的系统。\n\t2.然后在一台linux系统里安装部署ansible,采用yum安装。\n\t3.编写好一键安装nginx的脚本,连同nginx.conf配置文件都指定好内容,方便后面的playbook使用。\n\t4.编写好一键安装MySQL的脚本,连同my.cnf配置文件都指定好内容,方便后面的playbook使用。\n\t5.在ansible服务器和所有的nginx,MySQL,NFS服务器之间建立ssh免密通道\n\t6.最后编写ansible的playbook文件去统一部署nginx,MySQL,nfs服务器\n\t7.测试整个安装部署是否成功\n项目心得:\n\t1.对ansible的在大规模集群里的使用有了一些了解,深入体会到批量部署的便捷\n\t2.对集群有了一定的认识\n\t3.编写脚本的能力有了提升\n\t4.自己对*个故障的排除,提升自己的troubleshooting的能力\n============================================================================================\n写项目时\n1.摆数据\n```\n\n\n\n---\n\nnginx\n\n​\t\t是什么?有什么用?\n\n​\t\tnginx是一个web服务器\n\n​\t\tweb就是网站\n\n\n\n---\n\ndns\n\n​\t\tdomain name system 域名解析系统\n\n​\t\t[www.aliyun.com](http://www.aliyun.com) --> ip\n\n​\t\t为什么需要DNS?\n\n​\t\t\t\t方便记住某个网站名字\n\n​\t\t\t\tip很难记\n\n \n\n正向解析:域名 --> ip\n\n反向解析: ip --> 域名\n\n \n\n在浏览器输入www,baidu.com回车后发生了什么?\n\n​\t\t1、浏览器缓存\n\n​\t\t2、hosts文件\n\n​\t\t3、本地dns服务器\n\n​\t\t4、转发服务器\n\n​\t\t5、根域名服务器\n\n​\t\t6、迭代过程\n\n​\t\t7、递归返回\n\n​\t\t8、直接访问\n\n\n\n---\n\nCDN内容分发网络:加速\t(就近解析)\n\n\\#注:缓存有滞后的\n\n\\#注:视频业务大量使用CDN\n\n---\n\n记录类型\n\n​\t\tA记录 --> address record\n\n​\t\twww --> 120.77.248.190\n\n---\n\n需要上线一个自己的网站,有哪些流程(工作要做)?\n\n1、购买云服务器,部署nginx,mysql,Python等环境\n\n2、购买域名 www.chenpeng.com,绑定域名和云服务器 --> A记录 --> 备案(服务器在国内必须备案)\n\n3、开发网站 --> 写网站\n\n4、测试网站\n\n5、上传到云服务器的nginx网页根目录下 --> 上线\n\n---\n\n```bash\n[root@cPen_C lianxi]# yum provides nslookup\n#注:查看命令从哪个包安装\n```\n\n---\n\nNFS\n\n​\t\tnetwork file system\t网络文件系统\n\n​\t\t有什么用?\n\n​\t\t\t\t共享文件 --> 多台服务器使用相同的内容\n\n\\#注:NFS是最廉价的解放方案,受网络影响、服务器硬件配置低,磁盘的速度,CPU,内存,网络带宽 都是比较差的\n\n \n\n\\#注:比较贵的解决方案:上专业存储\n\n\\#注:更好的是 SAN 光纤设备\n\n \n\nSAN --> \n\nNAS --> 网络附加存储\n\n \n\nSAN一般指存储区域网络。存储区域网络(Storage Area Network,简称SAN)采用网状通道(Fibre Channel ,简称FC,区别与Fiber Channel光纤通道)技术,通过FC交换机连接存储阵列和服务器主机,建立专用于数据存储的区域网络\n\nNAS(Network Attached Storage:网络附属存储)按字面简单说就是连接在网络上,具备资料存储功能的装置,因此也称为“网络存储器”。\n\n---\n\nansible\n\n​\t\t项目\n\ndns\n\nnginx一键部署\n\n网站上线\n\nNFS\n\n​\t\tSAN\n\n​\t\tNAS\n\n---\n\n```bash\nnginx一键安装 脚本\n#!/bin/bash\n\n#author:cali\n#time:2020-49\n#company:sanchuang\n#email:695811769@qq.com\n\nmkdir -p /nginx2\ncd /nginx2\n#download nginx\ncurl -O http://nginx.org/download/nginx-1.17.9.tar.gz\n\n#创建用户\nuseradd lihu\n\n#解压\ntar xf nginx-1.17.9.tar.gz \n\n#进入解压目录\ncd nginx-1.17.9\n\n#解决依赖关系\nyum -y install zlib zlib-devel openssl openssl-devel pcre pcre-devel gcc gcc-c++ autoconf automake make \n\n#配置\n./configure --prefix=/usr/local/nginx9 --user=lihu --group=lihu --with-threads --with-file-aio --with-http_ssl_module --with-http_stub_status_module --with-stream \n\n#编译和安装\nmake -j 2 ; make install\n\n#开机启动\necho \"/usr/local/nginx9/sbin/nginx\" >>/etc/rc.local \nchmod +x /etc/rc.d/rc.local \n\n#修改PATH变量\necho \"PATH=/usr/local/nginx9/sbin:$PATH\" >>/etc/profile\nPATH=/usr/local/nginx9/sbin:$PATH\n\n#启动\nnginx\n```\n\n\n\n","tags":["Linux"],"categories":["Linux"]},{"title":"25_Linux基础-NFS服务","url":"/posts/317b0311.html","content":"日志轮转:\n\nhttps://blog.csdn.net/weixin_43265596/article/details/85469405\n\nhttps://www.cnblogs.com/liangyuxing/p/11962863.html\n\nhttps://blog.csdn.net/dhxaohei/article/details/8014764\n\n---\n\n# 一. NFS简介\n\n**NFS(Network File System的简称,即网络文件系统)**可以通过网络,让不同的机器、不同的操作系统可以共享彼此的文件。NFS可以将远程的计算机磁盘挂载到本地,读写文件像访问本地磁盘一样操作\n\n**前提**:关闭selinx\n\t\t\t关闭iptables\n\n\n\n```bash\n1、安装\n[root@cPen_A lianxi]# yum install nfs-utils\n--------------------------------------------------------------------------------------------\n2、修改配置文件\t/etc/exports\n[root@cPen_A lianxi]# vim /etc/exports\t\t#注:配置文件\n/opt/www 192.168.255.0/24(rw,no_root_squash)\t\t\t\t\n#注:192.168.255.0/24共享,rw权限 读写,no_root_squash 将远程根用户当成本地根用户,即不压制root\n首先创建/opt/www目录,在这下面创建index.html文件,文件内容”this is test nfs”\n再添加exports配置,nfs的配置:vim /etc/exports\n添加如下行:\n/opt/www 192.168.255.0/24(rw)\n表示共享/opt/www目录,给192.168.255./24这个网段的主机都可以通过nfs来访问我本地的/opt/www目录\n括号()里面的表示选项,rw表示读写\n\n生效配置:\nexportfs -a 或者重启服务\n\n[root@cPen_A opt]# cd /opt\n[root@cPen_A opt]# mkdir www\n[root@cPen_A opt]# cd www\n[root@cPen_A www]# vim index.html\nthis is test nfs\n[root@cPen_A www]# pwd\n/opt/www\n\n#注:/opt\t放额外的软件包的目录\n--------------------------------------------------------------------------------------------\n3、启动nfs服务\n[root@cPen_A www]# service nfs start\t\t#注:启动服务\n[root@cPen_A www]# showmount -e\t\t\t#注:检测是否可以连接\nExport list for cPen_A:\n/opt/www 192.168.255.0/24\n#注:centos8下 启动 [root@cPen_B ~]# service nfs-server start\n---------------------------------------------------------------\nNFS的连接查看\n可以在server端先自我测试一下是否可以连接。\n命令:showmount [-ae] [hostname | IP]\n-a:显示当前主机与客户端的NFS连接共享的状态\n-e:显示某台主机的/etc/exports所共享的目录数据\n---------------------------------------------------------------\n4、在另一台机器上测试\n出现返回 表示ok\n[root@cPen_C ~]# showmount -e 192.168.255.28\t#注:后面指定分析的机器的ip地址\nExport list for 192.168.255.28:\t\t\t\t\t#注:出现这种情况,表示可以连接 连通性没有问题\n/opt/www 192.168.255.0/24\n\n5、挂载网络文件\n在另外一台机器\n[root@cPen_C ~]# mkdir /mnt2\n[root@cPen_C ~]# mount -t nfs 192.168.255.28:/opt/www /mnt2\t\t#注:挂载网络文件\n[root@cPen_C ~]# df\t\t\t#注:使用df命令看磁盘挂载情况(这是网络磁盘挂载)\n192.168.255.28:/opt/www 17811456 2165760 15645696 13% /mnt2\n\n[root@cPen_C ~]# cd /mnt2\n[root@cPen_C mnt2]# ls\nindex.html\n[root@cPen_C mnt2]# cat index.html \nthis is test nfs\n[root@cPen_C mnt2]# ls\nindex.html\n[root@cPen_A ~]# cd /opt/www/\t\t\t\t\t#注:服务端A主机 操作\n[root@cPen_A www]# touch index2.html\t\t\t#注:服务端操作\n[root@cPen_C mnt2]# ls\nindex2.html index.html\n[root@cPen_C mnt2]# mkdir index2.html\nmkdir: 无法创建目录\"index2.html\": 权限不够\n#注:客户机C没有权限去操作服务器A文件\n#没有权限的话 /etc/exports 设置 no_root_squash ,就可以操作了\nno_root_squash 将远程根用户当成本地根用户,即不压制root\n#注:让服务器将 远端的root用户 识别成 本地根用户\n#注:修改配置文件后,需要使用exportfs -a 生效配置;再重新挂载(先取消挂载,再重新挂载)\n\n#示例:取消挂载\n[root@cPen_C mnt2]# cd ..\t\t\t#注:先退出mnt2目录,否则报繁忙\n[root@cPen_C /]# umount /mnt2\t\t#注:然后取消挂载\n\n#修改配置文件后,需要使用exportfs -a 生效\n#重新挂载:\n 先退出/mnt2目录,然后执行:\n umount /mnt2\n 再执行挂载\n```\n\n\n\n---\n\n# 二. npcbind和nfs\n\n启动nfs之前,确保rpcbind服务已经启动\nnfs启动的时候,会向rpcbind服务注册端口,会返回一个端口给nfs使用\n可以使用\n\t\t`rpcinfo -p`\t命令 **查看nfs端口是否已经注册成功**\nrpcbind就像房东,nfs是租客\n#注:nfs自己不能起端口,rpcbind为nfs注册端口\n#注:nfs起来之前 要确保rpcbind起来\n[root@cPen_A www]# `rpcinfo -p`\t\t\t#注:**rpcbind为nfs起2049端口**\n\t100003 3 tcp 2049 nfs\n\n\n\n---\n\n# 三. 实验:nfs和nginx 搭配使用 负载均衡和文件共享\n\nA:\t192.168.0.73\tnfs\t真实机\nB:\t192.168.0.79\t代理机+真实机\nC:\t192.168.0.53\t真实机\n\n前提:\n三台主机都安装好nginx,其中一台开启nfs服务\n在A机器上开启了nfs服务,网站目录存放在/opt/www下,B、C可以挂载A的/opt/www目录到本地\nA机器配置好nfs服务,开启nfs服务,然后在A、C两台上 执行:\n[root@cPen_B ~]# mount -t nfs 192.168.0.73:/opt/www /opt/www\n[root@cPen_C ~]# mount -t nfs 192.168.0.73:/opt/www /opt/www\n\n\n\n```bash\nB机器变成代理机\n第1步:把8080端口起来\n修改A、B、C三台主机nginx的配置,启动8080端口,绑定域名www.sc.com\n#注:配置文件目录:/etc/nginx\n#注:进入 /etc/nginx/conf.d目录下 创建 sc.conf\n输入以下内容\n[root@cPen_A ~]# cd /etc/nginx/\n[root@cPen_A nginx]# cd conf.d/\n[root@cPen_A conf.d]# vim sc.conf\t\t#注:后缀必须是 .conf,自动加载读取 该配置文件\nserver {\n listen 8080;\t\t\t\t\t\t#注:监听8080端口\n server_name www.sc.com;\t\t\t#注:指定域名\n\n root /opt/www;\t\t\t\t\t\t#注:指定网站家目录,默认去家目录下找index.html\n\n}\n[root@cPen_A conf.d]# nginx -t\t\t\t#注:进行语法检测\n[root@cPen_A conf.d]# nginx -s reload\t\t#注:生效配置\n[root@cPen_A conf.d]# lsof -i:8080\t\t#注:8080端口起来了\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nnginx 3193 root 6u IPv4 50354 0t0 TCP *:webcache (LISTEN)\nnginx 3194 nginx 6u IPv4 50354 0t0 TCP *:webcache (LISTEN)\nnginx 3195 nginx 6u IPv4 50354 0t0 TCP *:webcache (LISTEN)\n\n使用lsof -i:8080\t端口是否启动\n使用curl -H \"Host: www.sc.com\" http://192.168.0.73:8080\t 查看返回的内容是否一致\n访问192.168.0.68的8080端口,以www.sc.com域名去访问\n[root@cPen_A ~]# curl -H \"Host: www.sc.com\" http://192.168.0.73:8080\nthis is test nfs\n#注:三台机器访问返回的内容相同 都是 this is test nfs\n\n--------------------------------------------------------------------------------------------\n#注:在B机器上添加反向代理\n对B机器进行负载均衡:把请求转发到其他机器(代理转发)(高可用)\n[root@cPen_B conf.d]# vim sc.conf \nserver {\n listen 8080;\n server_name www.sc.com;\t\n\n root /opt/www;\n\n}\n\nupstream sc {\t\t\t\t\t\t#注:代理转发,为upstream取名为sc\n server 192.168.0.73:8080;\n server 192.168.0.53:8080;\n server 192.168.0.79:8080;\n}\n#注:虚拟主机,让不同的域名做不同的事情\nserver {\t\t\t\t\t\t\t\n listen 80;\n server_name www.sc.com;\t\t\n\n root /opt/www;\n\n location / {\t\t\t\t\t\t#注:访问网站的/目录,都会转发到sc\n proxy_set_header Host $host;\t#注:头部信息,不加的话 可能变成B的主机地址\n\t\t#注:让客户端发过来的头部host字段信息 和转发包的头部host字段保持一致\n proxy_pass http://sc;\t\t\t#注:设置后端代理服务器\n }\n}\n\nserver {\n listen 80;\n server_name www.sc1.com;\n\n root /usr/share/www;\n\n location / {\n proxy_set_header Host $host;\n proxy_pass http://sc;\n }\n}\n\n#注:输出www.sc.com时,请求时,会有数据包存放host头部信息:www.sc.com ,80端口收到这个包之后,知道是要转发到8080端口。B机器帮你请求A、B、C的8080端口发起请求\n#注:客户机发起请求 www.sc.com,host头部信息www.sc.com(请求包里的,客户机携带的头部信息),B主机交给相应的server去处理,请求B主机的80端口去处理,转发到8080端口,B主机帮你去请求,B收到包的时候,交给server去处理。这时候A发起的这个包的头部信息 可能就是B的ip地址了(不是www.sc.com了),8080端口收到请求后,没有B的ip地址的server_name,会转发失败。所以 proxy_set_header Host $host 让它们的头部信息保持一致\n\n--------------------------------------------------------------------------------------------\n#生效配置\n[root@cPen_B conf.d]# nginx -t\n[root@cPen_B conf.d]# nginx -s reload\n\n--------------------------------------------------------------------------------------------\n#然后多次访问80端口,查看返回内容是否一致,以及查看每台机器的/var/log/nginx/access.log日志是否有新的请求过来 tail -f /var/log/nginx/access.log\n\n[root@cPen_B conf.d]# curl -H \"Host: www.sc.com\" http://192.168.0.79\nthis is test nfs\n#注:代理转发,访问80端口,转发到8080端口,分发到3台机器去执行了(负载均衡)\n\n[root@cPen_C conf.d]# tail -f /var/log/nginx/access.log \t#注:C主机下 ,B主机帮请求\n192.168.0.79 - - [01/Dec/2020:17:21:54 +0800] \"GET / HTTP/1.0\" 200 17 \"-\" \"curl/7.61.1\" \"-\"\n#注:平均打到3台,默认做轮转\n```\n\n> ![image-20221011191610524](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011191610524.png)\n\n\n\n\\#注:可以使用 killall nginx 全部杀死\n\n\\#注:404 没找到,403 forbid 禁止\n\n\n\n>#注:A、B换成B、A\n>nginx代理机+真实机\n>\n>A\n>\n>nginx真实机\n>\n>B **nfs**\n>\n>nginx真实机\n>\n>C\n>\n>客户端访问www.sc.com\t访问A nginx代理机的80端口(代理的意思是转发)\n>A机器 返回本机的8080去处理,或者B机器的8080去处理,或者C机器的8080去处理\n>负载均衡:2万人访问A机器80端口,80端口不会去处理请求,只是做代理转发,交给本机8080处理,或者B机器的8080处理,C机器的8080处理。A、B、C三台返回的页面网站 都要保持一致\n>把B机器/opt/www目录 挂载到A上和C上 (保存文件的一致性,改的都是B机器的nfs)\n\n\n\n> ![image-20221011191803355](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20221011191803355.png)\n\n\n\n>\\#注:网络问题\n>\n>桥接模式\tVMnet0\t同网段\n>\n>NAT模式\tVMnet8\t同网段\n\n\n\n","tags":["Linux","NFS"],"categories":["Linux"]},{"title":"24_Linux基础-DNS服务","url":"/posts/ecc378ee.html","content":"参考文章:https://blog.csdn.net/loukundeboke/article/details/80012231\n\n**DNS服务**\n**DNS( Domain Name System) 域名系统**\n\n> 前提:\n>\n> 我们网络中都是使用ip地址通信,无论是访问服务,还是不同主机间进行数据交换\n>\n> ip地址非常多,如果每个服务都通过ip地址来登录的话,用户就需要记住这些很复杂的ip地址,不方便用户使用\n>\n> \n>\n> 就像保存在手机里的电话号码一样,会有一个备注,通过这个备注 就可以找到正确的相应联系人的电话\n>\n> 那域名解析跟这个实现差不多,在普通用户中,我们用域名来访问服务,域名就通过域名解析来获取到ip地址\n>\n> dns服务就像电话簿,提供了可以查询的域名到ip地址的映射关系\n>\n> \n>\n> \\#注:在浏览器中输入www.taobao.com,敲回车的一瞬间,先去解析域名\n>\n> \\#注:域名系统;提供域名解析;ip对于用户来说,使用没有域名方便\n\n\n\n---\n\n# 1. 完全限定域名 FQDN\n\n**FQDN**:Full Qualified Domain Name,**完全限定域名**,即每个域在全球网络都是唯一的;另外值得提到的一点是域并不是指诸如www.google.com这样的域名,而google.com才是域\n\n#注:www.music.163.com/\t\t163.com是域,前面是主机名\n\n```bash\n安装dns服务软件包bind\n[root@cPen_B ~]# yum install bind\n#注:安装后,数据存放在/var/named/下\n[root@cPen_B ~]# cd /var/named/\n[root@cPen_B named]# ls\ndata dynamic named.ca named.empty named.localhost named.loopback slaves\n```\n\n\n\n---\n\n# 2. 域的分类\n\n> 一、根域(.) 全球13组根域名服务器以英文字母A到M依序命名,域名格式为“字母.root-servers.net”\n>\n> ​\t\t在/var/named/name.ca文件中可以查看\t\t# 注:标识为.\n>\n> 二、顶级域\n>\n> ​\t\t顶级域:顶级域(Top Level Domain,简称TLD)分为三类\n>\n> ​\t\t 1> 通用顶级域:诸如 .com(商业机构) .org(非营利性组织) .net(网络服务机构)等\n>\n> \t\t 2> 国家顶级域:诸如 .cn(中国) .uk(英国) .us(美国) .jp(日本) .hk\n>\t\n> \t\t 3> 反向域(基础建设顶级域):.arpa,即从IP到FQDN的反向解析\t# 注:反向查找\n>\n> \\#注:正向域:从域名到ip; 反向域:从ip到域名\n>\n> 三、\n>\n> ​\t\t二级域\n>\n> ​\t\t三级域\n>\n> [\t\twww.sc.163.com](http://www.sc.163.com)\t--> 顶级域.com -->二级域163.com -->三级域sc.163.com\n>\n> ​\t\t\\#注:前面的www是它的主机名\n\n\n\n---\n\n# 3. DNS解析\n\n正向解析\t域名 --> ip\n\n反向解析\tip --> 域名\n\n\n\n## 常用命令域名解析命令\n\n```bash\n常用命令域名解析命令\n1、Ping\n[root@cPen_A ~]# ping www.baidu.com\nPING www.a.shifen.com (14.215.177.38) 56(84) bytes of data.\n64 bytes from 14.215.177.38 (14.215.177.38): icmp_seq=1 ttl=55 time=16.3 ms\n#注:ping命令只能返回1个ip\n\n2、host\n安装bind-utils软件包\nyum install bind-utils\n[root@cPen_A ~]# host www.baidu.com\nwww.baidu.com is an alias for www.a.shifen.com.#注:为www.a.shifen.com取别名www.baidu.com\nwww.a.shifen.com has address 14.215.177.38\t#注:ip地址\nwww.a.shifen.com has address 14.215.177.39\n\n3、dig\t\t\t\t\t#注:看的比较详细,推荐\n[root@cPen_A ~]# dig www.baidu.com\n;; ANSWER SECTION:\nwww.baidu.com.\t\t34\tIN\tCNAME\twww.a.shifen.com.\nwww.a.shifen.com.\t216\tIN\tA\t14.215.177.38\nwww.a.shifen.com.\t216\tIN\tA\t14.215.177.39\n\n4、nslookup\n[root@cPen_A ~]# nslookup www.baidu.com\nwww.baidu.com\tcanonical name = www.a.shifen.com.\t#注:查询的时候会加上根域,平时感觉不到\nAddress: 14.215.177.38\nAddress: 14.215.177.39\n\n#注:可以拿DNS实现分流的作用。将新机器的域名地址解析成2个ip\n#注:负载均衡:把很多机器当做1台机器使用。DNS可以做到负载均衡,把流量分发到很多机器\n#注:高可用:1台机器去服务 它跪掉了,高可用就是这台机器跪掉了,把流量引导其他机器\n#注:高可用\t避免单点故障\n#注:运维思想:备份、高可用。比如系统盘2块,其中1块跪掉了,另外一块还能继续服务\n#注:负载均衡和高可用 一般一起存在\n```\n\n\n\n## DNS服务软件:bind\n\n```bash\nDNS服务软件:bind\n默认端口 udp协议 53号端口\n[root@cPen_A ~]# less /etc/services \ndomain 53/udp\n\n\n示例:修改/etc/hosts文件\n--------------------------------------------------------------------------------------------\n[root@cPen_A ~]# cat /etc/hosts\n127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n::1 localhost localhost.localdomain localhost6 localhost6.localdomain6\n[root@cPen_A ~]# ping localhost\t\t\t#注:解析成127.0.0.1\nPING localhost (127.0.0.1) 56(84) bytes of data.\n[root@cPen_A ~]# cat /etc/hosts\n127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\n::1 localhost localhost.localdomain localhost6 localhost6.localdomain6\n127.0.0.1 www.baidu.com baid.com\t\t#注:添加这一行\n[root@cPen_A ~]# ping www.baidu.com\nPING www.baidu.com (127.0.0.1) 56(84) bytes of data.\t#注:解析成127.0.0.1\n[root@cPen_A ~]# ping baid.com\nPING www.baidu.com (127.0.0.1) 56(84) bytes of data.\t#注:解析成127.0.0.1\n#注:/etc/hosts文件 解析时 优先级最高\n\n示例\n--------------------------------------------------------------------------------------------\n[root@cPen_A html]# pwd\n/usr/share/nginx/html\n[root@cPen_A html]# vim index.html\nhello world\ncPen\n[root@cPen_A html]# ip a\n\tinet 192.168.0.19/24 brd 192.168.0.255 scope global noprefixroute dynamic ens33\n#Windows机器上\nWindows:C:\\Windows\\System32\\drivers\\etc\\hosts\n#注:hosts文件里\n# localhost name resolution is handled within DNS itself.\n#\t127.0.0.1 localhost\n#\t::1 localhost\n192.168.0.39 www.ldj.com\t\t\t\t#注:添加这一条\n这样在浏览器查找 www.ldj.com 就会访问到linux机器上的网址。www.ldj.com被解析成192.168.0.39\n```\n\n\n\n---\n\n# 4. DNS解析过程\n\n> DNS解析过程:\n> #注:面试题:**当敲入www.baidu.com 发生什么事情**\n> 1、先查找**本地hosts文件**,linux:/etc/hosts; Windows:C:\\Windows\\System32\\drivers\\etc\\hosts\n> 可以解析就直接返回地址\n> 2、hosts文件不能解析,去看**本地缓存**。如果有,则返回结果,没有就进行下一步查找\n> \t\tlinux下域名缓存:nscd服务\n> \t\t[root@cPen_A html]# yum install nscd\n> \t\t[root@cPen_A html]# service nscd restart\t\t#注:清除缓存 (重启服务就是清除缓存)\n> \t\t缓存会有缓存时间,缓存多久可以指定的\n> \t\t#注:设置了DNS服务,但是设置了没有生效,考虑1、缓存 清除缓存和2、/etc/hosts是否写死\n> 3、本地缓存没有找到,就会去请求**本地的域名服务器**,本地域名服务器有 就返回查询结果\n> **Linux下指定域名解析服务器文件 /etc/resolv.conf (配置本地域名服务器ip地址的文件)**\n> 第1个指定的nameserver就是首选dns服务器,剩下的都是备选dns服务器\n>\n> ```bash\n> [root@cPen_A html]# vim /etc/resolv.conf \n> # Generated by NetworkManager\n> nameserver 114.114.114.114\t\t\t\t\t\t#注:可以指定多个ip 去解析ip\n> nameserver 192.168.0.1\t\t\t\t\t\t\t#注:用nameserver指定\n> [root@cPen_A html]# dig www.baidu.com\n> ;; SERVER: 114.114.114.114#53(114.114.114.114)\t\t#注:访问114.114.114.114 53号端口去解析ip\n> ```\n>\n> 4、本地域名服务器没有找到相应记录,如果**设置转发**查找,就会去**转发的服务器**上去查询。如果**没有设置转发,或者都没有找到**,就会去**根域查找** (迭代查找)\n> 本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该**顶级域名服务器的一个IP**。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机\n>\n> \n\n> #注:**面试题:当敲入www.baidu.com 发生什么事情 (DNS解析流程)**\n> 答:DNS解析流程\n> 第1步 先去 `本地hosts文件`(/etc/hosts)去找 `ip和域名的映射关系`。有就返回。没有就去\n> 第2步 `本地DNS缓存` 找…。有就返回。没有就去\n> 第3步 `本地的域名服务器` (/etc/resolv.conf)找…。有就返回。没有就\n> 第4步 如果本地域名服务器 `设置转发`查找,就会去转发的服务器 上找…, 有就返回。\n> 没有找到 或 没有设置 就去 `根域查找`,先在`根域`里找到`顶级域的服务器ip地址 返回顶级域`的ip地址给`本地域名服务器`\n> `本地域名服务器`再去`顶级域名服务器` 找,没有找到就返回`二级域服务器`的ip地址,本地域名服务器去`二级域里找`,没有找到 `返回三级域`的ip地址`给本地域名服务器`……迭代查找,直到找到整个域名才返回\n> 或者说 去根域查找,迭代查找, 直到找到为止\n\n\n\n---\n\n# 5. dns服务的类型\n\n**dns服务的类型**\n\n1. **缓存域名服务器**\n2. **主域名服务器**\n 这上面定义了真正的ip到域名的映射关系\n3. **从域名服务器**\n 上面的数据域名映射 从主域名服务器获取\n\n\n\n**1、缓存域名服务器**\n\t\t也称为 唯高速缓存服务器\n\t\t通过向其他域名服务器查询获得域名->IP地址记录 \n\t\t将域名查询结果缓存到本地,提高重复查询时的速度\n**2、主域名服务器**\n\t\t特定DNS区域的官方服务器,具有唯一性,权威性 \n\t\t负责维护该区域内所有域名->IP地址的映射记录\n**3、从域名服务器**\n\t\t也称为 辅助域名服务器\n\t\t其维护的 域名->IP地址记录 来源于主域名服务器\n\n\n\n---\n\n# 6. 域名服务器配置\n\n```bash\n1、安装bind、bind-utils\n域名解析主程序\n[root@cPen_B etc]# which named\n/usr/sbin/named\n\n2、配置文件\n如果没有安装bind-chroot软件包\n主配置文件: /etc/named.conf 数据文件位于:/var/named/目录\n[root@cPen_B etc]# less /etc/named.conf \n\n3、修改配置\n\t1、 vim /etc/named.conf\t\t\t\t\t# 注:全局配置文件\noptions {\n listen-on port 53 { 127.0.0.1; };\t\n listen-on port 53 { any; };\t\t\t# 注:将监听地址改成any,设置监听在本机的任意ip上\n allow-query { localhost; };\t\t# 注:允许访问服务的主机 \n allow-query { any; };\t\t\t# 注:将权限设置为any,允许任何人来查询\nzone \".\" IN {\t\t\t\t# 注:定义根域\n type hint;\t\t\t# 注:指定根域\n file \"named.ca\";\t# 注:在named.ca里去找 /var/named/named.ca\n};\ninclude \"/etc/named.rfc1912.zones\";\t\t\t# 注:定义其他域\ninclude \"/etc/named.root.key\";\n\t2、域配置文件 /etc/named.rfc1912.zones\n添加域配置:\n[root@cPen_B ~]# vim /etc/named.rfc1912.zones\nzone \"sc.com\" IN {\t\t\t\t\t\t# 注:添加sc.com域的解析\n type master;\t\t\t\t\t# 注:主域名服务器\n file \"\"sc.com\"\";\t\t\t\t# 注:域名配置存放文件 (域的解析从哪里文件里去找)\n allow-update { none; };\n};\n\n4、配置指定域的解析文件\n目录:/var/named\n#注:注意权限, named用户要可读\n#注:注意属组\n[root@cPen_B named]# cp named.empty sc.com\n[root@cPen_B named]# pwd\n/var/named\n[root@cPen_B named]# vim sc.com \n$TTL 3H\t\t\t\t\t\t\t; 注:缓存时间\n@ IN SOA sc.com. (\t\t\t; 注:修改的地方\n 0 ; serial\n 1D ; refresh\n 1H ; retry\n 1W ; expire\n 3H ) ; minimum\n NS @\n A 127.0.0.1\n AAAA ::1\n;注:A记录\t正向解析记录\t\ndns A 192.168.136.129\t\t\t;注:dns服务器的IP地址\nwww A 192.168.136.129\t\t\t;注:www服务器的IP地址\n* A 192.168.136.123\t\t\t;注:配置泛域名解析\n;mail MX 192.168.136.129\t\t;注:分号注释\n;dns IN 600 A 192.168.136.129\t;注:配置A记录解析 缓存时间为600s\n[root@cPen_B named]# service named restart\t# 注:重启服务\n[root@cPen_B named]# lsof -i:53\t\t\t\t# 注:端口起来了\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nnamed 1839 named 21u IPv4 42519 0t0 TCP localhost:domain (LISTEN)\nnamed 1839 named 22u IPv4 42521 0t0 TCP cPen_B:domain (LISTEN)\nnamed 1839 named 23u IPv6 42523 0t0 TCP localhost:domain (LISTEN)\n[root@cPen_B named]# dig www.sanchuang.com\n;; SERVER: 192.168.136.2#53(192.168.136.2)\n[root@cPen_B named]# cat /etc/resolv.conf \t# 注:指定本机的DNS服务器\n# Generated by NetworkManager\nsearch localdomain\nnameserver 192.168.136.2\n[root@cPen_B named]# dig www.sc.com @192.168.136.129\t\t# 注:用192.168.136.129去解析\n;; QUESTION SECTION:\n;www.sc.com.\t\t\tIN\tA\n\n;; ANSWER SECTION:\nwww.sc.com.\t\t10800\tIN\tA\t192.168.136.129\t\t# 注:解析成功\n\n;; AUTHORITY SECTION:\nsc.com.\t\t\t10800\tIN\tNS\tsc.com.\n\n```\n\n```bash\n#设置反向域\n[root@cPen_B named]# vim /etc/named.rfc1912.zones\nzone \"1.0.0.127.in-addr.arpa\" IN {\n type master;\n file \"named.loopback\";\n allow-update { none; };\n};\n\n[root@cPen_B named]# pwd\n/var/named\n[root@cPen_B named]# less named.loopback \n\n```\n\n\n\n---\n\n# 7. 资源记录类型\n\n> **资源记录类型**\n> (1)A记录(Address)正向解析\n> A记录是将一个主机名(全称域名FQDN)和一个IP地址关联起来。这也是大多数客户端程序默认的查询类型。\n>\n> (2)PTR记录(Pointer)反向解析\n> PTR记录将一个IP地址对应到主机名(全称域名FQDN)。这些记录保存在in-addr.arpa域中。\n>\n> (3)CNAME记录(Canonical Name)别名\n> 别名记录,也称为规范名字(Canonical Name)。这种记录允许您将多个名字映射到同一台计算机。\n>\n> (4)MX记录(Mail eXchange)\n> MX记录是邮件交换记录,它指向一个邮件服务器,用于电子邮件系统发邮件时根据 收信人的地址后缀来定位邮件服务器。MX记录也叫做邮件路由记录,用户可以将该域名下的邮件服务器指向到自己的mail server上,然后即可自行操控所有的邮箱设置。\n> \t当有多个MX记录(即有多个邮件服务器)时,则需要设置数值来确定其优先级。通过设置优先级数字来指明首选服务器,数字越小表示优先级越高。\n>\n> (5)NS记录(Name Server)\n> NS(Name Server)记录是域名服务器记录,也称为授权服务器,用来指定该域名由哪个DNS服务器来进行解析。\n> 将网站的NS记录指向到目标地址,在设置NS记录的同时还需要设置目标网站的指向,否则NS记录将无法正常解析\n> NS记录优先于A记录。即,如果一个主机地址同时存在NS记录和A记录,则A记录不生效。\n\n\n\n---\n\n# 8. 小节\n\n**DNS服务**\n**DNS( Domain Name System) 域名系统**\n#注:域名系统;提供域名解析;ip对于用户来说,使用没有域名方便\n\n\n\n> FQDN\t完全限定域名\n> \t\twww.baidu.com\n> \t\t\t\t域:baidu.com\n> \t\t\t\t主机名:www\n\n> **域名分类**\n> \t\t根类(.)\t全国只有13组\n> \t\t顶级域\t通用域名\n> \t\t\t\t\t\t\t\t.com\t用于商业\n> \t\t\t\t\t\t\t\t.org\t非盈利性组织\n> \t\t\t\t\t\t\t\t.net\t网络服务\n> \t\t\t\t\t\t国家\n> \t\t\t\t\t\t\t\t.cn\n> \t\t\t\t\t\t\t\t.jp\n> \t\t\t\t\t\t\t\t.hk\n> \t\t\t\t\t\t\t\t.us\n> \t\t\t\t\t\t反向解析域\t.arpa\n> \t\t\t\t\t\t二级域,三级域……\n\n> **DNS解析**\n> \t\t正向解析\t把域名解析成ip\n> \t\t反向解析\t把ip解析成域名\n\n> **DNS解析流程(面试)**\n>\n> 1、先查找本地hosts文件 有没有对应ip和域名的映射关系,存在就返回\n>\n> 2、hosts文件里没有找到,就会在本地缓存中查找,如果找到就返回结果 完成解析\n>\n> 3、本地缓存中没有找到,就会去本地域名服务器查找,找到返回结果 完成解析\n>\n> 4、本地域名服务器中没有,如果设置了转发查找 就会去转发服务器查找。如果没有找到 就会去根域去找顶级域的服务器ip地址,返回给本地域名服务器,本地域名服务器再去顶级域服务器上 找二级域服务器ip地址,依次类推 直到找到整个域名结果为止\n>\n> 5、DNS迭代查询之后,如果拿到结果 就返回给本地域名服务器,本地域名服务器再返回给客户端\n>\n> \\#注:DNS客户机迭代查找\n\n\n\n**DNS服务简单搭建**\n\n> **软件包安装**\n> \t\tbind\n> \t\tbind-utils\n>\n> **配置文件**\n> \t\t主配置文件\t/etc/named.conf\n> \t\t域配置文件\t/etc/named.rfc1912.zones\n> \t\t数据目录\t\t/var/named\t下面文件 需要给named用户可读权限\n>\n> **DNS端口**\t53\tUDP\n>\n> **记录类型**\n> \t\tA记录\t正向解析记录\n> \t\tPTR记录\t反向解析记录\n> \t\tCNAME\t别名\n> \t\tMX\t\t邮件记录\n> \t\tNS\t\t授权dns服务器\n>\n> **泛域名解析**\n> \t对于域sc.com添加:* A 192.168.0.39\t\t#注:只是对主机名的泛域名解析\n> \t\t\t表示主机名任意\t123.sc.com\t\t\t\t#注:abc.123.sc.com不可以\n> \t\t\t\t\t\t\t\t\t\t\tabc.sc.com\n\n\n\n**常见的域名解析命令**\n\n> ping\n> host\n> dig\n> nslookup\n\n\n\n**相关配置文件**\n\n> /etc/hosts\t\t\t 指定域名和ip的对应关系,优先级最高\n> /etc/resolv.conf\t指定dns服务器地址\n> \t\t\t\t\t\t\t\t网络连通性都是访问服务的前提条件\n\n\n\n","tags":["Linux","DNS"],"categories":["Linux"]},{"title":"23_Linux基础-ansible2","url":"/posts/b0a8892b.html","content":"# 一. 云计算\n\n> **云计算**\n> openstack\n> docker\n> kvm\n> 虚拟化技术:在本身物理机的基础上虚拟出云主机\n> #唯一的不好是 安全性不高 数据保存在别人那里的 (影响不大)\n\n> #trouble shooting的能力 问题解答的能力\n>\n> #注:ssh开启2种验证 - 先公钥认证\t再密码认证\t密码认证失败 提示permit deny\n\n\n\n---\n\n# 二. ansible不是守护进程\n\n> #ansible 不是守护进程 执行ansible命令的时候才会执行ansible\n> #守护进程:一直在内存里面,等待别人连接\n> #ssh是守护进程\n> #执行1条命令 命令不是守护进程\n>\n> #ansible不是一个守护进程(守护进程:起来后一直在内存中运行,等待其他人访问)\n> #ansible就是一个命令脚本,使用Python写的\n>\n> #[root@cPen_A ansible]# sudo -i\t\t\t#注:直接回到root用户\n\n\n\n---\n\n# 三. ansible的模块\n\n**ansible的模块**\n\n## 1. copy模块\n\n> 从本地copy文件分发到目录主机路径 \n> \t参数说明:\n> \tsrc= 源文件路径\t\t\t# 注:source 源\n>\n> ​\tdest= 目标路径 \t\t# 注:destination 目的地\n>\n> ​\t注意src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去\n> ​\tcontent= 自行填充的文件内容\n> ​\towner 属主\n> ​\tgroup 属组\n> ​\tmode权限\n\n\n\n```bash\n示例1:shell模块、copy模块\n---------------------------------------------------------------------------------------------------------------------------------\n#示例1:使用ansible 在B、C主机创建/lianxi 目录\n#-m\t指定模块\n#-a\t传的参数\nansible 接 指定主机 -m 指定模块 -a 执行的参数\n[root@cPen_A ansible]# ansible all -m shell -a \"mkdir /lianxi -p\"\n#注:rc ==> reutrn code --> 为0表示执行成功\n#注:rc ==> reutrn code --> 为1表示执行失败\n\n#示例2:将ansible-copy文件 复制到主机B、C/lianxi/ansible目录下,指定权限属主数组\n[root@cPen_A lianxi]# vim ansible-copy\n[root@cPen_A lianxi]# ansible all -m copy -a \"src=/lianxi/ansible-copy dest=/lianxi/ansible mode=777 owner=sanchuang group=sanchuang\"\n#注:确认B、C主机 指定的用户sanchuang和组sanchuang存在\n#md5sum\t一般来说 是 信息的摘要\t\t判定文件是否被修改\n```\n\n\n\n```bash\n示例2:指定webser组,将/etc/passwd 赋值到主机/tmp目录下,指定权限777\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A lianxi]# ansible webser -m copy -a \"src=/etc/passwd dest=/tmp mode=777\"\n\n===========================================================================================\n\n示例3:copy src路径后面带/不带/的区别\n---------------------------------------------------------------------------------------------------------------------------------\n#注:src= 路径后面带/ 表示带里面的所有内容复制到目标目录下,不带/是目录递归复制过去\n#注:不带/\n[root@cPen_A copy_dir]# ansible all -m copy -a \"src=/lianxi/copy_dir dest=/lianxi/ansible\"\n#注:带/\n[root@cPen_A copy_dir]# ansible all -m copy -a \"src=/lianxi/copy_dir/ dest=/lianxi/ansible\"\n\n#带/表示拷贝目录下的子文件或者子文件夹\n#不带/表示拷贝整个目录\n```\n\n\n\n## 2. fetch模块\n\n#注:从远程主机拉取文件到本地\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A lianxi]# ansible webser -m fetch -a \"src=/etc/hostname dest=/lianxi mode=644\"\n192.168.0.22 | CHANGED => {\n \"changed\": true, \n \"checksum\": \"c468f7340237d9f531122f5b03345ce8ac5641b4\", \t\t # 注:拉去下来后会比较\n \"dest\": \"/lianxi/192.168.0.22/etc/hostname\", \n \"md5sum\": \"8d23b0947f191eb9c20728677271eb4d\", \n \"remote_checksum\": \"c468f7340237d9f531122f5b03345ce8ac5641b4\", # 注:和远程比较 内容是否变更\n \"remote_md5sum\": null\n}\n#注:大文件传送中途 突然断掉了 ,文件没有传完 保存的md5sum和它的md5sum不一样\n#注:如果2个值一致\t说明传完了\n[root@cPen_A lianxi]# ls\t\t\t\t# 注:路径自动加了个以ip地址为名的文件夹\n192.168.0.20 192.168.0.22 ansible-copy copy_dir\n[root@cPen_A lianxi]# cd 192.168.0.20\n[root@cPen_A 192.168.0.20]# ls\netc\n```\n\n\n\n```bash\n从远程主机拉取文件到本地\nfetch会自动的在dest指定目录后加上远程主机命名的目录结构后面接src目录结构\nfetch存储到本地的目录结构\tdest + 远程主机名 + src\n\n#注:md5可以判定\t1、文件是否修改;2、文件是否传完\n#注:或者使用任何hash算法中的其中一种,去比较值是否相等\n```\n\n\n\n## 3. command模块\n\n在远程主机上执行命令,属于裸执行,非键值对显示;不进行shell解析\n\n```bash\n示例1:command、shell\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A 192.168.0.20]# ansible all -m command -a \"ifconfig\"\n[root@cPen_A 192.168.0.20]# ansible all -m shell -a \"ifconfig\"\n\n示例2:command裸执行 (后面传的参数不会做解析)\n---------------------------------------------------------------------------------------------------------------------------------\n#注:把ifconfig|grep inet整个当做1个命令去执行\n[root@cPen_A 192.168.0.20]# ansible all -m command -a \"ifconfig|grep inet\"\n192.168.0.22 | FAILED | rc=2 >>\n[Errno 2] 没有那个文件或目录\n#属于裸执行,不会解析它的管道符号 会认为ifconfig|grep inet 是一个命令\n\n#注:shell可以 (后面传的参数会做解析)\n[root@cPen_A 192.168.0.20]# ansible all -m shell -a \"ifconfig|grep inet\"\n\n============================================================================================\n[root@cPen_A ansible]# ifconfig\t\t\t# 注:查看网卡(看的东西多一点)\n#注:可以看接收包、返回包、字节,有多少错误\n[root@cPen_A ansible]# ip a\t\t\t\t# 注:查看网卡\n```\n\n\n\n## 4. shell模块\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A 192.168.0.20]# ansible all -m shell -a \"ifconfig|grep inet\"\n跟command一样,只不过shell模块可以解析管道之类的功能\n```\n\n\n\n## 5. file模块\n\n> 设置文件属性(创建文件)\n> \t常用参数:\n> \tpath目标路径\n> \tstate directory为目录,link为软件链接\n> \tgroup 目录属组\n> \towner 属主\n> \t等,其他参数通过ansible-doc -s file 获取\n>\n> state --\n> \tabsent\t\t删除文件和目录的\n> \tdirectory\t目录\n> \ttouch\t\t 新建空文件\n> \tlink\t\t\t 软链接\n> \thard\t\t\t硬链接\n\n```bash\n示例1:查看file文件帮助信息\n--------------------------------------------------------------------------------------------\n[root@cPen_A lianxi]# ansible-doc -s file\t\t\t# 注:查看file文件帮助信息\n============================================================================================\n\n示例2:在目标主机/tmp目录下创建目录\n#注:创建文件目录\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A lianxi]# ansible all -m file -a \"path=/tmp/sanchuang state=directory\"\n============================================================================================\n\n示例3:设置修改文件属性\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A lianxi]# ansible all -m file -a \"path=/tmp/passwd owner=sanchuang\"\n```\n\n\n\n## 6. cron模块\n\n通过cron模块对目标主机生成计划任务\n常用参数:\n除了分(minute)时(hour)日(day)月(month)周(week)外\nname: 本次计划任务的名称\nstate: present 生成(默认) |absent 删除 (基于name)\n\n```bash\n#注:首先查看程序有没有起来\n[root@cPen_A ~]# ps -ef |grep crond\nroot 702 1 0 10:59 ? 00:00:00 /usr/sbin/crond -n\nroot 3582 3553 0 14:41 pts/3 00:00:00 grep --color=auto crond\n#注:学会看日志\n[root@cPen_A ~]# cd /var/log/\n[root@cPen_A log]# less cron\nNov 25 12:01:01 cPen_A run-parts(/etc/cron.hourly)[3498]: finished 0anacron\n```\n\n\n\n```bash\n示例1:添加计划任务\n---------------------------------------------------------------------------------------------------------------------------------\n#注:每三分钟输出当前时间,到/tmp/time.txt文件中\n[root@cPen_A log]# ansible all -m cron -a \"minute=*/3 job='date >>/tmp/time.txt' name=date_test state=present\"\t\t# 注:minute=*/3\t指定每3分钟 date >>/tmp/time.txt 命令\n[root@cPen_B ~]# crontab -l\n#Ansible: date_test\n*/3 * * * * date >>/tmp/time.txt\n\n[root@cPen_A log]# ansible 192.168.0.20 -m cron -a \"minute=*/3 job='date >>/tmp/time.txt' name=date_test state=present\"\t\t# 注:可以单独为某个主机设置 并非一定批量处理\n\n============================================================================================\n\n示例2:删除计划任务\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A log]# ansible 192.168.0.20 -m cron -a \"name=date_test state=absent\"\n```\n\n\n\n```bash\nntp服务是一个时间管理服务器\n示例:ntp服务 系统时间管理服务\n[root@cPen_A log]# yum install ntp\t\t\t\t# 注:centos7\n[root@cPen_B ~]# yum install chrony\t\t\t\t# 注:centos8里面 ntp已被 chrony取代\n[root@cPen_A log]# ntpdate ntp1.aliyun.com\t\t# 注:同步阿里云的时间\n#注:使用ntp客户端 同步ntp的服务器 把时间同步\n```\n\n\n\n## 7. yum模块\n\n故名思义就是yum安装软件包的模块;\n常用参数说明:\nenablerepo,disablerepo表示启用与禁用某repo库\nname 安装包名\nstate (present' orinstalled', latest')表示安装, (absent' or `removed') 表示删除\n\n#注:name安装的包名\tstate 安装还是卸载\n\n```bash\n示例:安装wget\n[root@cPen_A log]# ansible all -m yum -a \"name=wget state=installed\"\n示例:卸载wget\n[root@cPen_A log]# ansible all -m yum -a \"name=wget state=absent\"\n```\n\n\n\n## 8. service模块\n\n服务管理模块\n常用参数:\nname:服务名\nstate:服务状态 started(启动)\tstopped(关闭)\trestarted(重启)\treloaded(重新加载)\nenabled: 是否开机启动 true|false\nrunlevel: 启动级别 (systemed方式忽略)\n\n```bash\n#安装文件传输服务vsftpd\n[root@cPen_A log]# ansible all -m yum -a \"name=vsftpd state=installed\"\n\n示例:关闭vsftpd服务\n[root@cPen_A log]# ansible all -m service -a \"name=vsftpd state=stopped\"\n示例:开启vsftpd服务\n[root@cPen_A log]# ansible all -m service -a \"name=vsftpd state=started\"\n```\n\n\n\n## 9. script模块\n\n1、把本地的脚本传到远端执行;前提是到远端可以执行,不要把Linux下的脚本同步到windows下执行;\n\n\\#注:只在远程服务器执行脚本,不上传脚本到远程服务器\n\n```bash\n[root@cPen_A ~]# vim test.sh\n#!/bin/bash\necho \"test ansible\" >>/tmp/ansible.txt\n[root@cPen_A ~]# ansible all -m script -a \"/root/test.sh\"\t# 注:/root/test.sh脚本路径\n\n--------------------------------------------------------------------------------------------\n示例:执行慢 机器多 怎么解决\n答:可以使用多进程去执行\n-f 6\t\t指定6个进程去执行\n\ncommand模块不能识别管道符号、shell模块 可以识别\ncopy模块 推送\nscript模块 不需要上传脚本,在远程服务器执行脚本\n```\n\n\n\n---\n\n# 四. 查看系统版本\n\n```bash\n示例:查看系统版本\n[root@cPen_B ~]# uname -r\t\t\t\t\t\t# 注:查看系统内核\n4.18.0-193.el8.x86_64\n[root@cPen_B ~]# cat /etc/redhat-release \t\t# 注:查看/etc/redhat-release 去查看系统版本\nCentOS Linux release 8.2.2004 (Core) \n```\n\n\n\n---\n\n# 五. 链接\n\n```bash\n示例:软链接\n[root@cPen_A lianxi]# ln -s ansible-copy ansible-copy-likcs-s\t#注:前面原文件 后面链接文件\n[root@cPen_A lianxi]# ls -al \t\t# 注:-s soft软\nlrwxrwxrwx 1 root root 12 11月 25 11:30 ansible-copy-likcs-s -> ansible-copy\n#注:软连接\t相当于快捷方式\n#注:软链接删掉不会影响原文件,软链接的原文件删掉了会影响链接文件\n\n示例:硬链接\n[root@cPen_A lianxi]# ln ansible-copy ansible-copy-link\n[root@cPen_A lianxi]# ls -al\n-rw-r--r-- 2 root root 20 11月 25 10:12 ansible-copy-link\nrm -rf 删除源文件 硬链接文件 依旧没事\n#注:硬链接 可以去做备份\n#注:硬链接的原文件删掉了不会影响链接文件\n\n#软链接、硬链接\n#创建一个硬链接 文件的链接数会+1\n#删除硬链接文件或者是源文件 只是把文件的链接数-1 文件不会被真正删除\n#创建一个硬链接\n[root@cPen_A lianxi]# ls -al\n-rw-r--r-- 2 root root 20 11月 25 10:12 ansible-copy\t\t# 注:链接为2\n#注:软链接\nlrwxrwxrwx 1 root root 12 11月 25 11:30 ansible-copy-likcs-s -> ansible-copy # 注:链接为1\n#注:硬链接\n-rw-r--r-- 2 root root 20 11月 25 10:12 ansible-copy-link\t# 注:链接为2\n符号链接数 1 是\nrm -rf 删除的是 文件名 和 磁盘里面data的链接\ndata还存在于磁盘里 ,过一段时间 新的数据会覆盖 data\n#注:为1表示删除了后就没有了,为2表示删除后还有\n```\n\n\n\n---\n\n# 六. playbook\n\n如果ansible的各模块(能实现各种功能)是车间里的各工具;playbook就是指导手册,目标远程主机就是库存和原料对象\n#注:**语法 yaml格式配置**\n\n> **1、playbook的核心元素**\n> hosts : playbook配置文件作用的主机\n> tasks: 任务列表\n> variables: 变量 \n> templates:包含模板语法的文本文件\n> handlers :由特定条件触发的任务\n> roles :用于层次性、结构化地组织playbook。roles 能够根据层次型结构自动装载变量文件、tasks以及handlers等\n> **2、playbook运行方式**\n> ansible-playbook --check 只检测可能会发生的改变,但不真执行操作\n> ansible-playbook --list-hosts 列出运行任务的主机\n> ansible-playbook --syntax-check playbook.yaml 语法检测\n> ansible-playbook -t TAGS_NAME playbook.yaml 只执行TAGS_NAME任务\n> ansible-playbook playbook.yaml 运行\n\n```bash\n示例:编写/执行 playbook\n--------------------------------------------------------------------------------------------\n#注:把A机器的/etc/passwd复制到其他机器的/tmp/passwd_tmp下\n[root@cPen_A ~]# vim ansible_playbook_sc.yaml\t\t#注:编写playbook\n- hosts: all\n remote_user: root\n tasks:\n - name: up file\n copy: src=/etc/passwd dest=/tmp/passwd_tmp\n#执行playbook\n[root@cPen_A ~]# ansible-playbook ansible_playbook_sc.yaml \n============================================================================================\n\n示例:yaml文件怎么去编写\n--------------------------------------------------------------------------------------------\n#第1步 先安装python3:yum install python3\n#第2步 使用pip3安装PyYaml模块\n[root@cPen_A ~]# pip3 install PyYaml\n[root@cPen_A ~]# python3\n>>> import yaml\n>>> fp = open(\"ansible_playbook_sc.yaml\")\n>>> dict = yaml.load(fp)\n>>> dict\n[{'hosts': 'all', 'remote_user': 'root', 'tasks': [{'name': 'up file', 'copy': 'src=/etc/passwd dest=/tmp/passwd_tmp'}]}]\n```\n\n\n\n```bash\n#注:使用\n1、创建yaml文件\n[root@cPen_A ~]# cat ansible_playbook_sc.yaml \t# 注:类似于字典形式 - 相当于list ;里面相当于字典\n- hosts: all\t\t\t\t\t\t\t\t# 注:对所有主机生效(什么组)\n remote_user: root\t\t\t\t\t\t\t# 注:root用户执行\n tasks:\t\t\t\t\t\t\t\t\t# 注:让它做什么事情\n - name: up file\t\t\t\t\t\t\t# 注:事情名字叫up file\n copy: src=/etc/passwd dest=/tmp/passwd_tmp\t# 注:使用copy模块 执行源 目的地址\n2、可以使用Python解析yaml\n>>> import yaml\n>>> fp = open(\"ansible_playbook_sc.yaml\")\n>>> dict = yaml.load(fp)\n>>> dict\n[{'hosts': 'all', 'remote_user': 'root', 'tasks': [{'name': 'up file', 'copy': 'src=/etc/passwd dest=/tmp/passwd_tmp'}]}]\n#注:使用copy模块 来指定src dest\n```\n\n\n\n```bash\n示例:多个操作\n--------------------------------------------------------------------------------------------\n[root@cPen_A ~]# vim ansible_playbook_sc.yaml\t\t\t\t\t# 注:编写\n- hosts: all\n remote_user: root\n tasks:\n - name: up file\n copy: src=/etc/passwd dest=/tmp/passwd_tmp\n - name: download redis\n yum: name=redis state=installed\n- hosts: webser\n tasks:\n - name: remove file\n shell: rm -rf /tmp/passwd_tmp\n[root@cPen_A ~]# ansible-playbook ansible_playbook_sc.yaml \t\t# 注:运行\n```\n\n\n\n# 七. 总结\n\n> ansible通过常用模块在命令行就可以针对主机清单来管理配置远程主机,无需要代理客户端程序,但需要目标主机有ssh和python2.4+;基于ssh协议既可以通过用户名和密码,也可以通过私钥,推荐使用私钥;\n> windows上需要安装powershell及winrm服务也可以做到,关于这方面 可以参考我之前的博客 [ansible自动化管理windows](http://blog.51cto.com/dyc2005/2064746)\n> 通过ansib-doc来获取模块信息及指定模块帮助信息;\n> ansible-playbook 基于YAML语法配置;可以对playbook文件进行测试,解析并执行应用于指定无端主机;非常方便我们统一编排分发管理远程主机;\n\n\n\n# 八. 练习\n\n```bash\n示例:每天凌晨1点 检查/etc/passwd 文件是否被修改,并且生成检查报告\n\n示例:编写脚本 实现ansible node节点(管理的主机)服务器备份 备份/var/log/messages日志 备份到/backup目录下,并且取名2020-11-25-01-log.tar.gz,每一个小时执行一次\n############################################################################################\n示例:每天凌晨1点 检查/etc/passwd 文件是否被修改,并且生成检查报告\n-----------------------------------------------------------------------------------------------------------\n方法1 md5sum 检查文件是否修改 md5sum -c --status\ncheck_file.sh\nmd5sum -c --status d.md5 &&echo \"文件未被修改\" ||echo \"文件已被修改\"\nmd5sum /etc/passwd &> d.md5\t\t\t#注:文件名必须是 d.md5\n-----------------------------------------------------------------------------------------------------------\n方法2\ncheck_ectpasswd.sh\na='md5sum /etc/passwd'\t\t\t\t#注:现在的md5值\nb='tail -n1 /root/b' \t\t\t\t#注:上次的md5值\n[[ $a==$b ]]&&echo \"文件未被修改!\" >> /root/c||echo \"文件已被修改!\" >> /root/c\n$a >> /root/b\n-----------------------------------------------------------------------------------------------------------\n方法3\ntouch /tmp/passwd.log\ntouch /tmp/passwd.txt\na=`md5sum /etc/passwd`\nb=`md5sum /tmp/passwd.txt`\nc=${a:0:32}\t\t\t\t\t\t\t#注:因为md5sum是任意长度的输入 固定长度的输出\nd=${b:0:32}\nif [ $c = $d ] \nthen\n echo \"$(date)文件未被修改\" >>/tmp/passwd.log \n cat /etc/passwd >/tmp/passwd.txt\nelse\n echo \"$(date)文件已被修改\" >>/tmp/passwd.log\n cat /etc/passwd >/tmp/passwd.txt\nfi \n===========================================================================================================\nansible_playbook_zuoye.yaml\n - hosts: all\n remote_user: root\n tasks: \n - name: check file\n cron: hour=1 day=*/1 job='/usr/bin/bash ~/check_file.sh'\n#注:需要把脚本file到各个虚拟机,没有写这一步\n```\n\n\n\n```bash\n示例:编写脚本 实现ansible node节点(管理的主机)服务器备份 备份/var/log/messages日志 备份到/backup目录下,并且取名2020-11-25-01-log.tar.gz,每一个小时执行一次\n - hosts: all\n remote_user: root\n tasks: \n - name: backup messages\n cron: hour=1 job='tar czf /backup/$(date +%Y-%m-%d-%H-log.tar.gz) /var/log/messages'\n```\n\n\n\n```bash\n示例:md5sum 检查文件是否修改 md5sum -c --status\n[root@cPen_A lianxi]# man md5sum\n -c, --check\n read MD5 sums from the FILEs and check them\n --status\n don't output anything, status code shows success\n[root@cPen_A lianxi]# md5sum /etc/passwd > d.md5\t\t#注:写进这个文件 文件名必须是这个 不能变\n[root@cPen_A lianxi]# cat d.md5 \n28b2503e7fb565ddc0b8ec1f9ad6a9c7 /etc/passwd\n[root@cPen_A lianxi]# md5sum -c --status d.md5\t\t\t#注:检查文件是否修改\n[root@cPen_A lianxi]# echo $?\t\t\t\t\t\t\t#注:文件未修改,返回0\n0\n[root@cPen_A lianxi]# useradd chen223344\n[root@cPen_A lianxi]# md5sum -c --status d.md5\n[root@cPen_A lianxi]# echo $?\t\t\t\t\t\t\t#注:文件修改,返回1\n1\n```\n\n\n\n","tags":["Linux","Ansible"],"categories":["Linux"]},{"title":"01_Other-Supervisor管理进程-Twikoo版本升级","url":"/posts/88a726.html","content":"## 1. Supervisor 管理 Twikoo\n\n### 参考文章\n\n> 参考文章:\n>\n> https://blog.csdn.net/cyt0906/article/details/107344361\n>\n> https://www.cnblogs.com/loveCrane/p/15954893.html\n>\n> ```bash\n> yum install epel-release #安装yum源\n> yum install -y supervisor\n> \n> supervisord -c /etc/supervisord.conf\n> \n> ```\n>\n> ```bash\n> cat /etc/supervisord.d/test.conf\n> #项目名\n> [program:blog]\n> #脚本目录\n> directory=/opt/bin\n> #脚本执行命令\n> command=/usr/bin/python /opt/bin/test.py\n> \n> #supervisor启动的时候是否随着同时启动,默认True\n> autostart=true\n> #当程序exit的时候,这个program不会自动重启,默认unexpected,设置子进程挂掉后自动重启的情况,有三个选项,false,unexpected和true。如果为false的时候,无论什么情况下,都不会被重新启动,如果为unexpected,只有当进程的退出码不在下面的exitcodes里面定义的\n> autorestart=false\n> #这个选项是子进程启动多少秒之后,此时状态如果是running,则我们认为启动成功了。默认值为1\n> startsecs=1\n> \n> #脚本运行的用户身份 \n> user = test\n> \n> #日志输出 \n> stderr_logfile=/tmp/blog_stderr.log \n> stdout_logfile=/tmp/blog_stdout.log \n> #把stderr重定向到stdout,默认 false\n> redirect_stderr = true\n> #stdout日志文件大小,默认 50MB\n> stdout_logfile_maxbytes = 20MB\n> #stdout日志文件备份数\n> stdout_logfile_backups = 20\n> \n> ```\n>\n> ```bash\n> supervisorctl status //查看所有进程的状态\n> supervisorctl stop es //停止es\n> supervisorctl start es //启动es\n> supervisorctl restart //重启es\n> supervisorctl update //配置文件修改后使用该命令加载新的配置\n> supervisorctl reload //重新启动配置中的所有程序\n> \n> ```\n>\n> \n\n\n\n### 个人样例\n\n```bash\n# supervisor主配置文件\n$ cat /etc/supervisord.conf\n...\n[include]\nfiles = supervisord.d/*.ini\nfiles = /root/sh_file/supervisord.d/*.ini\n\n\n$ ls /root/sh_file/supervisord.d/\ntkserver.ini\n\n\n# twikoo服务 配置\n$ cat /root/sh_file/supervisord.d/tkserver.ini\n#项目名\n[program:tkserver]\n#脚本目录\ndirectory=/root/sh_file/twikoo\n#脚本执行命令\ncommand=/bin/bash /root/sh_file/twikoo/tkserver.sh\n\n#supervisor启动的时候是否随着同时启动,默认True\nautostart=true\n#当程序exit的时候,这个program不会自动重启,默认unexpected,设置子进程挂掉后自动重启的情况,有三个选项,false,unexpected和true。如果为false的时候,无论什么情况下,都不会被重新启动,如果为unexpected,只有当进程的退出码不在下面的exitcodes里面定 义的\nautorestart=false\n#这个选项是子进程启动多少秒之后,此时状态如果是running,则我们认为启动成功了。默认值为1\nstartsecs=1\n\n#脚本运行的用户身份\nuser = root\n\n#日志输出\nstderr_logfile=/tmp/blog_stderr.log\nstdout_logfile=/tmp/blog_stdout.log\n#把stderr重定向到stdout,默认 false\nredirect_stderr = true\n#stdout日志文件大小,默认 50MB\nstdout_logfile_maxbytes = 20MB\n#stdout日志文件备份数\nstdout_logfile_backups = 20\n\n\n# 运行twikoo的脚本\n$ cat /root/sh_file/twikoo/tkserver.sh\n#!/bin/bash\n\ntkserver\n\n\n# 启动supervisord\n$ supervisord -c /etc/supervisord.conf\n\n\n$ supervisorctl status\n\n```\n\n\n\n```bash\n# 相关命令\n\n# 安装 supervisor\nyum install epel-release #安装yum源\nyum install -y supervisor\n\n# 启动 supervisor\n$ supervisord -c /etc/supervisord.conf\n\n# supervisor 命令\nsupervisorctl status # 查看所有进程的状态\nsupervisorctl stop tkserver # 停止tkserver\nsupervisorctl start tkserver # 启动tkserver\nsupervisorctl restart tkserver # 重启tkserver\nsupervisorctl update # 配置文件修改后使用该命令加载新的配置\nsupervisorctl reload # 重新启动配置中的所有程序\n# 注:把es换成all可以管理配置中的所有进程。直接输入supervisorctl进入supervisorctl的shell交互界面,此时上面的命令不带supervisorctl可直接使用。\n\n\n```\n\n\n\n---\n\n## 2. Twikoo版本升级(私有部署)\n\n\n\n### 更新 1.6.22\n\n时间:2023-10-10,版本 **1.6.22** <= 1.6.7\n\n参考:[twikoo.js.org](https://twikoo.js.org/update.html#%E9%92%88%E5%AF%B9%E7%A7%81%E6%9C%89%E9%83%A8%E7%BD%B2%E7%9A%84%E6%9B%B4%E6%96%B0%E6%96%B9%E5%BC%8F)\n\n1.6.22 支持评论/访问量数据 json 导出了\n\n\n\n官网步骤:\n\n1. 停止旧版本 `kill $(ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}')`\n2. 拉取新版本 `npm i -g tkserver@latest`\n3. 启动新版本 `nohup tkserver >> tkserver.log 2>&1 &`\n\n\n\n我的步骤:\n\n1. 先备份,我的数据路径 **/root/sh_file/twikoo**,`cp -r twikoo twikoo_bak`\n\n2. 更新\n\n ```bash\n supervisorctl status tkserver\n \n supervisorctl stop tkserver\n \n ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}'\n \n # 1. 停止旧版本\n kill $(ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}')\n \n # 2. 拉取新版本\n npm i -g tkserver@latest\n \n # 3. 启动新版本\n supervisorctl start tkserver\n \n rm -rf twikoo_bak\t# 删备份\n \n ```\n \n3. 更新 butterfly 前端资源,CDN.option.twikoo,[www.staticfile.org](https://www.staticfile.org/) 上查找\n\n\n\n### 前言\n\n乌龙事件,原本以为自己的 twikoo 版本过低,打算升级解决。后来发现是 butterfly 内置的 twikoo js 版本低,换个 js 就行。\n\n主题配置文件 _config.butterfly.yml 新增 twikoo cdn\n\n```yaml\nCDN:\n option:\n twikoo: https://npm.elemecdn.com/twikoo@1.6.7/dist/twikoo.all.min.js\n```\n\n\n\n### 参考文章\n\n**参考自**:[twikoo 官网](https://twikoo.js.org/quick-start.html#%E9%92%88%E5%AF%B9%E7%A7%81%E6%9C%89%E9%83%A8%E7%BD%B2%E7%9A%84%E6%9B%B4%E6%96%B0%E6%96%B9%E5%BC%8F)\n\n1. 停止旧版本 `kill $(ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}')`\n2. 拉取新版本 `npm i -g tkserver@latest`\n3. 启动新版本 `nohup tkserver >> tkserver.log 2>&1 &`\n\n\n\n### 个人样例\n\n**个人步骤记录**\n\n1. 检查是否异常\n\n```bash\n# 发现 supervisor 未执行,启动程序\n$ supervisorctl status tkserver\nunix:///run/supervisor/supervisor.sock refused connection\n\n$ supervisord -c /etc/supervisord.conf\nUnlinking stale socket /run/supervisor/supervisor.sock\n\n$ supervisorctl status tkserver\ntkserver RUNNING pid 3268176, uptime 0:00:03\n\n```\n\n\n\n2. 停止旧版本 `supervisorctl stop tkserver` && `kill $(ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}')`\n\n```bash\n# 停止 twikoo 进程\n$ supervisorctl stop tkserver\ntkserver: ERROR (not running)\n\n$ supervisorctl status tkserver\ntkserver EXITED Nov 06 07:00 PM\n\n$ ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}'\n1618196\n1618197\n\n# 停止旧版本\n$ kill $(ps -ef | grep tkserver | grep -v 'grep' | awk '{print $2}')\n\n$ ps aux |grep twikoo\n\n```\n\n\n\n3. 拉取新版本 `npm i -g tkserver@latest`\n4. 启动新版本 `supervisorctl start tkserver`\n\n```bash\n# 拉取新版本\n$ pwd\n/root/sh_file/twikoo\n\n$ npm i -g tkserver@latest\n\n\n# 启动新版本\n$ supervisorctl start tkserver\ntkserver: started\n\n$ ps aux |grep twikoo\nroot 3308516 0.0 0.1 16956 2892 ? S 19:06 0:00 /bin/bash /root/sh_file/twikoo/tkserver.sh\n\n```\n\n\n\n \n\n","tags":["Twikoo","Other","Supervisor"],"categories":["Other"]},{"title":"01_Error-Nginx 反代后端接口报错","url":"/posts/5552.html","content":"## 一. 前言\n\n> NGINX 反向代理 后端接口时报错:`[error] ...: *1918 readv() failed (104: Connection reset by peer) while reading upstream ...`\n>\n> 控制台报错信息\n>\n> ![image-20220917210427284](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220917210427284.png)\n>\n> NGINX错误日志\n>\n> ![image-20220917210540055](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220917210540055.png)\n\n\n\n## 二. 解决办法\n\n> **参考文章** [http://blog.51yip.com/apachenginx/2203.html](http://blog.51yip.com/apachenginx/2203.html)\n>\n> 查看nginx error错误,发现上传接口报以下错:\n>\n> `2019/10/10 19:58:25 [error] 299784#0: \\*5967188 readv() failed (104: Connection reset by peer) while reading upstream, client: 59.34.155.7, server: xxxxxxxx, request: \"POST /stream/tracking/file HTTP/1.1\", upstream: \"http://xxxxxxxx/stream/tracking/file\", host: \"xxxxxxxx\"`\n>\n> 这种错误日志不多,第一感觉就是上传文件过大,传输时间过长,然后连接被中断。\n>\n> `当使用nginx作为反向代理时,为了支持长连接,需要做到两点:`\n>\n> `从client到nginx的连接是长连接,对于客户端来说,nginx长连接是默认开启的。\n> 从nginx到server的连接是长连接,需要自己开启`\n>\n> ```nginx\n> upstream bigdata { \n> server 10.0.20.xx:18018; \n> server 10.0.20.xx:18018; \n> server 10.0.20.xx:18018; \n> server 10.0.20.xx:18018; \n> keepalive 100; //根据qps来调整 \n> } \n> \n> location ~ / { \n> 。。。。。。。。。省略。。。。。。。。。。。。。 \n> proxy_connect_timeout 120; //加大120 \n> proxy_send_timeout 120; //加大120 \n> proxy_read_timeout 120; //加大120 \n> proxy_http_version 1.1; //开启后端,长连接 \n> proxy_set_header Connection \"\"; //开启后端,长连接 \n> } \n> ```\n>\n> 注意:`keepalive指定的数值是Nginx每个worker连接后端的最大长连接数,而不是整个Nginx的.`\n>\n> 作者:海底苍鹰\n>\n> 地址:http://blog.51yip.com/apachenginx/2203.html\n\n\n\n## 三. 个人配置记录\n\n```nginx\n$ cat cpen.top.conf\nserver {\n listen xxx ssl;\n\n server_name xxx.xxx;\n\n location / {\n proxy_pass http://127.0.0.1:xxx;\n proxy_connect_timeout 120; # 加大120\n proxy_send_timeout 120; # 加大120\n proxy_read_timeout 120; # 加大120\n proxy_http_version 1.1; # 开启后端,长连接\n proxy_set_header Connection \"\"; # 开启后端,长连接\n proxy_set_header Host $host;\n proxy_set_header X-Real-IP $remote_addr;\n proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n proxy_set_header Upgrade $http_upgrade;\n }\n\n ssl_certificate /usr/local/nginx/ssl/xxx.pem;\n ssl_certificate_key /usr/local/nginx/ssl/xxx.key;\n\n access_log /data/service_logs/nginx/xxx.log misc;\n error_log /data/service_logs/nginx/xxx.log;\n}\n```\n\n","tags":["Error","Nginx","Troubleshooting"],"categories":["Error"]},{"title":"01_PHP-CentOS8.2 编译安装 PHP8.1.10","url":"/posts/63259.html","content":"## 一. 前言\n\n因 [https://www.jsdelivr.com/](https://www.jsdelivr.com/) 失效,博主打算将 GitHub 托管的图床备份到其他平台。\n\n网上看到 [兰空图床](https://github.com/lsky-org/lsky-pro) 萌生了自建图床的念头,搭建环境要求 PHP >= 8.0.2,于是打算编译安装 PHP。\n\n最终因服务器配置太低(1核2G)编译失败而放弃。转而投身之前已经搭建好环境的又拍云平台。\n\n博文内容:`PHP-CentOS8.2 编译安装 PHP8.1.10` + `编写GitHub图床迁移至又拍云的脚本(ftp)` + `编写批量修改文章内容的脚本`\n\n\n\n## 二. 正文\n\n### 2.1❤ CentOS8.2 编译安装 PHP8.1.10\n\n**2.1.1** PHP8 和 oniguruma 源码下载并上传至服务器 /mnt 目录\n\nhttps://www.php.net/distributions/php-8.1.10.tar.gz\n\nhttps://codeload.github.com/kkos/oniguruma/tar.gz/refs/tags/v6.9.4\n\n```bash\n# 解压\ntar xzf oniguruma-6.9.4.tar.gz\ntar xzf php-8.1.10.tar.gz\n```\n\n\n\n**2.1.2** 安装 PHP8 依赖包\n\n```bash\n# 2 安装 PHP8 依赖包\nyum -y install autoconf freetype gd libpng libpng-devel libjpeg libxml2 libxml2-devel zlib curl curl-devel net-snmp-devel libjpeg-devel php-ldap openldap-devel openldap-clients freetype-devel gmp-devel libzip libzip-devel sqlite-devel automake libtool\n```\n\n\n\n**2.1.3** 编译 PHP8 依赖包 oniguruma\n\n```bash\n# 3.1 生成 configure\ncd /mnt/oniguruma-6.9.4\n./autogen.sh\n\n# 3.2 生成编译配置文件\n./configure --prefix=/usr\n\n# 3.3 编译并安装\nmake && make install\n```\n\n\n\n**2.1.4** 编译 PHP8 主包\n\n```bash\n# 4.1 生成编译配置文件\ncd /mnt/php-8.1.10\n./configure --prefix=/usr/local/php --with-config-file-path=/usr/local/php/etc --enable-fpm --with-fpm-user=nginx --with-fpm-group=nginx --enable-mysqlnd --with-mysqli --with-pdo-mysql --enable-opcache --with-pcre-jit --enable-gd --with-jpeg --with-freetype --with-gettext --with-curl --with-openssl --enable-sockets --enable-mbstring --enable-xml --with-zip --with-zlib --with-snmp --with-mhash --enable-ftp --enable-bcmath --enable-soap --enable-shmop --enable-sysvsem --enable-pcntl --with-gmp\n\n# 4.2 编译并安装\nmake && make install\n```\n\n因为配置过低,编译失败。\n\n\n\n**2.1.5** 编译安装后目录\n\n/usr/local/php\n\n\n\n**参考**\n\n[https://www.bilibili.com/read/cv9248283/](https://www.bilibili.com/read/cv9248283/)\n\n[https://www.bilibili.com/video/BV13U4y1T7VS](https://www.bilibili.com/video/BV13U4y1T7VS)\n\n\n\n### 2.2 基于 FTP 将GitHub图床迁移至又拍云\n\n**参考**\n\n[官方视频教程 - 创建存储服务和使用 FTP 上传](https://techs.upyun.com/videos/cdnpage/creating_storage.html)\t可以得到用户名和密码\n\n默认已经完成了又拍云云存储服务的申请 + 绑定自定义域名 [https://help.upyun.com/knowledge-base/quick_start/](https://help.upyun.com/knowledge-base/quick_start/)\n\n\n\n**2.2.1** 编写 Python 脚本 实现批量\n\n源码来自\t[http://blog.csdn.net/ouyang_peng/article/details/79271113](http://blog.csdn.net/ouyang_peng/article/details/79271113)\n\n```python\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\n\n\nfrom cmath import log\nfrom ftplib import FTP\nimport os\nimport sys\nimport time\nimport socket\nimport subprocess\n\nclass MyFTP:\n \"\"\"\n ftp自动下载、自动上传脚本,可以递归目录操作\n 作者:欧阳鹏\n 博客地址:http://blog.csdn.net/ouyang_peng/article/details/79271113\n \"\"\"\n\n def __init__(self, host, port=21):\n \"\"\" 初始化 FTP 客户端\n 参数:\n host:ip地址\n\n port:端口号\n \"\"\"\n # print(\"__init__()---> host = %s ,port = %s\" % (host, port))\n\n self.host = host\n self.port = port\n self.ftp = FTP()\n # 重新设置下编码方式\n #self.ftp.encoding = 'gbk'\n self.ftp.encoding = 'utf8'\n # 获取脚本路径\n path = os.path.dirname(os.path.realpath(__file__))\n self.log_file = open(path + \"/log.txt\", \"a\", encoding='utf-8')\n self.file_list = []\n\n def login(self, username, password):\n \"\"\" 初始化 FTP 客户端\n 参数:\n username: 用户名\n\n password: 密码\n \"\"\"\n try:\n timeout = 60\n socket.setdefaulttimeout(timeout)\n # 0主动模式 1 #被动模式\n self.ftp.set_pasv(True)\n # 打开调试级别2,显示详细信息\n # self.ftp.set_debuglevel(2)\n\n self.debug_print('开始尝试连接到 %s' % self.host)\n self.ftp.connect(self.host, self.port)\n self.debug_print('成功连接到 %s' % self.host)\n\n self.debug_print('开始尝试登录到 %s' % self.host)\n self.ftp.login(username, password)\n self.debug_print('成功登录到 %s' % self.host)\n\n self.debug_print(self.ftp.welcome)\n except Exception as err:\n self.deal_error(\"FTP 连接或登录失败 ,错误描述为:%s\" % err)\n pass\n\n def is_same_size(self, local_file, remote_file):\n \"\"\"判断远程文件和本地文件大小是否一致\n\n 参数:\n local_file: 本地文件\n\n remote_file: 远程文件\n \"\"\"\n try:\n remote_file_size = self.ftp.size(remote_file)\n except Exception as err:\n # self.debug_print(\"is_same_size() 错误描述为:%s\" % err)\n remote_file_size = -1\n\n try:\n local_file_size = os.path.getsize(local_file)\n except Exception as err:\n # self.debug_print(\"is_same_size() 错误描述为:%s\" % err)\n local_file_size = -1\n\n self.debug_print('local_file_size:%d , remote_file_size:%d' % (local_file_size, remote_file_size))\n if remote_file_size == local_file_size:\n return 1\n else:\n return 0\n\n def download_file(self, local_file, remote_file):\n \"\"\"从ftp下载文件\n 参数:\n local_file: 本地文件\n\n remote_file: 远程文件\n \"\"\"\n self.debug_print(\"download_file()---> local_path = %s ,remote_path = %s\" % (local_file, remote_file))\n\n if self.is_same_size(local_file, remote_file):\n self.debug_print('%s 文件大小相同,无需下载' % local_file)\n return\n else:\n try:\n self.debug_print('>>>>>>>>>>>>下载文件 %s ... ...' % local_file)\n buf_size = 1024\n file_handler = open(local_file, 'wb')\n self.ftp.retrbinary('RETR %s' % remote_file, file_handler.write, buf_size)\n file_handler.close()\n except Exception as err:\n self.debug_print('下载文件出错,出现异常:%s ' % err)\n return\n\n def download_file_tree(self, local_path, remote_path):\n \"\"\"从远程目录下载多个文件到本地目录\n 参数:\n local_path: 本地路径\n\n remote_path: 远程路径\n \"\"\"\n print(\"download_file_tree()---> local_path = %s ,remote_path = %s\" % (local_path, remote_path))\n try:\n self.ftp.cwd(remote_path)\n except Exception as err:\n self.debug_print('远程目录%s不存在,继续...' % remote_path + \" ,具体错误描述为:%s\" % err)\n return\n\n if not os.path.isdir(local_path):\n self.debug_print('本地目录%s不存在,先创建本地目录' % local_path)\n os.makedirs(local_path)\n\n self.debug_print('切换至目录: %s' % self.ftp.pwd())\n\n self.file_list = []\n # 方法回调\n self.ftp.dir(self.get_file_list)\n\n remote_names = self.file_list\n self.debug_print('远程目录 列表: %s' % remote_names)\n for item in remote_names:\n file_type = item[0]\n file_name = item[1]\n local = os.path.join(local_path, file_name)\n if file_type == 'd':\n print(\"download_file_tree()---> 下载目录: %s\" % file_name)\n self.download_file_tree(local, file_name)\n elif file_type == '-':\n print(\"download_file()---> 下载文件: %s\" % file_name)\n self.download_file(local, file_name)\n self.ftp.cwd(\"..\")\n self.debug_print('返回上层目录 %s' % self.ftp.pwd())\n return True\n\n def upload_file(self, local_file, remote_file):\n \"\"\"从本地上传文件到ftp\n\n 参数:\n local_path: 本地文件\n\n remote_path: 远程文件\n \"\"\"\n if not os.path.isfile(local_file):\n self.debug_print('%s 不存在' % local_file)\n return\n\n if self.is_same_size(local_file, remote_file):\n self.debug_print('跳过相等的文件: %s' % local_file)\n return\n\n buf_size = 1024\n file_handler = open(local_file, 'rb')\n self.ftp.storbinary('STOR %s' % remote_file, file_handler, buf_size)\n file_handler.close()\n self.debug_print('上传: %s' % local_file + \"成功!\")\n\n def upload_file_tree(self, local_path, remote_path):\n \"\"\"从本地上传目录下多个文件到ftp\n 参数:\n\n local_path: 本地路径\n\n remote_path: 远程路径\n \"\"\"\n if not os.path.isdir(local_path):\n self.debug_print('本地目录 %s 不存在' % local_path)\n return\n\n self.ftp.cwd(remote_path)\n self.debug_print('切换至远程目录: %s' % self.ftp.pwd())\n\n local_name_list = os.listdir(local_path)\n for local_name in local_name_list:\n src = os.path.join(local_path, local_name)\n if os.path.isdir(src):\n try:\n self.ftp.mkd(local_name)\n except Exception as err:\n self.debug_print(\"目录已存在 %s ,具体错误描述为:%s\" % (local_name, err))\n self.debug_print(\"upload_file_tree()---> 上传目录: %s\" % local_name)\n self.upload_file_tree(src, local_name)\n else:\n self.debug_print(\"upload_file_tree()---> 上传文件: %s\" % local_name)\n self.upload_file(src, local_name)\n self.ftp.cwd(\"..\")\n\n def close(self):\n \"\"\" 退出ftp\n \"\"\"\n self.debug_print(\"close()---> FTP退出\")\n self.ftp.quit()\n self.log_file.close()\n\n def debug_print(self, s):\n \"\"\" 打印日志\n \"\"\"\n self.write_log(s)\n\n def deal_error(self, e):\n \"\"\" 处理错误异常\n 参数:\n e:异常\n \"\"\"\n log_str = '发生错误: %s' % e\n self.write_log(log_str)\n sys.exit()\n\n def write_log(self, log_str):\n \"\"\" 记录日志\n 参数:\n log_str:日志\n \"\"\"\n time_now = time.localtime()\n date_now = time.strftime('%Y-%m-%d', time_now)\n format_log_str = \"%s ---> %s \\n \" % (date_now, log_str)\n print(format_log_str)\n self.log_file.write(format_log_str)\n\n def get_file_list(self, line):\n \"\"\" 获取文件列表\n 参数:\n line:\n \"\"\"\n file_arr = self.get_file_name(line)\n # 去除 . 和 ..\n if file_arr[1] not in ['.', '..']:\n self.file_list.append(file_arr)\n\n def get_file_name(self, line):\n \"\"\" 获取文件名\n 参数:\n line:\n \"\"\"\n pos = line.rfind(':')\n while (line[pos] != ' '):\n pos += 1\n while (line[pos] == ' '):\n pos += 1\n file_arr = [line[0], line[pos:]]\n return file_arr\n\n\nif __name__ == \"__main__\":\n # 清除日志\n path = os.path.dirname(os.path.realpath(__file__)) # 脚本路径\n if os.path.exists(path + '/log.txt'):\n log_file = path + '/log.txt 'if os.sep == \"/\" else path + '\\\\' + 'log.txt'\n subprocess.Popen(f'rm -rf {log_file}', shell=True)\n time.sleep(1)\n\n my_ftp = MyFTP(\"xxx.ftp.upyun.com\")\n my_ftp.login(\"xxx/xxx\", \"xxx\")\n\n\n # 下载单个文件\n # my_ftp.download_file(\"E:/code_zone/image_bed/image/wallpaper/1.jpg\", \"/image/wallpaper/1.jpg\")\n\n # 上传单个文件\n # my_ftp.upload_file(\"G:/ftp_test/Release/XTCLauncher.apk\", \"/App/AutoUpload/ouyangpeng/I12/Release/XTCLauncher.apk\")\n\n # 下载目录\n # image.cpen.top/image/ → 本地 E:/code_zone/image_bed/image/ (本地图床目录, 又拍云路径)\n if os.sep == \"\\\\\":\n my_ftp.download_file_tree(\"E:/code_zone/image_bed/image/\", \"/image/\")\n elif os.sep == \"/\": # aliyun\n my_ftp.download_file_tree(\"/root/code_zone/image_bed/image/\", \"/image/\")\n\n # 上传目录\n # 本地 E:/code_zone/image_bed/image/ → image.cpen.top/image/ (本地图床目录, 又拍云路径)\n if os.sep == \"\\\\\": # Windows\n my_ftp.upload_file_tree(\"E:/code_zone/image_bed/image/\", \"/image/\") \n my_ftp.close()\n elif os.sep == \"/\": # aliyun\n my_ftp.upload_file_tree(\"/root/code_zone/image_bed/image/\", \"/image/\") \n my_ftp.close()\n\n\n# 命令\n# python E:/code_zone/tools/python-ftp/ftp.py\n# python3 /root/code_zone/tools/python-ftp/ftp.py\n\n```\n\n\n\n**2.2.2** 说明\n\n`my_ftp.login(\"用户名xxx/xxx\", \"密码xxx\")` 参考 [https://techs.upyun.com/videos/cdnpage/creating_storage.html](https://techs.upyun.com/videos/cdnpage/creating_storage.html)\n\n后期又将脚本传到云服务器上,通过计划任务,每15分钟同步,保持 GitHub 与又拍云图床一致\n\n```bash\n# root @ CentOS in ~ [18:05:59]\n$ crontab -l\n*/15 * * * * cd /root/code_zone/image_bed/; git pull; python3 /root/code_zone/tools/python-ftp/ftp.py; bash git.sh\n```\n\n\n\n迁移好图床后,博客中调用图片资源时 浏览器自动 http 跳 https,因为没有证书导致图片失效,于是又申请了 ssl 证书,上传至又拍云。\n\n> ![image-20220910180219146](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220910180219146.png)\n\n\n\n### 2.3 编写批量修改文章内容的脚本\n\n源码参考\t[https://blog.csdn.net/qq_38150250/article/details/118026219](https://blog.csdn.net/qq_38150250/article/details/118026219)\n\n```python\n#!/usr/bin/python\n# -*- coding: UTF-8 -*-\n\n# 源码参考 https://blog.csdn.net/qq_38150250/article/details/118026219\n\nimport os\nimport re\n\n# 文件查找 find . -name file_name -type f\n# 查找函数:search_path 查找根路径 \n\n# 获取文章路径\ndef search(search_path, search_result):\n # 获取当前路径下地所有文件\n all_file = os.listdir(search_path)\n # 对于每一个文件\n for each_file in all_file:\n # 若文件为一个文件夹\n if os.path.isdir(search_path + each_file):\n # 递归查找\n search(search_path + each_file + '/', search_result)\n # 如果是需要被查找的文件\n else:\n if re.findall('.*\\.md$', each_file) == [each_file]:\n # 输出路径\n search_result.append(search_path + each_file)\n\n\n# 替换 sed -i 's/old_str/new_str/'\n# 文本替换 replace_file_name 需要替换的文件路径,replace_old_str 要替换的字符,replace_new_str 替换的字符\ndef replace(replace_file_name, replace_old_str, replace_new_str):\n with open(replace_file_name, \"r\", encoding = \"UTF-8\") as f1: \n content = f1.read()\n f1.close()\n t = content.replace(replace_old_str, replace_new_str)\n with open(replace_file_name, \"w\", encoding = \"UTF-8\") as f2:\n f2.write(t)\n f2.close()\n\n\n# 需要改的地方\n#path = 'E:/code_zone/.history/20220831_blog/source/_posts/'\npath_list = [\n 'E:/code_zone/hexo-source/source/_posts/',\n 'E:/code_zone/hexo-source-butterfly/source/_posts/',\n 'E:/code_zone/hexo-source-diary/source/_posts/',\n]\nold_str = 'https://dlvr.cpen.top/gh/mycpen/image_bed/image/'\nnew_str = 'https://dlvr.cpen.top/gh/mycpen/image_bed/image/'\nsearch_result = []\n\nif __name__ == '__main__':\n result = [] # 存放文件路径\n # 默认当前目录\n # path = os.getcwd()\n for path in path_list:\n search(path, result) # 获取文章路径\n count = 0\n for file_name in result:\n replace(file_name, old_str, new_str)\n count += 1\n print(\"{} done {}\".format(file_name, count))\n\n# 命令\n# python E:/code_zone/tools/python-replace/replace.py\n\n```\n\n\n\n**2.3.1** 说明\n\n`search`\t函数指定文件类型为 .md,可获得文章的完整路径;\n\n`path_list`\t列表存放需要修改的文章父目录路径,可以递归查询子目录;\n\n`old_str`\t需要替换的内容\n\n`new_str`\t新内容\n\n","tags":["PHP","脚本"],"categories":["PHP"]},{"title":"10_Python-CSDN_内存管理","url":"/posts/62975.html","content":"\n> ```\n> Python内存管理三大块\n> ○ 引用计数\n> ○ 垃圾回收\n> ○ 内存池\n> Python的内存管理以引用计数为主,垃圾回收为辅,还有个内存池\n> ```\n>\n> \n\n\n\n---\n\n## 一. 引用机制\n\n> ● 引用机制\n>\n> \n>\n> Python动态类型\n>\n> ○ ==对象==是储存在内存中的实体。\n>\n> ○ 我们在程序中写的==对象名==,只是指向这一对象的引用(reference)\n>\n> ○ ==引用和对象分离==,是动态类型的核心\n>\n> ○ 引用可以随时指向一个新的对象(内存地址会不一样)\n\n\n\n---\n\n## 二. 引用计数\n\n> ● 引用计数\n>\n> \n>\n> **在Python中,每个对象都有存有指向该对象的引用总数,即引用计数(reference count)**\n>\n> \n>\n> 引用计数器原理\n>\n> ○ 每个对象维护一个 ob_ref 字段,用来记录该对象当前被引用的次数 每当**新的引用指向该对象**时,它的**引用计数ob_ref加1**\n>\n> ○ 每当该对象的**引用失效时计数ob_ref减1**\n>\n> ○ **一旦对象的引用计数为0**,该**对象可以被回收,对象占用的内存空间将被释放**。 它的缺点是需要额外的空间维护引用计数,这个问题是其次的\n>\n> ○ 最主要的问题是它不能解决对象的“循环引用”\n>\n> \n>\n> ```python\n> # 示例\n> # a = 1 , b = 1 ,1的引用计数为2(保存它被引用的次数)\n> # a = 2 , b = 3 , 1的引用计数为0(内存里面不需要它了,回收销毁,这块对象被回收了,对象占用的内存空间将被释放)\n> ```\n>\n> \n>\n> ```python\n> 获取引用计数: getrefcount()\n> ○ 当使用某个引用作为参数,传递给getrefcount()时,参数实际上创建了一个临时的引用。因此,\n> getrefcount()所得到的结果,会比期望的多1\n> \n> # 示例\n> from sys import getrefcount\t\t# 导入模块\n> a = [1,2,3]\n> print(getrefcount(a)) # 获取对象a的引用计数 , 结果为2\n> ```\n>\n> \n>\n> ```python\n> 增加引用计数\n> ○ 当一个对象A被另一个对象B引用时,A的引用计数将增加1\n> \n> \n> 减少引用计数\n> ○ del删除或重新引用时,引用计数会变化(del只是删除引用)\n> \n> # 示例\n> from sys import getrefcount\n> a = [1,2,3]\t# 真实引用计数:1\n> b = a\t\t# 真实引用计数:2\n> c = [a,a]\t\t# 真实引用计数:4\n> del c[0] # del删除引用\t引用计数 - 1 ; 真实引用计数: 3\n> print(c) # c 是列表对象\t输出为 [[1, 2, 3]]\n> \n> print(getrefcount(a)) # 引用计数为4,真实引用计数为3\n> ```\n>\n> \n>\n> ```python\n> 循环引用的情况\n> x = []\n> y = []\n> x.append(y) y.append(x)\n> ○ 对于上面相互引用的情况,如果不存在其他对象对他们的引用,这两个对象所占用的内存也还是无法回收,从而导致内存泄漏\n> \n> # 示例1\n> >>> x = [1]\n> >>> y = [2]\n> \n> >>> x.append(y)\n> >>> x\n> [1, [2]]\n> >>> y.append(x)\n> >>> y\n> [2, [1, [...]]]\t\t# 注:发生死循环\n> \n> # 示例2\n> >>> from sys import getrefcount\n> >>> x = [\"x\"]\n> >>> y = [\"y\"]\n> >>> getrefcount(x)\n> 2\n> >>> getrefcount(y)\n> 2\n> >>> x.append(y)\n> >>> getrefcount(x)\n> 2\n> >>> getrefcount(y)\n> 3\n> >>> y.append(x)\n> >>> getrefcount(x)\n> 3\n> >>> x\n> ['x', ['y', [...]]]\n> >>> y\n> ['y', ['x', [...]]]\n> >>> del x\t\n> >>> y\n> ['y', ['x', [...]]]\n> >>> del y\t\t\t\t# del x;del y引用删除,这块内存区域获取不到了\n> ```\n>\n> \n>\n> ```\n> 引用计数机制的优点:\n> ○ 简单\n> ○ 实时性\n> ```\n>\n> \n>\n> ```\n> 引用计数机制的缺点:\n> ○ 维护引用计数消耗资源\n> ○ 循环引用时,无法回收\n> ```\n>\n> \n\n\n\n---\n\n## 三. 垃圾回收\n\n> **● 垃圾回收**\n>\n> \n>\n> **回收原则**\n>\n> ○ 当Python的某个对象的引用计数降为0时,==可以==被垃圾回收\n>\n> \n>\n> \n>\n> **gc机制**\n>\n> ○ GC作为现代编程语言的自动内存管理机制,专注于两件事\n>\n> ○ 找到内存中无用的垃圾资源\n>\n> ○ 清除这些垃圾并把内存让出来给其他对象使用\n>\n> GC彻底把程序员从资源管理的重担中解放出来,让他们有更多的时间放在业务逻辑上。但这并不意味着码农就可以不去了解GC,毕竟多了解GC知识还是有利于我们写出更健壮的代码\n>\n> \n>\n> \n>\n> **效率问题**\n>\n> ○ 垃圾回收时,Python不能进行其它的任务。频繁的垃圾回收将大大降低Python的工作效率\n>\n> ○ 当Python运行时,会记录其中分配对象(object allocation)和取消分配对象(object deallocation)的次数。当两者的差值高于某个阈值时,垃圾回收才会启动\n>\n> \n>\n> ```python\n> # 示例\n> >>> import gc\n> >>> print(gc.get_threshold())\n> (700, 10, 10)\t\t\t\t\t# 注:默认值\n> \n> # 示例\n> >>> del x\n> >>> del y\n> >>> gc.collect()\n> 2\t\t\t\t\t\t\t# 删除了2个循环引用\n> \n> >>> a = \"x1 xx\"\n> >>> b = \"x1 xx\"\n> >>> a = 1\n> >>> b = 2\n> >>> gc.collect()\n> 0\n> ```\n>\n> \n>\n> ```\n> 三种情况触发垃圾回收\n> ○ 调用gc.collect()\n> ○ GC达到阀值时\n> ○ 程序退出时\n> ```\n>\n> \n>\n> ```\n> 分代(generation)回收\n> \t这一策略的基本假设是:存活时间越久的对象,越不可能在后面的程序中变成垃圾\n> ○ Python将所有的对象分为0,1,2三代\n> ○ 所有的新建对象都是0代对象\n> ○ 当某一代对象经历过垃圾回收,依然存活,那么它就被归入下一代对象\n> \t○ 垃圾回收启动时,一定会扫描所有的0代对象\n> \t○ 如果0代经过一定次数垃圾回收,那么就启动对0代和1代的扫描清理\n> \t○ 当1代也经历了一定次数的垃圾回收后,那么会启动对0,1,2,即对所有对象进行扫描\n> ```\n>\n> \n>\n> 标记清除\n>\n> ​\t\t标记-清除机制,顾名思义,首先标记对象(垃圾检测),然后清除垃圾(垃圾回收)。\n>\n> ​\t\t主要用于解决==循环引用==。\n>\n> ○ 1.标记:活动(有被引用), 非活动(可被删除)\n>\n> ○ 2.清除:清除所有非活动的对象\n\n\n\n---\n\n## 四. 缓冲池\n\n> ● 缓冲池\n>\n> \n>\n> **整数对象缓冲池**\n>\n> ○ 对于==[-5,256]== 这样的**小整数**,系统已经初始化好,可以直接拿来用。而对于其他的大整数,系统则提前申请了一块内存空间,等需要的时候在这上面创建大整数对象\n>\n> \n>\n> ```python\n> # 示例:小整数而言 id都是一样的\n> >>> a = 777\t\t# a和b不是一样的\n> >>> b = 777\n> >>> id(a)\t\t\t# 内存地址不同\n> 140133545530064\n> >>> id(b)\t\t\t# 内存地址不同\n> 140133545530384\n> >>> a = b = 777\n> >>> id(a)\n> 140133545530480\n> >>> id(b)\n> 140133545530480\n> >>> a = 1\t\t\t# a和b是一样的\n> >>> b = 1\t\t\t# python的整数对象缓冲池\n> >>> id(a)\n> 140133544871840\t# 内存地址一样\n> >>> id(b)\n> 140133544871840\t# 内存地址一样\n> >>> from sys import getrefcount\n> >>> getrefcount(a)\n> 801\n> ```\n>\n> \n>\n> ```python\n> 字符串缓存\n> ○ 为了检验两个引用指向同一个对象,我们可以用is关键字。is用于判断两个引用所指的对象是否相同。\n> 当触发缓存机制时,只是创造了新的引用,而不是对象本身\n> \n> # 示例\n> >>> a = \"xxx\"\n> >>> b = \"xxx\"\n> >>> id(a)\n> 140133545760616\n> >>> id(b)\n> 140133545760616\n> >>> a = \"xxx \"\t\t# 注:特殊字符不能放到缓冲区\n> >>> b = \"xxx \"\n> >>> id(a)\n> 140133545760672\t\t# 内存地址不一样\n> >>> id(b)\n> 140133545760728\n> >>> a = \"xxx_\"\t\t# 注:数字、字母、下划线的组合 放在字符串缓冲区\n> >>> b = \"xxx_\"\n> >>> id(a)\n> 140133545760616\t\t# 内存地址一样\n> >>> id(b)\n> 140133545760616\n> >>> a = \"hello world\"\n> >>> b = \"hello world\"\n> >>> id(a)\t\t\t\t# 内存地址不一样\n> 140133545242928\n> >>> id(b)\n> 140133545242992\n> >>> a = \"helloworld\"\t\n> >>> b = \"helloworld\"\n> >>> id(a)\t\t\t\t# 内存地址一样\n> 140133545243120\n> >>> id(b)\n> 140133545243120\n> \n> >>> a = \"你好\"\n> >>> b = \"你好\"\n> >>> id(a)\n> 140612691332856\n> >>> id(b)\n> 140612688894592\n> \n> \n> # 示例:对于乘法创建的字符 只会缓冲20个\n> >>> a = \"x\"*21\n> >>> b = \"x\"*21\n> >>> id(a)\t\t\t# 内存地址不一样\n> 140133545742176\n> >>> id(b)\n> 140133545742248\n> >>> a = \"x\"*20\t# 内存地址一样\n> >>> b = \"x\"*20\n> >>> id(a)\n> 140133545246768\n> >>> id(b)\n> 140133545246768\n> ```\n>\n> \n>\n> **注意**\n>\n> ○ 这对于经常使用的数字和字符串来说也是一种优化的方案\n>\n> \n>\n> **字符串的intern机制**\n>\n> ○ python对于短小的,只含有==字母数字==的字符串自动触发缓存机制。其他情况不会缓存\n\n\n\n---\n\n## 五. 深拷贝与浅拷贝\n\n> **● 深拷贝与浅拷贝**\n>\n> \n>\n> **浅拷贝**\n>\n> ○ 拷贝第一层数据(地址)\n>\n> \n>\n> ```python\n> # 示例\n> >>> a = {\"first\":[1,2,3]}\n> >>> b = a.copy()\t\t\t# 拷贝第一层数据(地址)\n> >>> a\n> {'first': [1, 2, 3]}\n> >>> b\n> {'first': [1, 2, 3]}\n> >>> id(a)\t\t\t\t\t# a、b引用变了\n> 140133410603584\n> >>> id(b)\n> 140133545741768\n> >>> a[\"second\"] = \"No.2\"\n> >>> a\n> {'first': [1, 2, 3], 'second': 'No.2'}\n> >>> b\n> {'first': [1, 2, 3]}\n> >>> a[\"first\"].append(4)\t\t# a、b里面的”first”引用 没有改变\n> >>> a\t\t\t\t\t\t\t# 拷贝第一层数据(地址)\n> {'first': [1, 2, 3, 4], 'second': 'No.2'}\n> >>> b\n> {'first': [1, 2, 3, 4]}\n> >>> id(a[\"first\"])\t\t\t\t# 第一层数据(地址) 内存地址相同\n> 140133413100296\n> >>> id(b[\"first\"])\n> 140133413100296\n> ```\n>\n> \n>\n> **深拷贝**\n>\n> ○ 递归拷贝所有层的数据\n>\n> \n>\n> ```python\n> # 示例\n> >>> a = {\"first\":[1,2,3]}\n> >>> import copy\t\t\t\t# 导入模块\n> >>> b = copy.deepcopy(a)\n> >>> id(a)\t\t\t\t\t# 内存地址不同\n> 140133545248160\n> >>> id(b)\n> 140133410604736\n> >>> a[\"second\"] = \"No.2\"\n> >>> a[\"first\"].append(4)\n> >>> a\n> {'first': [1, 2, 3, 4], 'second': 'No.2'}\t# 递归拷贝所有层的数据\n> >>> b\n> {'first': [1, 2, 3]}\t\t\t\t\t\t# 递归拷贝所有层的数据\n> ```\n>\n> \n>\n> 小结\n>\n> ○ 数字和字符串、元组,不能改变对象本身,只能改变引用的指向,称为==不可变数据对象==(immutable object)\n>\n> ○ 列表、字典、集合可以通过引用其元素,改变对象自身(in-place change)。这种对象类型,称为==可变数据对象==(mutable object)\n>\n> \n>\n> ```python\n> # 示例\n> >>> a=[1,2,3]\n> >>> b=[1,2,[4,5]]\t\t\t# 可变数据对象,有影响\n> >>> c = b[:]\n> >>> c\n> [1, 2, [4, 5]]\n> >>> b[2].append(7)\n> >>> b\n> [1, 2, [4, 5, 7]]\n> >>> c\n> [1, 2, [4, 5, 7]]\n> >>> b=[1,2,3]\t\t\t\t# 不可变数据对象,没有影响\n> >>> c = b[:]\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Python","内存管理"],"categories":["Python"]},{"title":"09_Python-CSDN_上下文管理器","url":"/posts/9186.html","content":"## 一. 介绍\n\n> ● 介绍\n>\n> \n>\n> 上下文管理器是装饰器的近亲,与装饰器类似的,它们都是包装其他代码的工具\n>\n> ○ 装饰器:包装用于定义的代码块\n>\n> ○ 上下文管理器:可以包装任意格式的代码块\n>\n> \n>\n> **上下文管理器是一个包装任意代码块的对象,上下文管理器保证:**\n>\n> ○ 进入上下文管理器时,每次代码执行的一致性\n>\n> ○ 当退出上下文管理器时,相关的资源会被正确地回收(即使内部代码出错,退出步骤也执行)\n>\n> \n>\n> **上下文管理器的应用**\n>\n> ○ 上下文管理器被用到最多的就是——作为确保资源正确清理的一种方式\n\n\n\n---\n\n## 二. 语法\n\n> **with语句**\n>\n> ○ python2.5中加入的关键字with\n>\n> ○ with语句仅仅能对支持上下文管理协议的对象使用。\n>\n> ○ with语句的表达式的作用是返回一个遵循特定协议的对象,具体来说,该对象必须定义一个==\\_\\_enter\\_\\_==方法和==\\_\\_exit\\_\\_==方法\n>\n> \n>\n> **with语句执行的解析**\n>\n> ○ 语法:with context_expr as cm: do_sth()\n>\n> ○ 当with语句执行时,便执行上下文表达式(context_expr)来获得一个上下文管理器对象,上下文管理器的职责是提供一个上下文对象,用于在with语句块中处理细节:\n>\n> ​\t\t○ 一旦获得了上下文对象,就会调用它的\\_\\_enter\\_\\_()方法\n>\n> ​\t\t○ 将完成with语句块执行前的所有准备工作\n>\n> ​\t\t○ 如果with语句后面跟了as语句,==方法返回的结果==会被赋值给as关键字后面的变量\n>\n> ​\t\t○ 除了self参数,\\_\\_enter\\_\\_方法不接受任何其他参数。\n>\n> ​\t\t○ \\_\\_enter\\_\\_方法一般负责执行一些配置\n>\n> \n>\n> ```python\n> # 示例:上下文管理器 基本语法\n> \n> # 1、普通方法打开文件对象\n> fp = open(\"test.txt\",\"a+\") # a+ 追加写\n> print(dir(fp))\n> #结果为 [ …'__enter__', …, '__exit__'…]\n> #注:有__enter__、__exit__方法,是上下文管理器\n> fp.write(\"this is test\")\n> fp.close() #注:处理结束后,把它关掉,不然占资源\n> \n> # 2、用with语句执行\n> with open(\"test.txt\",\"a+\") as f: #注:赋给f对象\n> f.write(\"write test\")\n> #退出语句执行之后 with自动回收对象\n> #因为打开的文件对象是上下文管理器\n> #注:open(\"test.txt\",\"a+\"):上下文表达式\n> \n> with语句执行的解析\n> ○ 当with语句块结束时,无论是正常结束,还是由于异常,都会调用上下文对象的__exit__()方法\n> \t○ __exit__()方法有3个参数\n> \t○ 如果with语句正常结束,三个参数全部都是 None\n> \t○ 如果发生异常,三个参数的值分别等于调用sys.exc_info()函数返回的三个值:类型(异常类)、值(异常实例)和跟踪记录(traceback),相应的跟踪记录对象。\n> \t○ 因为上下文管理器主要作用于共享资源,__enter__()和__exit__()方法基本是完成的是分配和释放资源的低层次工作,比如:数据库连接、锁分配、信号量加/减、状态管理、文件打开/关闭、异常处理等\n> ```\n>\n> \n\n\n\n---\n\n## 三. 异常处理\n\n> ● 异常处理\n>\n> \n>\n> **上下文管理器必须定义\\_\\_exit\\_\\_方法,该方法可以选择性地处理包装代码块中出现的异常,或者处理其他需要关闭上下文状态的事情**\n>\n> \n>\n> **\\_\\_exit\\_\\_方法接收了异常信息,就有处理这个异常的义务,通常可以做以下几件:**\n>\n> ○ 传播异常\n>\n> ○ 中止异常\n>\n> ○ 抛出不同异常\n>\n> \n>\n> ```python\n> # 示例:__exit__\n> #__exit__ 接受三个参数 异常类,异常值,回溯信息\n> \n> #上下文管理器 传播异常 终止异常\n> \n> class MyException():\n> def __enter__(self):\n> return self\n> def __exit__(self, exc_type, exc_val, exc_tb):\n> if exc_val: #注:如果有异常发生\n> print(f\"My exception: {exc_val}\")\n> # return False #注:传播异常,给解释器识别\n> return True #注:中止异常\n> \n> with MyException():#使用上下文管理器\n> print(1+1) #注:没有异常,输出为2\n> with MyException():\n> print(1/0) #注:False时 有异常\n> #False时 结果为 My exception: division by zero\n> #True时 结果为\n> # My exception: division by zero\t#注:True时 不报错,程序不中断\n> #注:True时 把异常传递出去,给解释器知道\n> \n> print(\"end......\")\n> #注:return False 不会执行 end......\n> #注:return True 执行了 end......\n> \n> # 示例:如果是ValueError异常,终止异常;如果不是,传播异常\n> class MyException():\n> def __enter__(self):\n> return self\n> def __exit__(self, exc_type, exc_val, exc_tb):\n> if issubclass(exc_type, ValueError): #注:如果是ValueError异常及子类异常\n> # if exc_type == ValueError: #注:exc_type是类,所以判断条件ValueError类\n> return True #终止异常\n> return False #传播异常\n> \n> with MyException():\n> print(1+1)\n> raise ValueError(\"test value error\")\n> \n> #注:issubclass(exc_type, ValueError) 如果是ValueError异常及子类异常\n> ```\n>\n> \n\n\n\n---\n\n## 四. contextlib模块\n\n> ```\n> ● contextlib模块\n> \n> contextlib模块介绍\n> \t○ contextlib模块实现上下文自动管理\n> \t○ 这个生成器可以用更简单的方法创建上下文管理器\n> ```\n>\n> \n>\n> ```python\n> # 示例:contextlib实现上下文管理器\n> import contextlib\n> \n> @contextlib.contextmanager\n> def mycontext():\n> print(\"enter context\")\n> yield #注:生成器函数\n> print(\"exit context\")\n> \n> c1 = mycontext()\n> print(dir(c1))\n> #结果为 […'__enter__', '__exit__'…]\n> #注:使用装饰器后 就是上下文管理器了。不使用装饰器,只是生成器对象\n> \n> with c1:\n> print(\"xxxxxxxxxx\")\n> #结果为\n> # enter context\n> # xxxxxxxxxx\n> # exit context\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Python","上下文管理器"],"categories":["Python"]},{"title":"08_Python-CSDN_面向对象练习","url":"/posts/13683.html","content":"[菜鸟教程:面向对象\nhttps://www.runoob.com/python3/python3-class.html](https://www.runoob.com/python3/python3-class.html)\n\n## 一. 回合制对战游戏\n\n> ```\n> ● ①、回合制对战游戏\n> \n> ○回合制对战游戏\n> ●创建角色:名字、性别、血量、装备 ●战斗\n> ●创建房间: ●装备-防弹衣\n> ●角色可加入房间 ●血量默认100\n> ●房间内的人可互打 ●正常被攻击-10滴血\n> ●房间上限2人 ●有防弹衣-5滴血\n> ```\n>\n> \n>\n> ```python\n> class Role():\n> def __init__(self,name,sex,blood=100,body_armor=None):\n> self.name = name\n> self.sex = sex\n> self.blood = blood\n> self.body_armor = body_armor\n> self.room = None\n> def attack(self,other):\n> if self.room == other.room:\t# 注:同一房间\n> if self != other:\t\t# 注:不同的人\n> if self.blood > 0 and other.blood > 0:\n> reduce_blood = 5 if other.body_armor else 10\n> \t\t\t\t# 注:body_armor为假 返回10(没有设置防弹衣)\n> other.blood -= reduce_blood\n> print(f\"{self.name}攻击{other.name} {reduce_blood}点血量\\t{self.name}当前血量:{self.blood}\\t{other.name}当前血量:{other.blood}\")\n> else:\n> print(\"其中一方已死亡,不能攻击\")\n> exit()\n> else:\n> print(\"你不能攻击自己\")\n> else:\n> print(\"攻击对象,不在同一个房间\")\n> class Room():\n> def __init__(self,name):\n> self.member = []\n> self.name = name\n> def join(self,role):\n> if role.room == None:\n> \t# 注:在角色的类里定义的属性room\n> if len(self.member) < 2:\n> self.member.append(role)\n> \t\t# 注:member房间的属性,房间只能加2个人 所以<2\n> role.room = self.name\n> \t\t# 注:达到条件,定义角色加入到 某个房间\n> else:\n> print(\"此房间已满\")\n> else:\n> print(\"此角色已经加入房间了\")\n> \n> role_dict = {} # 存放初始化实例\t# 注:存放名字和对象的关系\n> room_dict = {} # 存放初始化实例\n> while True:\n> print(\"请选择:1.创建角色\\t2.创建房间\\t3.加入房间\\t4.开始战斗\\t5.退出\")\n> enter_number = input(\"请输入你的选择\\t\")\n> if enter_number.isdigit():\n> enter_number = int(enter_number)\n> if 1 <= enter_number <=5:\n> if enter_number == 1:\n> name, sex = input(\"请输入角色的姓名与性别,空格隔开\\n\").split()\n> \t\t#注:split()是为了 分割 将字符 赋给2个变量\n> role_dict[name] = Role(name, sex)\n> def_blood = input(\"输入自定义血量\\n\")\n> if def_blood.isdigit():\n> role_dict[name].blood = int(def_blood)\n> print(f\"自定义成功,用户{name}当前血量{role_dict[name].blood}\")\n> else:\n> print(f\"自定义失败,用户{name}当前血量{role_dict[name].blood}\")\n> wear_body_armor = input(\"输入y装备防弹衣\\n\")\n> if wear_body_armor == \"y\":\n> role_dict[name].body_armor = 1\n> elif enter_number == 2:\n> name = input(\"请输入房间的名字\\n\")\n> room_dict[name] = Room(name)\n> \t\t# 注:创建好的对象(实例化对象) 保存在字典里\n> elif enter_number == 3:\n> print(f\"当前角色有{role_dict.keys()},当前房间有{room_dict.keys()}\")\n> role_name, room_name = input(\"请输入要加入的角色和房间名,空格隔开\\n\").split()\n> \t\t# 注:这里可以做1个判断 (考虑到各种情况)\n> room_dict[room_name].join(role_dict[role_name])\n> \t\t# 注:从字典 取出房间对象,调用房间对象的join()方法\n> elif enter_number == 4:\n> print(f\"当前房间有{room_dict.keys()}\")\n> room_name = input(\"请输入房间的名字\\n\")\t# 注:选择房间\n> if len(room_dict[room_name].member) == 2:\n> \t\t# 注:len()==2 这是保证房间里有2个人 才能对打\n> while True:\n> room_dict[room_name].member[0].attack(room_dict[room_name].member[1])\n> room_dict[room_name].member[1].attack(room_dict[room_name].member[0])\n> \t\t\t# 注:通过字典获取房间实例对象,member是房间的属性\n> \t\t\t# 注:为什么房间实例能获取到创建角色类的对象?因为选项3 是角色类属性 加入 房间member属性,保证了这一步能调用成功实例化对象\n> else:\n> print(f\"房间{room_name}人数不足2人,对战失败!\")\n> continue\n> elif enter_number == 5:\n> print(\"退出对战\")\n> break\n> else:\n> print(\"输入错误,请输入1-5选择操作!\")\n> else:\n> print(\"输入错误,请输入1-5选择操作!\")\n> ```\n>\n> \n>\n> ![image-20220505044926926](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505044926926.png)\n>\n> \n\n\n\n---\n\n## 二. 模拟ATM\n\n> ```\n> ● ②、模拟ATM\n> \n> ○模拟ATM\n> ●1、创建ATM\n> ○ATM里的总金额\n> ○ATM可向里面加钱\n> ○ATM里的钱取出来\n> \n> ●2、创建账户去取钱\n> ○账户属性 名称、余额、密码\n> ○账户要选择1台ATM进行操作\n> ○可以取钱、存钱、查询余额\n> ```\n>\n> \n>\n> ```python\n> class Atm():\n> def __init__(self,name,atm_total):\n> self.name = name\n> self.atm_total = atm_total\n> def add(self,money):\n> self.atm_total += money\n> print(f\"机器{self.name}增加金额{money}元,{self.name}当前总金额为{self.atm_total}元\")\n> def decrease(self,money):\n> if self.atm_total < money:\n> print(f\"{self.name}余额不足,取钱失败\")\n> else:\n> self.atm_total -= money\n> print(f\"机器{self.name}取出金额{money}元,{self.name}当前总金额为{self.atm_total}元\")\n> class Account():\n> def __init__(self,name,balance,passwd):\n> self.name = name\n> self.balance = balance\n> self.passwd = passwd\n> def draw(self,atm,money):\n> if money <= self.balance:\n> if money <= atm.atm_total:\n> self.balance -= money\n> atm.atm_total -= money\n> print(f\"成功取款{money}元,{self.name}当前余额为{self.balance}元\")\n> else:\n> print(f\"ATM机 {atm.name}余额不足,取款失败!\")\n> else:\n> print(\"您输入的金额大于您的账户余额,取款失败!\")\n> def save(self,atm,money):\n> self.balance += money\n> atm.atm_total += money\n> print(f\"成功存款{money}元,{self.name}当前余额为{self.balance}元\")\n> def look(self):\n> print(f\"{self.name}当前余额为{self.balance}元\")\n> \n> # 管理员操作\n> def atm_os():\n> # 管理员登录验证\n> name, paaswd = input(\"请输入管理员账号和密码,空格隔开\\n\").split()\n> if (name, paaswd) in admin_dict.items():\n> pass\n> else:\n> print(\"管理员账号出错\")\n> return\n> while True:\n> print(\"请选择:1.创建ATM\\t2.ATM加钱\\t3.ATM取钱\\t4.返回上一级\")\n> enter_number = input(\"请输入你的选择\\t\")\n> if enter_number.isdigit():\n> enter_number = int(enter_number)\n> if 1 <= enter_number <= 4:\n> # 1、创建ATM\n> if enter_number == 1:\n> name, atm_total = input(\"请输入ATM名称,总金额,空格隔开\\n\").split()\n> atm_total = int(atm_total)\n> atm_dict[name] = Atm(name,atm_total)\n> print(f\"创建ATM机 {name}成功,{name}当前总金额{atm_total}元\")\n> # 2、ATM加钱\n> elif enter_number == 2:\n> print(f\"当前存在的ATM机器:{atm_dict.keys()}\")\n> atm_name = input(\"请输入ATM名称\\n\")\n> if atm_name in atm_dict.keys():\n> money = int(input(\"请输入金额\\n\"))\n> atm_dict[atm_name].add(money)\n> else:\n> print(f\"{atm_name}不存在\")\n> # 3、ATM取钱\n> elif enter_number == 3:\n> print(f\"当前存在的ATM机器:{atm_dict.keys()}\")\n> atm_name = input(\"请输入ATM名称\\n\")\n> if atm_name in atm_dict.keys():\n> money = int(input(\"请输入金额\\n\"))\n> if money > 0:\n> atm_dict[atm_name].decrease(money)\n> else:\n> print(\"取出的金额不能为负\")\n> else:\n> print(f\"{atm_name}不存在\")\n> elif enter_number == 4:\n> print(\"退出ATM操作\")\n> break\n> else:\n> print(\"输入错误,请输入1-4选择操作\")\n> # 账户操作\n> def account_os():\n> while True:\n> print(\"请选择:1.创建账户\\t2.取钱\\t3.存钱\\t4.查询余额\\t5.返回上一级\")\n> enter_number = input(\"请输入你的选择\\t\")\n> if enter_number.isdigit():\n> enter_number = int(enter_number)\n> if 1 <= enter_number <= 5:\n> # 1、创建账户\n> if enter_number == 1:\n> name, balance, passwd = input(\"请输入账户名称、余额和密码进行创建,空格分割\\n\").split()\n> balance = int(balance)\n> account_dict[name] = Account(name,balance,passwd)\n> account_passwd[name] = passwd\n> print(f\"创建用户 {name}成功,余额为{balance}\")\n> elif enter_number == 2 or enter_number == 3 or enter_number == 4:\n> print(f\"当前的ATM机有{atm_dict.keys()}\")\n> atm, name, passwd = input(\"请输入您选择的ATM机、您的账户名称和密码进行登陆,空格分割\\n\").split()\n> # 验证ATM是否存在\n> if atm in atm_dict.keys():\n> # 验证账户\n> if (name, passwd) in account_passwd.items():\n> atm = atm_dict[atm]\n> # 2、取钱\n> if enter_number == 2:\n> money = int(input(\"请输入取款金额\\n\"))\n> account_dict[name].draw(atm, money)\n> # 3、存钱\n> elif enter_number == 3:\n> money = int(input(\"请输入存款金额\\n\"))\n> account_dict[name].save(atm, money)\n> # 4、查询余额\n> elif enter_number == 4:\n> account_dict[name].look()\n> else:\n> print(\"账户错误\")\n> else:\n> print(f\"{atm}不存在\")\n> elif enter_number == 5:\n> print(\"退出账户操作\")\n> break\n> else:\n> print(\"输入错误,请输入1-5选择操作\")\n> \n> admin_dict = {\"admin\":\"123456\"} # 管理员信息\n> account_passwd = {} # 账户信息\n> atm_dict = {} # 存放初始化实例\n> account_dict = {} # 存放初始化实例\n> while True:\n> print(\"请选择:1.ATM操作\\t2.账户操作\\t3.退出\")\n> enter_number = input(\"请输入你的选择\\t\")\n> if enter_number.isdigit():\n> enter_number = int(enter_number)\n> if 1 <= enter_number <= 3:\n> # 1、ATM操作\n> if enter_number == 1:\n> atm_os()\n> # 2、账户操作\n> elif enter_number == 2:\n> account_os()\n> else:\n> print(\"退出操作!\")\n> exit()\n> else:\n> print(\"输入错误,请输入1-3选择操作\")\n> else:\n> print(\"输入错误,请输入1-3选择操作\")\n> ```\n>\n> \n>\n> ![image-20220505045128067](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505045128067.png)\n>\n> \n\n\n\n---\n\n## 三. Linux用户管理类\n\n> ```\n> ● ③、Linux用户管理类\n> \n> Linux用户管理类\n> ●基类:实现往linux系统里添加用户\n> ●子类A:\n> ○能够查看、修改uid和gid、shell等信息 ●子类C(A,B):\n> ●子类B: ○1.可以单独新建组\n> ○1.能删除用户 ○2.可以将某个用户的gid修改为新建的组的gid\n> ○2.能删除组 ○3.加入异常机制,异常的名字需要自己定义\n> ```\n>\n> \n>\n> ```python\n> import subprocess\n> class Base():\n> def add(self,name,passwd):\n> subprocess.Popen(f'useradd {name} -p {passwd}&>/dev/null && echo \"{name}创建成功\" ||echo \"创建失败\"', shell=True)\n> \n> class A(Base):\n> def look(self,name):\n> p = subprocess.Popen(f'cut -d \":\" -f 1,3,4,7 /etc/passwd|grep -E ^{name}:', shell=True)\n> def modify(self,name,uid,gid,shell):\n> p = subprocess.Popen(f'usermod -u {uid} -g {gid} -s {shell} {name}&>/dev/null && echo \"修改成功\" ||echo \"修改失败\"', shell=True)\n> \n> class B(Base):\n> def del_user(self,name):\n> p = subprocess.Popen(f'userdel -r {name}&>/dev/null && echo \"删除成功\" ||echo \"创建失败\"', shell=True)\n> def del_group(self,name):\n> p = subprocess.Popen(f'groupdel {name}&>/dev/null && echo \"删除成功\" ||echo \"删除失败\"', shell=True)\n> \n> class C(A,B):\n> group_member = []\n> def group_add(self,gid,name):\n> p = subprocess.Popen(f'groupadd -g {gid} {name}&>/dev/null && echo \"创建成功\" ||echo \"创建失败\"', shell=True)\n> C.group_member.append(gid)\n> def gid_modify(self,gid,name):\n> if gid in C.group_member:\n> p = subprocess.Popen(f'usermod -g {gid} {name}&>/dev/null && echo \"修改成功\" ||echo \"修改失败\"', shell=True)\n> else:\n> print(f\"修改失败,{gid}不是新建的组id\")\n> \n> class DefinedError(Exception):\n> def __str__(self):\n> return \"这是自定义异常\"\n> \n> while True:\n> print('''请选择:\n> 1.添加用户\\t2.查看uid、gid和shell信息\\t3.修改uid、gid和shell信息\n> 4.删除用户\\t5.删除组\\t6.新建组\\t7.修改用户gid\\t8.触发异常\\t9.退出''')\n> enter_number = input(\"请输入你的选择\\t\")\n> if enter_number.isdigit():\n> enter_number = int(enter_number)\n> if 1 <= enter_number <= 9:\n> if enter_number == 1:\n> sample = Base()\n> name, passwd = input(\"请输入用户名和密码,空格分割\\n(2个参数)\\t\").split()\n> sample.add(name, passwd)\n> elif enter_number == 2:\n> sample = A()\n> name = input(\"请输入用户名\\n\")\n> sample.look(name)\n> elif enter_number == 3:\n> sample = A()\n> name,uid,gid,shell = input(\"请输入用户名,修改后的uid、gid和shell,空格分割\\n(4个参数)\\t\").split()\n> sample.modify(name,uid,gid,shell)\n> elif enter_number == 4:\n> sample = B()\n> name = input(\"请输入用户名\\n\")\n> sample.del_user(name)\n> elif enter_number == 5:\n> sample = B()\n> name = input(\"请输入组名\\n\")\n> sample.del_group(name)\n> elif enter_number == 6:\n> sample = C()\n> name, gid = input(\"请输入组名、指定的gid,空格分割\\n(2个参数)\\t\").split()\n> sample.group_add(gid,name)\n> elif enter_number == 7:\n> sample = C()\n> name, gid = input(\"请输入用户名、gid\\n(2个参数)\\t\").split()\n> sample.gid_modify(gid,name)\n> elif enter_number == 8:\n> raise DefinedError\n> elif enter_number == 9:\n> print(\"退出系统\")\n> exit()\n> else:\n> print(\"输入错误,请输入1-5选择操作!\")\n> else:\n> print(\"输入错误,请输入1-5选择操作!\")\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Python","OOP"],"categories":["Python"]},{"title":"07_Python-CSDN_高阶函数","url":"/posts/46.html","content":"\n> ```python\n> 高阶函数:把函数作为参数传入,这样的函数称为高阶函数。\n> \n> # 示例\n> def func01(a, b):\n> print(f\"{a} {b}\")\n> \n> def func02(func,a,b): # 注:把函数作为参数传递;func02称为高阶函数\n> print(\"start func......\")\n> func(a,b)\n> \n> func02(func01,\"x\",\"y\")\n> ```\n>\n> \n\n\n\n---\n\n## 常用高阶函数\n\n### map\n\n> ● map\n>\n> \n>\n> **用Python-map代码实现:f(x)=x\\*x**\n>\n> ●内置函数map,map()函数接收两个参数,一个是==函数==,一个是==Iterable(可多个)。==\n>\n> ●map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。\n>\n> ●map()传入的第一个参数是f,即函数对象本身。\n>\n> ●由于结果r是一个Iterator,Iterator是惰性序列。\n>\n> ●可通过list()函数让它把整个序列都计算出来并返回一个list。\n>\n> ●map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x**2,还可以计算任意复杂的函数。\n>\n> \n>\n> ```python\n> # 示例1:map 映射\n> def func(item): # 接收1个参数item\n> return item*item # 返回数的平方\n> \n> a = [1,2,3,4,5,6] # 注:a是可迭代对象\n> result = map(func, a)\n> print(result) # 注:返回 map对象\n> #结果为 <map object at 0x0000020EDE156970>\n> print(list(result))\n> #结果为 [1, 4, 9, 16, 25, 36]\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例2:保留2位小数\n> b = [1.239865,4.56,3.2,9.82356]\n> \n> result = map(lambda x:round(x,2), b)\n> print(list(result))\n> #结果为 [1.24, 4.56, 3.2, 9.82]\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例3:转化为百分数,并且保留2位小数\n> c = [0.000564, 0.456723, 0.5, 0.71345]\n> result = map(lambda x:format(x,'.2%'), c)\n> print(list(result))\n> #结果为 ['0.06%', '45.67%', '50.00%', '71.34%']\n> ```\n>\n> \n\n\n\n---\n\n### filter\n\n> ○ filter\n>\n> \n>\n> **用Python-filter代码实现:在一个list中,删掉偶数,只保留奇数**\n>\n> ○Python内建的filter()函数用于过滤序列。和map()类似,filter()也接收一个函数和一个序列。\n>\n> ○filter()把传入的函数依次作用于每个元素,然后==根据返回值是True还是False决定保留还是丢弃==该元素。\n>\n> ○注意到filter()函数返回的是一个Iterator,也就是一个惰性序列。\n>\n> \n>\n> ```python\n> # 示例1:保留奇数\n> a = [1,2,3,4,5,6,7,8]\n> def func01(x):\n> return x % 2 == 1 # 注:保留奇数;返回结果true\\false\n> \n> result = filter(func01, a)\n> print(list(result))\n> #结果为 [1, 3, 5, 7]\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例2:返回100以内的回数\n> b = range(1, 101) # 注:字符串反向切片\n> def func02(x):\n> return str(x) == str(x)[::-1]\n> result = filter(func02, b)\n> print(list(result))\n> #结果为 [1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 22, 33, 44, 55, 66, 77, 88, 99]\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例3:过滤出 1-100 以内 开平方根 是整数的数\n> # 方法:开平方后还在原列表里\n> # 过滤出 1-100 以内 开平方根 是整数的数\n> from math import sqrt\n> c = range(1, 101)\n> result = filter(lambda x:sqrt(x) in range(1, 101) , range(1, 101))\n> print(list(result)) # 注:开平方后的数还在 c 里面\n> #结果为 [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]\n> ```\n>\n> \n\n\n\n### sorted\n\n> ● sorted\n>\n> \n>\n> **用Python-sorted代码实现:按绝对值大小排序**\n>\n> sorted()函数也是一个高阶函数,它还可以接收一个key函数来实现自定义的排序。\n>\n> key指定的函数将作用于list的每一个元素上,并根据key函数返回的结果进行排序。\n>\n> 对比原始的list和经过key=abs处理过的list:\n>\n> ●执行语句:==sorted([36, 5, -12, 9, -21], key=abs)==\n>\n> 1.\t原始字符:list = [36, 5, -12, 9, -21]\n>\n> 2.\t经过key-abs对应得到:[36, 5, 12, 9, 21]\n>\n> 3.\t按照keys-abs排序结果:[5, 9, 12, 21, 36]\n>\n> 4.\t原始字符串最终结果:[5, 9, -12, -21, 36]\n>\n> \n>\n> ```python\n> # 示例1:sorted(a)和a.sort()\n> >>> a = [1,2,4,3,0]\t\t# 注:不会改变a的值\n> >>> sorted(a)\t\t\t\t# 注:从小到大排序\n> [0, 1, 2, 3, 4]\n> >>> a.sort()\t\t\t\t# 注:会改变a的值\n> >>> a\n> [0, 1, 2, 3, 4]\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例2:全为布尔型,可以排序\n> >>> a = [1,True,0,False,\"c\"==\"c\"]\n> >>> sorted(a)\n> [0, False, 1, True, True]\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例3:按照字符串长度排序\n> # 注:按照首字母的ASCII码排序\n> >>> a = [\"abc\",\"defg\",\"123456\",\"1\",\"sbbbfg\"]\n> >>> sorted(a)\n> ['1', '123456', 'abc', 'defg', 'sbbbfg']\n> # 注:按照字符串长度排序\n> >>> sorted(a,key=len)\n> ['1', 'abc', 'defg', '123456', 'sbbbfg']\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例4:元组排序\n> # 元组的排序,先比较第一个值,再比较第二个,依次类推\n> >>> a=[(1,2),(2,2),(1,0),(2,4),(True,False)]\n> >>> sorted(a)\n> [(1, 0), (True, False), (1, 2), (2, 2), (2, 4)]\n> >>> sorted(a,reverse=True)\t\t\t\t\t\t# 注:反序 reverse=True\n> [(2, 4), (2, 2), (1, 2), (1, 0), (True, False)]\n> ```\n>\n> \n\n\n\n### reduce\n\n> ○ reduce\n>\n> \n>\n> **用Python-reduce代码实现:将列表[1,3,5,7,9],变成整数13579**\n>\n> ○reduce把一个函数作用在一个序列[x1, x2, x3, ...]上\n>\n> ○这个函数必须接收两个参数\n>\n> ○reduce把结果继续和序列的下一个元素做累积计算\n>\n> ○==reduce(f, [x1, x2, x3, x4]) => f(f(f(x1, x2), x3), x4)==\n>\n> \n>\n> ```python\n> # 示例1:[1,2,3,4] --> 转化成1234\n> from functools import reduce\t\t# 注:导入模块\n> a = [1,2,3,4]\n> def func1(x,y):\t\t\t# 注:这个函数接收2个参数\n> return x*10+y\n> print(reduce(func1,a))\n> #结果为 1234\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例2:reduce 实现python的int功能\n> from functools import reduce\n> a = input(\"输入想要转化的数字:\")\n> b = {'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'0':0}\n> c = list(map(lambda i:b.get(i),a))\n> print(c)\n> def func(x,y):\n> return x*10+y\n> result = reduce(func,c)\n> print(result,type(result))\n> \n> ---------------------------------------------------------------------------------------------------------------------------------\n> # 示例3:实现阶乘\n> from functools import reduce\n> n = int(input(\"输入\"))\n> redu =reduce(lambda x,y:x*y,range(1,n+1))\n> print(redu)\n> #结果为 输入:4\n> #24\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Python","函数"],"categories":["Python"]},{"title":"06_Python-CSDN_psutil模块","url":"/posts/314.html","content":"## 一. 介绍\n\n> ```\n> 介绍\n> \t● process and system utilities\n> \t● 能够轻松的实现获取系统运行的进程和系统利用率(CPU、内存、磁盘、网络等)信息,主要应用于系统监控\n> \t● 实现了同等命令命令行实现的功能:ps、top、lsof、netstat、ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、pidof、tty、taskset、pmap等\n> \t● 跨平台:linux、windows、OS X、FreeBSD和Sun Solaris等\n> \t● 主要功能包含:CPU、磁盘、内存、网络、进程\n> ```\n\n\n\n---\n\n## 二. 安装\n\n> ```bash\n> 安装\n> \t● 源码安装:git clone https://github.com/giampaolo/psutil.git\n> \t\tcd psutil\n> \t\tpython3 setup.py install\n> \t● 先安装相关库:yum install python3-devel,(用yum list |grep python|grep dev 找到包名), pip3 install psutil\n> \t● 导入使用模块: import psutil\n> \n> [root@cPen_B ~]# yum list |grep python |grep dev\n> python36-devel.x86_64 3.6.8-2.module_el8.1.0+245+c39af44f @AppStream\n> [root@cPen_B ~]# yum install python36-devel.x86_64\n> [root@cPen_B ~]# pip3 install psutil\n> ```\n>\n> \n\n\n\n---\n\n## 三. 获取系统基本信息\n\n### CPU\n\n> ```python\n> 1、cpu\n> \t● psutil.cpu_count(,[logical]):默认返回逻辑CPU的个数,当设置logical的参数为False时,返回物理CPU的个数\n> \t● psutil.cpu_percent(,[percpu],[interval]):返回CPU的利用率,percpu为True时显示所有物理核心的利用率,interval不为0时,则阻塞时显示interval执行的时间内的平均利用率\n> \t● psutil.cpu_times(,[percpu]):以命名元组(namedtuple)的形式返回cpu的时间花费,percpu=True表示获取每个CPU的时间花费\n> \t\tuser:执行用户进程的时间\n> \t\tsystem:执行内核进程时间\n> \t\tidle:闲置的时间\n> \t\tiowait:等待io操作的时间\n> \t\tirp:硬中断时间\n> \t\tsoftirq:软中断时间\n> \t● psutil.cpu_times_percent(,[percpu]):功能和cpu_times大致相同,返回耗时比例\n> \t● psutil.cpu_stats(): 以命名元组的形式返回CPU的统计信息,包括上下文切换,中断,软中断和系统调用次数\n> \t\tctx_switches:上下文切换次数\n> \t\tinterrupts:中断次数\n> \t\tsoft_interrupts:软中断次数\n> \t\tsyscalls:系统调用次数,linux上始终为0\n> \t● psutil.cpu_freq(): 返回cpu频率\n> \n> # 示例1:返回CPU个数\n> >>> import psutil\n> >>> psutil.cpu_count()\t\t\t\t\t# 注:返回逻辑CPU个数\n> 2\n> >>> psutil.cpu_count(logical=False)\t\t# 注:返回物理CPU个数\n> 2\n> # 示例2:CPU使用率 百分比利用率\n> >>> psutil.cpu_percent() \n> 0.1\n> # 示例3:cpu_times\n> >>> psutil.cpu_times()\t\t# 注:花费的时间占用总时间的百分比\n> scputimes(user=105.27, nice=0.1, system=81.87, idle=69229.05, iowait=11.17, irq=0.0, softirq=5.25, steal=0.0, guest=0.0, guest_nice=0.0)\n> # 示例4:返回每个核的利用率\n> >>> psutil.cpu_percent(percpu = True)\n> [0.1, 0.1]\n> ```\n>\n> \n\n\n\n### memory\n\n> ```python\n> 2、memory\n> \t● virtual_memory():以命名元组的形式返回内存使用情况,单位为字节\n> \t\ttotal:总物理内存\n> \t\tavailable:可用内存,available ~free + buffers + cached\n> \t\tpercent:使用率: percent = (total - available) / total * 100\n> \t\tused:使用的内存: used = total - free - buffers - cache\t\n> \t\tfree:完全没用使用内存\n> \t\tactive:最近被访问的内存\n> \t\tinactive:长时间未被访问的内存\n> \t\tbuffers:缓存\n> \t\tcached:缓存\n> \t\tslab:内核数据结构缓存的内存\n> \t● swap_memory:以命名元组的形式返回swap/memory使用情况,包含swap中页的换入和换出\n> \n> # 示例1:virtual_memory\n> >>> psutil.virtual_memory()\n> svmem(total=3953979392, available=3447025664, percent=12.8, used=249577472, free=3045027840, active=350208000, inactive=329723904, buffers=2162688, cached=657211392, shared=12365824, slab=117297152)\n> ```\n>\n> \n\n\n\n### disk\n\n> ```python\n> 3、disk(linux命令:iostat,df)\n> \t● psutil.disk_io_counters([perdisk]):以命名元组的形式返回磁盘io统计信息(汇总的),包括读、写的次数,读、写的字节数等\n> \t● psutil.disk_partitions():磁盘挂载分区信息\n> \t\tdevice:分区\n> \t\tmountpoint:挂载点\n> \t\tfstype:文件系统格式(fat、ext4、 xfs)\n> \t\topts:挂载参数\n> \t● disk_usage:磁盘使用情况,需要传入一个路径参数\n> \t\t>>> psutil.disk_usage('/')\n> \t\tsdiskusage(total=250685575168, used=103938019328, free=134242258944, percent=43.6)\n> \t● iostat : %util 数值越大越忙碌,到达了io瓶颈(安装包:yum install sysstat)\n> \n> # 示例1:磁盘挂载分区信息 disk_partitions\n> >>> psutil.disk_partitions() \n> [sdiskpart(device='/dev/mapper/centos-root', mountpoint='/', fstype='xfs', opts='rw,relatime,attr2,inode64,noquota'), sdiskpart(device='/dev/sda1', mountpoint='/boot', fstype='xfs', opts='rw,relatime,attr2,inode64,noquota')]\n> # 示例2:磁盘使用情况 disk_usage\n> >>> psutil.disk_usage(\"/\")\t\t\t\t\t# 注:需要接挂载点\n> sdiskusage(total=18238930944, used=2300264448, free=15938666496, percent=12.6)\n> ```\n>\n> \n\n\n\n### Network\n\n> ```python\n> 4、Network(linux命令:ifconfig、who、uptime,netstat)\n> \t● psutil.net_io_counters([pernic]):以命名元组的形式返回当前系统中每块网卡的网络io统计信息,包括收发字节数,收发包的数量、出错的情况和删包情况。当pernic为True时,则列出所有网卡的统计信息\n> \t● psutil.net_connections([kind]):以列表的形式返回每个网络连接的详细信息(namedtuple)\n> \t\tfd:文件描述符\n> \t\tfamily:地址簇,ipv4(AF_INET),ipv6\n> \t\ttype:SOCK_STREAM(tcp)、udp\n> \t\tladdr:本地ip地址\n> \t\traddr\n> \t\tstatus\n> \t\tpid\n> \t● psutil.net_if_addrs():以字典的形式返回网卡的配置信息,包括IP地址和mac地址、子网掩码和广播地址\n> \t● psutil.net_if_stats():返回网卡的详细信息,包括是否启动、通信类型、传输速度与mtu\n> \t\tmtu:最大传输单元\n> \t● psutil.users():以命名元组的方式返回当前登陆用户的信息,包括用户名,登陆时间,终端\n> \t● psutil.boot_time():以时间戳的形式返回系统的启动时间\n> \n> # 示例1:psutil.users 以命名元组的方式返回当前登陆用户的信息,包括用户名,登陆时间,终端\n> >>> psutil.users()\t\t\t\t\t\t# 注:w、who命令\n> [suser(name='root', terminal='tty1', host='', started=1606217600.0, pid=708), suser(name='root', terminal='pts/0', host='192.168.0.42', started=1606361216.0, pid=5921), suser(name='root', terminal='pts/2', host='192.168.0.42', started=1606361216.0, pid=5942), suser(name='root', terminal='pts/6', host='192.168.0.42', started=1606354816.0, pid=5239), suser(name='root', terminal='pts/7', host='192.168.0.42', started=1606357120.0, pid=5312)]\n> # 示例2:net_if_addrs\n> >>> psutil.net_if_addrs()\t\t\t# 注:lo本地回环地址 127.0.0.1\n> {'lo': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='00:00:00:00:00:00', netmask=None, broadcast=None, ptp=None)], 'ens33': [snicaddr(family=<AddressFamily.AF_INET: 2>, address='192.168.0.21', netmask='255.255.255.0', broadcast='192.168.0.255', ptp=None), snicaddr(family=<AddressFamily.AF_INET6: 10>, address='fe80::22d8:5740:d6d7:d1ff%ens33', netmask='ffff:ffff:ffff:ffff::', broadcast=None, ptp=None), snicaddr(family=<AddressFamily.AF_PACKET: 17>, address='00:0c:29:d1:80:fa', netmask=None, broadcast='ff:ff:ff:ff:ff:ff', ptp=None)]}\n> ```\n>\n> \n\n\n\n### 进程管理\n\n> ```python\n> 5、进程管理(linux命令:ps、kill)\n> \t● psutil.pids():以列表的形式返回当前正在运行的进程\n> \t● psutil.pid_exists(1):判断给点定的pid是否存在\n> \t● psutil.Process(1):对进程进行封装,可以使用该类的方法获取进行的详细信息,或者给进程发送信号\n> \t● psutil.process_iter():迭代当前正在运行的进程,返回的是每个进程的Process对象\n> \t\tname:获取进程的名称\n> \t\tcmdline:获取启动进程的命令行参数\n> \t\tcreate_time:获取进程的创建时间\n> \t\tuids:进程uid信息\n> \t\tnum_threads:开启的线程数\n> \t\texe:进程工作的绝对路径\n> \t\tkill:发送SIGKILL信号结束进程\n> \n> 示例:process_iter 迭代当前正在运行的进程\n> >>> psutil.process_iter() \n> <generator object process_iter at 0x7f56eb912888>\n> >>> p = psutil.process_iter()\n> >>> next(p)\n> psutil.Process(pid=1, name='systemd', status='sleeping', started='01:52:52')\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Python","模块","Psutil"],"categories":["Python"]},{"title":"05_Python-CSDN_排序算法","url":"/posts/49827.html","content":"## 一. 顺序查找\n\n> ```python\n> ● 顺序查找\n> 顺序查找:也叫线性查找,从列表第一个元素开始,顺序进行搜索,直到找到元素或搜索到列表最后一个元素为止。\n> 时间复杂度:O(n)\n> \n> def Linear_search(li, val): # 注:li列表 ;val待查找的元素\n> for ind, v in enumerate(li): # 注:因为要返回个下标 所以用 enumerate index和值都需要\n> if v == val: # 注:如果v == 我们要找的那个值 那就返回 它的index\n> return ind\n> else: # 如果for循环结束后还没有找到 返回None\n> return None\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=7](https://www.bilibili.com/video/BV1mp4y1D7UP?p=7)\n> [菜鸟教程 Python线性查找\n> https://www.runoob.com/python3/python-linear-search.html](https://www.runoob.com/python3/python-linear-search.html)\n\n\n\n---\n\n## 二. 二分查找\n\n> ```python\n> ● 二分查找\n> 二分查找:又叫折半查找,从有序列表的初始候选区li[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。\n> \n> 时间复杂度:O(logn)\n> \n> def binary_search(li, val): # li 列表 val待查找的值\n> left = 0\n> right = len(li) - 1\n> while left <= right: # 注:循环条件 说明候选区有值\n> mid = (left + right) // 2 # 注:中间值(下标) 是整除2\n> if li[mid] == val: # 注:== 找到的情况 每次对比都是对比的li[mid]\n> return mid # 注:返回下标 mid\n> elif li[mid] > val: # 注:代表 待查找的值val在 mid左边\n> right = mid - 1 # 注:更新候选区了 这种情况就可以继续循环\n> else: # 注:第3种情况 li[mid] < val 待查找的值在mid右侧\n> left = mid + 1 # 注:更新候选区 继续循环\n> else:\n> return None # 注:如果找不到的情况 即不满足 left <= right 时\n> \n> li = [1,2,3,4,5,6,7,8,9]\n> print(binary_search(li,3)) # 注:调用二分查找 查3\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=8](https://www.bilibili.com/video/BV1mp4y1D7UP?p=8)\n> [菜鸟教程 Python二分查找\n> https://www.runoob.com/python3/python-binary-search.html](https://www.runoob.com/python3/python-binary-search.html)\n\n\n\n---\n\n## 三. 冒泡排序\n\n> ```python\n> 冒泡排序:列表每两个相邻的数,如果前面比后面大,则交换这两个数。\n> 时间复杂度:O(n**2)\n> \n> def bubble_sort2(li):\n> for i in range(len(li)-1):\n> for j in range(len(li)-i-1):\n> if li[j] > li[j+1]:\n> li[j], li[j+1] = li[j+1], li[j]\n> \n> 改进:如果冒泡排序中的一趟排序没有发生交换,则说明列表已经有序,可以直接结束算法。\n> def bubble_sort_1(li):\n> for i in range(len(li)-1):\n> exchange = False # 在第i趟那加标志位\n> for j in range(len(li)-i-1):\n> if li[j] > li[j+1]:\n> li[j], li[j+1] = li[j+1], li[j]\n> exchange = True # 注:如果有交换 把它识成True 交换这里也是1个标志位\n> if not exchange: # 注:如果每1趟结束后 exchange没有发生交换 (这个在for里面)\n> return # 注:就直接结束掉这个函数\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=12](https://www.bilibili.com/video/BV1mp4y1D7UP?p=12)\n> [菜鸟教程 Python冒泡排序\n> https://www.runoob.com/python3/python-bubble-sort.html](https://www.runoob.com/python3/python-bubble-sort.html)\n\n\n\n---\n\n## 四. 选择排序\n\n> ```python\n> 选择排序:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。\n> 时间复杂度:O(n**2)\n> \n> def select_sort(li):\n> for i in range(len(li) - 1):\n> min_loc = i\n> for j in range(i+1, len(li)):\n> if li[j] < li[min_loc]:\n> min_loc = j\n> if min_loc != i:\n> li[i], li[min_loc] = li[min_loc], li[i]\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=14](https://www.bilibili.com/video/BV1mp4y1D7UP?p=14)\n> [菜鸟教程 Python选择排序\n> https://www.runoob.com/python3/python-selection-sort.html](https://www.runoob.com/python3/python-selection-sort.html)\n\n\n\n---\n\n## 五. 插入排序\n\n> ```python\n> 插入排序:它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。\n> 时间复杂度:O(n**2)\n> \n> def insert_sort(li):\n> for i in range(1, len(li)):\n> tmp = li[i]\n> j = i - 1\n> while j >= 0 and tmp < li[j]:\n> li[j + 1] = li[j]\n> j = j - 1\n> li[j + 1] = tmp\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=15](https://www.bilibili.com/video/BV1mp4y1D7UP?p=15)\n> [菜鸟教程 Python插入排序\n> https://www.runoob.com/python3/python-insertion-sort.html](https://www.runoob.com/python3/python-insertion-sort.html)\n\n\n\n---\n\n## 六. 快速排序\n\n> ```python\n> 快速排序:快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为较小和较大的2个子序列,然后递归地排序两个子序列。\n> 时间复杂度:O(nlogn)\n> \n> # 快速排序-partition函数\n> def partition(li, left, right):\n> tmp = li[left]\n> while left < right:\n> while left < right and li[right] >= tmp: # 从右边找比tmp小的数\n> right -= 1 # 往右走一步\n> li[left] = li[right] # 把右边的值写到左边空位上\n> while left < right and li[left] <= tmp:\n> left += 1\n> li[right] = li[left] # 把左边的值写到右边空位上\n> li[left] = tmp # 把tmp归位\n> return left # mid 是 这个函数返回left值的目的\n> \n> # 快速排序-框架\n> def quick_sort(li, left, right):\n> if left < right: # 至少2个元素\n> mid = partition(li, left, right) # 这个函数返回left值的目的\n> quick_sort(li, left, mid - 1) # 左边部分\n> quick_sort(li, mid + 1, right) # 右边部分\n> \n> li = [5,7,4,6,3,1,2,9,8]\n> quick_sort(li, 0, len(li)-1)\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=16](https://www.bilibili.com/video/BV1mp4y1D7UP?p=16)\n> [菜鸟教程 Python快速排序\n> https://www.runoob.com/python3/python-quicksort.html](https://www.runoob.com/python3/python-quicksort.html)\n\n\n\n---\n\n## 七. 堆排序\n\n> ```python\n> 堆排序:堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。\n> 时间复杂度:O(nlogn)\n> \n> def sift(li, low, high): # 向下调整函数\n> # li:列表\n> # low: 堆的根节点位置\n> # high: 堆的最后一个元素的位置\n> i = low # i最开始指向根节点\n> j = 2 * i + 1 # j开始是左孩子\n> tmp = li[low] # 把堆顶存起来\n> while j <= high: # 只要j位置有数\n> if j + 1 <= high and li[j+1] > li[j]: # 如果有孩子有并且比较大\n> j = j + 1 # j指向右孩子\n> if li[j] > tmp:\n> li[i] = li[j]\n> i = j # 往下看一层\n> j = 2 * i + 1\n> else: # tmp更大,把tmp放到i的位置上\n> li[i] = tmp # 该语句可省 # 把tmp放到某一级领导位置上\n> break\n> else:\n> li[i] = tmp # 把tmp放到叶子节点上\n> \n> def heap_sort(li): # 建堆函数\n> n = len(li)\n> for i in range((n-2)//2, -1, -1):\n> # i表示建堆的时候调整的部分的根的下标\n> sift(li, i, n-1) # 这里不是递归\n> #建堆完成了\n> #---------------------这一步 挨个出数的步骤\n> for i in range(n-1, -1, -1):\n> # i指向当前堆的最后一个元素\n> li[0], li[i] = li[i], li[0]\n> sift(li, 0, i - 1) # i-1是新的high\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=22](https://www.bilibili.com/video/BV1mp4y1D7UP?p=22)\n> [菜鸟教程 Python堆排序\n> https://www.runoob.com/python3/python-heap-sort.html](https://www.runoob.com/python3/python-heap-sort.html)\n\n\n\n---\n\n## 八. 归并排序\n\n> ```python\n> 归并排序:创建在归并操作上的一种有效的排序算法。\n> 时间复杂度:O(nlogn)\n> \n> def merge(li, low, mid, high):\n> i = low\n> j = mid + 1\n> ltmp = []\n> while i<=mid and j<=high: # 只要左右两边都有数\n> if li[i] < li[j]:\n> ltmp.append(li[i])\n> i +=1\n> else:\n> ltmp.append(li[j])\n> j += 1\n> # while执行完,肯定有一部分没数了\n> while i <= mid:\n> ltmp.append(li[i])\n> i += 1\n> while j <= high:\n> ltmp.append(li[j])\n> j += 1\n> li[low:high+1] = ltmp\n> \n> def merge_sort(li, low, high):\n> if low < high: # 至少有2个元素,递归\n> mid = (low + high) // 2\n> merge_sort(li, low, mid)\n> merge_sort(li, mid+1, high)\n> merge(li, low, mid, high)\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=30](https://www.bilibili.com/video/BV1mp4y1D7UP?p=30)\n> [菜鸟教程 Python归并排序\n> https://www.runoob.com/python3/python-merge-sort.html](https://www.runoob.com/python3/python-merge-sort.html)\n\n\n\n---\n\n## 九. 希尔排序\n\n> ```python\n> 希尔排序:希尔排序(Shell Sort)是一种分组插入排序算法。\n> 时间复杂度讨论比较复杂,并且和选取的gap序列有关。\n> \n> def insert_sort_gap(li, gap):\n> for i in range(gap, len(li)): # i 表示摸到的牌的下标\n> tmp = li[i]\n> j = i - gap # j指的是手里牌的下标\n> while j >= 0 and li[j] > tmp:\n> li[j+gap] = li[j]\n> j = j - gap\n> li[j+gap] = tmp\n> \n> def shell_sort(li):\n> d = len(li) // 2\n> while d >= 1:\n> insert_sort_gap(li, d)\n> d //= 2\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=34](https://www.bilibili.com/video/BV1mp4y1D7UP?p=34)\n> [菜鸟教程 Python希尔排序\n> https://www.runoob.com/python3/python-shellsort.html](https://www.runoob.com/python3/python-shellsort.html)\n\n\n\n---\n\n## 十. 计数排序\n\n> ```python\n> 计数排序:计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。\n> 时间复杂度:O(n)\n> \n> def count_sort(li, max_count=100):\n> count = [0 for _ in range(max_count+1)]\n> for val in li:\n> count[val] += 1\n> li.clear()\n> for ind, val in enumerate(count):\n> for i in range(val):\n> li.append(ind)\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=36](https://www.bilibili.com/video/BV1mp4y1D7UP?p=36)\n> [菜鸟教程 Python计数排序\n> https://www.runoob.com/python3/python-counting-sort.html](https://www.runoob.com/python3/python-counting-sort.html)\n\n\n\n---\n\n## 十一. 桶排序\n\n> ```python\n> 桶排序:首先将元素分在不同的桶中,在对每个桶中的元素排序。\n> 时间复杂度 取决于数据的分布\n> \n> def bucket_sort(li, n=100, max_num=10000):\n> buckets = [[] for _ in range(n)] # 创建桶\n> for var in li:\n> i = min(var // (max_num // n), n-1) # i表示var放到几号桶里\n> buckets[i].append(var) # 把var加到桶里面\n> # 保持桶内的顺序\n> for j in range(len(buckets[i])-1, 0, -1):\n> if buckets[i][j] < buckets[i][j-1]:\n> buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]\n> else:\n> break\n> sorted_li = []\n> for buc in buckets:\n> sorted_li.extend(buc)\n> return sorted_li\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=37](https://www.bilibili.com/video/BV1mp4y1D7UP?p=37)\n> [菜鸟教程 桶排序\n> https://www.runoob.com/w3cnote/bucket-sort.html](https://www.runoob.com/w3cnote/bucket-sort.html)\n\n\n\n---\n\n## 十二. 基数排序\n\n> ```python\n> 基数排序:基数排序是一种非比较型整数排序算法,其原理是将整数按位数切割成不同的数字,然后按每个位数分别比较。\n> 时间复杂度:O(kn)\n> \n> def list_to_buckets(li, base, iteration):\n> buckets = [[] for _ in range(base)]\n> for number in li:\n> digit = (number // (base ** iteration)) % base\n> buckets[digit].append(number)\n> return buckets\n> \n> def buckets_to_list(buckets):\n> return [x for bucket in buckets for x in bucket]\n> \n> def radix_sort(li, base=10):\n> maxval = max(li)\n> it = 0\n> while base ** it <= maxval:\n> li = buckets_to_list(list_to_buckets(list_to_buckets(li, base, it)))\n> it += 1\n> return li\n> ```\n>\n> \n>\n> [b站视频 路飞IT学城\n> https://www.bilibili.com/video/BV1mp4y1D7UP?p=39](https://www.bilibili.com/video/BV1mp4y1D7UP?p=39)\n> [菜鸟教程 基数排序\n> https://www.runoob.com/w3cnote/radix-sort.html](https://www.runoob.com/w3cnote/radix-sort.html)\n\n\n\n---\n\n","tags":["Python","算法"],"categories":["Python"]},{"title":"04_Python-CSDN_mail模块","url":"/posts/33188.html","content":"## 一. 理论\n\n> ```\n> mail模块作用\n> 1、邮件报警\n> 2、发送报表\n> \n> 邮件协议\n> 1、smtp (simple mail transfer protocol) 简单邮件传输协议,主要用来发送文件 默认端口 25号\n> 2、pop3 主要用来接收邮件 默认端口 110 客户端的操作不会反馈到服务器端\n> 3、imap 主要用来接收邮件 默认端口 143 客户端的操作会反馈到服务器端\n> \n> [参考:菜鸟教程 https://www.runoob.com/python3/python3-smtp.html\n> ](https://www.runoob.com/python3/python3-smtp.html)\n> ```\n>\n> \n\n\n\n---\n\n## 二. 步骤\n\n### QQ邮箱获取授权码\n\n> ○ QQ邮箱获取授权码\n>\n> [参考:获取授权码]\n>\n> (https://service.mail.qq.com/cgi-bin/help?subtype=1&&id=28&&no=1001256)\n>\n> \n>\n> 先进入设置 -> 帐户页面找到入口\n>\n> (1)点击“开启”\n>\n> (2)验证密保\n>\n> (3)获取授权码\n>\n> \n>\n> ![image-20220505035438263](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035438263.png)\n>\n> ![image-20220505035449933](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035449933.png)\n>\n> ![image-20220505035503147](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035503147.png)\n>\n> \n>\n> 或者开启IMAP/SMTP服务,同理\n>\n> ![image-20220505035521956](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035521956.png)\n\n\n\n### 代码部分\n\n> ```python\n> ○ 代码部分\n> □ 示例1\n> from smtplib import SMTP # 导入smtplib模块的SMTP类\n> s = SMTP(\"smtp.qq.com\") # 使用qq邮箱去发送\n> s.login(\"848723505@qq.com\",\"hopo**secret**bbdj\") # 发件人邮箱账号、授权码\n> tolist = [\"1533431376@qq.com\"] # 收件人邮箱账号\n> msg = \"\"\"\\\n> From: 848723505@qq.com@qq.com\n> TO: 1533431376@qq.com\n> Subject: mail module study\n> \n> this is cPen test\n> \"\"\"\n> \n> s.sendmail(\"848723505@qq.com\",tolist, msg)\n> ```\n>\n> \n>\n> 效果图\n>\n> ![image-20220505035651514](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035651514.png)\n>\n> \n>\n> ```python\n> □ 示例2\n> from smtplib import SMTP\n> from email.mime.text import MIMEText\n> \n> # 第三方smtp服务设置\n> mail_host = \"smtp.qq.com\"\n> mail_user = \"848723505@qq.com\" # 发件人邮箱账号\n> mail_pass = \"hopo**secret**bbdj\" # 发件人授权码\n> \n> recv = \"1533431376@qq.com\" # 收件人邮箱账号\n> \n> # 构造邮件内容\n> # 正文内容、正文内容类型、正文内容编码\n> message = MIMEText(\"Hello World ~ cPen\", \"plain\", \"utf-8\") # plain是普通的文本\n> \n> message[\"From\"] = mail_user # 把对象像字典一样传参\n> message[\"To\"] = recv\n> message[\"Subject\"] = \"I Love Coding\"\n> \n> s = SMTP(\"smtp.qq.com\") # 使用qq邮箱去发送\n> s.login(\"848723505@qq.com\",\"hopo**secret**bbdj\") # 登录\n> s.sendmail(mail_user,recv,message.as_string()) # 文件内容需要转换成字符型\n> ```\n>\n> \n>\n> 效果图\n>\n> ![image-20220505035746706](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035746706.png)\n>\n> \n>\n> ```python\n> □ 示例3\n> from smtplib import SMTP\n> from email.mime.text import MIMEText\n> \n> # 第三方smtp服务设置\n> mail_host = \"smtp.qq.com\"\n> mail_user = \"848723505@qq.com\" # 发件人邮箱账号\n> mail_pass = \"hopo**secret**bbdj\" # 发件人授权码\n> \n> recv = \"1533431376@qq.com\" # 收件人邮箱账号\n> \n> # 把内容识别成网页传送\n> html_msg = \" <p>Python mail module test</p><p><a href='https://www.baidu.com'>点击进入百度</a></p>\"\n> message = MIMEText(html_msg,'html','utf-8')\n> \n> message[\"From\"] = mail_user # 把对象像字典一样传参\n> message[\"To\"] = recv\n> message[\"Subject\"] = \"cPen mail\"\n> \n> s = SMTP(\"smtp.qq.com\") # 使用qq邮箱去发送\n> s.login(\"848723505@qq.com\",\"hopo**secret**bbdj\") # 登录\n> s.sendmail(mail_user,recv,message.as_string()) # 文件内容转换成字符型\n> ```\n>\n> \n>\n> 效果图\n>\n> ![image-20220505035846092](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505035846092.png)\n>\n> \n\n\n\n### Foxmail登录\n\n> ○ Foxmail登录\n>\n> \n>\n> [下载Foxmail客户端]\\(https://www.foxmail.com/)\n>\n> \n>\n> 先进入设置 -> 新建账号,填入E-mail地址和授权码\n>\n> \n>\n> □ 使用POP3协议登录\n>\n> ![image-20220505040116717](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505040116717.png)\n>\n> \n>\n> □ 使用IMAP协议登录\n>\n> ![image-20220505040144841](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505040144841.png)\n>\n> \n>\n> 效果图\n>\n> ![image-20220505040202531](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220505040202531.png)\n\n\n\n---\n\n","tags":["Python","模块","Mail"],"categories":["Python"]},{"title":"03_Python-CSDN_数据类型2","url":"/posts/37069.html","content":"容器类型\n\n```\n4种内置数据结构(容器类型)\n\t列表:list=>[val1,val2,val3,val4]\n\t元组:tuple=>(val1,val2,val3,val4)\n\t字典:dict=>{key1:val1,key2:val2}\n\t集合:set=>{key1,key2,key3,key4}\n```\n\n\n\n## 一. 列表(list)\n\n```\n列表是处理一组有序项目的数据结构\n列表是python中最具灵活性的有序集合对象类型\n列表可以包含任何类型的对象:字符串、数字甚至其他列表\n列表是可变的数据类型,即这种类型的值是可以被修改的\nExample:表示一个购物清单\n\tgoods=['牛奶'、'运动鞋'、'咖啡'、'手机'、'羊肉'、'葡萄'、'桔子']\n\n列表通过方括号中用逗号分割的项目定义\n```\n\n\n\n```python\n# 示例\n# 定义空列表\n>>> lst = []\n>>> type(lst)\n<class 'list'>\n>>> lst2 = list()\t\t# 注:工厂函数\n>>> type(lst2)\n<class 'list'>\n# 列表可装入python的任何对象:\n>>> lst3 = list(\"abc\")\t\t# 注:字符串\n>>> lst3 \n['a', 'b', 'c']\n>>> lst = [1,'abc',2.5,True]\n>>> lst = [1,'abc',2.5,True,lst3]\t# 注:其他列表\n>>> lst\n[1, 'abc', 2.5, True, ['a', 'b', 'c']]\n```\n\n\n\n### 列表基本操作\n\n#### 索引\n\n​\t通过下标访问列表中的元素,下标从0开始计数,可取出一个元素\n\n```python\n# 示例\n>>> lst = [1,2,3]\n>>> id(lst)\n140078683813384\n>>> lst += [4]\n>>> id(lst)\n140078683813384\t# 注:内存地址不变\n>>> lst[0]\n1\n>>> lst[0] = \"a\"\t# 注:改变列表里的元素值\n>>> id(lst)\n140078683813384\n# 下标不能越界(Index Error:list index out of range)\n>>> lst\n['b', 2, 3, 4]\n>>> lst[4]\t\t# 注:下标越界 会报错\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nIndexError: list index out of range\n```\n\n\n\n#### 切片\n\n```\n切片是通过下标访问列表中的元素,切片可以取出一个子列表\n起止区间:[ start,end )\nstep:默认=>1\nstart:默认=>step为正时,start为0;step为负时,start为-1\nend:默认=>step为正时,end为列表结尾;step为负时,end为列表开始\n注意:三个值都为选填项\n```\n\n```python\n# 示例:正切片\n>>> a = [1,2,3,4,5,6]\n>>> a[0:4]\t# 注:切片,前4个\n[1, 2, 3, 4]\n>>> str = \"123456\"\n>>> str[0:4]\t# 注:切片,前4个\n'1234'\n>>> a[:4]\t\t# 注:效果一样\n[1, 2, 3, 4]\n\n# 示例:负切片,步长为-1\n>>> a = [1,2,3,4,5,6]\n>>> a[-1:3:-1]\t# 注:-1指向6, 3指向4,-1从右往左\n[6, 5]\n>>> a[-1:-4:-1]\t# 注:-1指向6,-4指向3,-1从右往左\n[6, 5, 4]\n>>> a[-1:-44:-1]\t# 注:-1指向6,-44越界,-1从右往左\n[6, 5, 4, 3, 2, 1]\n>>> a[-1:4:-1]\t# 注:-1指向6, 4指向5,-1从右往左\n[6]\n>>> a[-3:4:-1]\t# 注:-3指向4, 4指向5,4向左取不到5\n[]\t\t\t\t# 注:为空 起始位置有误时,切出来会是空(不会报错)\n```\n\n\n\n```\n切片对象(slice函数)\n\tslice函数的用途:生成一个slice对象,相当于可以给要切的内容取个名字。\n```\n\n```python\n# 示例\n>>> a = [\"a\",\"b\",\"c\",\"d\"]\n>>> a\n['a', 'b', 'c', 'd']\n>>> b = [1,2,3,4,5,6]\n>>> s1 = slice(0,3,1)\t\t# 注:引用时需要传参进去\n>>> a[s1]\t\t\t\t\t# 注:切片 前3个\n['a', 'b', 'c']\n>>> b[s1]\t\t\t\t\t# 注:切片 前3个\n[1, 2, 3]\n>>> c = [\"xx\",\"yy\",\"zz\",\"ee\"]\t\n>>> c[s1]\t\t\t\t\t# 注:切片 前3个\n['xx', 'yy', 'zz']\n```\n\n\n\n#### 增加\n\n```\n增加列表元素的方式\n\tappend:在末尾,作为整体追加,类型不限\n\tinsert:在index位置插入元素\n\textend:扩展列表\n```\n\n```python\n# 示例\n# append\n>>> a = [\"apple\", \"orange\", 123, 0.1111, \"cali\"]\n>>> a.append(\"test\")\t# 注:追加字符串\n>>> a\n['apple', 'orange', 123, 0.1111, 'cali', 'test']\n>>> lst = ['a','b','c']\n>>> lst2 = [1,2,3]\n>>> lst.append(lst2)\t# 注:追加的类型是数组\n>>> lst\n['a', 'b', 'c', [1, 2, 3]]\t# 注:追加的类型是数组\n# insert\n>>> lst = ['a','b','c']\n>>> lst.insert(1,'d')\t\t# 注:在第2个元素前插入数据\n>>> lst\n['a', 'd', 'b', 'c']\n# extend\n>>> a = [1,2,3]\n>>> str = \"abc\"\n>>> a.extend(str)\t\t# 注:扩展字符串\n>>> a\n[1, 2, 3, 'a', 'b', 'c']\n```\n\n\n\n```\nextend与+\n\t注意:只限可转为list的类型(str,list,tuple)\n```\n\n```python\n# 示例\n>>> a = ['a','b','c']\n>>> a2 = [1,2,3]\n>>> a.extend(a2)\n>>> a\n['a', 'b', 'c', 1, 2, 3]\n>>> a + [\"5\"]\t\t\t\t# 注:+ 法只能list 和 list 相加\n['a', 'b', 'c', 1, 2, 3, '5']\n>>> a\n['a', 'b', 'c', 1, 2, 3]\t# 注:+ 法 运行结束后 数组a没有变化\n>>> b = a + [\"5\"]\t\t\t# 注:赋值给数组b\n>>> b\t\t\t\t\t# 注:可以通过 赋值给数组b的方法来保存 变化\n['a', 'b', 'c', 1, 2, 3, '5']\n>>> id(a)\n140273972677768\n>>> a += [\"6\"]\n>>> id(a)\n140273972677768\t# 注:a += [\"6\"] \t内存地址不变 对象不变,内容改变\n>>> a = a + [\"7\"]\n>>> id(a)\n140273837551816\t# 注:a = a + [\"7\"]内存地址改变\n```\n\n\n\n#### 删除\n\n```\n删除列表元素的方式\n\tpop:删除元素,默认最后一个(指定index删除)\n\tremove:删除指定的元素(要删除的数据不存在时,会出错)\n\tdel:根据下标删除\n\t\tdel是python的一个关键字,用于删除变量(的引用)\n\tclear:清空列表\n```\n\n```python\n# 示例\n# pop\n>>> a.pop()\t# 注:默认删除最后1个\n'7'\t\t\t# 注:返回值,删除的元素\n>>> a.pop(2)\t# 注:指定索引2 删除第3个元素\n'c'\n# remove\n>>> a = [\"xx\",\"yy\",\"xx\"]\n>>> a.remove(\"xx\")\t\t# 注:删除指定元素,只删除第1个\n>>> a\n['yy', 'xx']\n>>> a\n['yy', 'xx']\n>>> a.remove(\"zz\")\t\t# 注:要删除的数据不存在时,会报错\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nValueError: list.remove(x): x not in list\n# del\n>>> a = [1,2,3,\"xx\",\"yy\",\"zz\"]\n>>> del a[3]\t\t# 注:删除索引3 第4个\n>>> a\n[1, 2, 3, 'yy', 'zz']\n>>> del a[0:2]\t# 注:切片删除\n>>> c = 1\n>>> del c\t\t\t# 注:del删除变量的引用\n>>> c\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nNameError: name 'c' is not defined\n# clear\n>>> a\n[3, 'yy', 'zz']\n>>> a.clear()\n>>> a\n[]\t\t\t# 注:clear清空\n```\n\n\n\n#### 修改\n\n修改元素主要是利用下标和切片来修改或增加、删除\n\n```\n# 示例\n>>> a = [1,2,3,'a','b','c']\n>>> a\n[1, 2, 3, 'a', 'b', 'c']\n>>> a[2] = \"x\"\t# 注:修改元素\n>>> a\n[1, 2, 'x', 'a', 'b', 'c']\n>>> a[1:1]\t\t# 注:[1,1)\n[]\t\t\t\t# 注:为空\n>>> a[1:1] = \"abc\"\t# 注:在起始位置 索引为1 处之前 增加列表 str类型转换为列表\n>>> a\n[1, 'a', 'b', 'c', 2, 'x', 'a', 'b', 'c']\n>>> b = [\"a\",\"b\",\"c\"]\n>>> b[2:2] = [\"x\",\"y\"]\t\t# 注:索引为2处之前 增加列表\n>>> b\n['a', 'b', 'x', 'y', 'c']\n>>> b[2:4] = [\"x\",\"y\",\"z\"]\t# 注:索引2、3 的值 替换\n>>> b\n['a', 'b', 'x', 'y', 'z', 'c']\n>>> b[1:5] = \"12\"\t\t# 注:切出来后,再转换为列表。str类型转换为列表\n>>> b\t\t\t\t# 注:索引1、2、3、4 的值 替换 为 ‘1’‘2’\n['a', '1', '2', 'c']\n>>> b\n['a', '1', '2', 'c']\n>>> b[5:-3]\t\t\t\n[]\n>>> b[3:-3]\t\t\t# 注:获取不到\n[]\n>>> b[3:-3] = \"xy\"\t\t# 注:这个位置开始(start位置开始),替换成其他的list\n>>> b\t\t\t\t# 注:看 找出的元素是否为空\n['a', '1', '2', 'x', 'y', 'c']\n>>> c = [\"a\",\"b\",\"c\",\"d\",\"1\"]\n>>> c[1:4] = \"hello\"\t# 注:找出b c d 把bcd 替换成h e l l o\n>>> c\n['a', 'h', 'e', 'l', 'l', 'o', '1']\n>>> c = ['a', 'h', 'e', 'l', 'l', 'o', '1']\n>>> c[5:3]\t\t\t\t# 注:获取不到\n[]\n>>> c[5:3] = [\"x\",\"y\"]\t\t# 注:c[5:3]为空,在 o (下标5)处插入x y\n>>> c\n['a', 'h', 'e', 'l', 'l', 'x', 'y', 'o', '1']\n```\n\n\n\n#### 反转\n\n​\t反转列表-reverse 或 切片\n\n```python\n# 示例\n# 1.负切片 实现反转,输出的值反转\n>>> a = [1,2,3,4]\n>>> a[::-1]\t\t\t# 注:负切片\n[4, 3, 2, 1]\n>>> a\t\t\t\t# 注:a本身的值 没有反转\n[1, 2, 3, 4]\n# 2.reverse 字符串的反转\n>>> a\n[1, 2, 3, 4]\n>>> a.reverse()\n>>> a\t\t# 注:a本身的值 反转\n[4, 3, 2, 1]\n```\n\n\n\n#### 排序\n\n​\t列表排序-sort\n\n```python\n# 示例\n>>> a\n[4, 3, 2, 1]\n>>> a.sort()\n>>> a\n[1, 2, 3, 4]\t\t\t# 注:排序后 a本身的值发生改变\n# 反向排序\na.sort(reverse=True)\n>>> a\n[1, 2, 3, 4]\n>>> a.sort(reverse=True)\t# 注:反向排序,升序变成降序\n>>> a\n[4, 3, 2, 1]\t\t\t\t# 注:从大到小排序\n# 不支持int和str混合 的排序:\n>>> a = [\"a\",1,\"b\",2]\n>>> a.sort()\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: '<' not supported between instances of 'str' and 'int'\n>>> a = [\"a\",\"1\",\"b\",\"2\"]\n>>> a.sort()\n>>> a\n['1', '2', 'a', 'b']\n# 按 编码排序\n>>> a = [\"a\",\"1\",\"b\",\"2\",\"A\"]\n>>> a\n['a', '1', 'b', '2', 'A']\n```\n\n\n\n#### 统计\n\n​\tlen、count、index\n\n```python\n# 示例\n# len 总长度\n>>> a\n['a', '中', '序', '排', '文']\n>>> len(a)\n5\n>>> a.append([1,2,3])\n>>> len(a)\n6\n>>> a\n['a', '中', '序', '排', '文', [1, 2, 3]]\n>>> a.extend([1,2,3])\n>>> len(a)\n9\n# count统计元素出现的次数\n>>> a\n['a', '中', '序', '排', '文', [1, 2, 3], 1, 2, 3]\n>>> a.count(\"a\")\n1\n>>> a.count(1)\n1\n# index返回元素所在的索引位置\n>>> a = [\"x\",\"y\",\"x\",1]\n>>> a.count(\"x\")\n2\n>>> a.index(\"x\")\n0\n>>> a.index(\"z\")\t\t# 注:index通过元素找索引,如果没有会报错\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nValueError: 'z' is not in list\n```\n\n\n\n#### 遍历\n\n​\t遍历:依次取出对象中的每一项数据\n\n​\tlist是一个可迭代对象(iterable),可以直接用for遍历\n\n```python\n# 1.for i in a:\n>>> a\n['x', 'y', 'x', 1]\n>>> for i in a:\n... print(f\"item is --->{i}\")\n... \nitem is --->x\nitem is --->y\nitem is --->x\nitem is --->1\n\n# 2.enumerate()函数 \n# 特点:会返回元组,元组里包含每一个下标和值\n# 注:用1个i去遍历,获取的是元组\n>>> for i in enumerate(a):\n... print(f\"item is --->{i}\")\n... \nitem is --->(0, 'x')\nitem is --->(1, 'y')\nitem is --->(2, 'x')\nitem is --->(3, 1)\n# 用2个临时变量,获取enumerate(a)元组的返回\n>>> for i,j in enumerate(a):\n... print(f\"{i}-->{j}\")\n... \n0-->x\n1-->y\n2-->x\n3-->1\n```\n\n\n\n#### 判断成员关系\n\n​\t判断列表中是否有某个数据\n\n```python\n# 示例\n>>> lst = ['a','b','c','d']\n>>> print('a' in lst)\nTrue\n>>> print('x' in lst)\nFalse\n>>> s = 'a'\n>>> print(s, '在' if s in lst else '不在','列表里')\na 在 列表里\n```\n\n\n\n#### 类型转换\n\n​\t字符串(str)转列表(list)\n\n```python\n# 示例\n>>> str = 'abc 123'\n>>> list(str)\n['a', 'b', 'c', ' ', '1', '2', '3']\n```\n\n\n\n---\n\n## 二. 元组(tuple)\n\n```\n元组是处理一组有序项目的数据结构\n元组和字符串一样是不可变的,即你不能修改元组\n元组可以包含任何类型的对象:字符串、数字甚至其他列表\n适应场景:性别选择,数据库的查询结果\nExample:表示一个购物清单\n\tgoods=('牛奶'、'运动鞋'、'咖啡'、'手机'、'羊肉'、'葡萄'、'桔子')\n```\n\n\n\n```python\n# 示例\n# 元组通过圆括号中用逗号分割的项目定义\n>>> a = ()\n>>> type(a)\n<class 'tuple'>\n>>> a = (1)\t\t\t# 注:括号还可以代表集合\n>>> type(a)\n<class 'int'>\n# 元组中只有一个元素的时候,需要在元素后面加个,区分这个括号是表示结合还是表示元组\n>>> a = (1,)\t\t\t# 注:元组中只有1个元素时,需要加逗号(,)表示元组\n>>> type(a)\n<class 'tuple'>\n>>> a = tuple()\t\t# 注:定义空元组\n>>> type(a)\n<class 'tuple'>\n>>> a\n()\n# 元组可装入python的任何对象\n>>> a = (\"a\",1,1.2,True,print)\n>>> a\n('a', 1, 1.2, True, <built-in function print>)\n```\n\n\n\n### 元组基本操作\n\n#### 索引\n\n​\t通过下标访问列表中的元素,下标从0开始计数,可取出一个元素\n\n```python\n# 示例\n>>> a = (\"a\",1,1.2,True,print)\n>>> a[4]\n<built-in function print>\n>>> a[3]\nTrue\n# 下标不能越界,越界会报错\n>>> a = (\"a\",1,1.2,True,print)\n>>> a[5]\nTraceback (most recent call last):\nFile \"<stdin>\", line 1, in <module>\nIndexError: tuple index out of range\n```\n\n\n\n#### 切片\n\n```\n切片是通过下标访问元组中的元素,切片可以取出一个子元组\n起止区间:[start,end)\nstep:默认=>1\nstart:默认=>step为正时,start为0;step为负时,start为-1\nend:默认=>step为正时,end为列表结尾;step为负时,end为列表开始\n注意:三个值都为选填项\n```\n\n```python\n# 示例\n>>> a = (\"a\",1,1.2,True,print)\n>>> a[1:3]\n(1, 1.2)\n```\n\n\n\n#### 不可变性\n\n```python\n# 示例\n>>> a\n('a', 1, 1.2, True, <built-in function print>)\n>>> a[0] = 1\t\t\t\t\t# 注:报错\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: 'tuple' object does not support item assignment\n>>> tu1 = (1,2)\n>>> tu2 = (3,4)\n>>> tu3 = tu1 + tu2\n>>> tu3\n(1, 2, 3, 4)\n```\n\n\n\n#### 统计\n\n```python\n# 示例\n>>> a = ('a','b','c')\n>>> print(len(a))\n3\n```\n\n\n\n#### 遍历\n\n```python\n# 示例\n>>> a = [1,2,3]\n>>> for i in enumerate(a):\n... print(i)\n... \n(0, 1)\t\t# 注:返回值 是 元组\n(1, 2)\n(2, 3)\n>>> for i,j in enumerate(a):\n... print(f\"{i}---{j}\")\t\t# 注:用两个参数 来接收 返回值\n... \n0---1\n1---2\n2---3\n```\n\n\n\n#### 成员关系\n\n​\t成员关系: in , not in\n\n```python\n# 示例\n>>> a = (\"a\",\"b\",\"c\")\n>>> \"a\" in a\nTrue\n>>> \"d\" not in a\nTrue\n```\n\n\n\n## 三. 字典(dict)\n\n```\n字典是Python中一个键值映射的数据结构\n字典是无序的\n字典是可变对象\nkey必须是唯一的,so天生去重\nexample:\n\tsinger={key1:value,key2:value}\n\tsinger={\"李圣杰\":'痴心绝对','张韶涵':'阿刁','汪峰':'普通迪斯高'}\n```\n\n```\n字典的定义\n\t字典的key必须是可hash对象\n\tpython中所有字符串、数字、元组、布尔值、None都是可hash对象\n\t字典的value可以是任何值\n```\n\n\n\n```python\n# 示例\n# 定义空字典\n# 方法1:\n>>> a = {}\t\t# 注:定义空字典\n# 方法2:\n>>> b = dict()\t# 注:定义空字典,工厂函数\n>>> type(a)\n<class 'dict'>\n>>> type(b)\n<class 'dict'>\n\n# 示例\n>>> c = [('root','123456'),('admin','admin')]\n>>> d = dict(c)\t\t# 注:列表转换成字典 工厂函数\n>>> d\n{'root': '123456', 'admin': 'admin'}\n>>> e = [1,2,3]\n>>> e\n[1, 2, 3]\n>>> dict(e)\t\t\t# 注:转换的对象要有 键值映射 的格式\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: cannot convert dictionary update sequence element #0 to a sequence\n```\n\n\n\n### 字典基本操作\n\n#### 取值\n\n```\n用法1:dicts[key]=>当key不存在时,会引了KeyError错误\n用法2:dicts.get(key,default)=>当key不存在时,返回default值\n```\n\n```python\n# 示例\n>>> a = {\"a\":4,\"b\":2}\n>>> a['a']=3\t\t\t# 注:修改key=”a”的 value 值\n>>> a\n{'a': 3, 'b': 2}\n>>> a['c']=4\t\t\t# 注:增加键值对\n>>> a\n{'a': 3, 'b': 2, 'c': 4}\n>>> a['c']\t\t\t# 注:取值\n4\n>>> a['d']\t\t\t# 注:key不存在,报错\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nKeyError: 'd'\n# 推荐使用get\n>>> a\n{'a': 3, 'b': 2, 'c': 4}\n>>> a.get('d')\t\t# 注:不报错\n>>> c = a.get('d')\n>>> print(c)\nNone\t\t\t\t\t# 注:默认值没有设置\n```\n\n\n\n#### 增加/修改\n\n```\n用法:dicts[key]=value\n\t当key不存在时,表示增加一个键值对\n\t当key存在时,表示修改对应的value值\n```\n\n```python\n# 示例:修改\n>>> a\n{'a': 3, 'b': 2, 'c': 4}\n>>> a['a'] = 5\n>>> a\n{'a': 5, 'b': 2, 'c': 4}\n# 示例:新增\n>>> a['d'] = False\n>>> a\n{'a': 5, 'b': 2, 'c': 4, 'd': False}\n```\n\n\n\n#### 删除\n\n```\n用法1:dicts.pop(key)\n用法2:dicts.popitem()\n```\n\n```python\n# 示例:dicts.pop(key)\n>>> a = {'a':5,'b':2,'c':4,'d':False}\n>>> a.pop('a')\t\t# 注:删除 key=‘a’ 的元素\n5\t\t\t\t\t# 注:pop有返回值\n>>> c = a.pop('b')\t\t# 注:获取返回值\n>>> c\n2\n>>> a\n{'c': 4, 'd': False}\n# 示例:dicts.popitem()\n# python3里面删除的是最后一个\n>>> a = {\"x\":1,\"y\":2,\"z\":3}\n>>> a.popitem()\n('z', 3)\n>>> a.popitem()\n('y', 2)\n>>> a.popitem()\n('x', 1)\t\t\t\n```\n\n\n\n#### 合并\n\n```\n用法1:dict1.update(dict2)=>将dict2合并到dict1\n用法2:dict(dict1,**dict2)=>将dict1与dict2合并生成一个新字典\n```\n\n```python\n# 示例:dict1.update(dict2)\n>>> a = {\"x\":1,\"y\":3}\n>>> b = {\"q\":2,\"w\":3}\n>>> a.update(b)\t# 注:a自带的属性\n>>> a\n{'x': 1, 'y': 3, 'q': 2, 'w': 3}\n>>> b\n{'q': 2, 'w': 3}\n# 示例:dict(dict1, **dict2)\n>>> a = {\"x\":1,\"y\":3}\n>>> b = {\"q\":2,\"w\":3}\n>>> dict(a,**b)\t# 注:工厂函数,返回一个字典 a和b的合并\n{'x': 1, 'y': 3, 'q': 2, 'w': 3}\n>>> a\t# 注:a本身没有改变\n{'x': 1, 'y': 3}\n>>> dict()\n{}\n>>> c = dict(a,**b)\n>>> c\n{'x': 1, 'y': 3, 'q': 2, 'w': 3}\n```\n\n\n\n#### 成员关系\n\n```\n用法:\n\titem in dicts\n\titem not in dicts\n```\n\n```python\n# 示例\n>>> a = {\"x\":1,\"y\":2,\"z\":3}\n>>> a\n{'x': 1, 'y': 2, 'z': 3}\n>>> 'x' in a\t\t# 注:in 默认 对比的是key值\nTrue\n>>> 2 in a\nFalse\n>>> 2 in a.values()\t\t# 注:a.values()对比的是value值\nTrue\n```\n\n\n\n#### 遍历\n\n​\t默认遍历的是 key\n\n```python\n# 示例\n>>> a\n{'x': 1, 'y': 2, 'z': 3}\n\n# 遍历key值\n>>> for i in a:\n... print(i)\n... \nx # 注:遍历key值\ny\nz\n\n# 遍历value值\n>>> for i in a.values():\n... print(i)\n... \n1 # 注:遍历value值\n2\n3\n\n# 既想获得key 也想获得value\n# items返回的是元组\n# 方式1\n>>> for i in a.items():\n... print(i)\n... \n('x', 1)\n('y', 2)\n('z', 3)\n# 方式2\n>>> for i,j in a.items():\t# 注:2个参数获取返回值key,value\n... print(f\"key is {i}, value is {j}\")\n... \nkey is x, value is 1\nkey is y, value is 2\nkey is z, value is 3\n# 方式3\n>>> for i in a.items():\n... print(f\"key is {i[0]}, value is {i[1]}\")\t# 注:索引获取参数\n... \nkey is x, value is 1\nkey is y, value is 2\nkey is z, value is 3\n```\n\n\n\n---\n\n## 四. 集合(set)\n\n```\n集合是一个无序的,不重复的数据组合\n集合是一个只含有key的字典\n```\n\n```\n集合的作用\n\t去重:把一个列表变成集合,就自动去重了\n\t关系测试:测试两组数据之前的交集、差集、并集等关系\n\texample:\n\t\tsinger={\"李圣杰\",'张韶涵','汪峰'}\n```\n\n```\n集合的定义\n\t集合通过花括号中,而各个元素用逗号分割\n\t集合元素必须是可hash对象,跟字典一样\n\tset和dict的唯一区别仅在于没有存储对应的value\n```\n\n\n\n```python\n# 示例\n# 定义空集合(2种方式)\n>>> a = {1,2,3}\t# 注:第1种方式\n>>> type(a)\n<class 'set'>\n>>> a = set()\t\t# 注:第2种方式\n>>> a\nset()\n>>> type(a)\n<class 'set'>\n```\n\n\n\n### 集合基本操作\n\n#### 添加\n\n```\n用法:s.add(item)=>添加一项\n用法:s.update(someitems)=>添加多项\n```\n\n```python\n# 示例\n>>> s = {1,2,3}\n>>> s.add(4)\n>>> s\n{1, 2, 3, 4}\n>>> s.update(\"str\")\t# 注:str被扩展进来,是一个一个被扩展进来的\n>>> s\n{1, 2, 3, 4, 't', 'r', 's'}\n>>> s.update({\"x\":1,\"y\":2})\t# 注:字典 扩展的是 key值\n>>> s\n{1, 2, 3, 4, 'x', 't', 'y', 'r', 's'}\n```\n\n\n\n#### 移除\n\n```\n用法1:s.remove(item)=>移除一项(item不存在会出错KeyError)\n用法2:s.discard(item)=>移除一项(item不存在则什么也不做)\n```\n\n```python\n# 示例\n# remove\n>>> s\n{1, 2, 3, 4, 'x', 't', 'y', 'r', 's'}\n>>> s.remove('r')\n>>> s\n{1, 2, 3, 4, 'x', 't', 'y', 's'}\n>>> s.remove('p')\t# 注:“p”不存在,报错\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nKeyError: 'p'\n# discard\n>>> s\n{1, 2, 3, 4, 'x', 't', 'y', 's'}\n>>> s.discard('o')\t# 注:不存在 不报错 什么也不做\n>>> s.discard('x')\n>>> s\n{1, 2, 3, 4, 't', 'y', 's'}\n# pop\n>>> a={\"a\",\"b\",\"c\"}\n>>> a.pop()\n'c'\n>>> a.pop()\n'a'\n>>> a.pop()\n'b'\n```\n\n\n\n#### 集合操作\n\n```\n并集:t和s的并集,返回一个新的set包含s和t中的每一个元素\n交集:t和s的交集,返回一个新的set包含s和t中的公共元素\n差集:返回一个新的set包含s中有但是t中没有的元素\n对称差集:返回一个新的set包含s和t中不重复的元素(在t或s中,但不会同时出现在二者中)\n```\n\n```python\n# 示例\n# 创建集合\n>>> set('hello')\n{'e', 'o', 'l', 'h'}\n\n# 并集\n>>> s1 = {1,2,3}\n>>> s2 = {2,3,4}\n>>> s1 | s2\n{1, 2, 3, 4}\n>>> s1.union(s2)\n{1, 2, 3, 4}\n\n# 交集\n>>> s1 = {1,2,3}\n>>> s2 = {2,3,4}\n>>> s1 & s2\n{2, 3}\n>>> s1.intersection(s2)\n{2, 3}\n\n# 差集\n>>> s1 = {1,2,3}\n>>> s2 = {2,3,4}\n>>> s1 - s2\n{1}\n# 注:s1里面有的,s2里面没有的\n>>> s2 - s1\n{4}\n\n# 对称差集\n>>> s1 = {1,2,3}\n>>> s2 = {2,3,4}\n>>> s1 ^ s2\n{1, 4}\n# 注:除了交集 的部分\n```\n\n\n\n---\n\n","tags":["Python","数据类型"],"categories":["Python"]},{"title":"02_Python-CSDN_数据类型1","url":"/posts/4979.html","content":"## 基本类型\n\n### Python数字\n\n在Python中有3种类型的数——整数、浮点数和复数\n\n| 数字类型 | 示例 | 说明 |\n| -------- | ----------------------------------------------------- | ------------------------------------------------------------ |\n| 整数 | -2, 12389 <br/> 999999L, ∞ <br/> 0b1110, 0xabf, 0o126 | python2中区分整型、长整型,长整型的整数可以 无穷大 <br/> python3中统称为整型 <br/> 整型的二进制,十六进制,八进制表示法 |\n| 浮点数 | -3.23, -52.3E-4 | 在 python 中可以用科学计数法表示浮点数 |\n| 复数 | -5+4j,2.3-4.6j | 其中-5,4为实数,j为虚数 |\n\n1. ==int==\n\n python3 中只有 int(可存超长数据)\n\n | 整型进制表示法 | | |\n | -------------- | ------------------------------ | ------------------------ |\n | 进制 | 表示方法 | 示例 |\n | 二进制 | 以0b开头,只能包含0、1,逢2进1 | 0b11,0b12(错误的表示) |\n | 八进制 | 以0o开头,能包含0-7,逢8进1 | 0o11 |\n | 十六进制 | 以0x开头,能包含0-F,逢16进1 | 0x11 |\n | 十进制 | 直接由数字0-9组成,逢10进1 | 11 |\n\n \n\n 整型进制操作\n\n ```\n 进制转换-bin:任意进制转2进制,接收一个int,返回一个str\n 进制转换-oct:任意进制转8进制,接收一个int,返回一个str\n 进制转换-hex:任意进制转16进制,接收一个int,返回一个str\n 进制转换-int:任意进制转10进制,接收一个int/str,返回一个int\n ```\n\n ```python\n # 示例\n >>> bin(10)\t\t# 10进制转2进制\n '0b1010'\n >>> bin(0o71)\t# 8进制转2进制\n '0b111001'\n >>> bin(0x11)\t# 16进制转2进制\n '0b10001'\n >>> int(\"10\")\n 10\t\t\t\t# str 转换成 int\n >>> int(\"0o11\",base=8)\t# 8进制的字符串,要指定一下\n 9\n >>> int(0o11)\t\t# 8进制整型 直接转换\n 9\n ```\n\n \n\n2. ==float==\n\n float(浮点型):浮点数即带有小数点的数字\n\n ​\t\tfloat由整数位,小数点,小数位组成,也可以用科学计数法表示,例如-3.23,-52.3E-4,6.23E12\n\n ​\t\tfloat是不精确的\n\n **decimal模块**\n\n ​\t\tDecimal类型数据是精确的小数,可以传递给Decimal整型或者字符串参数\n\n \n\n 官方文档\t\n\n ​\t\tfloat\thttps://docs.python.org/3/library/functions.html#float\n\n ​\t\tdecimal\thttps://docs.python.org/3/library/decimal.html?highlight=decimal\n\n```python\n# 示例:浮点型数据float是不精确的\n>>> i = 1\n>>> i = i - 0.1\n>>> i\n0.9\n>>> i = i - 0.1\n>>> i\n0.8\n>>> i = i - 0.1\n>>> i\n0.7000000000000001\n>>> i = i - 0.1\n>>> i\n0.6000000000000001\n```\n\n\n\n```python\n# 示例:Decimal类型数据是精确的小数,可以传递给Decimal整型或者字符串参数\n>>> from decimal import getcontext, Decimal, Context\n>>> mydec = Decimal.from_float(12.222)\n>>> mydec\nDecimal('12.2219999999999995310417943983338773250579833984375')\n>>> mydec = Decimal(0.9)\n>>> mydec\nDecimal('0.90000000000000002220446049250313080847263336181640625')\n>>> mydec = Decimal(\"3.14\")\n>>> mydec\nDecimal('3.14')\n```\n\n\n\n3. ==complex==\n\n 复数complex:复数就是实数和虚数的统称\n\n 在数学中的表示:复数的基本形式是a+bi,其中a,b是实数,a称为实部,bi称为虚部,i是虚数单位\n\n complex的组成:复数由实数部分和虚数部分组成,一般形式为x+yj,其中的x是复数的实数部分,y是复数的虚数部分,这里的x和y都是实数\n\n ```python\n # 示例\n >>> a = 5 + 4j\n >>> a.real\n 5.0\t\t# 存放的是浮点型\n >>> a.imag\n 4.0\n ```\n\n\n\n### Python字符串\n\n字符串:字符串是字符的序列\n\n表示方法:单引号(');双引号(“);三引号('''或”””);原样输出\n\n| 符号 | 说明 | 示例 |\n| ---------------- | ---------------------------------------------------------- | ----------------------------------------------------------- |\n| 单引(') | 可引用包含双引号的字符串 | 'say“hello”' |\n| 双引号(“) | 可引用包含单引号的字符串 | “What'syourname?” |\n| 三号引('''或”””) | 可引用一个多行的字符串,在三引号中可自由使用单引号和双引号 | '''<br/>这是多行字符<br/>里面可包含单引号'和双引号”<br/>''' |\n| 特殊标记(r) | 不使得转义字符,将字符原样输出 | r”hello\\tworld!” |\n\n\n\n```python\n# 示例\n>>> a = 'test'\n>>> b = \"test\"\n>>> a\n'test'\n>>> b\n'test'\n>>> a = '''\n... t\n... e\n... s\n... t'''\n>>> a\n'\\nt\\ne\\ns\\nt'\n>>> print(a)\n\nt\ne\ns\nt\n# print(a)按照规定的格式打印输出\n>>> c = \"t1\\nt2\"\n>>> c\n't1\\nt2'\n>>> print(c)\nt1\nt2\n>>> c = 't1\\nt2'\n>>> c\n't1\\nt2'\n>>> print(c)\nt1\nt2\n>>> c = r\"t1\\nt2\"\n>>> print(c)\nt1\\nt2\n```\n\n\n\n- ==转义字符==\n\n ​\t转义字符是一种特殊的字符常量。转义字符以反斜线\"\\\"开头,后跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。\n\n| 转义字符 | 描述 | 转义字符 | 描述 | 转义字符 | 描述 |\n| ------------ | ---------- | -------- | ---------- | -------- | -------------------------------------------- |\n| \\\\(在行尾时) | 续行符 | \\n | 换行 | \\oyy | 八进制数,yy代表的字符,例如:\\o12代表换行 |\n| \\\\\\ | 反斜杠符号 | \\v | 纵向制表符 | \\xyy | 十六进制数,yy代表的字符,例如:\\x0a代表换行 |\n| \\\\' | 单引号 | \\t | 横向制表符 | \\other | 其它的字符以普通格式输出 |\n| \\\\\" | 双引号 | \\r | 回车 | \\b | 退格(Backspace) |\n| \\a | 响铃 | \\f | 换页 | \\e | 转义 |\n| \\000 | 空 | | | | |\n\n\n\n1. ==字符串取值==\n\n ​\t下标取值法(注意:下标从0开始)\n\n ​\t切片取值法\n\n```python\n# 示例\n>>> a = \"test\"\n>>> a[0]\n't'\n>>> a = \"test\"\n>>> a[0:2]\t# 取下标为0~2的数据。包括0,不包括2\n'te'\t\t# 前面包括,后面不包括\n```\n\n\n\n字符串的不可变的序列\n\n一旦创造了一个字符串,就不能再改变它\n\n```python\n# 示例\n>>> a = \"hello world\"\n>>> a[4] = \"1\"\nTraceback (most recent call last):\n File \"<stdin>\", line 1, in <module>\nTypeError: 'str' object does not support item assignment\n>>> id(a)\n140585442705648\n```\n\n\n\n级连字符串\n\n如果把两个字符串相邻放着,它们会被python自动级连\n\n```python\n# 示例\n>>> info = \"chen\"\"peng\"\n>>> info\n'chenpeng'\n```\n\n\n\n2. ==字符串常用方法==\n 1. ==字符串常用方法——判断系列(True/False)==\n\n| 方法 | 功能 |\n| ---- | ---- |\n|str.isdigit() |字符串中是否只包含数字|\n|str.isnumeric() |字符串中是否只包含数字(包括中文一到九等)|\n|str.isalnum() |字符串中是否只包含字母或数字|\n|str.istitle() |字符串中是否每个单词首字母大写,其他字母小写|\n|str.isalpha() |字符串中是否只包含字母(汉字会算作字母)|\n|str.isupper() |字符串中是否全为大写|\n|str.isidentifier() |字符串是否为合法标识符|\n|str.isprintable() |字符串是否为可打印字符|\n|str.islower() |字符串中是否全为小写|\n|str.isspace() |字符串中是否只包含空格(tab也算空格)|\n|str.startswith(prefix[,start[,end]]) |字符串是否以某字符串开始,可以通过start和stop参数设置搜索范围|\n|str.endswith(suffix[,start[,end]]) |字符串是否以某个字符串结束,可以通过start和stop参数设置搜索范围|\n\n\n\n```python\n# 示例\nmy_str = \"This Is TEST!\"\nmy_title = \"This is My Title\"\nmy_num = \"123\"\nmy_num2 = \"一二三四\"\nmy_str2 = \"hello\"\nmy_str3 = \"hello123\"\n\n# 判断系列\nprint(\"判断数字\", my_num.isdigit()) # 字符串中是否只包含数字\nprint(\"判断数字\", my_num.isnumeric()) # 字符串中是否只包含数字(包括中文一到九等)\nprint(\"判断数字\", my_num2.isdigit()) # 只能判断阿拉伯数字\nprint(\"判断数字\", my_num2.isnumeric()) # 可以判断中文数字\n\nprint(\"判断字母:\", my_str.isalpha()) # 有空格/“!”会报错 # 判断字母(汉字会算作字母)\nprint(\"判断字母数字:\", my_str3.isalnum()) # 有空格会报错 # 判断字母数字\n\nprint(\"判断字符串是否以This开始\", my_title.startswith(\"This\"))\nprint(\"判断字符串是否以This结束\", my_title.endswith(\"This\"))\n```\n\n​\t\t\n\n​\t\t\t2. ==字符串常用方法——查找统计类==\n\n| 方法 | 功能 |\n| ----------- | -------------- |\n| len(string) | 统计字符串长度 |\n|str.index(sub[,start[,end]]) |显示substring在字符串中第一次出现的下标位置,没有会报错|\n|str.find(sub[,start[,end]]) |查找substring,找到返回其起始位置,找不到返回-1|\n\n\n\n```python\n# 示例\n# 查找统计类\nmy_str = \"This Is TEST!\"\n\nprint(\"长度:\", len(my_str))\t\t# 空格、!占长度\nprint(\"i 第一次出现的位置\", my_str.index(\"i\"))\t# 字符串“i”第一次出现的位置\nprint(\"i 第一次出现的位置\", my_str.find(\"i\"))\t# 字符串“i”第一次出现的位置,找不到返回-1\nprint(\"i 出现的次数\", my_str.count(\"i\"))\n```\n\n\n\n​\t\t3. ==字符串常用方法——字符串转换类(返回一个新对象)==\n\n| 方法 | 功能 |\n| ---- | ---- |\n|str.upper() |将字符串转换为大写|\n|str.lower() |将字符串转换为小写|\n|str.title() |将字符串中的单词首字母大写,其他字母小写|\n|str.split('sep') |指定'sep'作为分隔符将字符串切割成列表,分隔符可以是任意字符(默认是空格)|\n|'str'.join(list) |将列表用str拼接成一个大字符串|\n|str.strip([string]) |去除字符串中首尾的字符串,不带参数默认去除空格|\n|str.zfill(number) |返回指定长度的字符串,原字符串右对齐,前面填充0|\n|str.replace('old','new'[,count]) |用新的字符替换老字符,还可以指定替换的个数,默认全部替换|\n|str.capitalize() |句子首字母大写|\n|str.center(width[,fillchar])str.ljust(width[,fillchar])str.rjust(width[,fillchar]) |返回一个原字符串居中(靠左/靠右)对齐,width为总长度,两边用一个字符fillchar填充,如果指定的长度小于原字符串的长度则返回原字符串|\n|str.expandtabs(number) |将\\t转换成number个空格|\n\n\n\n```python\n# 示例\n# 字符串转换类\nmsg = \" hEllo World Chen \"\n\nprint(\"大写\", msg.upper())\nprint(\"小写\", msg.lower())\nprint(\"标题\", msg.title())\n\nmsg2 = \"root:x:0:0:root:/root:/bin/bash\"\nprint(\"切割:\", msg2.split(\":\"))\nmsg3 = msg2.split(\":\")\nprint(\"拼接:\", \"#\".join(msg3))\nprint(\"去除首尾空白\", msg.strip(), \"######\")\nprint(\"去除root首尾:\", msg2.strip(\"root\"))\nprint(\"字符串填充:\", msg.zfill(40))\nprint(\"字符串替换\", msg2.replace(\":\", \"%\"))\nprint(\"整个字符串首字母大写\", msg.capitalize())\nmsg4 = \"xxx\"\nprint(msg4.center(50, ' '))\nprint(msg4.center(50, '-'))\nprint(msg4.ljust(50, \"-\"))\nprint(msg4.rjust(50, \"-\"))\n```\n\n\n\n3. ==字符串拼接==\n\n```python\n# 示例\n# 字符串拼接(+)\n>>> a = 'I' + 'Love' + 'Python'\n>>> print(a)\nILovePython\n\n#字符串拼接(join)\n>>> a = ['I', 'Love', 'Python']\n>>> print(''.join(a))\nILovePython\n```\n\n\n\n```\n+ 与 join的效率问题\n\t一般来说,+ 拼接 效率比 join 拼接低\n\t+拼接,每一次出现都会在内存中开辟1个新的空间,所有效率低,比较耗时\n\tjoin一次性拼接成1个大的字符串\n```\n\n\n\n4. ==字符串格式化==\n\n```\n字符串格式化(%)\n基本格式\n\t%[(name)][flags][width].[precision]typecode\n\t-(name):命名\n\t-flags:+,-,''或0。+表示右对齐;-表示左对齐;''为一个空格,表示在正数的左侧填充一个空格,从而与负数对齐,0表示使用0填充\n\t-width表示显示宽度\n\t-precision表示小数点后精度\n```\n\n```python\n# 示例\n# %格式化 \nname = \"wen\"\nage = 18\nprint(\"姓名: %s, 年龄: %s\"%(name, age))\nprint(\"姓名: %s, 年龄: %s\"%(age, \"wen2\"))\n```\n\n\n\n```\n字符串格式化(format)\n\t{变量:[填充字符][对齐方式 <^>][宽度][格式]}\n```\n\n```python\n# 示例\n# format 格式化\nname = \"wen\"\nage = 18\nprint(\"format01 --> 姓名:{}, 年龄:{}\".format(name, age))\nprint(\"format01 --> 姓名:{}, 年龄:{}\".format(age, name))\nprint(\"format02 --> 姓名: {1}, 年龄:{0}\".format(name, age))\nprint(\"format02 --> 姓名: {1}, 年龄:{0}\".format(age, name))\nprint(\"format03 --> 姓名:{name1}, 年龄:{age1}\".format(name1 = name, age1 = age))\nprint(\"format01 --> {0:*>10}\".format(10,20)) # 注:0 第1个变量\nprint(\"format01 --> {1:*>10}\".format(10,20)) # 注:1 第2个变量\nprint(\"format01 --> {1:*<10}\".format(10,20)) # 注::执行 ; * 填充字符\nprint(\"format01 --> {1:*^10}\".format(10,20)) # 注:^ 居中 ; 10 填充宽度10字符\nprint(\"format02 --> {0:.2f}\".format(1/3,5.333))\nprint(\"format02 --> {1:06.2f}\".format(1/3,5.333))\n# 二进制\nprint(\"format02 --> {0:b}\".format(10))\n# 八进制\t\t\t\t注:16进制是”{0:x}”.format(10)\nprint(\"format02 --> {0:o}\".format(10))\n# 千分位格式化\nprint(\"format02 --> {0:,}\".format(123456789))\n```\n\n\n\n```\n字符串格式化-f\n```\n\n```python\n# 示例\n# f标志符 格式化\na = \"I\"\nb = \"Love\"\nc = \"Python\"\nprint(f\"{a}{b}{c}\")\n#结果 ILovePython\nprint(\"{a}{b}{c}\".format(a = a, b = b, c = c))\t\t# 注:效果等同\n#结果 ILovePython\nprint(f\"{a}{b}{c:a^10}\")\t# 注:对字符串c的操作:用“a”填充宽度10,居中\n#结果 ILoveaaPythonaa\nprint(\"{a}{b}{c:a^10}\".format(a = a, b = b, c = c)) # 注:效果等同\n#结果 ILoveaaPythonaa\n```\n\n\n\n### Python数字-Booleans\n\n```\n布尔值(Booleans)是一个逻辑值\n取值范围只有True和False(真和假)\n布尔值为假:\n\t'',0,0.0,(),[],{},None,False\n\tNone是一个特殊的常量,表示一种特殊的数据类型(NoneType)\n值布尔值为真:\n\t除了为假的,其他的都为真\n```\n\n\n\n```python\n# 示例\n* 布尔值可以相互加减\n>>> a = 1\n>>> b = 2\n>>> print(a == b)\nFalse\n>>> c = (a == b) + (a == d)\t\t# 注:c = 0 +1\n>>> c\n1\n# 布尔值排序\n>>> lst=[(a==d),(a==b)] # 注:(a==d)为真,(a==b)为假\n>>> sorted(lst)\n[False, True] # 注:因为默认情况下 0为假,1为真\n```\n\n\n\n### Others\n\n```\n○常量\n\t常量是指一旦初始化后就不能修改的固定值\n\t注意:在Python中表示一个常量通常用大写(约定俗成,非强制)表示,如:PI=3.1415926\n○NoneType\n\tNone表示什么也没有\n```\n\n\n\n---\n\n","tags":["Python","数据类型"],"categories":["Python"]},{"title":"01_Python-CSDN_环境搭建","url":"/posts/16756.html","content":"## ① Python解释器 安装\n\n1. Windows平台\n\n 下载地址:https://www.python.org/ftp/python/3.9.5/python-3.9.5-amd64.exe(3.9版本)\n\n 安装python39\n\n ​\texe安装:注意修改目录、环境变量\n\n ​\t安装路径:C:/python39(安装路径可以自定,但注意不要包含中文或空格等特殊字符)\n\n ​\t验证:按键盘“win+R”,输入“cmd” , 在命令行测试\n\n ​\tC:\\Users\\cPenadm>==python -V==\n\n ​\tPython 3.9.5\n\n \n\n2. Linux平台\n\n 自带python(不同版本的操作系统带的python版本不一样)\n\n centos-yum安装(3.6版本)\n\n ```bash\n yum install epel-release\n yum install python36\n yum install python36-devel\n ```\n\n\n\n## ② pip工具 设置\n\npip是Python 包管理工具,该工具提供了对Python包的查找、下载、安装、卸载的功能。\n\n配置国内源\n\t解决安装慢的问题\n\n1. 方法 1\n\n 升级pip到10.0以上版本\n\n ```bash\n pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple\n ```\n\n\n\n2. 方法 2\n\n 1. Windows平台\n\n - 创建目录及文件 ==C:\\Users\\<你的用户名>\\pip\\pip.ini==\n\n - pip.ini文件内容如下:修改成阿里的源,其他国内源也可以\n\n ```\n [global]\n index-url=http://mirrors.aliyun.com/pypi/simple/\n [install]\n trusted-host=mirrors.aliyun.com\n ```\n\n 2. Linux平台\n\n ```bash\n mkdir ~/.pip\n vim ~/.pip/pip.conf\n #输入以下内容\n [global]\n index-url = https://pypi.tuna.tsinghua.edu.cn/simple\n ```\n\n\n\n## ③ PyCharm 安装\n\nPyCharm是由JetBrains打造的一款PythonIDE,支持macOS、Windows、Linux系统\n\n集成开发环境(IDE,IntegratedDevelopmentEnviroment)是用于提供程序开发环境的应用程序,一般包括代码编辑器、编译器、调试器和图形用户界面等工具\n\n优点:界面友好、调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版本控制等\n\n\n\n1. 下载地址\n\n 官网:http://www.jetbrains.com/pycharm/\n \n2. 安装\n\n 社区版:免费使用,不用激活\n\n 专业版:功能更丰富,需要激活\n \n3. 激活\n\n 打开pycharm,执行:Help-Register\n\n ![image-20220305214732025](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203052147100.png)\n \n4. 配置Python解释器\n\n 参考:https://zhuanlan.zhihu.com/p/40716785\n\n ![image-20220305214846212](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203052148253.png)\n\n\n\n---\n\n","tags":["Python","环境"],"categories":["Python"]},{"title":"04_Django-模板变量/标签/过滤器/继承-url反向解析","url":"/posts/65154.html","content":"[视频链接:https://www.bilibili.com/video/BV1vK4y1o7jH](https://www.bilibili.com/video/BV1vK4y1o7jH)\n\n\n## 一. 模板层 - 变量和标签\n\n### 变量\n\n- 视图函数中可以将Python变量封装到 **字典** 中传递到模板上\n\n样例:\n\n```python\ndef xxx_view(request):\n dic = {\n \"变量1\": \"值1\",\n \"变量2\": \"值2\",\n }\n return render(request, 'xxx.html', dic)\n```\n\n\n\n- 能传递到模板中的 **数据类型**\n\n```\nstr-字符串\tint-整型\nlist-数组\ttuple-元组\ndict-字典\tfunc-方法\nobj-类实例化的对象\n```\n\n\n\n- 在模板中使用变量语法\n\n```\n- {{ 变量名 }}\n- {{ 变量名.index }}\n- {{ 变量名.key }}\n- {{ 对象.方法 }}\n- {{ 函数名 }}\n```\n\n\n\n- 演示:\n\n```\nhttp://127.0.0.1:8000/test_html_param\n```\n\n![image-20220216013835514](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160138597.png)\n\n```python\n# mysite1/mysite1/urls.py\nurlpatterns = [\n ...\n path('test_html', views.test_html)\n]\n\n\n# mysite1/mysite1/views.py\ndef test_html_param(request):\n dic = {}\n dic['int'] = 88\n dic['str'] = 'peng'\n dic['lst'] = ['Tom', 'Jack', 'Lily']\n dic['dict'] = {'a':9, 'b':8}\n dic['func'] = say_hi\n dic['class_obj'] = Dog()\n dic['script'] = '<script>alert(1111)</script>'\n return render(request, 'test_html_param.html', dic)\n\ndef say_hi():\n return 'hahaha'\n\nclass Dog:\n def say(self):\n return 'wangwang'\n\n\n# mysite1/templates/test_html_param.html\n<h3>int 是 {{ int|add:\"2\" }}</h3>\n<h3>str 是 {{ str|upper }}</h3>\n<h3>lst 是 {{ lst }}</h3>\n<h3>lst 是 {{ lst.0 }}</h3>\n<h3>dict 是 {{ dict }}</h3>\n<h3>dict['a'] 是 {{ dict.a }}</h3>\n<h3>function 是 {{ func }}</h3>\n<h3>class_obj 是 {{ class_obj.say }}</h3>\n<h3>script 是 {{ script|safe }}</h3>\n```\n\n\n\n***\n\n### 标签\n\n**模板标签**\n\n- 作用:将一些服务器端的功能嵌入到模板中,例如流程控制等\n- 标签语法:\n\n```jinja2\n{% 标签 %}\n...\n{% 结束标签 %}\n```\n\n\n\n#### if标签\n\n- **语法**:\n\n```jinja2\n{% if 条件表达式1 %}\n...\n{% elif 条件表达式2 %}\n...\n{% elif 条件表达式3 %}\n...\n{% else %}\n...\n{% endif %}\t- 需要有结束标签\n```\n\n\n\n- **注意**:\n\n1. if条件表达式里可以用的运算符 ==, !=, <, > , <=, >=, in, not in, is, is not, not、and、or\n2. 在if标记中使用实际括号是无效的语法。如果需要它们指示优先级,则应使用嵌套的if标记。\n\n官方文档:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#if\n\n\n\n- **演示:**\n\n```\nhttp://127.0.0.1:8000/test_if_for\n```\n\n![image-20220216020405259](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160204292.png)\n\n```python\n# mysite1/mysite1/urls.py\nurlpatterns = [\n ...\n path('test_if_for', views.test_if_for),\n]\n\n# mysite1/mysite1/views.py\ndef test_if_for(request):\n dic = {}\n dic['x'] = 20\n dic['lst'] = ['Tom', 'Jack', 'Lily']\n return render(request, 'test_if_for.html', dic)\n\n# mysite1/templates/test_if_for.html\n{% if x > 10 %}\n今天天气很好\n{% else %}\n今天天气非常好\n{% endif %}\n\n<br>\n\n{% for name in lst %}\n {% if forloop.first %} &&&&& {% endif %}\n <p> {{ forloop.counter }} {{ name }}</p>\n {% if forloop.last %} ===== {% endif %}\n{% empty %}\n 当前没数据\n{% endfor %}\n```\n\n\n\n- **模板标签 - if标签 - 练习**\n\n 写一个简单的计算器页面,能够在服务端进行简单加减乘除计算(需记录用户上次填写状态、下拉列表选择状态)\n\n ![image-20220216020922893](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160209924.png)\n\n - 前端参考代码:\n\n ![image-20220216021536197](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160215265.png)\n\n \n\n - **演示:**\n\n ```\n http://127.0.0.1:8000/mycal\n ```\n\n ![image-20220216023528956](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160235992.png)\n\n ```python\n # mysite1/mysite1/urls.py\n urlpatterns = [\n ...\n path('mycal', views.test_mycal),\n ]\n \n \n # mysite1/mysite1/views.py\n def test_mycal(request):\n if request.method == 'GET':\n return render(request, 'mycal.html')\n elif request.method == 'POST':\n #处理计算\n x = int(request.POST['x'])\n y = int(request.POST['y'])\n op = request.POST['op']\n \n result = 0\n if op == 'add':\n result = x + y\n elif op == 'sub':\n result = x - y\n elif op == 'mul':\n result = x * y\n elif op == 'div':\n result = x / y\n \n #dic={'x':x, 'y':y, 'op':op}\n return render(request, 'mycal.html', locals())\t# locals方法-局部变量直接封装成字典(Python自带方法)\n \n \n # mysite1/templates/mycal.html\n <form action='/mycal' method='post'>\n <input type='text' name=\"x\" value=\"{{ x }}\">\n <select name='op'>\n <option value=\"add\" {% if op == 'add' %}selected{% endif %} > +加</option>\t# ☆ 记录op状态,option selected属性,使用了if标签\n <option value=\"sub\" {% if op == 'sub' %}selected{% endif %}> -减</option>\n <option value=\"mul\" {% if op == 'mul' %}selected{% endif %}> *乘</option>\n <option value=\"div\" {% if op == 'div' %}selected{% endif %}> /除</option>\n </select>\n <input type='text' name=\"y\" value=\"{{ y }}\"> = <span>{{ result }}</span>\n <div><input type=\"submit\" value='开始计算'></div>\n </form>\n \n ```\n\n\n\n#### for标签\n\n- **语法:**\n\n ```jinja2\n {% for 变量 in 可迭代对象 %}\n ... 循环语句\n {% empty %}\n ... 可迭代对象无数据时填充的语句\n {% endfor %}\n ```\n\n 官方文档:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/#for\n\n\n\n- **内置变量 - forloop**\n\n![image-20220216024655125](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160246199.png)\n\n\n\n- **演示:**\n\n```\nhttp://127.0.0.1:8000/test_if_for\n```\n\n![image-20220216025446396](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160254425.png)\n\n```python\n# mysite1/mysite1/urls.py\nurlpatterns = [\n ...\n path('test_if_for', views.test_if_for),\n]\n\n# mysite1/mysite1/views.py\ndef test_if_for(request):\n dic = {}\n dic['lst'] = ['Tom', 'Jack', 'Lily']\n return render(request, 'test_if_for.html', dic)\n\n# mysite1/templates/test_if_for.html\n{% for name in lst %}\n {% if forloop.first %} &&&&& {% endif %}\n <p> {{ forloop.counter }} {{ name }}</p>\n {% if forloop.last %} ===== {% endif %}\n{% empty %}\n 当前没数据\n{% endfor %}\n```\n\n\n\n### 小节\n\n- 变量调用 - 点大法\n- 标签语法 {% raw %}{% 标签 %} {% 结束标签 %}{% endraw %}\n\n\n\n***\n\n## 二. 模板层 - 过滤器和继承\n\n### 过滤器\n\n- 定义:在变量输出时对变量的值进行处理\n- 作用:可以通过使用 过滤器 来改变变量的输出显示\n- 语法:{% raw %}**{{ 变量 | 过滤器1:'参数1' | 过滤器2:'参数2' ... }}**{% endraw %}\n\n官方文档:https://docs.djangoproject.com/zh-hans/2.2/ref/templates/builtins/\n\n\n\n- **常用过滤器:**\n\n ![image-20220216030721308](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160307400.png)\n\n- 演示:\n\n```\nhttp://127.0.0.1:8000/test_html_param\n```\n\n![image-20220216031236417](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160312462.png)\n\n![image-20220216031311962](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160313992.png)\n\n\n\n```python\n# mysite1/mysite1/urls.py\nurlpatterns = [\n ...\n path('test_html', views.test_html)\n]\n\n\n# mysite1/mysite1/views.py\ndef test_html_param(request):\n dic = {}\n dic['int'] = 88\n dic['script'] = '<script>alert(1111)</script>'\n return render(request, 'test_html_param.html', dic)\n\ndef say_hi():\n return 'hahaha'\n\nclass Dog:\n def say(self):\n return 'wangwang'\n\n\n# mysite1/templates/test_html_param.html\n<h3>int 是 {{ int|add:\"2\" }}</h3>\n<h3>str 是 {{ str|upper }}</h3>\n<h3>script 是 {{ script|safe }}</h3>\n```\n\n\n\n### 继承\n\n**模板的继承**\n\n​\t如下样例:\n\n![image-20220216032123690](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202160321750.png)\n\n\n\n- 模板继承可以使父模板的内容重用,子模板直接继承父模板的全部内容并可以覆盖父模板中相应的块\n\n\n\n- 语法 - 父模板中:\n - [x] 定义父模板中的**块 block **标签\n - [x] 表时出哪些在**子模块**中是允许被**修改**的\n - [x] block 标签:**在父模板中定义,可以在子模板中覆盖**\n\n\n\n- 语法 - 子模板中:\n - [x] 继承模板 `extends` 标签(写在模板文件的第一行)\n \n 例如 `{% extends 'base.html' %}`\n \n - [x] 子模板 重写父模板中的内容块\n \n ```jinja2\n {% block block_name %}\n 子模板块用来覆盖父模板中 block_name 块的内容\n {% endblock block_name %}\t- block_name 可写可不写\n ```\n\n\n\n- 重写的覆盖规则\n - [x] 不重写,将按照父模板中的效果显示\n - [x] 重写,则按照重写效果显示\n\n\n\n- 注意\n - [x] 模板继承时,服务器端的动态内容无法继承\n\n\n\n- **演示:**\n\n```\nhttp://127.0.0.1:8000/base_index\n```\n\n\n\n![image-20220216150400013](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161504056.png)\n\n![image-20220216150430581](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161504615.png)\n\n\n\n```python\n# mysite1/mysite1/urls.py\nurlpatterns = [\n ...\n path('base_index', views.base_view, name='base_index'),\n path('music_index', views.music_view),\n path('sport_index', views.sport_view),\n]\n\n# mysite1/mysite1/views.py\ndef base_view(request):\n lst = ['Tom', 'Jack']\n return render(request, 'base.html', locals())\n\ndef music_view(request):\n return render(request, 'music.html')\n\ndef sport_view(request):\n return render(request, 'sport.html')\n\n#-------------------------------------------------------------\n# mysite1/templates/base.html\t\t# 父模板\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n {% block mytitle %}\n <title>主页</title>\t\t\t\t# 子模板能改的地方\n {% endblock %}\n</head>\n<body>\n{{ lst }}\t\t\t\t\t\t\t\t# 子模板无法继承变量(动态内容)\n<a href=\"/music_index\">音乐频道</a>\t\t# 子模板不能改\n<a href=\"/sport_index\">体育频道</a>\n<br>\n\n\n{% block info %}\n 这是主页\t\t\t\t\t\t\t# 子模板能改的地方\n{% endblock %}\n\n<br>\n\n<h3>有任何问题联系xxxx</h3>\t\t\t\t# 子模板不能改\n\n\n# mysite1/templates/music.html\t\t# 子模板\n{% extends 'base.html' %}\t\t\t\t# 继承父模板\n\n{% block mytitle %}\n <title>音乐频道</title>\t\t\t\t# 子模板重写block\n{% endblock %}\n\n{% block info %}\n 欢迎来到音乐频道\n{% endblock %}\n\n# mysite1/templates/sport.html\n{% extends 'base.html' %}\n\n{% block mytitle %}\n <title>体育频道</title>\n{% endblock %}\n\n{% block info %}\n 欢迎来到体育频道\n{% endblock %}\n\n```\n\n\n\n### 小节\n\n- **过滤器**\n\n { `变量` | `过滤器`1:'`参数值`1' | 过滤器2:'参数值2' ... }\n\n- **模板的继承**\n\n 父模板 - `定义可被修改的block`\n\n 子模板 - 继承`父模板`;按需修改`父模板中定义的block`\n\n\n\n***\n\n## 三. url反向解析\n\n- **代码中 url 出现位置**\n\n 1. ==模板== 【html中】\n\n 1. \\<a ==href==='url'>超链接\\</a>\n\n 点击后 页面跳转至 url\n\n 2. \\<form ==action==='url' method='post'>\n\n form表单中的数据 用post方法提交至 url\n\n 2. ==视图函数==中 - 302跳转 HttpResponseRedirect('url')\n\n 将用户地址栏中的地址跳转到 url\n\n\n\n- **代码中 url 书写规范**\n\n 1. ==绝对地址==\n\n ​\thttp://127.0.0.1:8000/page/1\n\n 2. ==相对地址==\n\n 1. '==/==page/1' -\t=='/' 开头的相对地址==,浏览器会把当前地址栏里的 协议,ip 和 端口 加上这个地址,作为最终访问地址,即如果当前页面地址栏为 http://127.0.0.1:8000/page/3;当前相对地址最终结果为 ==`http://127.0.0.1:8000`== + /page/1\t(☆ 高频使用)\n 2. 'page/1' -\t==没有 '/' 开头的相对地址==,浏览器会根据`当前 url 的最后一个 / 之前的内容 加上 该相对地址` 作为最终访问地址,例如当前地址栏地址为 ==http://127.0.0.1:8000/topic/==detail;则该相对地址最终结果为 ==`http://127.0.0.1:8000/topic/`== + page/1\n\n- **演示:**\n\n```\nhttp://127.0.0.1:8000/test/url\n```\n\n![image-20220216165641996](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161656031.png)\n\n![image-20220216165734057](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161657095.png)\n\n![image-20220216170206874](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161702913.png)\n\n```python\n# mysite1/mysite1/urls.py\nurlpatterns = [\n ...\n # http://127.0.0.1:8000/test/url\n path('test/url', views.test_url),\n path('test_url_result', views.test_url_result)\n]\n\n\n# mysite1/mysite1/views.py\ndef test_url(request):\n return render(request, 'test_url.html')\n\ndef test_url_result(request):\n return HttpResponse('---test url res is ok')\n\n\n# mysite1/templates/test_url.html\n<a href=\"http://127.0.0.1:8000/test_url_result\">绝对地址</a>\n<a href=\"/test_url_result\">带'/'的相对地址</a>\n<a href=\"test_url_result\">不带'/'的相对地址</a>\t\t# 浏览器解析为 http://127.0.0.1:8000/test/test_url_result\n\n```\n\n\n\n- **url 反向解析**\n\n - url 反向解析是指在视图或者模板中,用 ==path 定义的名称==来==动态查找或计算出相应的路由==\n\n - **path 函数的语法**\n\n - [x] path(route, views, ==name===\"别名\")\n - [x] path('page', views.page_view, name=\"page_url\")\n - 根据 path 中的 'name=' 关键字传给 url 确定了个唯一确定的名字,在模板或视图中,可以通过这个名字反向推断出此 url 信息\n\n - ==模板中== - 通过 url 标签实现地址的反向解析\n\n ```jinja2\n {% url '别名' %}\n {% url '别名' '参数值1' '参数值2' %}\n ex:\n {% url 'pagen' '400' %}\t\t--- 传参一律是 str\n {% url 'person' age='18' name='gxn' %}\n ```\n\n - **演示:在模板中使用**\n\n ```\n http://127.0.0.1:8000/test/url\n ```\n\n ![image-20220216172535944](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161725987.png)\n\n ```python\n # mysite1/mysite1/urls.py\n urlpatterns = [\n ...\n # http://127.0.0.1:8000/test/url\n path('test/url', views.test_url),\n path('test_urls_result/<int:age>', views.test_url_result, name='tr')\t\t# 起别名 tr\n ]\n \n # mysite1/mysite1/views.py\n def test_url(request):\n return render(request, 'test_url.html')\n \n def test_urls_result(request):\n return HttpResponse('---test url res is ok')\n \n # mysite1/templates/test_url.html\n <a href=\"{% url 'tr' '100' %}\">url反向解析版本</a>\t\t\t\t\t\t\t\t# ☆ 模板中使用别名\n \n ```\n\n \n\n - 在==视图函数==中 → 可调用 django 中的 ==reverse== 方法进行反向解析\n\n ```python\n from django.urls import reverse\n reverse('别名', args=[], kwargs={})\n ex:\n print(reverse('pagen', args=[300]))\n print(reverse('person', kwargs=\n {'name':'peng', 'age':23}))\n \n ```\n\n - 演示:\n\n ```\n http://127.0.0.1:8000/test/url\n \n # 302跳转 - 响应头里的 location 标记跳转地址\n ```\n\n ![image-20220216174234729](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161742771.png)\n\n ![image-20220216174547656](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202202161745717.png)\n\n ```python\n # mysite1/mysite1/urls.py\n urlpatterns = [\n ...\n path('base_index', views.base_view, name='base_index'),\t\t\t\t\t\t# 起别名 base_index\n # http://127.0.0.1:8000/test/url\n path('test/url', views.test_url),\n path('test_urls_result/<int:age>', views.test_url_result, name='tr')\t\t# 起别名 tr\n ]\n \n \n # mysite1/mysite1/views.py\n def base_view(request):\n lst = ['Tom', 'Jack']\n return render(request, 'base.html', locals())\n \n def test_url(request):\n return render(request, 'test_url.html')\n \n def test_url_result(request, age):\n #302跳转\n from django.urls import reverse\n url = reverse('base_index')\t\t\t\t\t\t\t\t\t\t\t\t\t# ☆ 视图函数中使用别名\n return HttpResponseRedirect(url)\n \n \n #---------------------------------------------------------------\n # mysite1/templates/test_url.html\n <a href=\"{% url 'tr' '100' %}\">url反向解析版本</a>\n \n # mysite1/templates/base.html\n 略\n \n ```\n\n \n\n## 四. 总结\n\n- 请求(request)和响应(HttpResponseqing)\n- GET/POST处理 - request.GET/POST\n- MVC 和 MTV\n- 模板层基础配置\n- 模板变量/标签/过滤器/继承\n- url反向解析\n\n\n\n***\n\n","tags":["Django","URL"],"categories":["Django"]},{"title":"03_Django-GET请求和POST请求-设计模式及模板层","url":"/posts/42935.html","content":"[视频链接:https://www.bilibili.com/video/BV1vK4y1o7jH](https://www.bilibili.com/video/BV1vK4y1o7jH)\n\n## 一. GET请求和POST请求\n\n### 定义\n\n> ·无论是GET还是POST,统一都由`视图函数`接收请求,通过判断request.method区分具体的请求动作\n>\n> ·样例:\n>\n> ```python\n> if requests.method == 'GET':\n> 处理GET请求时的业务逻辑\n> elif requests.method == 'POST':\n> 处理POST请求的业务逻辑\n> else:\n> 其他请求业务逻辑\n> ```\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> ```python\n> 演示\n> \n> <项目同名文件夹下>/views.py\n> def test_get_post(request):\n> if request.method == 'GET':\n> pass\n> elif request.method == 'POST':\n> #处理用户提交数据\n> pass\n> else:\n> pass\n> return HttpResponse('--test get post is ok--')\n> ```\n>\n> \n\n\n\n### GET处理\n\n> ·GET请求动作,一般用于向服务器`获取数据`\n>\n> ·能够产生GET请求的场景:\n>\n> ​\t\t\\- 浏览器地址栏中输入URL,回车后\n>\n> ​\t\t\\- \\<`a href`=\"地址?参数=值&参数=值\">\n>\n> ​\t\t\\- `form表单`中的`method为get`\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> GET请求方式中,如果有数据需要传递给服务器,通常会用`查询字符串(Query String)`传递【注意:`不要传递敏感数据`】\n>\n> URL格式:xxx`?参数名1=值1&参数名2=值2...`\n>\n> \\- 如:http://127.0.0.1:8000/page1`?a=100&b=200`\n>\n> 服务器端接收参数\n>\n> 获取客户端请求GET请求提交的数据\n>\n> ·方法示例:\n>\n> ```python\n> request.GET['参数名'] # QueryDict\n> request.GET.get('参数名', '默认值')\n> request.GET.getlist('参数名')\n> # mypage?a=100&b=200&c=300&b=400\n> # request.GET=QueryDict({'a': ['100'], 'b': ['200', '400'], 'c': ['300']})\n> # a = request.GET['a']\n> # b = request.GET['b'] # Error\n> ```\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> ```python\n> 演示\n> \n> http://127.0.0.1:8000/test_get_post?a=400\n> --test get post is ok--\n> 终端\n> <QueryDict: {'a': ['400', '200', '100']}>\n> 100\n> ['400', '200', '100']\n> no c\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> ...\n> path('test_get_post', views.test_get_post)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def test_get_post(request):\n> if request.method == 'GET':\n> print(request.GET)\n> print(request.GET['a'])\n> # 问卷调查 = form get 兴趣爱好 - 复选框\n> print(request.GET.getlist('a'))\n> print(request.GET.get('c', 'no c'))\n> elif request.method == 'POST':\n> #处理用户提交数据\n> pass\n> else:\n> pass\n> return HttpResponse('--test get post is ok--')\n> ```\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> ·思考:之前的计算器功能,能否拿查询字符串做?\n>\n> ​\t\thttp://127.0.0.1:8000/整数/操作符/整数\n>\n> ​\t\thttp://127.0.0.1:8000/cal?x=10&y=20&op=add\n>\n> \n\n\n\n### POST处理\n\n> ·POST请求动作,一般用于`向服务器提交大量/隐私数据`\n>\n> ·客户端通过表单等POST请求将数据传递给服务器端,如:\n>\n> ![image-20220505232318528](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052323569.png)\n>\n> ·服务器端`接收参数`\n>\n> ​\t\t通过request.method来判断是否为POST请求,如:\n>\n> ```python\n> if request.method == 'POST':\n> 处理POST请求的数据并响应\n> else:\n> 处理非POST请求的响应\n> ```\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> **使用post方式接收客户端数据**\n>\n> ```python\n> request.POST['参数名'] # request.POST 绑定QueryDict\n> request.POST.get('参数名', '')\n> request.POST.getlist('参数名')\n> ```\n>\n> **`取消csrf验证,否则Django将会拒绝客户端发来的POST请求,报403响应`**\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> **取消csrf验证**\n>\n> ​\t\t\\- 禁止掉settings.py中MIDDLEWARE中的CsrfviewsMiddleWare的中间件\n>\n> ```python\n> MIDDLEWARE = [\n> \t...\n> # 'django.middleware.csrf.CsrfViewMiddleware',\n> ...\n> ]\n> ```\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> 演示\n>\n> http://127.0.0.1:8000/test_get_post\n>\n> ![image-20220505233651466](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052336498.png)\n>\n> ```python\n> post is ok\n> 终端\n> uname is cpen\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> ...\n> path('test_get_post', views.test_get_post)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> POST_FORM = '''\n> <form method='post' action='/test_get_post'>\n> 用户名: <input type='text' name='uname'>\n> <input type='submit' value='提交'>\n> </form>\n> '''\n> def test_get_post(request):\n> if request.method == 'GET':\n> return HttpResponse(POST_FORM)\n> ...\n> ```\n>\n> \n>\n> \\---------------------------------------------------------------------------------------------------------------------------------\n>\n> 小节\n>\n> ·Django处理GET请求\n>\n> ​\t\t查询字符串 - 少量数据传递\n>\n> ·Django处理POST请求\n>\n> ​\t\t专用于浏览器提交数据\n\n\n\n---\n\n## 二. Django的设计模式及模板层\n\n### MVC和MTV\n\n#### 传统的MVC\n\n> MVC代表`Model-View-Controller`(模型-视图-控制器)模式。\n>\n> - [x] `M模型层(Model)`,主要用于对数据库层的封装\n>\n> - [x] `V视图层(View)`,用于向用户展示结果(WHAT + HOW)\n>\n> - [x] `C控制(Controller)`,用于处理请求、获取数据、返回结果(重要)\n>\n> \n>\n> 作用:`降低模块间的耦合度(解耦)`\n>\n> ![image-20220505233857207](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052338248.png)\n\n\n\n#### Django的MTV模式\n\n> MTV代表`Model-Template-View`(模型-模板-视图)模式。\n>\n> - [x] `M模型层(Model)`负责与数据库交互\n>\n> - [x] `T模板层(Template)`负责呈现内容到浏览器(HOW)\n>\n> - [x] `V视图层(View)`是核心,负责接收请求、获取数据、返回结果(WHAT)\n>\n> \n>\n> 作用:`降低模块间的耦合度(解耦)`\n>\n> ![image-20220505234057843](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052340887.png)\n>\n> \n>\n> \\---------------------------------------------------------------------------------------------------------------------------------\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052341004.jpg) \n\n\n\n\n### 模板层\n\n#### 什么是模板\n\n> 1、模板是可以根据`字典`数据动态变化的`html网页`\n>\n> 2、模板可以`根据视图中传递的字典数据动态生成相应的HTML网页`\n>\n> ![image-20220505234226094](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052342133.png)\n\n\n\n#### 模板配置\n\n> 创建模板文件夹 `<项目名>/templates`\n>\n> 在`settings.py`中`TEMPLATES`配置项\n>\n> ​\t\t1.BACKEND:指定模板的引擎\n>\n> ​\t\t2.`DIRS`:模板的搜索目录(可以是一个或多个)\n>\n> ​\t\t3.APP_DIRS:是否要在应用中的templates文件夹中搜索模板文件\n>\n> ​\t\t4.OPTIONS:有关模板的选项\n>\n> ·配置项中 需要修改部分\n>\n> ​\t\t设置DIRS - `'DIRS': [os.path.join(BASE_DIR, 'templates')],`\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> 演示\n>\n> ```python\n> \n> <项目同名文件夹下>/settings.py\n> TEMPLATES = [\n> {\n> ...\n> 'DIRS': [os.path.join(BASE_DIR, 'templates')],\n> ...\n> ```\n>\n> \n\n\n\n#### 模板的加载方式\n\n> **方案1** - 通过loader获取模板,通过HttpResponse进行响应(特点:麻烦)\n>\n> 在视图函数中:\n>\n> ```python\n> from django.template import loader\n> # 1.通过 loader 加载模板\n> t = loader.get_template(\"模板文件名\")\n> # 2.将 t 转换成 HTML 字符串\n> html = t.reader(字典数据)\n> # 3.用响应对象将转换的字符串内容返回给浏览器\n> return HttpResponse(html)\n> ```\n>\n> \n>\n> \\--------------------------------------------------------------------------------------\n>\n> **演示**\n>\n> http://127.0.0.1:8000/test_html\n>\n> ![image-20220505234508244](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052345270.png)\n>\n> ```python\n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> ...\n> path('test_html', views.test_html)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def test_html(request):\n> from django.template import loader\n> t = loader.get_template('test_html.html')\n> html = t.render()\n> return HttpResponse(html)\n> \n> <项目文件夹下>/templates/test_html.html\n> <h3>我是模板层的~~~~</h3>\n> ```\n>\n> \n>\n> \\---------------------------------------------------------------------------------------------------------------------------------\n>\n> **方案2** - 通过render() 直接加载并响应模板(特点:方便,大量使用这种)\n>\n> 在视图函数中:\n>\n> ```python\n> from django.shortcuts import render\n> return render(request, '模板文件名', 字典数据)\n> ```\n>\n> \n>\n> \\--------------------------------------------------------------------------------------\n>\n> **演示**\n>\n> http://127.0.0.1:8000/test_html\n>\n> ![image-20220505234639279](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052346308.png)\n>\n> ```python\n> <项目同名文件夹下>/views.py\n> def test_html(request):\n> # 方案2\n> from django.shortcuts import render\n> return render(request, 'test_html.html')\n> ```\n>\n> \n\n\n\n#### 视图层与模板层之间的交互\n\n> 1、视图函数中可以将Python`变量`封装到字典中传递到模板\n>\n> 样例:\n>\n> def xxx_view(request):\n> dic = {\n> \"变量1\": \"值1\",\n> \"变量2\": \"值2\",\n> }\n> return render(request, 'xxx.html', `dic`)\n>\n> \n>\n> 2、模板中,我们可以用 **{{ 变量名 }}** 的语法 调用视图传进来的变量\n>\n> \n>\n> \\--------------------------------------------------------------------------------------\n>\n> **演示**\n>\n> http://127.0.0.1:8000/test_html\n>\n> ![image-20220505234825246](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052348278.png)\n>\n> ```python\n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> ...\n> path('test_html', views.test_html)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def test_html(request):\n> from django.shortcuts import render\n> dic = {'username': 'peng', 'age': 23}\n> return render(request, 'test_html.html', dic)\n> \n> <项目文件夹下>/templates/test_html.html\n> <h3>{{ username }}是模板层的~~~~</h3>\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Django","MTV","HTTP","GET","POST","MVC"],"categories":["Django"]},{"title":"02_Django-路由配置-HTTP协议的请求和响应","url":"/posts/57095.html","content":"[视频链接:https://www.bilibili.com/video/BV1vK4y1o7jH](https://www.bilibili.com/video/BV1vK4y1o7jH)\n\n## 一. 路由配置\n\n> ==settings.py==中的 ==\\`ROOT_URLCONF\\`== 指定了主路由配置列表 ==urlpatterns== 的文件位置\n>\n> ```python\n> # file: <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> path('page/2003/', views.page_2003_view),\n> ... # 此处配置主路由\n> ]\n> ```\n>\n> \n\n\n\n### path()\n\n#### path()函数\n\n> path()函数\n>\n> 导入 - from django.urls import path\n>\n> 语法 - ==path(route, views, name=None)==\n>\n> 参数:\n>\n> ​\t\t1.==route==: 字符串类型,匹配的请求==路径==\n>\n> ​\t\t2.==views==: 指定路径所对应的==视图处理函数的名称==\n>\n> ​\t\t3.**name**: 为地址起 **别名**,在模块中地址反向解析时使用\n\n\n\n> 练习 - 建立一个小网站:\n>\n> ​\t\t输入网址:http://127.0.0.1:8000, 在网页中输出:这是我的首页\n>\n> ​\t\t输入网址:http://127.0.0.1:8000/page/1, 在网页中输出:这是编号为1的网页\n>\n> ​\t\t输入地址:http://127.0.0.1:8000/page/2, 在网页中输出:这是编号为2的网页\n>\n> \n>\n> ```\n> http://127.0.0.1:8000\n> http://127.0.0.1:8000/page/1\n> http://127.0.0.1:8000/page/2\n> ```\n>\n> ```python\n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> #http://127.0.0.1:8000\n> path('', views.index_view),\n> #http://127.0.0.1:8000/page/1\n> path('page/1', views.page1_view),\n> #http://127.0.0.1:8000/page/2\n> path('page/2', views.page2_view)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def index_view(request):\n> html = '这是我的首页'\n> return HttpResponse(html)\n> \n> def page1_view(request):\n> html = '这是编号为1的网页'\n> return HttpResponse(html)\n> \n> def page2_view(request):\n> html = '这是编号为2的网页'\n> return HttpResponse(html)\n> ```\n>\n> \n\n\n\n> 思考\n>\n> 建立如上一百个网页该怎么办?\n>\n> 例如:\n>\n> ​\t\thttp://127.0.0.1:8000/page/3\n>\n> ​\t\thttp://127.0.0.1:8000/page/4\n>\n> ​\t\t...\n>\n> ​\t\thttp://127.0.0.1:8000/page/100\n\n\n\n#### path转换器\n\n> 语法:==<转换器类型: 自定义名>==\n>\n> 作用:若转换器类型匹配到对应类型的==数据==,则将数据按照==关键字传参==的方式传递给==视图函数==\n>\n> 例子:path(‘page/==\\<int:page\\>==’, view.xxx)\n>\n> \n>\n> ==**转换器类型**:str、int、slug、path==\n>\n> ![image-20220504213759635](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205042137686.png)\n\n\n\n> ```python\n> http://127.0.0.1:8000/page/30\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> #http://127.0.0.1:8000/page/3-100\n> path('page/<int:pg>', views.pagen_view)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def pagen_view(request, pg):\n> html = '这是编号为%s的网页!'%(pg)\n> return HttpResponse(html)\n> ```\n>\n> \n\n\n\n> 练习:小计算器\n>\n> ​\t\t定义一个路由的格式为:\n>\n> ​\t\t==http://127.0.0.1:8000/整数/操作字符串[add/sub/mul]/整数==\n>\n> ​\t\t从路由中提取数据,做相应的操作后返回给浏览器\n>\n> ​\t\t效果如下:\n>\n> ​\t\t\t\t输入:==127.0.0.1:8000/100/add/200==\n>\n> ​\t\t\t\t页面显示结果:==300==\n>\n> \n>\n> ```python\n> http://127.0.0.1:8000/100/add/200\n> 结果为:300\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> #http://127.0.0.1:8000/整数/操作符/整数\n> path('<int:n>/<str:op>/<int:m>', views.cal_view)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def cal_view(request, n, op, m):\n> if op not in ['add', 'sub', 'mul']:\n> return HttpResponse('Your op is wrong')\n> result = 0\n> if op == 'add':\n> result = n + m\n> elif op == 'sub':\n> result = n - m\n> elif op == 'mul':\n> result = n * m\n> return HttpResponse('结果为:%s'%(result))\n> ```\n>\n> \n\n\n\n### re_path()\n\n#### re_path()函数\n\n> re_path()函数\n>\n> 在 url 的匹配过程中可以使用==正则==表达式进行精确匹配\n>\n> 语法:\n>\n> ​\t\tre_path(==reg==, view, name=xxx)\n>\n> ​\t\t正则表达式为==命名分组模式(**?P\\<name\\>**pattern)==; 匹配提取参数后用关键字传参方式传递给视图函数\n\n> ```python\n> 样例\n> # 可匹配 http://127.0.0.1:8000/20/mul/40\n> # 不可匹配 http://127.0.0.1:8000/200/mul/400\n> \n> http://127.0.0.1:8000/10/add/20 -> x:10 op:add y:20\n> \n> <项目同名文件夹下>/urls.py\n> from django.urls import path, re_path\n> \n> urlpatterns = [\n> #http://127.0.0.1:8000/整数2/操作符/整数2\n> re_path(r'^(?P<x>\\d{1,2})/(?P<op>\\w+)/(?P<y>\\d{1,2})$', views.cal2_view),\n> ]\t\t# \\d 整数; \\w 字符\n> \n> <项目同名文件夹下>/views.py\n> def cal2_view(request, x, op, y):\n> html = 'x:%s op:%s y:%s'%(x, op, y)\n> return HttpResponse(html)\n> ```\n>\n> \n\n\n\n> 练习\n>\n> 访问地址:\n>\n> ​\t\thttp://127.0.0.1:8000/birthday/四位数字/一到两位数字/一到两位数字\n>\n> ​\t\thttp://127.0.0.1:8000/birthday/一到两位数字/一到两位数字/四位数字\n>\n> 最终输出:生日为:xxxx年xx月xx日\n>\n> \n>\n> > 效果样例:\n> >\n> > ​\t\t输入网址:http://127.0.0.1:8000/birthday/2015/12/11\n> >\n> > ​\t\t显示为:生日为:2015年12月11日\n> >\n> > ​\t\t输入网址:http://127.0.0.1:8000/birthday/2/28/2008\n> >\n> > ​\t\t显示为:生日为:2008年2月28日\n>\n> \n>\n> ```python\n> http://127.0.0.1:8000/birthday/1992/01/01\n> 生日为1992年01月01日\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> #http://127.0.0.1:8000/birthday/年4/月2/日2\n> re_path(r'^birthday/(?P<y>\\d{4})/(?P<m>\\d{1,2})/(?P<d>\\d{1,2})$', views.birthday_view),\n> #http://127.0.0.1:8000/birthday/月2/日2/年4\n> re_path(r'^birthday/(?P<m>\\d{1,2})/(?P<d>\\d{1,2})/(?P<y>\\d{4})$', views.birthday_view),\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def birthday_view(request, y, m, d):\n> html = \"生日为%s年%s月%s日\"%(y, m, d)\n> return HttpResponse(html)\n> ```\n>\n> \n\n\n\n---\n\n**Django Day02**\n\n> 请求和响应\n>\n> GET请求和POST请求\n>\n> Django的设计模式及模板层\n>\n> 模板层 - 变量和标签\n>\n> 模板层 - 过滤器和继承\n>\n> url反向解析\n\n\n\n---\n\n## 二. HTTP协议的请求和响应\n\n> 定义\n>\n> ​\t\t==请求==是指浏览器端通过==HTTP协议==发送给服务器端的数据\n>\n> ​\t\t响应是指==服务器端接收到请求后==做相应的处理后再==回复给浏览器端的数据==\n>\n> ![image-20220505220331451](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052203494.png)\n\n\n\n### 请求\n\n#### 请求样例\n\n> **请求样例**\n>\n> ![image-20220505225754654](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052257694.png)\n\n\n\n#### 请求中的方法\n\n> 根据HTTP标准,HTTP请求可以使用多种请求方法\n>\n> `HTTP1.0`定义了三种请求方法:GET,POST和HEAD方法(最常用)\n>\n> `HTTP1.1`新增了五种请求方法:OPTIONS,PUT,DELETE,TRACE和CONNECT方法\n>\n> ![image-20220505225851617](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052258651.png)\n>\n> ![image-20220505225903610](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052259640.png)\n>\n> \n\n\n\n#### Django中的请求\n\n> 请求在Django中实则就是 `视图函数的第一个参数`,即HttpRequest对象\n>\n> `Django接收到http协议的请求后`,会根据`请求数据`报文创建`HttpRequest对象`\n>\n> HttpRequest对象 通过`属性` 描述了 请求的 所有相关信息\n\n\n\n> `·path_info`:URL字符串\n>\n> `·method`:字符串,表示HTTP请求方法,常用值:==\\`GET\\`==、==\\`POST\\`==\n>\n> `·GET`:`QueryDict`查询字典的对象,包含get请求方法的所有数据\n>\n> `·POST`:QueryDict查询字典的对象,包含post请求方式的所有数据\n>\n> `·FILES`:类似于字典的对象,包含所有的上传文件信息\n>\n> ·COOKIES:Python字典,包含所有的cookie,键和值都为字符串\n>\n> ·session:似于字典的对象,表示当前的会话\n>\n> ·body:字符串,请求体的内容(POST或PUT)\n>\n> ·scheme:请求协议('http'/'https')\n>\n> ·request.get_full_path():请求的完整路径\n>\n> ·request.META:请求中的元数据(消息头)\n>\n> ​\t\\- request.META['REMOTE_ADDR']:客户端IP地址\n\n\n\n> ```python\n> http://127.0.0.1:8000/test_request?a=1&b=1\n> test request ok\n> 终端\n> path info is /test_request\n> method is GET\n> querystring is <QueryDict: {'a': ['1'], 'b': ['1']}>\n> full path is /test_request?a=1&b=1\n> [20/Dec/2021 23:27:09] \"GET /test_request?a=1&b=1 HTTP/1.1\" 200 15\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> path('test_request', views.test_request)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> def test_request(request):\n> print('path info is', request.path_info)\n> print('method is', request.method)\n> print('querystring is', request.GET)\n> print('full path is', request.get_full_path())\n> return HttpResponse('test request ok')\n> ```\n>\n> \n\n\n\n### 响应\n\n#### 响应样例\n\n> **响应样例**\n>\n> ![image-20220505230704121](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052307158.png)\n\n\n\n#### 响应状态码\n\n> HTTP状态码的英文为HTTP Status Code\n>\n> 下面是常见的HTTP状态码:\n>\n> \\- `200` - 请求成功\n>\n> \\- `301` - 永久重定向-资源(网页等)被永久转移到其它URL\n>\n> \\- `302` - 临时重定向\n>\n> \\- `404` - 请求的资源(网页等)不存在\n>\n> \\- `500` - 内部服务器错误\n>\n> \n>\n> HTTP状态码由三个十进制数字组成,第一个十进制数字定义了状态码的类型,后两个数字没有分类的作用。HTTP状态码共分为5种类型:\n>\n> ![image-20220505230809542](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052308576.png)\n\n\n\n#### Django中的响应对象\n\n> 构造函数格式:\n>\n> ​\t\tHttpResponse(content=`响应体`, `content_type`=响应体数据类型, status=`状态码`)\n>\n> 作用:\n>\n> ​\t\t向客户端浏览器返回响应,同时携带响应体内容\n>\n> \n>\n> 常用的**`Conten-Type`**如下\n>\n> \\- '`text/html`'(默认的,html文件)\n>\n> \\- 'text/plain'(纯文本)\n>\n> \\- 'text/css'(css文件)\n>\n> \\- '`text/javascript`'(js文件)\n>\n> \\- 'multipart/form-data'(文件提交)\n>\n> \\- 'application/`json`'(json传输)\n>\n> \\- 'application/xml'(xml文件)\n>\n> \n>\n> \\------------------------------------------------------------------\n>\n> HttpResponse子类\n>\n> ![image-20220505231038952](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205052310989.png)\n>\n> \n>\n> ```python\n> http://127.0.0.1:8000/test_request\n> => http://127.0.0.1:8000/page/1\n> \n> <项目同名文件夹下>/urls.py\n> urlpatterns = [\n> path('test_request', views.test_request)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> from django.http import HttpResponse, HttpResponseRedirect\n> \n> def test_request(request):\n> return HttpResponseRedirect('/page/1')\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Django","HTTP","状态码"],"categories":["Django"]},{"title":"01_Django-介绍-项目结构-URL和视图函数","url":"/posts/14763.html","content":"[视频链接:https://www.bilibili.com/video/BV1vK4y1o7jH](https://www.bilibili.com/video/BV1vK4y1o7jH)\n\n## 一. 课程目录\n\n> Django介绍\n>\n> Django项目结构\n>\n> URL和视图函数\n>\n> 路由配置\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205042042834.jpg) \n\n\n\n---\n\n## 二. Django介绍\n\n### 起源\n\n> **2005年发布,采用Python语言编写的开源web框架**\n>\n> **早期的时候Django主做新闻和内容管理的**\n>\n> **重量级的Python Web框架,Django配备了常用的大部分组件**\n\n\n\n### 组件\n\n> 包含组件如下:\n>\n> ​\t\t基本配置文件/路由系统\n>\n> ​\t\t==模型层(M)/模块层(T)/视图层(V)==\n>\n> ​\t\tCookies和Session\n>\n> ​\t\t分页及发邮件\n>\n> ​\t\tAdmin管理后台\n\n\n\n### 用途\n\n> 用途一:网站/微信公众号/小程序后端开发\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205042044041.jpg) \n>\n> \n>\n> 用途二:人工智能平台融合\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205042044045.jpg) \n\n\n\n### 版本\n\n> Django官网:http://www.djangoproject.com\n>\n> Django中文文档参考网站:https://yiyibooks.cn/\n>\n> 版本\n>\n> ​\t\t最新版本3.0.x\n>\n> ​\t\t当前教学版本2.2.12\n\n\n\n### 安装\n\n> 支持Python的版本 - 3.5,3.6,3.7,3.8\n>\n> ==在线安装==\n>\n> ​\t\t虚拟机执行 ==sudo pip3 install django\\=\\=2.2.12==\n>\n> ​\t\t检查是否成功 sudo pip3 freeze |grep -i 'Django'\n>\n> ==离线安装== - 官方下载离线安装包\n>\n> ​\t\t将安装包复制到虚拟机\n>\n> ​\t\t解压缩 tar -xvf Django-2.2.12.tar.gz\n>\n> ​\t\t进入目录 cd Django-2.2.12\n>\n> ​\t\t执行安装 sudo python3 setup.py install\n>\n> ​\t\t检查是否成功 sudo pip3 freeze |grep -i 'Django'\n\n\n\n---\n\n## 三. Django项目结构\n\n### 创建项目\n\n> 成功安装 Django 后,虚拟机终端会有 django-admin 命令\n>\n> 执行 ==django-admin startproject 项目名== 即可创建出对应项目文件夹\n>\n> 例如 终端执行 django-admin startproject mysite1; 则创建出mysite1项目\n\n\n\n### 启动服务\n\n> 启动[测试开发阶段]\n>\n> ​\t\t1.终端cd进入到项目文件夹,例如 cd mysite1\n>\n> ​\t\t2.进入到项目文件夹后,执行 ==**python3 manage.py runserver**== 启动django服务完【注:该启动方式下,Django在前台启动服务,默认监听8000端口】\n>\n> ​\t\t3.浏览器访问 **http://127.0.0.1:8000** 可看到django的启动页面\n>\n> ​\t\t注:【如果想更换端口,则可以用 python3 manage.py runserver 端口号】\n\n\n\n### 关闭服务\n\n> 方式1:在runserver启动终端下\n>\n> ​\t\t执行 ==Ctrl + c== 可关闭Django服务\n>\n> 方式2:在取它终端下\n>\n> ​\t\t执行 sudo lsof -i:8000 查询出Django的进程id\n>\n> ​\t\t执行 ==kill -9== 对应Django进程id\n\n\n\n### 启动常见问题\n\n> 问题:启动时报错\n>\n> ​\t\t==Error: That port is already in use.==\n>\n> 问题原因:端口已被使用,证明当前Django启动时,默认监听的8000端口已被其他进程占用\n>\n> 解决方案:参考关闭服务\n\n\n\n### 结构解析\n\n> ```bash\n> 展开mysite1项目,结构如下\n> $ tree mysite1\n> mysite1\n> ├── db.sqlite3\t\t\t\t\t#注:默认django数据库存储文件\n> ├── manage.py\t\t\t\t\t# *\n> └── mysite1\t\t\t\t\t\t# *\n> ├── __init__.py\n> ├── __pycache__\n> │   ├── __init__.cpython-39.pyc\n> │   ├── settings.cpython-39.pyc\n> │   ├── urls.cpython-39.pyc\n> │   └── wsgi.cpython-39.pyc\n> ├── settings.py\n> ├── urls.py\n> └── wsgi.py\n> ```\n>\n> \n\n\n\n#### manage.py\n\n> ==manage.py包含项目管理的子命令==,如:\n>\n> ​\t\tpython3 manage.py runserver 启动服务\n>\n> ​\t\tpython3 manage.py startapp 创建应用\n>\n> ​\t\tpython3 manage.py migrate 数据库迁移\n>\n> ​\t\t...\n>\n> ​\t\t直接执行python3 manage.py 可列出所有的Django子命令\n\n\n\n#### 项目同名文件夹\n\n> 项目同名文件夹 - mysite1/mysite1\n>\n> ​\t\t==\\_\\_init\\_\\_==: Python包的初始化文件\n>\n> ​\t\t==wsgi.py==: WEB服务网关的配置文件 - Django正式启动时,需要用到\n>\n> ​\t\t==urls.py==: 项目的主路由配置 - HTTP请求进入Django时,优先调用该文件\n>\n> ​\t\t==settings.py==: 项目的配置文件 - 包含项目启动时需要的配置\n\n\n\n#### settings.py\n\n> settings.py包含了Django项目启动的所有配置项\n>\n> 配置项分为 公有配置 和 自定义配置\n>\n> 配置项格式例:BASE_DIR = 'xxxx'\n>\n> 公有配置 - Django官网提供的基础配置\n>\n> ​\t\thttps://docs/djangoproject.com/en/2.2/ref/settings/\n\n\n\n##### 公有配置\n\n> ==**BASE_DIR**==\n>\n> ​\t\t用于绑定当前项目的绝对路径(动态计算出来的),所有文件夹都可以依赖此路径\n>\n> \n>\n> ==**DEBUG**==\n>\n> ​\t\t用于配置Django项目的启动模式,取值:\n>\n> ​\t\tTrue表示开发环境中使用 开发调试模式(用于开发中)\n>\n> ​\t\tFalse表示当前项目运行在 生产环境中\n>\n> \n>\n> ==**ALLOWED_HOSTS**==\n>\n> 设置允许访问到本项目的host头值\n>\n> ​\t\t[]空列表, 表示只有请求头中host为 127.0.0.1, localhost 能访问本项目 - DEBUG = True时生效\n>\n> ​\t\t[‘*’], 表示任何请求头的host都能访问到当前项目\n>\n> ​\t\t[‘192.168.1.3’, ‘127.0.0.1’] 表示只有当前两个host头的值能访问当前项目\n>\n> 示例:如果要在局域网其它主机也能访问此主机的Django服务,启动方式如下:\n>\n> ​\t\t==python3 manage.py runserver 0.0.0.0:5000==\n>\n> ​\t\t指定网络设备如果内网环境下其它主机想正常访问该站点,需要加ALLOWED_HOSTS=[‘内网ip’]\n>\n> \n>\n> ==**INSTALLED_APPS**== - 指定当前项目中安装的应用列表\n>\n> ==**MIDDLEWARE**== - 用于注册中间件\n>\n> ==**TEMPLATES**== - 用于指定模板的配置信息\n>\n> ==**DATABASES**== - 用于指定数据库的配置信息\n>\n> ==**LANGUAGE_CODE**== - 用于指定语言配置\n>\n> ​\t\t英语: “en-us”\n>\n> ​\t\t中文: “zh-Hans”\n>\n> \n>\n> ==**TIME_ZONE**== - 用于指定当前服务器端时区\n>\n> ​\t\t世界标准时间: “UTC”\n>\n> ​\t\t中国时区: “Asia/Shanghai”\n>\n> ==**ROOT_URLCONF**== - 用于配置主url配置 ‘mysite1.urls’\n>\n> ​\t\tROOT_URLCONF = ‘mysite1.urls’\n>\n> \n>\n> ```python\n> #项目绝对路径\n> BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))\n> \n> DEBUG = True\n> # 启动模式\n> # True - 调试模式\n> # 1,检测代码改动后,立刻重启服务\n> # 2,报错页面\n> # False - 正式启动模式 / 上线模式\n> \n> #请求头Host头\n> ALLOWED_HOSTS = ['127.0.0.1']\n> #ALLOWED_HOSTS = ['www.tedu1.com']\n> ```\n>\n> \n\n\n\n##### 自定义配置\n\n> settings.py中也可以添加 开发人员 ==自定义的配置==\n>\n> 配置建议:名字尽量个性化 - 以防覆盖掉公有配置\n>\n> ​\t\t例如:ALIPAY_KEY = ‘xxxxxx’\n>\n> settings.py中的所有配置项,都可以按需的在代码中引入\n>\n> 引入方式:==from django.conf import settings==\n\n\n\n---\n\n## 四. URL和视图函数\n\n### URL - 结构\n\n> 定义 - 即统一资源定位符 Uniform Resource Locator\n>\n> 作用 - 用来表示互联网上某个资源的地址\n>\n> URL的一般语法格式为(注:[] 代表其中的内容可省略):\n>\n> ​\t\t==protocol://hostname[:port]/path[?query]\\[#fragment]==\n>\n> ​\t\thttp://tts.tmooc.cn/video/showVideo?menuld=657421&version=AID999#subject\n\n\n\n#### protocol(协议)\n\n> **==http://==tts.tmooc.cn**\n>\n> http 通过HTTP访问该资源。格式 http://\n>\n> https 通过安全的HTTPS访问该资源。格式 https://\n>\n> file资源是本地计算机上的文件。格式 file:///\n\n\n\n#### hostname(主机名)\n\n> **http:// ==tts.tmooc.cn==**\n>\n> 是指存放资源的服务器的域名系统(DNS)主机名、域名 或 IP地址\n\n\n\n#### port(端口号)\n\n> **http://tts.tmooc.cn ==:80==**\n>\n> 整数,可选,省略时使用方案的默认端口\n>\n> 各种传输协议都有默认的端口号,如http的默认端口为80\n\n\n\n#### path(路由地址)\n\n> **http://tts.tmooc.cn/ ==video/showVideo==**\n>\n> 由零或多个 “/” 符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。路由地址决定了服务器端如何处理这个请求\n\n\n\n#### query(查询)\n\n> **video/showVideo==?menuld=657421&version=AID999==**\n>\n> 可选,用于给动态网页传递参数,可有多个参数,用 “&” 符号隔开,每个参数的名和值用 “=” 符号隔开\n\n\n\n#### fragment(信息片段)\n\n> **Version=AID999==#subject==**\n>\n> https://docs.djangoproject.com/en/2.2/ ==#the-template-layer==\n>\n> 字符串,用于指定网络资源中的片段。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释\n\n\n\n### 处理URL请求\n\n> 浏览器 地址栏 -> **http://127.0.0.1:8000/page/2003/**\n>\n> ​\t\t1.Django从配置文件中 根据 ==ROOT_URLCONF== 找到 主路由文件;默认情况下,该文件在 项目同名目录下的urls;例如 ==mysite1/mysite1/urls.py==\n>\n> ​\t\t2.Django加载 主路由文件中的 ==urlpatterns== 变量【包含很多路由的数组】\n>\n> ​\t\t3.依次匹配 urlpatterns 中的 URL,匹配到第一个合适的中断后续匹配\n>\n> ​\t\t4.匹配成功 - 调用对应的视图函数处理请求,返回响应\n>\n> ​\t\t5.匹配失败 - 返回404响应\n\n\n\n### 主路由 - urls.py\n\n> 主路由 - urls.py 样例\n>\n> ```python\n> from django.urls import path\n> form . import views\n> \n> urlpatterns = [\n> path('admin/', admin.site.urls),\n> path('page/2003/', views.page_2003),\n> path('page/2004/', views.page_2004),\n> ]\n> ```\n>\n> \n\n\n\n### 视图函数\n\n> 视图函数是用于==接收一个浏览器请求==(==HttpRequest==对象)并通过==HttpRequest==对象==返回响应==的函数。此函数可以接收浏览器请求并根据业务逻辑返回相应的响应内容给浏览器\n>\n> \n>\n> 语法\n>\n> ​\t\tdef xxx_view(**==request==**[, 其它参数...]):\n>\n> ​\t\t\t\t**==return HttpResponse对象==**\n>\n> > 样例\n> >\n> > ```python\n> > # file: <项目同名文件夹下>/views.py\n> > from django.http import HttpResponse\n> > \n> > def page1_view(request):\n> > html = \"<h1>这是第1个页面</h1>\"\n> > return HttpResponse(html)\n> > ```\n> >\n> > \n\n\n\n### 示例\n\n> ```python\n> http://127.0.0.1:8000/page/2003/\n> \n> <项目同名文件夹下>/urls.py\n> from . import views\n> \n> urlpatterns = [\n> path('admin/', admin.site.urls),\n> #http://127.0.0.1:8000/page/2003/\n> path('page/2003/', views.page_2003_view)\n> ]\n> \n> <项目同名文件夹下>/views.py\n> from django.http import HttpResponse\n> \n> def page_2003_view(request):\n> html = \"<h1>这是第1个页面</h1>\"\n> return HttpResponse(html)\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Django","MTV","URL"],"categories":["Django"]},{"title":"03_Java-运算符-标识符命名规则规范-键盘输入-进制","url":"/posts/62652.html","content":"[视频链接:https://www.bilibili.com/video/BV1fh411y7R8](https://www.bilibili.com/video/BV1fh411y7R8)\n\n## 运算符\n\n**运算符**\n\n- 运算符介绍\n\n​\t\t运算符是一种特殊的符号,用以表示数据的运算、赋值和比较等。\n\n1. 算术运算符 \n\n2. 赋值运算符 \n\n3. 关系运算符 [比较运算符] \n\n4. 逻辑运算符 \n\n5. 位运算符 [需要二进制基础] \n\n6. 三元运算符 \n\n\n\n---\n\n### 一. 算术运算符\n\n**算术运算符**\n\n- 介绍 \n\n 算术运算符是对数值类型的变量进行运算的,在 Java 程序中使用的非常多。 \n\n\n\n- 算术运算符一览\n\n> `% 的本质\t看一个公式:a % b = a - a / b * b`\n>\n> `a % b\t当 a 是小数时,公式 = a - (int)a / b * b`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082301910.png\" alt=\"image-20220508230138805\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092131114.png\" alt=\"image-20220509213107049\" style=\"zoom:67%;\" />\n\n\n\n---\n\n- 案例演示\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082304543.png\" alt=\"image-20220508230401456\" style=\"zoom: 67%;\" />\n\n```java\n/**\n * 演示算术运算符的使用 \n */\npublic class ArithmeticOperator { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t// /使用\n\t\tSystem.out.println(10 / 4); //从数学来看是2.5, java中 2\n\t\tSystem.out.println(10.0 / 4); //java是2.5\n\t\t// 注释快捷键 ctrl + /, 再次输入 ctrl + / 取消注释\n\t\tdouble d = 10 / 4;//java中10 / 4 = 2, 2=>2.0 \n\t\tSystem.out.println(d);// 是2.0\n\n\t\t// % 取模 ,取余\n\t\t// 在 % 的本质 看一个公式!!!! a % b = a - a / b * b\n\t\t// -10 % 3 => -10 - (-10) / 3 * 3 = -10 + 9 = -1\n\t\t// 10 % -3 = 10 - 10 / (-3) * (-3) = 10 - 9 = 1\n\t\t// -10 % -3 = (-10) - (-10) / (-3) * (-3) = -10 + 9 = -1\n\t\tSystem.out.println(10 % 3); //1\n\n\t\tSystem.out.println(-10 % 3); // -1\n\t\tSystem.out.println(10 % -3); //1\n\t\tSystem.out.println(-10 % -3);//-1\n\n\t\t//++的使用\n\t\t//\n\t\tint i = 10;\n\t\ti++;//自增 等价于 i = i + 1; => i = 11\n\t\t++i;//自增 等价于 i = i + 1; => i = 12\n\t\tSystem.out.println(\"i=\" + i);//12\n\n\t\t/*\n\t\t作为表达式使用\n 前++:++i先自增后赋值\n 后++:i++先赋值后自增\n\t\t */\n\t\tint j = 8;\n\t\t//int k = ++j; //等价 j=j+1;k=j; \n\t\tint k = j++; // 等价 k =j;j=j+1;\n\t\tSystem.out.println(\"k=\" + k + \"j=\" + j);//8 9\n\t}\n}\n```\n\n\n\n- 细节说明\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082326729.png\" alt=\"image-20220508232614621\" style=\"zoom:67%;\" />\n\n\n\n---\n\n算数运算符使用\n\n- 面试题\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082326225.png\" alt=\"image-20220508232646110\" style=\"zoom: 67%;\" />\n>\n> - 自增,自减课堂练习, 看看输出什么\n>\n> > <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082338509.png\" alt=\"image-20220508233829424\" style=\"zoom:67%;\" />\n\n```java\n//练习\n\npublic class ArithmeticOperatorExercise01 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\t// int i = 1;//i->1\n\t\t// i = i++; //规则使用临时变量: (1) temp=i;(2) i=i+1;(3)i=temp;\n\t\t// System.out.println(i); // 1\n\n\n\t\t// int i=1;\n\t\t// i=++i; //规则使用临时变量: (1) i=i+1;(2) temp=i;(3)i=temp;\n\t\t// System.out.println(i); //2\n\t\t// \n\t\t// 测试输出\n\t\tint i1 = 10;\n\t int i2 = 20;\n int i = i1++;\n System.out.print(\"i=\"+i);//10\n System.out.println(\"i2=\"+i2);//20\n i = --i2; \n System.out.print(\"i=\"+i);//19\n System.out.println(\"i2=\"+i2);//19\n\n\n\t}\n}\n```\n\n\n\n- 课堂练习 2\t\t//ArithmeticOperatorExercise02.java \n\n1. 假如还有 59 天放假,问:合 xx 个星期零 xx 天 \n\n2. 定义一个变量保存华氏温度,华氏温度转换摄氏温度的公式为:5/9*(华氏温度-100),请求出华氏温度对应的摄氏温度。 [234.5] \n\n3. 代码 \n\n```java\n//课堂练习\n\npublic class ArithmeticOperatorExercise02 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//1.需求:\n\t\t//假如还有59天放假,问:合xx个星期零xx天\n\t\t//2.思路分析\n\t\t//(1) 使用int 变量 days 保存 天数\n\t\t//(2) 一个星期是7天 星期数weeks: days / 7 零xx天leftDays days % 7\n\t\t//(3) 输出\n\n\t\t//3.走代码\n\t\tint days = 25911;\n\t\tint weeks = days / 7;\n\t\tint leftDays = days % 7;\n\t\tSystem.out.println(days + \"天 合\" + weeks + \"星期零\" \n\t\t\t+ leftDays + \"天\");\n\n\t\t//1.需求\n\t\t//定义一个变量保存华氏温度,华氏温度转换摄氏温度的公式为\n\t\t//:5/9*(华氏温度-100),请求出华氏温度对应的摄氏温度\n\t\t//\n\t\t//2思路分析\n\t\t//(1) 先定义一个double huaShi 变量保存 华氏温度\n\t\t//(2) 根据给出的公式,进行计算即可5/9*(华氏温度-100)\n\t\t// 考虑数学公式和java语言的特性\n\t\t//(3) 将得到的结果保存到double sheShi\n\t\t//3走代码\n\t\tdouble huaShi = 1234.6;\n\t\tdouble sheShi = 5.0 / 9 * (huaShi - 100);\n\t\tSystem.out.println(\"华氏温度\" + huaShi \n\t\t\t+ \" 对应的摄氏温度=\" + sheShi);\n\n\t}\n}\n```\n\n\n\n---\n\n### 二. 关系运算符(比较运算符) \n\n**关系运算符(比较运算符) **\n\n- **介绍**\n\n1. 关系运算符的结果都是 boolean 型,也就是要么是 true,要么是 false \n\n2. 关系表达式 经常用在 if 结构的条件中或循环结构的条件中 \n\n\n\n- **关系运算符一览**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205090011985.png\" alt=\"image-20220509001153917\" style=\"zoom: 67%;\" />\n\n\n\n- **案例演示**\n\n案例演示关系运算符的使用(RelationalOperator.java)。 \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205090015981.png\" alt=\"image-20220509001501843\" style=\"zoom: 67%;\" />\n\n```java\n//演示关系运算符的使用\n//\n\npublic class RelationalOperator { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\tint a = 9; //老韩提示: 开发中,不可以使用 a, b \n\t\tint b = 8;\n\t\tSystem.out.println(a > b);\t//T \n\t\tSystem.out.println(a >= b); //T\n\t\tSystem.out.println(a <= b); //F\n\t\tSystem.out.println(a < b); //F\n\t\tSystem.out.println(a == b); //F\n\t\tSystem.out.println(a != b); //T\n\t\tboolean flag = a > b; //T\n\t\tSystem.out.println(\"flag=\" + flag);\n\t}\n}\n```\n\n\n\n- **细节说明**\n\n1. 关系运算符的结果都是 boolean 型,也就是要么是 true,要么是 false。 \n\n2. 关系运算符组成的表达式,我们称为关系表达式。 a > b \n\n3. 比较运算符\"==\"不能误写成\"=\" \n\n\n\n---\n\n### 三. 逻辑运算符\n\n**逻辑运算符**\n\n- **介绍**\n\n​\t\t用于连接多个条件(多个关系表达式),最终的结果也是一个 boolean 值。 \n\n\n\n- **逻辑运算符一览**\n\n分为两组学习 \n\n1. `短路与 && , 短路或 ||,取反 ! `\n\n2. `逻辑与 &,逻辑或 |,^ 逻辑异或 `\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205090021561.png\" alt=\"image-20220509002134483\" style=\"zoom: 67%;\" />\n\n\n\n- [x] **说明逻辑运算规则**: \n\n1. a&b : & 叫逻辑与:规则:当 a 和 b 同时为 true ,则结果为 true, 否则为 false \n\n2. a&&b : && 叫短路与:规则:当 a 和 b 同时为 true ,则结果为 true,否则为 false \n\n3. a|b : | 叫逻辑或,规则:当 a 和 b ,有一个为 true ,则结果为 true,否则为 false \n\n4. a||b : || 叫短路或,规则:当 a 和 b ,有一个为 true ,则结果为 true,否则为 false \n\n5. !a : 叫取反,或者非运算。当 a 为 true, 则结果为 false, 当 a 为 false 是,结果为 true \n\n6. a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为 true, 否则为 false\n\n\n\n---\n\n#### 短路与逻辑与\n\n- **&& 和 & 基本规则**\n\n| 名称 | 语法 | 特点 |\n| -------- | -------------- | ----------------------------------------- |\n| 短路与&& | 条件 1&&条件 2 | 两个条件都为 true,结果为 true,否则 false |\n| 逻辑与& | 条件 1&条件 2 | 两个条件都为 true,结果为 true,否则 false |\n\n\n\n- **&& 和 & 案例演示**\n\n案例演示&& 和 & 运算符的使用(LogicOperator01.java)。\n\n```java\n/**\n * 演示逻辑运算符的使用\n */\n\npublic class LogicOperator01 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//&&短路与 和 & 案例演示\n\t\tint age = 50;\n\t\tif(age > 20 && age < 90) {\n\t\t\tSystem.out.println(\"ok100\");\n\t\t}\n\n\t\t//&逻辑与使用\n\t\tif(age > 20 & age < 90) {\n\t\t\tSystem.out.println(\"ok200\");\n\t\t}\n\n\t\t//区别\n\t\tint a = 4;\n\t\tint b = 9;\n\t\t//对于&&短路与而言,如果第一个条件为false ,后面的条件不再判断\n\t\t//对于&逻辑与而言,如果第一个条件为false ,后面的条件仍然会判断\n\t\tif(a < 1 & ++b < 50) {\n\t\t\tSystem.out.println(\"ok300\");\n\t\t}\n\t\tSystem.out.println(\"a=\" + a + \" b=\" + b);// 4 10\n\t\t\n\t}\n}\n```\n\n\n\n- **&& 和 & 使用区别**\n\n1. &&短路与:如果第一个条件为 false,则第二个条件不会判断,最终结果为 false,效率高 \n\n2. & 逻辑与:不管第一个条件是否为 false,第二个条件都要判断,效率低 \n\n3. 开发中, 我们使用的基本是使用短路与`&&`, 效率高\n\n\n\n---\n\n#### 短路或逻辑或\n\n- **|| 和 | 基本规则**\n\n| 名称 | 语法 | 特点 |\n| ---------- | --------------- | -------------------------------------------------- |\n| 短路或\\|\\| | 条件 1\\|\\|条件2 | 两个条件中只要有一个成立,结果为 true,否则为 false |\n| 逻辑或\\| | 条件 1\\|条件2 | 只要有一个条件成立,结果为 true,否则为 false |\n\n\n\n- **|| 和 | 案例演示**\n\n案例演示&& || !运算符的使用(LogicOperator02.java)。\n\n```java\n//演示| || 使用\n\npublic class LogicOperator02 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//||短路或 和 |逻辑或 案例演示\n\t\t//|| 规则: 两个条件中只要有一个成立,结果为true,否则为false\n\t\t//| 规则: 两个条件中只要有一个成立,结果为true,否则为false\n\t\tint age = 50;\n\t\tif(age > 20 || age < 30) {\n\t\t\tSystem.out.println(\"ok100\");\n\t\t}\n\n\t\t//|逻辑或使用\n\t\tif(age > 20 | age < 30) {\n\t\t\tSystem.out.println(\"ok200\");\n\t\t}\n\n\t\t//看看区别\n\t\t//(1)||短路或:如果第一个条件为true,\n\t\t//则第二个条件不会判断,最终结果为true,效率高\n\t\t//(2)| 逻辑或:不管第一个条件是否为true,第二个条件都要判断,效率低\n\t\tint a = 4;\n\t\tint b = 9;\n\t\tif( a > 1 || ++b > 4) { // 可以换成 | 测试\n\t\t\tSystem.out.println(\"ok300\");\n\t\t}\n\t\tSystem.out.println(\"a=\" + a + \" b=\" + b); //4 9\n\n\t}\n}\n```\n\n\n\n- **|| 和 | 使用区别**\n\n1. ||短路或:如果第一个条件为 true,则第二个条件不会判断,最终结果为 true,效率高 \n\n2. | 逻辑或:不管第一个条件是否为 true,第二个条件都要判断,效率低 \n\n3. 开发中,我们基本使用 `||`\n\n\n\n---\n\n#### 逻辑非逻辑异或\n\n- **! 取反 基本规则**\n\n| 名称 | 语法 | 特点 |\n| ------------ | ----- | ------------------------------------------- |\n| ! 非(取反) | !条件 | 如果条件本身成立,结果为 false,否则为 true |\n\n\n\n- **! 案例演示**\n\n案例演示 !运算符的使用(InverseOperator.java)。 \n\n```java\n//!和^案例演示\n\npublic class InverseOperator { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//! 操作是取反 T->F , F -> T\n\t\tSystem.out.println(60 > 20); //T\n\t\tSystem.out.println(!(60 > 20)); //F\n\n\t\t//a^b: 叫逻辑异或,当 a 和 b 不同时,则结果为true, 否则为false\n\t\tboolean b = (10 > 1) ^ ( 3 > 5);\n\t\tSystem.out.println(\"b=\" + b);//T\n\t}\n}\n```\n\n\n\n- **^ 案例演示**\n\na^b: 叫逻辑异或,当 a 和 b 不同时,则结果为 true, 否则为 false\n\n^逻辑异或,System.out.println( (4 < 1) ^ (6 > 3) ); // T\n\n\n\n---\n\n**逻辑运算符练习**\n\n- 练习题 1 请写出每题的输出结果\n\n> x ++== 6,先比较,再自增\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091319381.png\" alt=\"image-20220509131958291\" style=\"zoom:67%;\" />\n\n```java\n//验证\n\npublic class Test { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t// int x = 5;\n\t\t// int y=5;\n\t\t// if(x++==6 & ++y==6){ //逻辑与\n\t\t// \tx = 11;\n\t\t// }\n\t\t// System.out.println(\"x=\"+x+\",y=\"+y);\n\t\t// //6, 6\n\t\t// int x = 5,y = 5;\n\n\t\t// if(x++==6 && ++y==6){\n\t\t// \tx = 11;\n\t\t// }\n\t\t// System.out.println(\"x=\"+x+\",y=\"+y);\n\t\t// //6, 5\n\t\t// \n\t\t// int x = 5,y = 5;\n\t\t// if(x++==5 | ++y==5){\n\t\t// \tx =11;\n\t\t// }\n\t\t// System.out.println(\"x=\"+x+\",y=\"+y);\n\t\t//11, 6\n\t\t//\n\t\t// int x = 5,y = 5;\n\t\t// if(x++==5 || ++y==5){\n\t\t// \tx =11;\n\t\t// }\n\t\t// System.out.println(\"x=\"+x+\",y=\"+y);\n\t\t//11, 5\n\t\t//\n\t\t//\n\t\tboolean x=true;\n\t\tboolean y=false;\n\t\tshort z=46;\n\t\tif( (z++==46)&& (y=true) ) z++; \n\t\tif((x=false) || (++z==49)) z++; \n\t\tSystem. out.println(\"z=\"+z); //50 \n\n\t}\n}\n```\n\n\n\n- 练习题 2 请写输出结果\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091324402.png\" alt=\"image-20220509132450314\" style=\"zoom:67%;\" />\n\n\n\n---\n\n### 四. 赋值运算符\n\n- **介绍**\n\n赋值运算符就是将某个运算后的值,赋给指定的变量。 \n\n\n\n- **赋值运算符的分类**\n\n- [x] 基本赋值运算符 = int a = 10; \n\n- [x] 复合赋值运算符 \n\n​\t\t+= ,-= ,*= , /= ,%= 等 , 重点讲解一个 += ,其它的使用是一个道理 \n\n​\t\ta += b; \t\t[等价 a = a + b; ] \n\n​\t\ta -= b; \t\t [等价 a = a - b; ]\n\n\n\n- **案例演示**\n\n案例演示赋值运算符的基本使用。AssignOperator.java \n\n1. 赋值基本案例 [int num1 = 10] \n\n2. += 的使用案例 \n\n```java\n//演示赋值运算符的使用\n\npublic class AssignOperator { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\tint n1 = 10;\n\t\tn1 += 4;// n1 = n1 + 4;\n\t\tSystem.out.println(n1); // 14\n\t\tn1 /= 3;// n1 = n1 / 3;//4\n\t\tSystem.out.println(n1); // 4\n\n\t\t//复合赋值运算符会进行类型转换\n\t\tbyte b = 3;\n\t\tb += 2; // 等价 b = (byte)(b + 2);\n\t\tb++; // b = (byte)(b+1);\n\t\t\n\t}\n}\n```\n\n\n\n- **赋值运算符特点**\n\n1. 运算顺序从右往左 int num = a + b + c; \n\n2. 赋值运算符的左边 只能是变量,右边 可以是变量、表达式、常量值 \n\n​\t\tint num = 20; int num2= 78 * 34 - 10; int num3 = a; \n\n3. 复合赋值运算符等价于下面的效果 \n\n​\t\t比如:a+=3;等价于 a=a+3; 其他类推 \n\n4. 复合赋值运算符会进行类型转换。 \n\n​\t\tbyte b = 2; b+=3; b++;\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091347006.png\" alt=\"image-20220509134732958\" style=\"zoom: 67%;\" />\n\n\n\n---\n\n### 五. 三元运算符\n\n- **基本语法**\n\n条件表达式 ? 表达式 1: 表达式 2; \n\n`运算规则`: \n\n1. 如果条件表达式为 true,运算后的结果是表达式 1; \n\n2. 如果条件表达式为 false,运算后的结果是表达式 2; \n\n口诀: [一灯大师:**一真大师**] \n\n\n\n- **案例演示** TernaryOperator.java\n\n```java\n//三元运算符使用\n\npublic class TernaryOperator { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\tint a = 10;\n\t\tint b = 99;\n\t\t// 解读\n\t\t// 1. a > b 为 false\n\t\t// 2. 返回 b--, 先返回 b的值,然后在 b-1\n\t\t// 3. 返回的结果是99 \n\t\tint result = a > b ? a++ : b--;\n\t\tSystem.out.println(\"result=\" + result);\n\t\tSystem.out.println(\"a=\" + a);\n\t\tSystem.out.println(\"b=\" + b);\n\n\t}\n}\n```\n\n\n\n---\n\n- **使用细节** TernaryOperatorDetail.java\n\n1. 表达式 1 和表达式 2 要为可以赋给接收变量的类型(或可以自动转换) \n\n2. 三元运算符可以转成 if--else 语句\n\n​\t\tint res = a > b ? a++ : --b; \n\n​\t\tif ( a > b) res = a++; \n\n​\t\telse res = --b; \n\n```java\n//三元运算符细节\n\npublic class TernaryOperatorDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//表达式1和表达式2要为可以赋给接收变量的类型\n\t\t//(或可以自动转换/或者强制转换)\n\t\tint a = 3;\n\t\tint b = 8;\n\t\tint c = a > b ? (int)1.1 : (int)3.4;//可以的\n\t\tdouble d = a > b ? a : b + 3;//可以的,满足 int -> double\n\t}\n}\n```\n\n\n\n- **课堂练习**\n\n**案例:实现三个数的最大值** TernaryOperatorExercise.java\n\n```java\npublic class TernaryOperatorExercise { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//案例:实现三个数的最大值\n\t\tint n1 = 553;\n\t\tint n2 = 33;\n\t\tint n3 = 123;\n\t\t//思路\n\t\t//1. 先得到 n1 和 n2 中最大数 , 保存到 max1\n\t\t//2. 然后再 求出 max1 和 n3中的最大数,保存到 max2\n\t\t\n\t\tint max1 = n1 > n2 ? n1 : n2;\n\t\tint max2 = max1 > n3 ? max1 : n3;\n\t\tSystem.out.println(\"最大数=\" + max2);\n\n\t\t//使用一条语句实现, 推荐使用上面方法\n\t\t//老师提示: 后面我们可以使用更好方法,比如排序\n\t\t// int max = (n1 > n2 ? n1 : n2) > n3 ? \n\t\t// \t\t\t\t(n1 > n2 ? n1 : n2) : n3;\n\t\t// System.out.println(\"最大数=\" + max);\t\n\t\t// \n\t\t\n\t}\n}\n```\n\n\n\n---\n\n### 六. 运算符优先级\n\n**运算符优先级**\n\n1. 运算符有不同的优先级,所谓优先级就是表达式运算中的运算顺序。如右表,上一行运算符总优先于下一行。 \n\n2. 只有单目运算符、赋值运算符是从右向左运算的。 \n\n3. 一览表, 不要背,使用多了,就熟悉了\n\n> **梳理小节**:小伙伴有一个大致印象,使用多了,就熟悉\n>\n> 1. () , {} 等\n> 2. 单目运算 ++ --\n> 3. 算数运算符\n> 4. 位移运算符\n> 5. 比较运算符\n> 6. 逻辑运算符\n> 7. 三元运算符\n> 8. 赋值运算符\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091622856.png\" alt=\"image-20220509162226749\" style=\"zoom: 67%;\" />\n\n\n\n---\n\n## 标识符命名规则和规范\n\n### 七. 标识符规则\n\n**标识符的命名`规则`和`规范`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091628391.png\" alt=\"image-20220509162810243\" style=\"zoom:67%;\" />\n\n```java\n\t\tint abcclass = 10;\n\t\tint n = 40;\n\t\tint N = 50;\n\t\tSystem.out.println(\"n=\" + n);//40\n\t\tSystem.out.println(\"N=\" + N);//50\n\n\t\t//? abc 和 aBc 是两个不同变量\n\t\tint abc = 100;\n\t\tint aBc = 200;\n\t\t\n\t\t//int a b = 300;\t//x\n\t\t//int a-b=10;\n\t\tint goto1 = 10;\n```\n\n\n\n- **判断下面变量名是否正确**\n\n```java\nhsp\t\t//ok \nhsp12\t//ok \n1hsp\t//错误, 数字不能开头 \nh-s\t\t// 错误 , 不能有 - \nx h\t\t// 错误, 有空格 \nh$4\t\t// ok \nclass\t//错误,class 关键字 \nint \t// 错误 ,int 是关键字 \ndouble\t//错误 ,double 是关键字 \npublic\t//错误 ,public 是关键字 \nstatic\t//错误 ,static 是关键字 \ngoto\t//错误, goto 是保留字 \nstu_name\t//ok\n```\n\n\n\n---\n\n### 八. 标识符规范\n\n**标识符命名规范[更加专业]**\n\n1. 包名:多单词组成时所有字母都小写:aaa.bbb.ccc //比如 com.hsp.crm \n\n2. 类名、接口名:多单词组成时,所有单词的首字母大写:XxxYyyZzz [大驼峰] \n\n​\t\t比如: TankShotGame \n\n3. 变量名、方法名:多单词组成时,第一个单词首字母小写,第二个单词开始每个单词首字母大写:xxxYyyZzz [小驼峰, 简称 驼峰法] \n\n​\t\t比如: tankShotGame \n\n4. 常量名:所有字母都大写。多单词时每个单词用下划线连接:XXX_YYY_ZZZ \n\n​\t\t比如 :定义一个所得税率 TAX_RATE \n\n5. 后面我们学习到 类,包,接口,等时,我们的命名规范要这样遵守,更加详细的看文档.\n\n\n\n---\n\n### 九. 关键字保留字\n\n**关键字**\n\n关键字的定义和特点 (**`不用背`**) \n\n定义:被 Java 语言赋予了特殊含义,用做 **专门用途的字符串**(单词) \n\n特点:关键字中所有字母都为小写\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091647948.png\" alt=\"image-20220509164734847\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091647396.png\" alt=\"image-20220509164755233\" style=\"zoom:67%;\" />\n\n\n\n---\n\n**保留字**\n\n- **介绍**\n\n​\t\tJava 保留字:现有 Java 版本**尚未使用**,但**以后版本可能会作为关键字使用**。自己命名标识符时要避免使用这些保留字 \n\nbyValue、cast、future、 generic、 inner、 operator、 outer、 rest、 var 、 goto 、const \n\n\n\n---\n\n## 键盘输入\n\n### 十. 键盘输入\n\n**键盘输入语句**\n\n- **介绍**\n\n在编程中,需要接收用户输入的数据,就可以使用键盘输入语句来获取。Input.java , 需要一个 扫描器(对象), 就是 Scanner\n\n\n\n- **步骤 :**\n\n1. 导入该类的所在包, java.util.* \n\n2. 创建该类对象(声明变量) \n\n3. 调用里面的功能 \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091653715.png\" alt=\"image-20220509165317654\" style=\"zoom: 67%;\" />\n\n\n\n- **案例演示:** \n\n要求:可以从控制台接收用户信息,【姓名,年龄,薪水】\n\n```java\nimport java.util.Scanner;//表示把java.util下的Scanner类导入 \npublic class Input { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//演示接受用户的输入\n\t\t//步骤\n\t\t//Scanner类 表示 简单文本扫描器,在java.util 包\n\t\t//1. 引入/导入 Scanner类所在的包\n\t\t//2. 创建 Scanner 对象 , new 创建一个对象,体会\n\t\t// myScanner 就是 Scanner类的对象\n\t\tScanner myScanner = new Scanner(System.in);\n\t\t//3. 接收用户输入了, 使用 相关的方法\n\t\tSystem.out.println(\"请输入名字\");\n\n\t\t//当程序执行到 next 方法时,会等待用户输入~~~\n\t\tString name = myScanner.next(); //接收用户输入字符串\n\t\tSystem.out.println(\"请输入年龄\");\n\t\tint age = myScanner.nextInt(); //接收用户输入int\n\t\tSystem.out.println(\"请输入薪水\");\n\t\tdouble sal = myScanner.nextDouble(); //接收用户输入double\n\t\tSystem.out.println(\"人的信息如下:\");\n\t\tSystem.out.println(\"名字=\" + name \n\t\t\t+ \" 年龄=\" + age + \" 薪水=\" + sal);\n\n\t}\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091705772.png\" alt=\"image-20220509170543727\" style=\"zoom:67%;\" />\n\n\n\n---\n\n## 进制\n\n### 十一. 四种进制介绍\n\n**进制(程序员的基本功)**\n\n- **进制介绍**\n\n对于整数,有四种表示方式: \n\n二进制:0,1 ,满 2 进 1.以 0b 或 0B 开头。 \n\n十进制:0-9 ,满 10 进 1。 \n\n八进制:0-7 ,满 8 进 1. 以数字 0 开头表示。 \n\n十六进制:0-9 及 A(10)-F(15),满 16 进 1. 以 **0x** **或** **0X** 开头表示。此处的 A-F 不区分大小写。\n\n\n\n- **举例说明** BinaryTest.java\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091711778.png\" alt=\"image-20220509171113729\" style=\"zoom: 80%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091713548.png\" alt=\"image-20220509171329500\" style=\"zoom: 80%;\" />\n\n```java\n//演示四种进制\n//\npublic class BinaryTest { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//n1 二进制\n\t\tint n1 = 0b1010;\n\t\t//n2 10进制\n\t\tint n2 = 1010;\n\t\t//n3 8进制\n\t\tint n3 = 01010;\n\t\t//n4 16进制\n\t\tint n4 = 0X10101;\n\t\tSystem.out.println(\"n1=\" + n1);\n\t\tSystem.out.println(\"n2=\" + n2);\n\t\tSystem.out.println(\"n3=\" + n3);\n\t\tSystem.out.println(\"n4=\" + n4);\n\t\tSystem.out.println(0x23A);\n\n\t}\n}\n```\n\n\n\n- **进制的图示**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091714710.png\" alt=\"image-20220509171412620\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091715746.png\" alt=\"image-20220509171547659\" style=\"zoom:67%;\" />\n\n\n\n---\n\n**进制的转换(基本功)**\n\n**进制转换的介绍**\n\n- 第一组: \n\n1. 二进制转十进制 \n\n2. 八进制转十进制 \n\n3. 十六进制转十进制 \n\n- 第二组: \n\n1. 十进制转二进制 \n\n2. 十进制转八进制 \n\n3. 十进制转十六进制 \n\n- 第三组 \n\n1. 二进制转八进制 \n\n2. 二进制转十六进制 \n\n- 第四组 \n\n1. 八进制转二进制 \n\n2. 十六进制转二进制 \n\n\n\n- **其他进制转十进制**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091721120.png\" style=\"zoom: 67%;\" />\n\n\n\n### 十二. 2进制转10进制\n\n**二进制转换成十进制示例**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091722031.png\" alt=\"image-20220509172209929\" style=\"zoom: 67%;\" />\n\n\n\n### 十三. 8进制转10进制\n\n**八进制转换成十进制示例**\n\n> ![image-20220509172629860](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091726949.png)\n\n\n\n### 十四. 16进制转10进制\n\n**十六进制转换成十进制示例**\n\n规则:`从最低位(右边)开始,将每个位上的数提取出来,乘以 16 的(位数-1)次方,然后求和`。 \n\n\n\n案例:请将 0x23A 转成十进制的数 \n\n0x23A = 10 * 16^0 + 3 * 16 ^ 1 + 2 * 16^2 = 10 + 48 + 512 = 570 \n\n```java\n\t\tSystem.out.println(0x23A);\t//570\n```\n\n\n\n课堂练习:请将 \n\n0b110001100 转成 十进制 \n\n02456 转成十进制 \n\n0xA45 转成十进制 \n\n\n\n---\n\n**十进制转其它进制**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091733796.png\" alt=\"image-20220509173320742\" style=\"zoom: 67%;\" />\n\n\n\n### 十五. 10进制转2进制\n\n**十进制转换成二进制**\n\n规则:`将该数不断除以 2,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的二进制`。 \n\n案例:请将 `34` 转成二进制 = `0B00100010`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091941102.png\" alt=\"image-20220509194122002\" style=\"zoom:50%;\" />\n\n\n\n### 十六. 10进制转8进制\n\n**十进制转换成八进制**\n\n规则:`将该数不断除以 8,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的八进制`。 \n\n案例:请将 `131` 转成八进制 => `0203`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091945088.png\" alt=\"image-20220509194522001\" style=\"zoom:50%;\" />\n\n\n\n### 十七. 10进制转16进制\n\n**十进制转换成十六进制**\n\n规则:`将该数不断除以 16,直到商为 0 为止,然后将每步得到的余数倒过来,就是对应的十六进制`。 \n\n案例:请将 `237` 转成十六进制 => `0xED`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091946894.png\" alt=\"image-20220509194651804\" style=\"zoom:50%;\" />\n\n\n\n- 课堂练习:(一定练习,使用计算器/用程序去验证) \n\n​\t\t123 转成 二进制 => ? \n\n​\t\t678 转成八进制 => 04126\n\n​\t\t8912 转成十六进制 => ? \n\n\n\n---\n\n**二进制转换成八进制、十六进制**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091950138.png\" alt=\"image-20220509195013056\" style=\"zoom:67%;\" />\n\n\n\n### 十八. 2进制转8进制\n\n规则:`从低位开始,将二进制数每三位一组,转成对应的八进制数即可`。 \n\n案例:请将 `ob11010101` 转成八进制 \n\nob11(3)010(2)101(5) => `0325`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091954021.png\" alt=\"image-20220509195435973\" style=\"zoom: 67%;\" />\n\n\n\n### 十九. 2进制转16进制\n\n规则:`从低位开始,将二进制数每四位一组,转成对应的十六进制数即可`。 \n\n案例:请将 `ob11010101` 转成十六进制 \n\nob1101(D)0101(5) = `0xD5 `\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091957282.png\" alt=\"image-20220509195728223\" style=\"zoom:67%;\" />\n\n\n\n课堂练习:请将 \n\n​\t\t0b11100101 转成 八进制 \n\n​\t\t0b1110010110 转成 十六进制 => 0x396\n\n\n\n---\n\n**八进制、十六进制转成二进制**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205091959650.png\" alt=\"image-20220509195905562\" style=\"zoom:67%;\" />\n\n\n\n### 二十. 8进制转2进制\n\n规则:`将八进制数每 1 位,转成对应的一个 3 位的二进制数即可`。 \n\n案例:请将 `0237` 转成二进制 \n\n02(010)3(011)7(111) = `0b10011111 `\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092004043.png\" alt=\"image-20220509200424994\" style=\"zoom: 67%;\" />\n\n\n\n### 二一. 16进制转2进制\n\n规则:`将十六进制数每 1 位,转成对应的` **`4 位的一个二进制数`**`即可`。 \n\n案例:请将 `0x23B` 转成二进制 \n\n0x2(0010)3(0011)B(1011) = `0b001000111011`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092015230.png\" alt=\"image-20220509201525174\" style=\"zoom:67%;\" />\n\n\n\n- 课堂练习:请将 \n\n01230 转成 二进制 \n\n0xAB29 转成二进制 => 0xA(1010)B(1011)2(0010)9(1001) =>0b1010101100101001\n\n\n\n---\n\n### 二二. 位运算思考题\n\n**位运算的思考题**\n\n1. 请看下面的代码段,回答 a,b,c,d,e 结果是多少? \n\n```java\npublic static void maiin(String []args) \n{ \n\n\tint a=1>>2;\t// 1 向右位移 2 位 \n\n\tint b=-1>>2;//算术右移 \n\n\tint c=1<<2;//算术左移 \n\n\tint d=-1<<2;// \n\n\tint e=3>>>2;//无符号右移 \n\n\t//a,b,c,d,e 结果是多少 \n\n\tSystem.out.println(\"a=\"+a); \n\n\tSystem.out.println(\"b=\"+b); \n\n\tSystem.out.println(\"c=\"+c); \n\n\tSystem.out.println(\"d=\"+d); \n\n\tSystem.out.println(\"e=\"+e); \n\n} \n```\n\n\n\n2. 请回答在 java 中,下面的表达式运算的结果是: (位操作), 晚上练习 \n\n```java\n~2=?\t// 按位取反 \n\n2&3=?\t// 2 按位与 3 \n\n2|3=? \n\n~-5=? \n\n13&7=? \n\n5|4=? \n\n-3^3=?\t//^ 按位异或\n```\n\n\n\n---\n\n### 二三. 原码反码补码\n\n**二进制在运算中的说明**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092025779.png\" alt=\"image-20220509202541652\" style=\"zoom: 67%;\" />\n\n\n\n**`原码、反码、补码(重点 难点)`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092027076.png\" alt=\"image-20220509202730922\" style=\"zoom:67%;\" />\n>\n> 第 7 点,因为补码把正数、负数统一起来了\n\n\n\n---\n\n### 二四. 位运算\n\n**位运算符**\n\n- java 中有 7 个位运算(&、|、^、~、>>、<<和 >>>)\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092039745.png\" alt=\"image-20220509203957600\" style=\"zoom: 50%;\" />\n\n```java\n//位运算\n\n\npublic class BitOperator { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n // 2&3\n\t\t//看老师的推导过程\n\t\t//1. 先得到 2的补码 => 2的原码 00000000 00000000 00000000 00000010\n\t\t// 2的补码 00000000 00000000 00000000 00000010\n\t\t//2. 3的补码 3的原码 00000000 00000000 00000000 00000011\n\t\t// 3的补码 00000000 00000000 00000000 00000011\n\t\t//3. 按位&\n\t\t// 00000000 00000000 00000000 00000010\n\t\t// 00000000 00000000 00000000 00000011 \n\t\t// 00000000 00000000 00000000 00000010 & 运算后的补码\n\t\t// 运算后的原码 也是 00000000 00000000 00000000 00000010\n\t\t// 结果就是 2\n\t\tSystem.out.println(2&3);//2\n\n // ~-2\n\t\t//推导\n\t\t//1. 先得到 -2的原码 10000000 00000000 00000000 00000010\n\t\t//2. -2的 反码 \t 11111111 11111111 11111111 11111101\n\t\t//3. -2的 补码 11111111 11111111 11111111 11111110\n\t\t//4. ~-2操作 00000000 00000000 00000000 00000001运算后的补码\n\t\t//5. 运算后的原码 就是 00000000 00000000 00000000 00000001 => 1\n\t\tSystem.out.println(~-2);//1\n\n\t\t//推导\n\t\t//1. 得到2的补码 00000000 00000000 00000000 00000010\n\t\t//2. ~2操作 11111111 11111111 11111111 11111101 运算后的补码\n\t\t//3. 运算后的反码 11111111 11111111 11111111 11111100\n\t\t//4. 运算后的原码 10000000 00000000 00000000 00000011=>-3\n\t\tSystem.out.println(~2); //-3\n\t}\n}\n```\n\n\n\n**位运算符**\n\n- 还有 3 个位运算符 ``>>、<< 和 >>>`` , 运算规则:\n\n1. 算术右移 >>:低位溢出,符号位不变,并用符号位补溢出的高位 \n\n2. 算术左移 <<: 符号位不变,低位补 0 \n\n3. \\>>> 逻辑右移也叫无符号右移,运算规则是: 低位溢出,高位补 0 \n\n4. 特别说明:没有 <<< 符号 \n\n\n\n- 应用案例 BitOperator02.java\n\n1. int a=1>>2; //1 => 00000001 => 00000000 本质 1 / 2 / 2 =0 \n\n2. int c=1<<2; //1 => 00000001 => 00000100 本质 1 * 2 * 2 = 4 \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092121652.png\" alt=\"image-20220509212136583\" style=\"zoom:67%;\" />\n\n```java\n\npublic class BitOperator02 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(1 >> 2); //0\n\t\tSystem.out.println(1 << 2); //4\n\t\tSystem.out.println(4 << 3); // 4 * 2 * 2 * 2 = 32\n\t\tSystem.out.println(15 >> 2); // 15 / 2 / 2 = 3\n\n\t}\n}\n```\n\n\n\n- 完成前面的案例\n\n建议:掌握老师讲解的即可,不用再深入\n\n\n\n---\n\n**本章作业**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092125669.png\" alt=\"image-20220509212539569\" style=\"zoom:50%;\" />\n\n```java\n\t\tSystem.out.println(-10.4%3); // -1.4近似值\n\n\t\tint i=66;\n\t\tSystem.out.println(++i+i); //134\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092135664.png\" alt=\"image-20220509213557540\" style=\"zoom:50%;\" />\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205092137307.png\" alt=\"image-20220509213758196\" style=\"zoom:50%;\" />\n\n\n\n---\n\n","tags":["Java","运算符","进制"],"categories":["Java"]},{"title":"02_Java-变量-数据类型","url":"/posts/47697.html","content":"[视频链接:https://www.bilibili.com/video/BV1fh411y7R8](https://www.bilibili.com/video/BV1fh411y7R8)\n\n## 一. 变量\n\n### 变量原理\n\n**变量**\n\n- 为什么需要变量\n\n> 一个程序就是一个世界\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081522508.png\" alt=\"image-20220508152241409\" style=\"zoom:50%;\" />\n\n\n\n- `变量是程序的基本组成单位`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081525550.png\" alt=\"image-20220508152541414\" style=\"zoom:50%;\" />\n\n\n\n- **`简单的原理示意图`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081526570.png\" alt=\"image-20220508152603437\" style=\"zoom:67%;\" />\n\n\n\n---\n\n### 变量概念\n\n**变(变化)量(值)的介绍 **\n\n- 概念\n\n​\t\t**`变量相当于内存中一个数据存储空间`**的表示,你可以把变量看做是一个房间的门牌号,通过**门牌号**我们可以找到房 \n\n间,而通过变量名可以访问到变量(值)。\n\n\n\n- 变量使用的基本步骤\n\n1. 声明变量 \n\n​\t\tint a; \n\n2. 赋值\n\n​\t\ta = 60; //应该这么说: 把 60 赋给 a \n\n3. 使用 System.out.println(a); \n\n​\t\t//也可以一步到位\t[int a = 60; 通常我们是一步完成] \n\n\n\n```java\npublic class Var01 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//声明变量\n\t\tint a;\n\t\ta = 100;\n\t\tSystem.out.println(a); \n\n\t\t//还可以这样使用\n\t\tint b = 800;\n\t\tSystem.out.println(b); \n\t}\n}\n```\n\n\n\n---\n\n### 变量入门\n\n**变量快速入门**\n\n变量使用入门案例 \n\n看演示并对代码进行说明, **演示记录 人的信息的代码**\n\n> ![image-20220508154108162](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081541203.png)\n\n```java\npublic class Var02 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//记录人的信息\n\t\tint age = 30;\n\t\tdouble score = 88.9;\n\t\tchar gender = '男';\n\t\tString name = \"king\";\n\t\t//输出信息, 快捷键\n\t\tSystem.out.println(\"人的信息如下:\");\n\t\tSystem.out.println(name);\n\t\tSystem.out.println(age);\n\t\tSystem.out.println(score);\n\t\tSystem.out.println(gender);\n\t\t\n\t}\n}\n```\n\n\n\n---\n\n### 变量细节\n\n- 变量使用注意事项\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081544320.png\" alt=\"image-20220508154442205\" style=\"zoom: 50%;\" />\n>\n> \n\n```java\npublic class VarDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//变量必须先声明,后使用, 即有顺序\n\t\tint a = 50;//int\n\t\tSystem.out.println(a);//50\n\t\t//该区域的数据/值可以在同一类型范围内不断变化\n\t\t//a = \"jack\"; //×\n\t\ta = 88; //对\n\t\tSystem.out.println(a);//88\n\t\t\n\t\t//变量在同一个作用域内不能重名\n\t\t//int a = 77;//错误\n\n\n\t}\n}\n\nclass Dog {\n\tpublic static void main(String[] args) {\n\t\tint a = 666;//对\n\t}\n}\n```\n\n\n\n---\n\n### 加号使用\n\n- **`程序中 +号的使用`**\n\n> ![image-20220508155649918](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081556066.png)\n\n```java\npublic class Plus { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(100 + 98); //198\n\t\tSystem.out.println(\"100\" + 98);//10098\n\n\t\tSystem.out.println(100 + 3 + \"hello\");//103hello\n\t\tSystem.out.println(\"hello\" + 100 +3); //hello1003\n\n\t}\n}\n```\n\n\n\n---\n\n## 二. 数据类型\n\n**数据类型**\n\n每一种数据都定义了明确的数据类型,在内存中分配了不同大小的内存空间(字节)。\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081601014.png\" alt=\"image-20220508160100958\" style=\"zoom: 67%;\" />\n>\n> ---\n>\n> - [x] `上图说明 [老韩要求小伙伴,背下来!!!!] `\n>\n> 1. **java 数据类型分为两大类 `基本数据类型, 引用类型`**\n> 1. **基本数据类型有 `8 种 数值型 [byte , short , int , long , float ,double] char , boolean` **\n> 1. **`引用类型 [类,接口, 数组]`**\n\n\n\n---\n\n### 整型\n\n**整数类型**\n\n- 基本介绍\n\n> Java 的整数类型就是用于存放整数值的,比如 12 , 30, 3456 等等\n\n\n\n- 案例演示:\n\n> byte n1 = 10; \n>\n> short n2 = 10; \n>\n> int n3 = 10;//4 个字节 \n>\n> long n4 = 10; //8 个字节\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081615524.png\" alt=\"image-20220508161536496\" style=\"zoom: 80%;\" />\n\n\n\n- **`整型的类型`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081612814.png\" alt=\"image-20220508161227727\" style=\"zoom: 67%;\" />\n\n\n\n- **`整型的使用细节`** IntDetail.java\n\n> `bit:计算机中的最小存储单位` ;`byte:计算机中基本存储单位`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081740262.png\" alt=\"image-20220508174011108\" style=\"zoom: 50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081749504.png\" alt=\"image-20220508174900285\" style=\"zoom: 67%;\" />\n\n```java\npublic class IntDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//Java的整型常量(具体值)默认为 int 型,声明long型常量须后加‘l’或‘L’\n\t\tint n1 = 1;//4个字节\n\t\t//int n2 = 1L;\t//不对\n\t\tlong n3 = 1L;\t//对\n\n\t}\n}\n```\n\n\n\n---\n\n### 浮点数\n\n**浮点类型**\n\n- 基本介绍\n\n> Java 的浮点类型可以表示一个小数,比如 123.4 ,7.8 ,0.12 等等\n\n\n\n- 案例演示\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081756499.png\" alt=\"image-20220508175600469\" style=\"zoom: 67%;\" />\n\n\n\n- `浮点型的分类`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081756711.png\" alt=\"image-20220508175638655\" style=\"zoom: 67%;\" />\n\n\n\n- **说明一下**\n\n1. 关于浮点数在机器中存放形式的简单说明,**`浮点数=符号位+指数位+尾数位 `**\n2. 尾数部分可能丢失,`造成精度损失`(小数都是近似值)。 \n\n\n\n---\n\n**浮点数细节**\n\n- `浮点型使用细节` FloatDetail.java \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081759392.png\" alt=\"image-20220508175933221\" style=\"zoom: 50%;\" />\n\n```java\npublic class FloatDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//Java 的浮点型常量(具体值)默认为double型,声明float型常量,须后加‘f’或‘F'\n\t\t//float num1 = 1.1; //错误\n\t\tfloat num2 = 1.1F; //对的\n\t\tdouble num3 = 1.1; //对\n\t\tdouble num4 = 1.1f; //对\n\n\t\t//十进制数形式:如:5.12 512.0f .512 (必须有小数点)\n\t\tdouble num5 = .123; //等价 0.123\n\t\tSystem.out.println(num5);\n\t\t//科学计数法形式:如:5.12e2 [5.12 * 10的2次方 ] 5.12E-2 [5.12 / 10的2次方] \n\t\tSystem.out.println(5.12e2);//512.0\n\t\tSystem.out.println(5.12E-2);//0.0512\n\n\n\t\t//通常情况下,应该使用double型,因为它比float型更精确。\n\t\t//[举例说明]double num9 = 2.1234567851;float num10 = 2.1234567851F;\n\t\tdouble num9 = 2.1234567851;\n\t\tfloat num10 = 2.1234567851F;\n\t\tSystem.out.println(num9);\n\t\tSystem.out.println(num10);\n\n\t\t//浮点数使用陷阱: 2.7 和 8.1 / 3 比较\n\t\t//看看一段代码\n\t\tdouble num11 = 2.7;\n\t\tdouble num12 = 2.7;\t//8.1 / 3; //2.7\n\t\tSystem.out.println(num11);//2.7\n\t\tSystem.out.println(num12);//接近2.7的一个小数,而不是2.7\n\t\t//得到一个重要的使用点: 当我们对运算结果是小数的进行相等判断是,要小心\n\t\t//应该是以两个数的差值的绝对值,在某个精度范围内判断\n\t\tif( num11 == num12) {\n\t\t\tSystem.out.println(\"num11 == num12 相等\");\n\t\t}\n\t\t//正确的写法 , ctrl + / 注释快捷键, 再次输入就取消注释\n\t\tif(Math.abs(num11 - num12) < 0.000001 ) {\n\t\t\tSystem.out.println(\"差值非常小,到我的规定精度,认为相等...\");\n\t\t}\n\t\t// 可以通过java API 来看 下一个视频介绍如何使用API\n\t\tSystem.out.println(Math.abs(num11 - num12));\n\t\t//细节:如果是直接查询得的的小数或者直接赋值,是可以判断相等\n\t\t\n\t\t\n\t}\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081810094.png\" alt=\"image-20220508181024027\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081819949.png\" alt=\"image-20220508181900845\" style=\"zoom:67%;\" />\n\n\n\n---\n\n### Java API文档\n\n**Java API 文档**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081822551.png\" alt=\"image-20220508182220368\" style=\"zoom:50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081851674.png\" alt=\"image-20220508185115534\" style=\"zoom: 67%;\" />\n\n\n\n---\n\n### 字符型\n\n**字符类型(char)**\n\n- 基本介绍\n\n​\t\t字符类型可以表示`单个字符`,字符类型是 char,char 是两个字节(可以存放汉字),多个字符我们用字符串 String(我们后面详细讲解 String) \n\n\n\n- **案例演示** Char01.java \n\n```java\n#代码 \nchar c1 = 'a'; \nchar c2 = '\\t'; \nchar c3 = '韩'; \nchar c4 = 97;\n```\n\n```java\n//演示char的基本使用\n\npublic class Char01 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\tchar c1 = 'a';\n\t\tchar c2 = '\\t';\n\t\tchar c3 = '韩';\n\t\tchar c4 = 97; //说明: 字符类型可以直接存放一个数字\n\n\t\tSystem.out.println(c1);\n\t\tSystem.out.println(c2);\n\t\tSystem.out.println(c3);\n\t\tSystem.out.println(c4);//当输出c4时候,会输出97表示的字符 => 编码的概念\t(输出为 a)\n\t\t\n\t}\n}\n```\n\n\n\n---\n\n**字符型细节**\n\n- **`字符类型使用细节`**\n\n> ![image-20220508191001995](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081910193.png)\n\n```java\npublic class CharDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//在java中,char的本质是一个整数,在默认输出时,是unicode码对应的字符\n\t\t//要输出对应的数字,可以(int)字符\n\t\tchar c1 = 97;\n\t\tSystem.out.println(c1); // a\n\n\t\tchar c2 = 'a'; //输出'a' 对应的 数字\n\t\tSystem.out.println((int)c2);\t\t\t//强转为 int类型\n\t\tchar c3 = '韩';\n\t\tSystem.out.println((int)c3);//38889\n\t\tchar c4 = 38889;\n\t\tSystem.out.println(c4);//韩\n\n\t\t//char类型是可以进行运算的,相当于一个整数,因为它都对应有Unicode码.\n\t\t\n\t\tSystem.out.println('a' + 10);//107\n\n\t\t//课堂小测试\n\t\tchar c5 = 'b' + 1;//98+1==> 99\n\t\tSystem.out.println((int)c5); //99\n\t\tSystem.out.println(c5); //99 -> 对应的字符 -> 编码表ASCII(规定好的) => c\n\t}\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081912794.png\" alt=\"image-20220508191250728\" style=\"zoom: 67%;\" />\n>\n> ---\n>\n> ASCII码对照表:\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081920627.png\" alt=\"ASCII码对照表\" style=\"zoom:50%;\" />\n>\n> \n\n\n\n---\n\n**字符型本质**\n\n- **`字符类型本质探讨`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081923962.png\" alt=\"image-20220508192303779\" style=\"zoom:67%;\" />\n\n\n\n---\n\n**常用编码**\n\n> - `ASCII 码介绍(了解) `\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081938505.png\" alt=\"image-20220508193828402\" style=\"zoom:67%;\" />\n>\n> \n>\n> - `Unicode 编码介绍(了解)`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081939699.png\" alt=\"image-20220508193912565\" style=\"zoom:67%;\" />\n>\n> \n>\n> - `UTF-8 编码介绍(了解) `\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081939863.png\" alt=\"image-20220508193948746\" style=\"zoom:67%;\" />\n\n\n\n---\n\n### 布尔类型\n\n**布尔类型**\n\n- 布尔类型:boolean\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081949760.png\" alt=\"image-20220508194909551\" style=\"zoom: 50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081958309.png\" alt=\"image-20220508195843226\" style=\"zoom:50%;\" />\n\n```java\npublic class Boolean01 { \n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//演示判断成绩是否通过的案例\n\t\t//定义一个布尔变量\n\t\tboolean isPass = true;//\n\t\tif(isPass == true) {\n\t\t\tSystem.out.println(\"考试通过,恭喜\");\n\t\t} else {\n\t\t\tSystem.out.println(\"考试没有通过,下次努力\");\n\t\t}\n\t}\n}\n```\n\n\n\n---\n\n### 基本数据类型转换\n\n#### 自动类型转\n\n**自动类型转换基础**\n\n- **`自动类型转换`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082000505.png\" alt=\"image-20220508200046295\" style=\"zoom:50%;\" />\n\n```java\npublic class AutoConvert { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//演示自动转换\n\t\tint num = 'a';\t\t//ok char -> int\n\t\tdouble d1 = 80; \t//ok int -> double\n\t\tSystem.out.println(num);\t//97\n\t\tSystem.out.println(d1);\t\t//80.0\n\n\t}\n}\n```\n\n\n\n---\n\n**自动类型转换细节**\n\n- `自动类型转换注意和细节`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082001882.png\" alt=\"image-20220508200129693\" style=\"zoom:50%;\" />\n\n```java\n//自动类型转换细节\npublic class AutoConvertDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//细节1: 有多种类型的数据混合运算时,\n\t\t//系统首先自动将所有数据转换成容量最大的那种数据类型,然后再进行计算\n\t\tint n1 = 10; //ok\n\t\t//float d1 = n1 + 1.1;\t//错误 n1 + 1.1 => 结果类型是 double\n\t\t//double d1 = n1 + 1.1;\t//对 n1 + 1.1 => 结果类型是 double\n\t\tfloat d1 = n1 + 1.1F;\t//对 n1 + 1.1 => 结果类型是 float\n\n\t\t//细节2: 当我们把精度(容量)大 的数据类型赋值给精度(容量)小 的数据类型时,\n\t\t//就会报错,反之就会进行自动类型转换。\n\t\t//\n\t\t//int n2 = 1.1;//错误 double -> int \n\t\t\n\t\t//细节3: (byte, short) 和 char之间不会相互自动转换\n\t\t//当把具体数赋给 byte 时,(1)先判断该数是否在byte范围内,如果是就可以\n\t\tbyte b1 = 10; //对 , -128-127\n\t\t// int n2 = 1; //n2 是int \n\t\t// byte b2 = n2; //错误,原因: 如果是变量赋值,判断类型\n\t\t// \n\t\t// char c1 = b1; //错误, 原因 byte 不能自动转成 char\n\t\t// \n\t\t// \n\t\t\n\t\t//细节4: byte,short,char 他们三者可以计算,在计算时首先转换为int类型\n\t\t\n\t\tbyte b2 = 1;\n\t\tbyte b3 = 2;\n\t\tshort s1 = 1;\n\t\t//short s2 = b2 + s1;\t//错, b2 + s1 => int\n\t\tint s2 = b2 + s1;\t\t//对, b2 + s1 => int\n\n\t\t//byte b4 = b2 + b3; \t//错误: b2 + b3 => int\n\t\t//\n\t\t\n\t\t//boolean 不参与转换\n\t\tboolean pass = true;\n\t\t//int num100 = pass;// boolean 不参与类型的自动转换\n\n\t\t//自动提升原则: 表达式结果的类型自动提升为 操作数中最大的类型\n\t\t//看一道题\n\t\t\n\t\tbyte b4 = 1;\n\t\tshort s3 = 100;\n\t\tint num200 = 1;\n\t\tfloat num300 = 1.1F;\n\n\t\tdouble num500 = b4 + s3 + num200 + num300; //float -> double\n\t}\n}\n```\n\n\n\n---\n\n#### 强制类型转换\n\n**`强制类型转换`**\n\n- 介绍\n\n​\t\t自动类型转换的逆过程,**将容量大的数据类型转换为容量小的数据类型**。使用时要加上强制转换符 ( ),但可能造成 **精度降低或溢出**,`格外要注意`。 \n\n\n\n- 案例演示 ForceConvert.java \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082035050.png\" alt=\"image-20220508203534000\" style=\"zoom: 67%;\" />\n\n```java\npublic class ForceConvert { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\t//演示强制类型转换\n\t\tint n1 = (int)1.9;\n\t\tSystem.out.println(\"n1=\" + n1);//1, 造成精度损失\n\n\t\tint n2 = 2000;\n\t\tbyte b1 = (byte)n2;\n\t\tSystem.out.println(\"b1=\" + b1);//造成 数据溢出\n\t}\n}\n```\n\n\n\n---\n\n- `强制类型转换细节说明`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082040412.png\" alt=\"image-20220508204000221\" style=\"zoom:67%;\" />\n\n```java\npublic class ForceConvertDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\t//演示强制类型转换\n\t\t//强转符号只针对于最近的操作数有效,往往会使用小括号提升优先级\n\t\t//int x = (int)10*3.5+6*1.5;\t//编译错误: double -> int \n\t\tint x = (int)(10*3.5+6*1.5);\t// (int)44.0 -> 44\n\t\tSystem.out.println(x);//44\n\n\n\t\tchar c1 = 100; //ok\n\t\tint m = 100; //ok\n\t\t//char c2 = m; //错误\n\t\tchar c3 = (char)m; //ok\n\t\tSystem.out.println(c3);//100对应的字符, d字符\n\n\t\t\n\t}\n}\n```\n\n\n\n---\n\n### 类型转换练习\n\n- 基本数据类型转换-练习题\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082047938.png\" alt=\"image-20220508204706715\" style=\"zoom:67%;\" />\n>\n> \n\n\n\n---\n\n### 基本数据类型和String类型的转换\n\n**基本数据类型和 String 类型的转换**\n\n- 介绍和使用 \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082051513.png\" alt=\"image-20220508205109331\" style=\"zoom:67%;\" />\n\n```java\npublic class StringToBasic { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\t//基本数据类型 -> String\n\t\t\n\t\tint n1 = 100;\n\t\tfloat f1 = 1.1F;\n\t\tdouble d1 = 4.5;\n\t\tboolean b1 = true;\n\t\tString s1 = n1 + \"\";\n\t\tString s2 = f1 + \"\";\n\t\tString s3 = d1 + \"\";\n\t\tString s4 = b1 + \"\";\n\t\tSystem.out.println(s1 + \" \" + s2 + \" \" + s3 + \" \" + s4);\t// 100 1.1 4.5 true\n\n\t\t//String -> 对应的基本数据类型\n\t\tString s5 = \"123\";\n\t\t//会在OOP 讲对象和方法的时候回详细\n\t\t//解读 使用 基本数据类型对应的包装类,的相应方法,得到基本数据类型\n\t\tint num1 = Integer.parseInt(s5);\n\t\tdouble num2 = Double.parseDouble(s5);\n\t\tfloat num3 = Float.parseFloat(s5);\n\t\tlong num4 = Long.parseLong(s5);\n\t\tbyte num5 = Byte.parseByte(s5);\n\t\tboolean b = Boolean.parseBoolean(\"true\");\n\t\tshort num6 = Short.parseShort(s5);\n\n\t\tSystem.out.println(\"===================\");\n\t\tSystem.out.println(num1);//123\n\t\tSystem.out.println(num2);//123.0\n\t\tSystem.out.println(num3);//123.0\n\t\tSystem.out.println(num4);//123\n\t\tSystem.out.println(num5);//123\n\t\tSystem.out.println(num6);//123\n\t\tSystem.out.println(b);//true\n\n\t\t//怎么把字符串转成字符char -> 含义是指 把字符串的第一个字符得到\n\t\t//解读 s5.charAt(0) 得到 s5字符串的第一个字符 '1'\n\t\tSystem.out.println(s5.charAt(0));\n\t\t\n\t}\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082126362.png\" alt=\"image-20220508212639235\" style=\"zoom:67%;\" />\n\n\n\n---\n\n**String转基本类型细节**\n\n- 注意事项\n\n案例演示: StringToBasicDetail.java \n\n1. 在将 String 类型转成 基本数据类型时,`要确保 String 类型能够转成有效的数据`,比如 我们可以把 \"123\" , 转成一个整数,但是不能把 \"hello\" 转成一个整数\n\n2. 如果格式不正确,就会 **抛出异常,程序就会终止**, 这个问题在异常处理章节中,会处理 \n\n```java\n/**\n * 演示字符串转基本数据类型的细节\n */\npublic class StringToBasicDetail { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\tString str = \"hello\";\n\t\t//转成int\n\t\tint n1 = Integer.parseInt(str);\t\t// 抛异常\n\t\tSystem.out.println(n1);\n\t}\n}\n```\n\n\n\n---\n\n### 本章作业\n\n- 本章作业\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082139428.png\" alt=\"image-20220508213920336\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082139032.png\" alt=\"image-20220508213940898\" style=\"zoom:67%;\" />\n\n1. \n\n```java\npublic class Homework01 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\tint n1;\n n1 = 13;\n int n2;\n n2 = 17;\n int n3;\n n3 = n1 + n2;\n System.out.println(\"n3 = \" + n3);//30\n int n4 = 38;\n int n5 = n4 - n3;\n System.out.println(\"n5 = \" + n5);//8\n\n\t}\n}\n```\n\n2. \n\n```java\npublic class Homework02 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//使用 char 类型,分别保存 \\n \\t \\r \\\\ 1 2 3等字符,并打印输出\n\t\tchar c1 = '\\n'; //换行\n\t\tchar c2 = '\\t'; //制表位\n\t\tchar c3 = '\\r'; //回车\n\t\tchar c4 = '\\\\'; //输出\\\n\t\tchar c5 = '1'; //换行\n\t\tchar c6 = '2'; //换行\n\t\tchar c7 = '3'; //换行\n\t\tSystem.out.println(c1);\n\t\tSystem.out.println(c2);\n\t\tSystem.out.println(c3);\n\t\tSystem.out.println(c4);\n\t\tSystem.out.println(c5);\n\t\tSystem.out.println(c6);\n\t\tSystem.out.println(c7);\n\t}\n}\n```\n\n3. \n\n```java\npublic class Homework03 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//编程,保存两本书名,用+拼接,看效果。保存两个性别,\n\t\t//用加号拼接,看效果。保存两本书价格,用加号拼接,看效果\n\t\t\n\t\tString book1 = \"天龙八部\";\n\t\tString book2 = \"笑傲江湖\";\n\t\tSystem.out.println(book1 + book2);//天龙八部笑傲江湖\n\n\t\t//性别应该使用char保存\n\t\tchar c1 = '男';\n\t\tchar c2 = '女';\n\t\tSystem.out.println(c1 + c2);//得到 男 字符码值 + 女 字符码值\n\n\t\t//保存两本书价格\n\t\tdouble price1 = 123.56;\n\t\tdouble price2 = 100.11;\n\t\tSystem.out.println(price1 + price2);//就是 123.56+100.11\n\t}\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082200764.png\" alt=\"image-20220508220036706\" style=\"zoom: 67%;\" />\n\n4. \n\n```java\npublic class Homework04 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t/*\n\t\t 姓名\t年龄\t成绩\t性别\t爱好\n \txx\t\txx\txx\txx\txx\n\n\t\t要求:\n\t\t1) 用变量将姓名、年龄、成绩、性别、爱好存储\n\t\t2) 使用+\n\t\t3) 添加适当的注释\n\t\t4) 添加转义字符, 使用一条语句输出\n\n\t\t */\n\t\t//姓名\n\t\tString name = \"jack\";\n\t\tint age = 20;\n\t\tdouble score = 80.9;\n\t\tchar gender = '男';\n\t\tString hobby = \"打篮球\";\n\t\t//输出了信息, 可以使用换行\n\t\tSystem.out.println(\"姓名\\t年龄\\t成绩\\t性别\\t爱好\\n\" + name + \"\\t\" \n\t\t\t+ age + \"\\t\" + score + \"\\t\" + gender + \"\\t\" + hobby);\n\t}\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205082205511.png\" alt=\"image-20220508220526449\" style=\"zoom: 67%;\" />\n>\n> \n\n\n\n---\n\n","tags":["Java","编码"],"categories":["Java"]},{"title":"01_Java-特性-jdk-运行机制-转义字符-注释-代码规范","url":"/posts/12907.html","content":"[视频链接:https://www.bilibili.com/video/BV1fh411y7R8](https://www.bilibili.com/video/BV1fh411y7R8)\n\n## 一. 就业方向\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080320118.png\" alt=\"image-20220508032024978\" style=\"zoom:50%;\" />\n\n\n\n---\n\n## 二. 开发场景\n\nJava 开发场景举例 1-`SSM`\n\n![image-20220508032255198](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080322295.png)\n\n\n\nJava 开发场景举例 2:`Android 核心代码`\n\n![image-20220508032454652](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080324796.png)\n\n\n\nJava 开发场景举例 3:`大数据-hadoop `\n\n![image-20220508032545050](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080325177.png)\n\n\n\n---\n\n## 三. 应用领域\n\n- 企业级应用 \n\n主要指复杂的大企业的**`软件系统`**、各种类型的**`网站`**。应用领域包括金融、电信、交通、电子商务等。\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080327015.png\" alt=\"image-20220508032702906\" style=\"zoom:50%;\" />\n\n\n\n- Android 平台应用\n\nAndroid 应用程序使用 Java 语言编写。Android 开发水平的高低很大程度上取决于 Java 语言核心能力是否扎实。 \n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080327181.png\" alt=\"image-20220508032750052\" style=\"zoom:50%;\" />\n\n\n\n- 移动领域应用 \n\n主要表现在消费和嵌入式领域,是指在各种小型设备上的应用,包括机顶盒、车载的大屏影音娱乐设备、汽车通信设备、扫码的 POS 机等。\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080329788.png\" alt=\"image-20220508032900704\" style=\"zoom:50%;\" />\n\n\n\n---\n\n## 四. 程序举例\n\n- **什么是程序**\n\n程序:计算机执行某些操作或解决某个问题而 **`编写的一系列有序指令的集合`** \n\n举例说明: \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080343728.png\" alt=\"image-20220508034312623\" style=\"zoom:50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080343441.png\" alt=\"image-20220508034326323\" style=\"zoom: 67%;\" />\n\n\n\n```java\n//老师写的最简单的程序,完成 1+1, 体会\n\npublic class Test {\n public static void main(String[] args) {\n int res = 1 + 1;\n // 显示\n\t\tSystem.out.print(\"结果=\" + res);\n\t}\n}\n```\n\n![image-20220508040315730](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080403773.png)\n\n\n\n---\n\n## 五. 故事\n\n- Java 诞生小故事\n\n1. `1995年 第1个版本`\n2. `Java之父 gosling`\n3. `最新版本:15`\n4. `公司里用的最多的版本:8、11`\n5. `Java 所有权:甲骨文`\n\n\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080344966.png\" alt=\"image-20220508034456860\" style=\"zoom: 67%;\" />\n>\n> ![image-20220508040836044](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080408088.png)\n\n\n\n- Java 技术体系平台\n\n> `标准版、企业版、小型版`\n>\n> `Java SE、Java EE、Java ME`\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080412778.png\" style=\"zoom:50%;\" />\n\n\n\n---\n\n## 六. 特性\n\n- **Java 重要特点**\n\n1. Java 语言是面向对象的(**`oop`**) \n2. Java `语言是健壮的`。Java 的强类型机制、异常处理、垃圾的自动收集等是 Java 程序健壮性的重要保证 \n3. Java 语言是**`跨平台性的`**。[即: **一个编译好的.class 文件可以在多个系统下运行,这种特性称为跨平台**] \n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080415181.png\" style=\"zoom:50%;\" />\n\n4. Java 语言是解释型的[了解] \n\n​\t\t**解释性语言:javascript,PHP, java 编译性语言: c / c++**\n\n​\t\t区别是:`解释性语言`,编译后的代码,`不能直接被机器执行,需要解释器来执行`, `编译性语言`, 编译后的代码, 可以`直接被机器执行`, c /c++\n\n\n\n---\n\n- **Java 的开发工具**\n\n - 工具选择\n\n - 如何选择开发工具 \n\n ​\t我们先选择用文本编辑器本 sublime,到大家对 java 有一定了解后,我们再使用 IDEA 和 Eclipse 开发工具。\n\n - 这是为什么呢 \n\n ​\t更深刻的理解 java 技术,培养代码感。【面试时,往往程序员手写代码】 \n\n ​\t有利于公司面试\n\n\t\t\t> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080421152.png\" alt=\"image-20220508042124961\" style=\"zoom:50%;\" />\n\n\n\n---\n\n## 七. jdk介绍、安装、配置\n\n- **Java 运行机制及运行过程**\n\n - Java 语言的特点:`跨平台性`\n\n > <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080428588.png\" alt=\"image-20220508042849189\" style=\"zoom:50%;\" />\n\n - Java 核心机制-Java 虚拟机 [`JVM` java virtual machine]\n\n\n\n- `Java 核心机制-Java 虚拟机 [JVM java virtual machine]`\n\n**基本介绍** \n\n1. JVM 是一个虚拟的计算机,具有指令集并使用不同的存储区域。负责执行指令,管理数据、内存、寄存器,包含在 **`JDK 中`**. \n\n2. 对于不同的平台,有不同的虚拟机。 \n\n3. Java 虚拟机机制屏蔽了底层运行平台的差别,实现了“一次**`编译`**,到处**`运行`**” [说明] \n\n\n\n**示意图**\n\n> ```java\n> //指令\n> \tjavac\t\t// 编译\n> \tjava\t\t// 运行\n> ```\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080434503.png\" alt=\"image-20220508043429400\" style=\"zoom: 67%;\" />\n\n\n\n---\n\n**`什么是 JDK,JRE`**\n\n- `JDK 基本介绍 `\n\n1. JDK 的全称(Java Development Kit **`Java 开发工具包`**) \n\n​\t\tJDK = JRE + java 的开发工具 [java, javac,javadoc,javap 等] \n\n2. JDK 是提供给 Java 开发人员使用的,其中包含了 java 的开发工具,也包括了 JRE。所以安装了 JDK,就不用在单独安装 JRE 了。\n\n\n\n- `JRE 基本介绍`\n\n1. JRE(Java Runtime Environment ` Java 运行环境`) \n\n​\t\tJRE = JVM + Java 的核心类库[类] \n\n2. 包括 Java 虚拟机(JVM Java Virtual Machine)和 Java 程序所需的核心类库等,如果想要运行一个开发好的 Java 程序,计算机中只需要安装 JRE 即可。\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080445424.png\" style=\"zoom:67%;\" />\n\n\n\n- `JDK、JRE 和 JVM 的包含关系`\n\n1. **`JDK = JRE + 开发工具集`**(例如 Javac,java 编译工具等) \n\n2. **`JRE = JVM + Java SE`** **`标准类库`**(java 核心类库) \n\n3. 如果只想运行开发好的 .class 文件 只需要 JRE \n\n\n\n---\n\n**下载、安装 JDK**\n\n> https://www.oracle.com/java/technologies/downloads/\n>\n> ![](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080450598.png)\n\n\n\n**配置环境变量 path**\n\n- 为什么要配置 path\n\n > <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080507309.png\" alt=\"image-20220508050732153\" style=\"zoom:50%;\" />\n\n\n\n- 配置环境变量 path 的步骤\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080512224.png\" style=\"zoom:50%;\" />\n\n\n\n---\n\n安装 JDK 的练习\n\n> 请同学们安装好 JDK,配置好 path 环境变量。可以在控制台下正确的执行, (10min)\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080520103.png\" alt=\"image-20220508052000041\" style=\"zoom:50%;\" />\n>\n> 环境变量配置细节说明:\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080520181.png\" alt=\"image-20220508052022102\" style=\"zoom:50%;\" />\n>\n> ---\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080521628.png\" alt=\"image-20220508052141440\" style=\"zoom: 50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080528717.png\" alt=\"image-20220508052824602\" style=\"zoom:50%;\" />\n>\n> ---\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080529498.png\" alt=\"image-20220508052931384\" style=\"zoom:50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080533822.png\" alt=\"image-20220508053340793\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080534562.png\" alt=\"image-20220508053443524\" style=\"zoom:67%;\" />\n>\n> \n\n\n\n---\n\n## 八. 快速入门\n\n- 需求说明\n\n要求开发一个 Hello.java 程序,可以输出 \"hello,world!\" \n\n\n\n- 开发步骤 \n\n1. 将 Java 代码编写到扩展名为 `Hello.java 的文件`中。[代码说明] \n\n2. 通过 `javac` 命令对该 java 文件进行`编译`,生成 `.class` 文件。 \n\n3. 通过 `java` 命令对生成的 class 文件进行`运行`。\n\n\n\n- 运行原理示意图\n\n><img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080545433.png\" alt=\"image-20220508054554366\" style=\"zoom: 67%;\" />\n\n\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080607424.png\" alt=\"image-20220508060705278\" style=\"zoom:50%;\" />\n>\n> \n\n\n\n```java\n//这是java的快速入门, 演示java的开发步骤\n//对代码的相关说明\n//1. public class Hello 表示Hello是一个类,是一个public公有的类\n//2. Hello{ } 表示一个类的开始和结束\n//3. public static void main(String[] args) 表示一个主方法,即我们程序的入口\n//4. main() {} 表示方法的开始和结束\n//5. System.out.println(\"hello,world~\"); 表示输出\"hello,world~\"到屏幕\n//6. ;表示语句结束\npublic class Hello {\n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"韩顺平教育 hello\");\n\t}\n\n}\n\n//一个源文件中最多只能有一个public类。其它类的个数不限。[演示]\n//Dog 是一个类\n//编译后,每一个类,都对于一个.class\nclass Dog {\n\t\n\t//一个源文件中最多只能有一个public类。其它类的个数不限,也可以将main方法写在非public类中,\n\t//然后指定运行非public 类,这样入口方法就是非public 的main方法\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"hello, 小狗狗~\");\n\t}\n}\n\nclass Tiger {\n\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"hello, 小老虎~\");\n\t}\n\n}\n\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080611636.png\" alt=\"image-20220508061152606\" style=\"zoom:67%;\" />\n\n\n\n---\n\n## 九. 运行机制\n\n**Java 开发快速入门**\n\n- `Java执行流程分析`\n\n> .java文件\t\t源文件\n>\n> .class文件\t\t字节码文件\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080612745.png\" alt=\"image-20220508061231609\" style=\"zoom: 67%;\" />\n\n\n\n- `什么是编译`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080619173.png\" alt=\"image-20220508061953033\" style=\"zoom: 67%;\" />\n\n\n\n- `什么是运行`\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080623909.png\" alt=\"image-20220508062339779\" style=\"zoom:67%;\" />\n\n\n\n---\n\n## 十. 开发细节\n\n- **`Java开发注意事项和细节说明`**\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080627135.png\" alt=\"image-20220508062754938\" style=\"zoom: 50%;\" />\n\n\n\n```java\npublic class Hello {\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"韩顺平教育 hello\");\n\t}\n}\n\n//一个源文件中最多只能有一个public类。其它类的个数不限。[演示]\n//Dog 是一个类\n//编译后,每一个类,都对于一个.class\nclass Dog {\n\t\n\t//一个源文件中最多只能有一个public类。其它类的个数不限,也可以将main方法写在非public类中,\n\t//然后指定运行非public 类,这样入口方法就是非public 的main方法\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"hello, 小狗狗~\");\n\t}\n}\n\nclass Tiger {\n\n\tpublic static void main(String[] args) {\n\t\tSystem.out.println(\"hello, 小老虎~\");\n\t}\n\n}\n\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205080638351.png\" alt=\"image-20220508063831299\" style=\"zoom: 67%;\" />\n\n\n\n---\n\n## 十一. 学习方法\n\n> - 老韩聊: 如何快速掌握技术或知识点\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081310765.png\" alt=\"image-20220508131030628\" style=\"zoom: 80%;\" />\n>\n> \n\n\n\n---\n\n## 十二. 转义字符\n\n**Java 转义字符**\n\n- `Java 常用的转义字符`\n\n在控制台,输入 tab 键,可以实现命令补全 \n\n1. `\\t` :一个`制表位`,实现对齐的功能 \n\n2. `\\n` :`换行符` \n\n3. `\\\\` :`一个\\ `\n\n4. `\\\"` :`一个\" `\n\n5. `\\'` :`一个' `\n\n6. **`\\r`** :**`一个回车`** System.out.println(\"韩顺平教育\\r 北京\");\n\n\n\n- 说明\n\n应用实例\n\n```java\n//演示转义字符的使用\npublic class ChangeChar {\n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t\n\t\t// \\t :一个制表位,实现对齐的功能\n\t\tSystem.out.println(\"北京\\t天津\\t上海\");\n\t\t// \\n :换行符\n\t\tSystem.out.println(\"jack\\nsmith\\nmary\");\n\t\t// \\\\ :一个\\ \\\\\n\t\tSystem.out.println(\"C:\\\\Windows\\\\System32\\\\cmd.exe\");\n\t\t// \\\" :一个\"\n\t\tSystem.out.println(\"老韩说:\\\"要好好学习java,有前途\\\"\");\n\t\t// \\' :一个'\n\t\tSystem.out.println(\"老韩说:\\'要好好学习java,有前途\\'\");\n\t\t\n\t\t// \\r :一个回车 System.out.println(\"韩顺平教育\\r北京\");\n\t\t// 解读\n\t\t// 1. 输出 韩顺平教育\n\t\t// 2. \\r表示回车 \n\t\tSystem.out.println(\"韩顺平教育\\r北京\"); // 北京平教育\n\t}\n\n}\n```\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081323663.png\" alt=\"image-20220508132315623\" style=\"zoom: 67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081327844.png\" alt=\"image-20220508132732792\" style=\"zoom: 67%;\" />\n>\n> ---\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081328387.png\" alt=\"image-20220508132852344\" style=\"zoom:67%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081329085.png\" alt=\"image-20220508132927045\" style=\"zoom:67%;\" />\n\n\n\n---\n\n- 课堂练习\n\n要求:请使用一句输出语句,达到输入如下图形的效果 2min\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081331278.png\" alt=\"image-20220508133105218\" style=\"zoom:67%;\" />\n\n```java\npublic class ChangeCharExer01 {\n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//完成代码\n\t\tSystem.out.println(\"书名\\t作者\\t价格\\t销量\\n三国\\t罗贯中\\t120\\t1000\");\n\n\t\t//示意 => 可读性很好\n\t\t//下面代码完成 两个数相加\n\t\t//定义变量\n\t\tint n1 = 10;\n\t\tint n2 = 30;\n\t\t//求和\n\t\tint sum = n1 + n2;\n\t\t//输出结果\n\t\tSystem.out.println(\"结果=\" + sum);\n\t}\n}\n```\n\n\n\n---\n\n## 十三. 易犯错误\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081335827.png\" alt=\"image-20220508133503644\" style=\"zoom: 50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081336546.png\" alt=\"image-20220508133644384\" style=\"zoom:50%;\" />\n\n\n\n---\n\n## 十四. 注释\n\n**注释(comment)**\n\n- 介绍: \n\n​\t\t用于注解说明解释程序的文字就是注释,注释提高了代码的阅读性(可读性);注释是`一个程序员必须要具有的良好编程习惯`。将自己的思想通过注释先整理出来,再用代码去体现。 [举例] \n\n\n\n- **`Java 中的注释类型`**\n\n1. `单行注释 // `\n\n2. `多行注释 /* */ `\n\n3. `文档注释 /** */ `\n\n\n\n- `单行注释: `\n\n基本格式 \n\n格式: //注释文字 \n\n\n\n- `多行注释: `\n\n基本格式 \n\n格式: /* 注释文字 */ \n\n\n\n```java\n//演示注释使用\n\npublic class Comment01 {\n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\n\t\t//单行注释\n\t\t\n\t\t//多行注释\n\t\t/* \t示意 => 可读性很好\n\t\t\t下面代码完成 两个数相加\n\t\t\t定义变量 \n\n\t\t\t注释\n\t\t\t注释\n\t\t\tint n1 = 10;... \n\t\t\tSystem.out.println(\"ok~~\");\n\t\t\t*/\n\t\tint n1 = 10;\n\t\tint n2 = 30;\n\t\t//求和\n\t\tint sum = n1 + n2;\n\t\t//输出结果\n\t\tSystem.out.println(\"结果=\" + sum);\n\t}\n}\n```\n\n\n\n- 使用细节 \n\n1. 被注释的文字,不会被 JVM(java 虚拟机)解释执行 \n\n2. 多行注释里面不允许有多行注释嵌套 \n\n\n\n- `文档注释:`\n\n> ![image-20220508140217257](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081402422.png)\n>\n> \n>\n> ```java\n> /**\n> * @author 韩顺平\n> * @version 1.0\n> */\n> public class Comment02 { \n> \n> \t//编写一个main方法\n> \tpublic static void main(String[] args) {\n> \t}\n> }\n> ```\n>\n> \n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081404635.png\" alt=\"image-20220508140443548\" style=\"zoom:50%;\" />\n>\n> \n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081405177.png\" alt=\"image-20220508140522118\" style=\"zoom:50%;\" />\n>\n> \n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081405617.png\" alt=\"image-20220508140555554\" style=\"zoom:50%;\" />\n>\n> \n\n\n\n---\n\n- **javadoc 标签**\n\njavadoc 工具软件识别以下标签:\n\n| 标签 | 描述 | 示例 |\n| ------------- | ------------------------------------------------------ | ------------------------------------------------------------ |\n| @author | 标识一个类的作者 | @author description |\n| @deprecated | 指名一个过期的类或成员 | @deprecated description |\n| {@docRoot} | 指明当前文档根目录的路径 | Directory Path |\n| @exception | 标志一个类抛出的异常 | @exception exception-name explanation |\n| {@inheritDoc} | 从直接父类继承的注释 | Inherits a comment from the immediate surperclass. |\n| {@link} | 插入一个到另一个主题的链接 | {@link name text} |\n| {@linkplain} | 插入一个到另一个主题的链接,但是该链接显示纯文本字体 | Inserts an in-line link to another topic. |\n| @param | 说明一个方法的参数 | @param parameter-name explanation |\n| @return | 说明返回值类型 | @return explanation |\n| @see | 指定一个到另一个主题的链接 | @see anchor |\n| @serial | 说明一个序列化属性 | @serial description |\n| @serialData | 说明通过writeObject( ) 和 writeExternal( )方法写的数据 | @serialData description |\n| @serialField | 说明一个ObjectStreamField组件 | @serialField name type description |\n| @since | 标记当引入一个特定的变化时 | @since release |\n| @throws | 和 @exception标签一样. | The @throws tag has the same meaning as the @exception tag. |\n| {@value} | 显示常量的值,该常量必须是static属性。 | Displays the value of a constant, which must be a static field. |\n| @version | 指定类的版本 | @version info |\n\n \n\n---\n\n- 代码演示\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081414164.png\" alt=\"image-20220508141428106\" style=\"zoom:50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081414376.png\" alt=\"image-20220508141447322\" style=\"zoom:50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081415068.png\" alt=\"image-20220508141519015\" style=\"zoom:50%;\" />\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081415355.png\" alt=\"image-20220508141539312\" style=\"zoom:50%;\" />\n\n\n\n---\n\n## 十五. 代码规范\n\n- `Java 代码规范`\n\n> ![image-20220508141621467](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081416659.png)\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081421585.png\" alt=\"image-20220508142107515\" style=\"zoom:50%;\" />\n>\n> \n\n\n\n---\n\n## 十六. DOS原理-路径-DOS指令\n\n- DOS 命令(了解) \n\nDOS 介绍 \n\nDos: Disk Operating System 磁盘操作系统, 简单说一下 windows 的目录结构。[**原理图**] \n\n> **原理图**\n>\n> ![image-20220508142750248](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081427390.png)\n>\n> \n\n\n\n- 相关的知识补充: **`相对路径, 绝对路径`**\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081429068.png\" alt=\"image-20220508142920905\" style=\"zoom: 67%;\" />\n>\n> \n\n\n\n- **`常用的`** `dos 命令 `\n\n1. 查看`当前目录是有什么内容` dir\n\n​\t\tdir \t\t`dir d:\\abc2\\test200 `\n\n2. 切换到其他盘下:盘符号 cd : change directory \n\n​\t\t案例演示:切换到 c 盘 \t\t`cd /D c: `\n\n3. 切换到当前盘的其他目录下 (使用相对路径和绝对路径演示), ..\\表示上一级目录 \n\n​\t\t案例演示: `cd d:\\abc2\\test200 `\tcd ..\\\\..\\\\abc2\\test200 \n\n4. 切换到上一级: \n\n​\t\t案例演示: `cd .. `\n\n5. 切换到根目录:`cd \\ `\n\n​\t\t案例演示:cd \\ \n\n6. 查看指定的目录下所有的子级目录 `tree `\n\n7. `清屏 cls`\n\n8. 退出 DOS `exit `\n\n9. 说明: **因为小伙伴后面使用** **DOS** **非常少**,所以对下面的几个指令,老韩给大家演示下, 大家了解即可 (`md[创建目录],rd[删除目录],copy[拷贝文件],del[删除文件],echo[输入内容到文件],type,move[剪切]`) => **Linux**,\n\n\n\n---\n\n## 十七. 本章作业\n\n- 本章作业\n\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205081452380.png\" alt=\"image-20220508145216238\" style=\"zoom:50%;\" />\n>\n> ---\n>\n> - 1\n\n```java\npublic class Homework01 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//编写hello, world程序\n\t\tSystem.out.println(\"hello,world\"); \n\t}\n}\n```\n\n> - 2\n\n```java\n//将个人的基本信息(姓名、性别、籍贯、住址)打印到控制台上输出。各条信息分别占一行\n//\npublic class Homework02 { \n\n\t//编写一个main方法\n\tpublic static void main(String[] args) {\n\t\t//考察对转义字符\n\t\tSystem.out.println(\"姓名\\t性别\\t籍贯\\t住址\\n顺平\\t男\\t四川\\t北京\"); \n\t}\n}\n```\n\n> - 3\n>\n> ```java\n> //JDK,JRE,JVM的关系\n> //\n> 答:\n> 1. JDK = JRE + java开发工具\n> 2. JRE = JVM + 核心类库\n> ```\n>\n> - 4\n>\n> ```java\n> //环境变量path配置及其作用\n> 1. 环境变量的作用是为了在 dos 的任意目录,可以去使用 java 和 javac 命令\n> 2. 先配置 JAVA_HOME = 指向 jdk 安装的主目录\n> 3. 编辑 path 环境变量,增加 %JAVA_HOME%\\bin \n> ```\n>\n> - 5\n>\n> ```java\n> //Java编写步骤\n> 1. 编写java的源代码\n> 2. javac 编译 ,得到对应的 .class 字节码文件\n> 3. java 运行, 本质就是把 .class 加载到 jvm 运行\n> ```\n>\n> - 6\n>\n> ```java\n> //Java编写7个规范\n> 1. 类,方法的注释,使用javadoc的方式,即文档注释\n> 2. 非javadoc注释,往往是对代码的说明(给程序的维护者),说明如何修改,注意事项\n> 3. 使用tab ,整体将代码右移, 使用 shift+tab 整体左移\n> 4. 运算符和 = 的两边,给空格,代码看上去清楚 int n = 1 + 4;\n> 5. 源码文件使用 utf-8 编码\n> 6. 行宽字符不要超过 80\n> 7. 代码编程风格有两种 次行风格,行尾风格(推荐)\n> ```\n>\n> - 7\n>\n> ```java\n> //初学者java易犯错误 \n> 1. 编译或者运行时,找不到文件 javac Hell0.java, 把文件名或者目录找对\n> 2. 主类名和文件名不一致 , 修改时保持一致即可\n> 3. 缺少;\n> 4. 拼写错误,比如 1 -> l 0->0, void -> viod , 要求写代码时,一定要小心\n> \n> 强调: 先思考->自己练习->看老师评讲\n> \n> ```\n>\n> \n\n\n\n---\n\n","tags":["Java"],"categories":["Java"]},{"title":"01_Hexo-Hexo + Pure搭建博客-自定义","url":"/posts/8236.html","content":"# Hexo 搭建私人博客\n\n## 一. 介绍\n\n### 1.1 Hexo\n\n> Hexo 是一个快速、简洁且高效的博客框架。Hexo 使用 [Markdown](http://daringfireball.net/projects/markdown/)(或其他渲染引擎)解析文章,在几秒内,即可利用靓丽的主题生成静态网页。[Hexo 官网](https://hexo.io)\n\n\n\n### 1.2 Pure 主题\n\n[https://github.com/cofess/hexo-theme-pure](https://github.com/cofess/hexo-theme-pure)\n\n[https://blog.cofess.com/](https://blog.cofess.com/)\n\n\n\n---\n\n## 二. 参考\n\nHexo 官网\t[https://hexo.io/zh-cn/docs/index.html](https://hexo.io/zh-cn/docs/index.html)\n\nPure 项目地址\t[https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md](https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md)\n\n\n\n### 搭建 & 魔改\n\n- [Pure 项目中文文档](https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md)\n- [https://hwame.top](https://hwame.top/20200520/hello-hexo-setup-deploy.html)\n- [作者: Hexo博客主题pure使用说明](https://blog.cofess.com/2017/11/01/hexo-blog-theme-pure-usage-description.html)\n- [https://www.cnblogs.com/zzk31/p/14062887.html](https://www.cnblogs.com/zzk31/p/14062887.html)\n- [https://blog.csdn.net/qq_42983502/article/details/106745567](https://blog.csdn.net/qq_42983502/article/details/106745567)\n\n- gitalk\n - [https://www.jianshu.com/p/b1161eb3f848](https://www.jianshu.com/p/b1161eb3f848)\n - [https://cors-anywhere.herokuapp.com/corsdemo](https://cors-anywhere.herokuapp.com/corsdemo)\n - [https://www.cnblogs.com/qisi007/p/13731562.html](https://www.cnblogs.com/qisi007/p/13731562.html)\n - [https://www.jianshu.com/p/02fc71f3633f](https://www.jianshu.com/p/02fc71f3633f)\n\n\n\n---\n\n## 三. 命令\n\n```bash\nhexo clean ; hexo g ; hexo d ; hexo s\n```\n\n\n\n---\n\n## 四. 评论 & 收录\n\nValine 评论\t[https://www.leancloud.cn/](https://www.leancloud.cn/)\n\nValine 评论\t[https://www.leancloud.app/](https://www.leancloud.app/)\t国外站点,国内账号受限,域名没白嫖成功,可能是这个原因 → [https://forum.leancloud.cn/t/2022-8/25408](https://forum.leancloud.cn/t/2022-8/25408)\n\n谷歌收录\t[https://search.google.com/search-console]()\n\n百度收录\t[https://ziyuan.baidu.com](https://ziyuan.baidu.com)\n\nMD5 在线加密\t[https://md5jiami.bmcx.com/](https://md5jiami.bmcx.com/)\t评论区通过密文,识别博主身份\n\n\n\n---\n\n## 五. 相关路径\n\n```markdown\n[文章路径]: \n\t\\source\\_posts\n[站点配置文件]: \n\t\\_config.yml\n[主题配置文件]: \n\t\\themes\\pure\\_config.yml\t\"关于、个人介绍、公告\"\n[友链文件]: \n\t\\source\\_data\\links.yml\n[语言]: \n\t\\themes\\pure\\languages\n[左下角运行时间]: \n\t\\themes\\pure\\layout\\_common\\footer.ejs\t\"时间、版权\"\n[评论角色配置]: \n\t\\themes\\pure\\layout\\_script\\_comment\\valine.ejs\n[css样式]:\n\t\\themes\\pure\\source\\css\\style.css\n[搜索栏限制]: \n\t\\themes\\pure\\source\\js\\insight.js\t\"160行\"\n```\n\n\n\n\n---\n\n## 六. 内容样例\n\n```markdown\n---\ntitle: Test\ndate: 2022-08-28 00:09:00\nupdated: 2022-08-28 00:09:01\nthumbnail: https://dlvr.cpen.top/gh/mycpen/image_bed/image/test.png\ntags:\n - Test\ncategory:\n - Test\ntoc: true\ntop: true\n---\n描述<!-- more -->\n```\n\n### 文章指定多个 category\n\n> 多个分类\n>\n> 如果我们的要求是将文章同时分到两个或者多个不同的类目下呢?官方给出的方法是:\n>\n> ```css\n> categories:\n> - [Sports]\n> - [Baseball]\n> ```\n>\n> 参考文章:[Hexo 一篇文章多个 categories https://www.jianshu.com/p/4438c417611e](https://www.jianshu.com/p/4438c417611e)\n\n\n\n---\n\n## 七. 自定义\n\n### 7.1 搜索框索引突破 5\n\n1. `F12` 定位到搜索框的 类选择器 为 ins-section-header\n2. grep,定位到配置文件为 `\\themes\\pure\\source\\js\\insight.js`\n3. Ctrl + F,搜索 5,定位到第 160 行,修改限制\n\n> ![image-20220830075511578](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830075511578.png)\n>\n> ![image-20220830075224471](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830075224471.png)\n>\n> ![image-20220830075722865](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830075722865.png)\n\n\n\n### 7.2 左侧头像链接,target 修改为 _self\n\na 标签,修改 target: '\\_blank' → '\\_self'\n\n> ![image-20220830080811356](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830080811356.png)\n>\n> ![image-20220830080916410](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830080916410.png)\n>\n> ![image-20220830080945424](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220830080945424.png)\n\n\n\n---\n\n### 7.3 文章目录,一级标题不跳转\n\n有时发现一级标题不会跳转\n\n~~配置文件\t`\\node_modules\\hexo\\lib\\plugins\\helper\\toc.js`~~\n\n~~更新下 `\\node_modules\\hexo\\lib\\plugins\\helper\\toc.js` 文件,又正常了。时灵时不灵的。。。~~\n\n~~参考\t[https://hwame.top/如何取消文章目录的自动编号](https://hwame.top/20200520/hello-hexo-troubleshooting.html#3-%E5%A6%82%E4%BD%95%E5%8F%96%E6%B6%88%E6%96%87%E7%AB%A0%E7%9B%AE%E5%BD%95%E7%9A%84%E8%87%AA%E5%8A%A8%E7%BC%96%E5%8F%B7)~~\n\n修改 \".\\node_modules\\hexo-renderer-markdown-it\\index.js\" level 为 1\n\n> ![image-20220906033013691](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220906033013691.png)\n\n\n\n- 参考文章:\n\n [https://blog.csdn.net/Fosu_Chenai/article/details/111192850 评论](https://blog.csdn.net/Fosu_Chenai/article/details/111192850)\n\n\n\n---\n\n### 7.4 滚动条加粗 + 加小箭头\n\n- 修改 css 样式,路径 `.\\hexo-source\\themes\\pure\\source\\css\\style.css`\n\n 1. `Ctlrl + F` 定位 `scrollbar`;\n 2. 调高 `height`,使代码框 右拉滚动条加粗;\n 3. 右侧下拉条变粗;\n\n > **7.4.1 代码框加粗**\n >\n > ```css\n > /*\n > * scrollbar\n > */\n > \n > ::-webkit-scrollbar {\n > width: 15px;\n > height: 14px;\t\t\t\t\t# 调高\n > background: transparent;\n > }\n > ```\n >\n > ![image-20220901164700329](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901164700329.png)\n >\n > **7.4.2 右侧下拉条变粗 + 添加小箭头**\n >\n > ```css\n > /*\n > * 滚动条箭头\t\t\t\t\t\t\t\n > */\n > ::-webkit-scrollbar-button {\n > width: 0px;\n > height: 4px;\n > display: block; \n > background-color: #c3c3c3;\n > }\n > ::-webkit-scrollbar {\n > width: 16px;\n > border: 5px solid white;\n > \n > }\n > \n > ::-webkit-scrollbar-thumb {\n > background-color: #b0b0b0;\n > background-clip: padding-box;\n > border: 0.05em solid #eeeeee;\n > }\n > \n > ::-webkit-scrollbar-track {\n > background-color: #bbbbbb;\n > }\n > /* Buttons */\n > ::-webkit-scrollbar-button:single-button {\n > background-color: #bbbbbb;\n > display: block;\n > border-style: solid;\n > height: 13px;\n > width: 16px;\n > }\n > /* Up */\n > ::-webkit-scrollbar-button:single-button:vertical:decrement {\n > border-width: 0px 8px 8px 8px;\n > border-color: transparent transparent #555555 transparent;\n > }\n > \n > ::-webkit-scrollbar-button:single-button:vertical:decrement:hover {\n > border-color: transparent transparent #777777 transparent;\n > }\n > /* Down */\n > ::-webkit-scrollbar-button:single-button:vertical:increment {\n > border-width: 8px 8px 0 8px;\n > border-color: #555555 transparent transparent transparent;\n > }\n > \n > ::-webkit-scrollbar-button:vertical:single-button:increment:hover {\n > border-color: #777777 transparent transparent transparent;\n > }\n > ```\n >\n > ![image-20220901164914382](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901164914382.png)\n\n**参考文章**\n\n- [右侧下拉条新增箭头](http://www.qianduanheidong.com/blog/article/27901/a1c9346c7830d6ffa3f2/)\n- [:-webkit-scrollbar 滚动条整体部分 https://www.php.cn/css-tutorial-475268.html](https://www.php.cn/css-tutorial-475268.html)\n\n\n\n### 7.5 Valine 评论框添加一言\n\n**参考文章**\n\n- [https://blog.justlovesmile.top/posts/27831.html](https://blog.justlovesmile.top/posts/27831.html)\n\n偶然看到的文章,然后自己就加了这个功能。\n\n- 路径:`.\\themes\\pure\\layout\\_script\\_comment\\valine.ejs`;\n\n- 加到最后 `</script>` 标签之前;c=j 请求获得网易云的句子,开始网抑云吧;\n\n ```ejs\n fetch('https://v1.hitokoto.cn/?c=j')\n .then(response => response.json())\n .then(data => {\n document.getElementById(\"veditor\").setAttribute(\"placeholder\",data.hitokoto+\"__\"+data.from);\n })\n .catch(console.error)\n ```\n\n> 修改方法:\n>\n> 1. 找到博客对应添加valine的位置,例如Ayer主题的位于hexo\\themes\\ayer\\layout\\_partial\\post\\valine.ejs\n>\n> 2. 在内部添加一段代码:\n>\n> ```ejs\n> <script type=\"text/javascript\">\n> fetch('https://v1.hitokoto.cn')\n> .then(response => response.json())\n> .then(data => {\n> document.getElementById(\"veditor\").setAttribute(\"placeholder\",data.hitokoto+\"__\"+data.from);\n> })\n> .catch(console.error)\n> </script>\n> ```\n>\n> 3. Api接口说明:\n> (1)https://v1.hitokoto.cn/ (从7种分类中随机抽取)\n> (2)https://v1.hitokoto.cn/?c=b (请求获得一个分类是漫画的句子)\n> 参数\t说明\n> a\t动画\n> b\t漫画\n> c\t游戏\n> d\t文学\n> e\t原创\n> f\t来自网络\n> g\t其他\n> h\t影视\n> i\t诗词\n> j\t网易云\n> k\t哲学\n> l\t抖机灵\n> 其他\t作为动画类型处理\n> 可选择多个分类,例如: ?c=a&c=c\n>\n> (3)https://v1.hitokoto.cn/?c=f&encode=text (请求获得一个来自网络的句子,并以纯文本格式输出)\n>\n> 4. 返回的格式说明\n> 返回参数名称\t描述\n> id\t一言标识\n> hitokoto\t一言正文。编码方式 unicode。使用 utf-8。\n> type\t类型\n> from\t一言的出处\n> from_who\t一言的作者\n> creator\t添加者\n> creator_uid\t添加者用户标识\n> reviewer\t审核员标识\n> uuid\t一言唯一标识;可以链接到 https://hitokoto.cn?uuid=[uuid] 查看这个一言的完整信息\n> commit_from\t提交方式\n> created_at\t添加时间\n> length\t句子长度\n> 例如:返回的data,通过data.hitokoto获取句子正文\n>\n> 作者: Justlovesmile\n> 链接: https://blog.justlovesmile.top/posts/27831.html\n> 来源: Justlovesmile's BLOG\n> 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。\n\nPS:这位大佬的博客真好看~~\n\n\n\n### 7.6 左侧 归档、分类 改为默认收起\n\n- 默认是展开的\n\n> ![image-20220901203849607](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901203849607.png)\n>\n> ![image-20220901203907981](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901203907981.png)\n\n\n\n- 修改以下文件,改为收起状态。如图\n - style=\"height: 0px\" 应该可以不用写,收起状态默认就是 0 ~~\n\n> `.\\themes\\pure\\layout\\categories.ejs`\n>\n> `.\\themes\\pure\\layout\\_partial\\archive.ejs`\n>\n> ![image-20220901203746673](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901203746673.png)\n>\n> ![image-20220901203807739](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901203807739.png)\n\n\n\n---\n\n## 八. 未解决的小需求\n\n1. (已解决,#7.3)一级目录,右侧导航栏 有时跳转失败;\n\n2. Valine 评论系统,下面的评论 被@后,未显示 @信息,而别人的是成功的;\n\n > 我的\n >\n > ![image-20220901171817579](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901171817579.png)\n >\n > 其他大佬的\n >\n > ![image-20220901171912131](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901171912131.png)\n\n3. 引用时 使用 #,会被导航目录误认为 一级标题;\n\n > ![image-20220901172133945](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901172133945.png)\n >\n > ![image-20220901172316157](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901172316157.png)\n\n4. (已解决)生成在 /public 目录的静态文件都被压缩了,~~我看别人的没被压缩,不清楚啥原因。~~ 因为配置了这个 [https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md 博客优化](https://github.com/cofess/hexo-theme-pure/blob/master/README.cn.md#%E5%8D%9A%E5%AE%A2%E4%BC%98%E5%8C%96) 压缩了文件\n\n > ![image-20220901175404486](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220901175404486.png)\n\n\n\n5. (已解决)文章内部一级、二级......标题左侧无锚点\n\n > 理想效果图\n >\n > ![image-20220906034109271](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220906034109271.png)\n >\n > ~~似乎是环境配置问题,我用虚拟机推送静态文件,就有显示;用真实 win机 推送 就没有锚点,重装 git 也没显示(可能不是 git 的问题)。。。~~\n >\n > 因为压缩了静态文件,全部注释 `hexo-neat` 配置。\n > 参考\n > \t\t[https://github.com/cofess/hexo-theme-pure#hexo-neat](https://github.com/cofess/hexo-theme-pure#hexo-neat)\n > \t\t[https://github.com/rozbo/hexo-neat#options](https://github.com/rozbo/hexo-neat#options)\n >\n > \n\n\n\n无伤大雅,~~我一般一级标题写的是文章标题~~;评论区也就是个摆设;~~静态文件被压缩,可能别人还觉得我是故意,嘿~~\\~~\n\n最后总结:魔改要适量,太费时 还得不到提升,不如多看几个前端视频 多写几篇文章。。。\n\n\n\n---\n\n","tags":["Hexo","Pure"],"categories":["Hexo"]},{"title":"22_Linux基础-ansible1","url":"/posts/22091.html","content":"## 一. selinux、established\n\n```bash\n示例1:永久修改selinux\n--------------------------------------------------------------------------------------------\n[root@cPen_A ~]# vim /etc/selinux/config \nSELINUX=disabled\n============================================================================================\n示例:排查连接不上\t4.00 - 9.00没写完\nps -ef igrep sshd\nlsof -i:2233\ncat /etc/services\n\n[root@cPen_B ~]# netstat -anplut igrep ssh\nActive Internet connections (servers and established)\nProto Recv-Q Send-Q Local Address Foreign Address State PID/Program name \ntcp 0 0 0.0.0.0:2233 0.0.0.0:* LISTEN 911/sshd \ntcp 0 36 192.168.0.31:2233 192.168.0.42:54290 ESTABLISHED 1402/sshd: root [pr \ntcp6 0 0 :::2233 :::* LISTEN 911/sshd \nudp 0 0 192.168.0.31:68 192.168.0.250:67 ESTABLISHED 893/NetworkManager \n[root@cPen_B ~]# netstat -aplut igrep ssh\nActive Internet connections (servers and established)\nProto Recv-Q Send-Q Local Address Foreign Address State PID/Program name \ntcp 0 0 0.0.0.0:infocrypt 0.0.0.0:* LISTEN 911/sshd \ntcp 0 36 cPen_B:infocrypt 192.168.0.42:54290 ESTABLISHED 1402/sshd: root [pr \ntcp6 0 0 [::]:infocrypt [::]:* LISTEN 911/sshd \nudp 0 0 cPen_B:bootpc 192.168.0.250:bootps ESTABLISHED 893/NetworkManager \n##############################################################################################################\n示例2:看当前系统有多少连接 (establish)\n--------------------------------------------------------------------------------------------\n[root@cPen_B ~]# netstat -anplut|grep -E \"ESTABLISHED|LISTEN|TIME_WAIT\"|awk -F\" \" {'print $6'}|sort|uniq -c\n 2 ESTABLISHED\n 2 LISTEN\n#-------------------------------------------------------------------------------\n[root@cPen_B ~]# netstat -anplut\nActive Internet connections (servers and established)\nProto Recv-Q Send-Q Local Address Foreign Address State PID/Program name \ntcp 0 0 0.0.0.0:2233 0.0.0.0:* LISTEN 911/sshd \ntcp 0 232 192.168.0.31:2233 192.168.0.42:54290 ESTABLISHED 1402/sshd: root [pr \n#-------------------------------------------------------------------------------------------------------------\n# pstree\t查看进程之间的关系\n# netstat\t查看当前网络连接\n```\n\n\n\n---\n\n## 二. SSH访问控制\n\n> **SSH使用TCP Wrappers实现访问控制 \t\t\t\t# 注:做访问控制**\n>\n> **主要配置文件**\n>\n> - /etc/hosts.allow\n> - /etc/hosts.deny\n>\n> ![image-20220826172246758](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220826172246758.png)\n\n\n\n> **TCP Wrappers可以控制哪些服务**\n>\n> - 受super daemon(xinetd)管理的服务 \t\t# 注:守护进程的服务\n> - 支持libwrap.so模块的服务\n\n\n\n> **TCP Wrappers的访问控制原则**\n>\n> - 首先检查 hosts.allow 文件,若找到相匹配的策略,则允许访问\n> - 否则继续检查 hosts.deny 文件,若找到相匹配的策略,则拒绝访问\n> - 如果两个文件中都没有相匹配的策略,则允许访问\n> \n>\n> \\#注:守护进程层面的控制\n>\n> ![image-20220826172422236](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220826172422236.png)\n\n\n\n```bash\n示例:/etc/hosts.deny\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_A ~]# vim /etc/hosts.deny \nsshd:192.168.0.31\t\n# 注:访问控制,拒绝192.168.0.31 不需要重启服务,有守护进程帮它控制\n```\n\n\n\n> \\#注:主机公钥在 /etc/ssh/下面\t默认使用ecdsa模式\n>\n> \\#注:known_hosts文件里有什么\t前面是ip地址,后面是公钥\n>\n> \\#注:authorized_keys\t放受信任的公钥\n\n\n\n---\n\n## 三. ssh隧道\n\n> **#注:本地端口转发**\n>\n> CSDN\thttps://www.cnblogs.com/keerya/p/7612715.html\n>\n> 端口转发:A、C、B主机。主机B起了个nginx服务 端口号80;主机A不能直接访问主机B,但主机A可以访问主机C,主机C可以访问主机B **(A-->C-->B)**;A可以ssh到C,A跳到C,然后访问B的80端口 (nginx)。现在 在主机C上面建立一个隧道,隧道开启15577端口连接B的80端口,A去访问15577端口相当于去访问B的80映射\n>\n> \\#注:ssh隧道 第一个用于不能直接访问的情况;第二个考虑密文传输\n\n\n\n```bash\n[root@cPen_C ~]# lsof -i:15577\t\t\t \t# 注:在C主机上操作,15577端口未被占用\n[root@cPen_C ~]# ssh -g -L 15577:192.168.0.39:80 sanchuang@192.168.0.39 -p 2233\n#注:192.168.0.39 右边B主机ip地址\t\t\t # 注:在C主机上开通一个隧道 端口为15577\n[root@cPen_A ~]# curl 192.168.0.48:15577\t# 注:模仿网络访问 (80端口nginx网页使用curl访问)\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">\t# 注:返回的内容\n#注:192.168.0.48 中间C主机ip地址\t\t\t\t# 注:注意防火墙\tiptables -F\n#注:访问中间C主机的15577端口 转接成右边B主机的80端口\n#注:注意 不能绑定到本地的回环地址 127.0.0.1\t只能访问自己 (所以 -g) -g作用 本地所有ip都是访问\n#注:- L是本地端口转发\n#注:一般可以开启65535个端口\n```\n\n\n\n> **#总结:ssh隧道**\n>\n> **端口转发**\n>\n> 1、关闭防火墙\n>\n> 2、关闭selinux\n>\n> \n>\n> **#本地端口转发**\n>\n> \\# ssh -g -L 15577:192.168.0.39:80 192.168.0.39 -p 2233\t# 注:**C主机上执行 把B主机80端口映射本地15577端口***\n>\n> ​\t\t\t\t\t\t\t\t**B主机80端口**\t\t\t**B主机**\n>\n> 实验环境:\n>\n> A主机:192.168.0.132\n>\n> C主机:192.168.0.48\n>\n> B主机:192.168.0.39\t\t\t\n>\n> 在C主机上执行:[root@cPen_C ~]# ssh -g -L 15577:192.168.0.39:80 192.168.0.39 -p 2233\n>\n> 把B主机的80端口映射到本地的15577端口\n>\n> 访问C主机的15577端口就是访问B主机的80端口\n\n\n\n> **#远程端口转发**\n>\n> \\# ssh -R 15566:192.168.0.39:80 -fN 192.168.0.132 -p 2233 # 注:**C主机上 把B主机80端口 映射到 A主机15566端口**\n>\n> ​\t\t\t\t\t\t\t\t**B主机**\t\t**80端口**\t\t**A主机**\t\t\n>\n> 远程端口转发:在C主机上执行:[root@C .ssh]# ssh -R 15566:192.168.0.39:80 -fN 192.168.0.132 -p 2233\n>\n> 把B主机的80端口映射到A主机的15566端口\n>\n> 访问A主机的15566就是访问B主机的80\n>\n> \\#注:A主机 192.168.0.132\n>\n> \\#注:B主机 192.168.0.39\n>\n> \\#注:在C主机上建立远程通道,在C主机上为A主机启动15566端口,映射到B主机\n>\n> \n>\n> ```bash\n> [root@cPen_A ~]# lsof -i:15566\t\t\t\t\t# 注:A主机开启15566端口\n> sshd 2067 root 8u IPv6 38604 0t0 TCP localhost:15566 (LISTEN)\t# 注:监听的是本地回环地址\n> sshd 2067 root 9u IPv4 38605 0t0 TCP localhost:15566 (LISTEN)\n> [root@cPen_A ~]# curl 127.0.0.1:15566\t\t\t# 注:访问本地15566端口映射到B主机的80端口\n> <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\"> # 返回的内容\n> ```\n\n\n\n---\n\n## 四. ansible服务\n\n> ansible是一个自动化运维工具的名称\n>\n> 基于Python开发,集合了众多运维工具的优点(puppet,fabric,slatstack),实现批量系统配置,程序的部署,批量运行命令等\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n> Linux运维:自动化(脚本),智能化,平台化\n>\n> \n>\n> Linux运维人员,人肉运维不可取\n>\n> 诞生了一系列的运维工具,ansible就是其中之一\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n> 日常运维:\n>\n> 1、软件安装\n>\n> 2、服务的配置\n>\n> 3、运行脚本\n>\n> 4、升级\n>\n> 5、备份\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n> ansible基于Python开发,依赖于:paramiko,PyYaml和jinja三个关键组件\n>\n> 基于ssh协议,只要……没写完\n>\n> \\#其他服务需要部署agent,而ansible只需要部署到server,只要十万台的key都上传到其他机器上\n>\n> \\#注:glibc\t内核底层的库\n\n\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n> **#实验环境**\n>\n> a: 192.168.0.132(ansible)\n>\n> c: 192.168.0.48\n>\n> b: 192.168.0.39\n>\n> 实验前提,做好免密码认证,详见ssh服务\n>\n> a --> b , a --> c \ta可以免密码登录到b和c\n>\n> \n>\n> **1、在a上安装ansible**\n>\n> [root@cPen_A .ssh]# yum install epel-release\t\t\t# 注:安装epel源\n>\n> [root@cPen_A .ssh]# yum install ansible \t\t\t\t\t# 注:安装ansible\n>\n> \n>\n> **2、配置**\n>\n> 配置目录:\n>\n> /etc/ansible/ansible.cfg\n>\n> ansible的主配置文件,这个文件主要定义了roles_path路径,主机清单路径,连接清单中的主机方式等配置,这些大部的默认配置已经足够我们平时使用,如需要特别配置可以自行去修改\n>\n> \n>\n> /etc/ansible/hosts\n>\n> 这个配置文件就是默认的主机清单配置文件,可以通过ansible.cfg重新定义\n>\n> \n>\n> 备份/etc/ansible/hosts文件\n>\n> 编辑/etc/ansible/hosts文件\n>\n> \\#将需要管理的主机添加到webser组\n>\n> \\#如果通过ssh登录的端口不是22号端口,就需要在配置文件中指明端口号\n>\n> \n>\n> ```bash\n> [root@cPen_A ansible]# cp hosts{,.bak}\t# 注:备份\n> [root@cPen_A ansible]# ls\n> ansible.cfg hosts hosts.bak roles\n> [root@cPen_A ansible]# >hosts\t\t\t# 注:老的清空\n> [root@cPen_A ansible]# vim hosts\t\t\t\n> [webser]\n> 192.168.0.31:2233\n> 192.168.0.55\n> ```\n\n\n\n> **ansible组成:**\n>\n> ​\t\t1、host inventory\t--#定义客户机,可以对客户机进行分类:db类,web类...等等\n>\n> ​\t\t2、playbook\t\t\t --#剧本 让主机按照我给定的剧本去完成一些事情\n>\n> ​\t\t3、module\t\t\t\t --#模块 实现一个个功能的程序\n>\n> ​\t\t4、pluging\t\t\t\t --#插件 实现一些额外的小功能\n\n\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n```bash\n[root@cPen_A /]# cd /etc\n[root@cPen_A etc]# ls |grep ansible\nansible\n[root@cPen_A etc]# cd ansible\n[root@cPen_A ansible]# ls\nansible.cfg hosts roles\t\t\t\t\t\t\t# 注:host定义主机清单\n[root@cPen_A ansible]# less ansible.cfg \n#inventory = /etc/ansible/hosts\t\t\t\t# 注:主机清单\n#library = /usr/share/my_modules/\n#module_utils = /usr/share/my_module_utils/\n#remote_tmp = ~/.ansible/tmp\n……\n[root@cPen_A ansible]# less hosts \n## [webservers]\t\t\t\t\t\t# 注:[中括号]里webservers 组名 对这个组进行访问控制\n## alpha.example.org\n## beta.example.org\n## 192.168.1.100\n## 192.168.1.110\n\n3、ansible使用\n-m\t指定模块名\n\nHOST-PATTERN \t#匹配主机模式,如all表示所有主机\n-m MOD_NAME \t#模块名 如:ping\n-a MOD_ARGS \t#模块执行的参数\n-f FORKS \t#生成几个子进行程执行\n-C \t#(不执行,模拟跑)\n-u Username \t#某主机的用户名\n-c CONNection \t#连接方式(default smart) \n```\n\n\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n> ansible \t\t\t\t\t主执行程序,一般用于命令行下执行\n> ansible-playbook \t\t\t执行playbook中的任务\n> ansible-doc \t\t\t获取各模块的帮助信息\n\n\n\n.--------------------------------------------------------------------------------------------------------------------------------------------\n\n```bash\n[root@cPen_A ~]# ansible -h\t\t\t\t\t# 注:ansible -h帮助文档\n\n#-------------------------------------------------------------------------\n[root@cPen_A ~]# ansible\n………………\nansible: error: too few arguments\n[root@cPen_A ~]# which ansible\n/usr/bin/ansible\n[root@cPen_A ~]# ls -al /bin/ansible\nlrwxrwxrwx 1 root root 20 11月 24 16:41 /bin/ansible -> /usr/bin/ansible-2.7\nAnsible\n[root@cPen_A ~]# ansible all -m shell -a \"ip a\"\t# 注:匹配所有主机 使用shell模块 执行ip a\n#注:指定ansible……没写完都执行命令\n[root@cPen_A ~]# ansible all -m shell -a \"mkdir /tmp/sc\"\n……\n192.168.0.55 | CHANGED | rc=0 >>\t\t\t\t# 注:返回0 执行执行成功\n……\n[root@cPen_A ~]# ansible webser -m shell -a \"mkdir /tmp/sc\"\t# 注:匹配webser组\n192.168.0.55 | FAILED | rc=1 >>\t\t\t\t\t# 注:返回1 表示执行失败\n```\n\n\n\n---","tags":["Linux","Ansible"],"categories":["Linux"]},{"title":"21_Linux基础-ssh服务3","url":"/posts/57744.html","content":"## 一. 回顾\n\n### 1.1 ssh\n\n**ssh**\n\nsecure shell\n\n- 远程登录连接,控制主机\n- 数据的传输都是加密的\n- 基于非对称加密技术\n \n\n### 1.2 加密技术\n\n**加密技术**\n\n**对称加密**\n\n- 双方共同拥有一把钥匙,其中一方拿着加密,另外一方就拿着解密\n\n- 弊端:这个公钥的钥匙很容易被有心人获取\n\n \n\n**非对称加密**\n\n- 使用公钥对进行加解密\n- 生成一对钥匙,其中一方作为私钥,另一方就是公钥\n- 私钥是只有自己知道,私钥保存在本地\n- 公钥是给需要通信的人,公钥可以给其他人\n- 使用公钥加密,私钥解密,一般用在数据加密传输\n (A、B 2个人,B给A用加密的方式传输数据,私钥在A手里,B用A的公钥对数据加密)\n- 使用私钥加密,公钥解密,一般用于认证\n (A向B发送数据,B用于确认是不是A发送的数据,客户端A用A的私钥对数据进行加密,服务端B拿A的公钥进行解密。只管认证,不管加密性)\n\n### 1.3 ssh登录\n\n**ssh登录**\n\n登录方式\n - 密码登录\n流程\n1、客户端发送登录请求\n2、服务器发送机器的公钥发送给客户端\n3、客户端用服务器的公钥对密码进行加密,发送给服务端\n4、服务器收到密文之后,用私钥进行解密,与/etc/shadow进行验证\n5、返回验证结果\n - 密钥登录,公钥认证\n1、客户端生成公钥对\n2、将客户端的用户公钥发送给服务器,保存在目标用户~/.ssh/authorized_keys\n3、客户端发送请求,服务器返回1个随机字符串\n4、客户端收到随机字符串之后,用自己的私钥加密,发送给服务器\n5、服务器收到密文之后,用客户端的公钥进行解密,拿到随机字符串与生成的字符串比较。返回认证结果(随机字符串其他人拿到了就拿到了,没有任何关系,因为A的公钥很多人都可以有)\n - 弊端\n - 第三方攻击\n - A无法判定收到的这个公钥是不是B的\n - 为了解决这个问题\n - 第一次登录的时候会进行人为确认\n - 确认了之后,将B机器主机公钥存放在~/.ssh/known_hosts,以后每次登录都会进行对比\t(如果系统重装后,登录不上,提示known_hosts……,将known_hosts删掉)\n\n\n\n**公钥认证**\n\n1、使用命令生成公钥对\n\n​\t\tssh-keygen\n\n​\t\t\t\t-t 选项 指定生成的加密算法\n\n​\t\t\t\t默认是rsa算法加密,过程中一直敲回车就可以了\n\n2、客户端将公钥发送给服务器\n\n​\t\t保存在目标用户的~/.ssh/authorized_keys\n\n3、检测权限\n\n​\t\tauthorized_keys 600权限\n\n​\t\t.ssh 以及家目录都给755以下权限\n\n或者 允许密码验证登录时(前提条件) # ssh-copy-id wy@192.168.0.39 -p 2233 把公钥发送过去\n\n[root@cPen_python ~]# ssh-copy-id wy@192.168.0.39 -p 2233\t# 注:需要可以支持密码登录\n\n\n\n### 1.4 ssh远程操作工具\n\n**ssh远程操作工具**\n\n> - ssh\n> - 远程执行命令,远程登录\n> - 登录方式\n> - ssh 服务器ip地址\n> - 使用当前用户和默认端口登录\n> - 使用客户端的当前用户名,登录到远端服务器的同名用户下,默认端口22\n> (没有同名用户,登录失败)\n> - ssh 用户名@服务器ip地址\n> - 登录到远端服务器的指定用户下,使用默认端口22登录\n> - ssh 服务器地址 -l 用户名 -p 端口号\n> - 指定用户名和端口去登录\n> - ssh -o 接一些配置选项 服务器的ip地址\n> #无序输入yes,自动保存hostkey\n> ssh -o StrictHostKeyChecking=no 192.168.0.132 -p 223\n> - ssh -i /tmp/id_rsa 指定私钥认证文件\n> 默认情况在~/.ssh/这下面找私钥\n> - ssh -vvv\n> 打印登录过程的详细信息\n\n\n\n### 1.5 服务配置\n\n**服务配置**\n\n- **服务安装包**\n - oepnssh\n -\n [root@cPen_python ~]# which ssh\n /usr/bin/ssh\n [root@cPen_python ~]# rpm -qf /usr/bin/ssh\n openssh-clients-7.4p1-21.el7.x86_64\n- **配置文件**\n - /etc/ssh/sshd_config\t服务端配置文件\n - /etc/ssh/ssh_config\t 客户端配置\n- **主程序**\n 服务端 /usr/sbin/sshd\n 客户端 /usr/bin/ssh\n- 重新加载配置\n 重启服务 service sshd restart/reload\n kill -1 sshd的pid\n kill -HUP sshd的pid号\n\n\n\n### 1.6 查看ssh服务启动情况\n\n**查看ssh服务启动情况**\n\n1、ps -aux/-ef\n\n2、pidof sshd\n\n3、netstat -autpln\t所有接口(a)的udp tcp连接,显示出所有程序(p) 监听状态(l) n数字显示端口号\n\n​\t\t\\# 注:查看网络连接状态\n\n​\t\t\\# ps -eo pid,uid,comm|grep sshd\t# 注:**-eo查看特定字段信息**\n\n4、lsof -i:22\t打印出程序所需要的文件\n\n\n\n```bash\n[root@localhost ~]# ps aux |grep sshd\nroot 1066 0.0 0.1 112924 4316 ? Ss 09:41 0:00 /usr/sbin/sshd -D\nroot 1608 0.0 0.1 158928 5608 ? Ss 09:43 0:00 sshd: root@pts/0\nroot 9546 0.0 0.0 112824 980 pts/0 S+ 11:26 0:00 grep --color=auto sshd\n[root@localhost ~]# ps -ef |grep sshd\nroot 1066 1 0 09:41 ? 00:00:00 /usr/sbin/sshd -D\nroot 1608 1066 0 09:43 ? 00:00:00 sshd: root@pts/0\nroot 9550 1612 0 11:26 pts/0 00:00:00 grep --color=auto sshd\n[root@localhost ~]# ps -eo pid,uid,comm|grep sshd\t# 注:-eo查看特定字段信息\n 1066 0 sshd\n 1608 0 sshd\n```\n\n\n\n### 1.7 ssh-agent\n\n**ssh-agent**\n\n​\t\t管理密钥\n\n​\t\t在你自己的机器上开启这个服务\n\n​\t\t配置: xshell--> 主机属性--》ssh --》勾选 使用xagent进行身份验证 ;勾选 使用代理转发\n\n\n\\#注:自己的机器是Windows,在Windows上开启ssh-agent服务,现在有A、B 2台机器,A、B两台机器都有Windows的公钥,这种情况开启ssh-agent(xshell里面开启),A登录B时默认情况会拿windows的公钥进行加密,B机器用Windows的私钥进行解密\t必须在xshell里进行操作,这都是xshell的行为\n\n \n\n---\n\n## 二. 跳板机\n\n> \\#注:跳板机给办公人员用的 跳板机/堡垒机 为了保护系统的安全\n>\n> \\#注:使用ssh-agent 访问跳板机和想要访问的主机\n>\n> \\#注:使用场景 阿里的业务 本来有10万台主机(在局域网里面,没有外网,外部不能访问),我在家里,十万台机器捞出一台,这1台主机可以访问外网(跳板机/堡垒机),这1台跳板机的配置尤其重要\n>\n> 开启ssh-agent,把自己主机的公钥添加到目标主机和堡垒机下 (目标主机的权限和堡垒机的权限)\n>\n> \\#注:连到A上,从A跳到B上,B不一定有当前主机的公私钥\n>\n> \\#跳板机 安全加固:\n>\n> 不能使用root直接登录,使用sudo赋予相应权限\n>\n> 不能使用默认端口登录\n>\n> 不能使用密码登录,都使用公钥登录\n>\n> 添加防火墙配置\n\n\n\n> 总结:\n>\n> \\#跳板机\n>\n> \\#安全加固\n>\n> ​\t\t1、不能使用密码登录\n>\n> ​\t\t2、不能使用root登录\n>\n> ​\t\t3、修改默认端口\n>\n> ​\t\t4、添加防火墙配置\n>\n> ​\t\t5、使用跳板机登录\n\n\n\n```bash\n示例1:查看路由 ip r\n--------------------------------------------------------------------------------------------\n[root@cPen_python ~]# ip r\t\t\t# 注:查看路由\ndefault via 192.168.0.1 dev ens33 proto dhcp metric 100 \n192.168.0.0/24 dev ens33 proto kernel scope link src 192.168.0.32 metric 100 \n[root@cPen_python ~]# ip r delete default via 192.168.0.1\t# 注:删除网关\n[root@cPen_python ~]# ip r\n192.168.0.0/24 dev ens33 proto kernel scope link src 192.168.0.32 metric 100 \n[root@cPen_python ~]# ping www.baidu.com\t\t# 注:删除后ping不通外网\nconnect: 网络不可达\n[root@cPen_python ~]# ping 8.8.8.8\nconnect: 网络不可达\n[root@cPen_python ~]# ip r add default via 192.168.0.1\t# 注:还原\n============================================================================================\n\n示例2:A机器登录到B机器(简化登录) vim .ssh/config\n#以后会遇到很多机器,ip地址是记不住的\n--------------------------------------------------------------------------------------------\n#A机器登录到B机器,操作前需要先把A机器公钥放到B机器上 进行授权\n#不修改全全局配置,只修改个人配置:在用户家目录下创建.隐藏文件\n#在客户端上配置(配到自己的主机上)\n#注:意思是将机器root@192.168.0.31 -p 2233 取个别名叫B\n#ForwardAgent yes\t\t\t\t# 注:转发 开启\n#StrictHostKeyChecking no\t\t# 注:不需要输入yes 直接把key保存在known_hosts里面\n#ServerAliveInterval 60\t\t\t# 注:存活状态,检测服务存活状态\n#IdentityFile ~/.ssh/id_rsa\t\t# 注:指定认证私钥\n#示例如下\n[root@cPen_python ~]# vim .ssh/config\n###############################################\nForwardAgent yes\nStrictHostKeyChecking no\nServerAliveInterval 60\nIdentityFile ~/.ssh/id_rsa\n###############################################\nHost B\n HostName 192.168.0.31\n User cPen\n Port 2233\n[root@cPen_python .ssh]# chmod 600 config\t\t# 注:授予权限 不执行这条语句 可能会报错\n[root@cPen_python .ssh]# ssh B\nLast login: Mon Nov 23 15:05:16 2020 from 192.168.0.32\t# 注:登录成功\n[root@cPen_centos8 ~]# \n#注:即简化 # ssh 192.168.0.31 -l root -p 2233 操作 (比如登录到ftp服务器 ssh ftp)\n============================================================================================\n\n示例3:查看端口连接状态 (客户机想访问服务器的时候使用 客户机上telnet) telnet 192.168.0.31 2233\n#注:这个命令只能测tcp的 udp的测不了,但是大部分服务都是tcp的\n#查看端口是否可以访问(即服务是否可达) telnet 192.168.0.31 2233\n--------------------------------------------------------------------------------------------\n#ping命令 是查看2台机器网络是否连通\n#查看服务是否可达使用 telnet命令\n#示例:查看端口是否可达(服务是否可达)\n[root@cPen_python .ssh]# yum install telnet -y\n[root@cPen_python .ssh]# telnet 192.168.0.31 2233\nTrying 192.168.0.31...\t\nConnected to 192.168.0.31.\t\t# 注:服务可达\nEscape character is '^]'.\nSSH-2.0-OpenSSH_8.0\n============================================================================================\n\n示例4:提示主机不被信任 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n--------------------------------------------------------------------------------------------\n#注:提示WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!\n将~/.ssh/known_hosts 删掉\n============================================================================================\n\n示例5:永久修改主机名 hostnamectl set-hostname \"A\"\n--------------------------------------------------------------------------------------------\n#方法1\n[root@cPen_python .ssh]# hostnamectl set-hostname \"A\"\n#注:其实是修改 /etc/hostname\n[root@A ~]# less /etc/hostname \n#方法2\n#或者直接修改 /etc/hostname\n#临时修改主机名\n[root@B ~]# hostname cp\n============================================================================================\n\n示例6:查看进程数 pstree -p\n--------------------------------------------------------------------------------------------\n#注:看程序树状结构 pstree -p\n[root@cPen_python .ssh]# pstree -p |grep sshd\n |-sshd(1065)-+-sshd(3782)---bash(3784)\n | |-sshd(3980)---bash(3982)-+-grep(4318)\n | |-sshd(4059)---bash(4061)\n | `-sshd(4288)---bash(4290)\n#注:前面是父程序,后面是父程序创造出来的子程序,子程序分配新的bash环境,bash环境在操作命令grep\n#注:父进程创造出子进程,子进程有创造出一个子进程,子进程创造出一个新的bash环境\n#-------------------------------------------------------------------------------------------\n#注:连接到B机器后bash环境多了一个ssh子进程去处理B机器\n[root@a ~]# ssh B\nLast login: Mon Nov 23 15:52:16 2020 from 192.168.0.32\n[root@a .ssh]# pstree -p |grep sshd\n |-sshd(1065)-+-sshd(3782)---bash(3784)\n | |-sshd(3980)---bash(3982)-+-grep(4325)\n | |-sshd(4059)---bash(4061)---ssh(4323)\n | `-sshd(4288)---bash(4290)\n============================================================================================\n\n示例7:修改客户端配置 ~/.ssh/config\n#配置文件:~/.ssh/config\n#工作中使用跳板机代理登录 (客户端的配置,方便开发配置)\n--------------------------------------------------------------------------------------------\n#注:假设现在有A、B、C三台机器,B是跳板机,假设A C不通,A通B,B通C,B通D,B通E…………\n#注:B机器当做跳板机,A是自己的本地机,A机器做代理,B机器自动做转发\n#注:在本地机A机器中操作\n[root@a ~]# vim ~/.ssh/config \n###############################################\nForwardAgent yes\nStrictHostKeyChecking no\nServerAliveInterval 60\nIdentityFile ~/.ssh/id_rsa\n###############################################\nHost B\n HostName 192.168.0.31\n User sanchuang\n Port 2233\n\nHost 192.168.0.54\n User sanchuang\n Port 2233\n ProxyCommand ssh 192.168.0.31 -W %h:%p -l sanchuang -p 2233\n#注:ProxyCommand表示 A通过跳板机(192.168.0.31)B登录到\n#-------------------------------------------------------------------------------------------\nHost *\t/ftp*\t/10.* 以10网段开头的ip地址 ssh 10.0.0.1 跳到这个配置执行\n User sanchuang\n Port 2233\n ProxyCommand ssh B nc %h %p -w 10 2>/dev/null\n#注:上课时冲突 前面写Host *与ssh B冲突\n============================================================================================\n\n示例8:远程执行命令 ssh B\n--------------------------------------------------------------------------------------------\n#不登录B机器,执行B机器上的命令 (一般用于脚本)\n[root@a ~]# ssh B ifconfig\t# 注:登录到B执行 ifconfig命令\n[root@a ~]# ssh B ip a\t\t# 注:登录到B执行 查看ip地址 命令 ;命令的返回是B机器给的\n[root@a ~]# ssh B \"/usr/sbin/ip a\"\t# 注:脚本里建议使用命令的绝对路径\n============================================================================================\n\n示例9:远程传输 scp (前提ssh可以连接)\n--------------------------------------------------------------------------------------------\n#注:传输文件\n[root@a ~]# touch ahost\n[root@a ~]# scp ahost B:/tmp\t# 注:将A机器 当前路径ahost文件cp到B机器下的/tmp路径下\nahost 100% 0 0.0KB/s 00:00 \n[root@a ~]# scp B:/tmp/bhost ./\t# 注:将B机器 /tmp/bhost文件cp到当前路径\nbhost 100% 0 0.0KB/s 00:00 \n[root@a ~]# scp B:tmp/testhost ./\t# 注:将B机器 家目录下 tmp/testhost文件cp到当前路径\n#注:传输目录 \n[root@a ~]# scp -r adir B:\t\t\t# 注:将A机器当前路径下 adir文件夹 cp到B机器家目录下\n[root@a ~]# scp -r adir B:bdir\t\t# 注:复制文件夹并改名\n[root@a ~]# scp -r adir B:bdir/\t\t# 注:和上面的没有区别\n============================================================================================\n\n示例10:sftp传输文件 (前提ssh可以连接)\n--------------------------------------------------------------------------------------------\n#注:ftp文件传输\n#注:sftp 传输文件 本地和异地传输文件\n#注:格式 sftp 用户名@主机名\n[sanchuang@a ~]$ sftp B\nConnected to B.\nsftp> ls\t\t\t\t\t\t\t# 注:显示远程目录列表\n2q aa adir bb bdir testdir testdir2 testhost \nsftp> get bdir\nFetching /home/sanchuang/bdir/ to bdir\nCannot download non-regular file: /home/sanchuang/bdir/\nsftp> mget bdir\nFetching /home/sanchuang/bdir/ to bdir\nCannot download non-regular file: /home/sanchuang/bdir/\nsftp> get 2q\t\t\t\t\t\t# 注:get 远程路径\t下载文件\nFetching /home/sanchuang/2q to 2q\n/home/sanchuang/2q 100% 226 107.5KB/s 00:00 \nsftp> exit\n============================================================================================\n\n示例11:pssh pscp命令 (前提ssh可以连接)\n--------------------------------------------------------------------------------------------\n#批量处理\npssh\n -h 指定主机文件列表,内容格式”[user@]host[:Port]”\n -i 指定每个服务器的处理信息\n[root@a ~]# yum install pssh -y\t\t# 注:没有的话需要安装epel源\n[root@a ~]# cat ip.txt \n192.168.0.31:2233\n192.168.0.54:22\n[root@a ~]# pssh -h ip.txt -i \"/usr/sbin/ip a\"\n[1] 17:18:13 [FAILURE] 192.168.0.54:22 Exited with error code 255、\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\n……\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:需要保证ssh能不能过去\n[2] 17:18:13 [SUCCESS] 192.168.0.31:2233\t\t\t# 注:返回SUCCESS表示执行成功\n……\n1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\n……\n2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen \n……\n#-------------------------------------------------------------------------------------------\n#ip.txt里面可以这样写\n[root@a ~]# vim ip.txt \nsanchuang@192.168.0.31:2233\nsanchuang@192.168.0.54:2233\n============================================================================================\n\n示例12:pscp.pssh 批量传输文件 (前提ssh可以连接)\n--------------------------------------------------------------------------------------------\n[root@a ~]# pscp.pssh -h ip.txt pscptest /tmp\n# 注:把当前目录下的pscptest文件传送到目标主机的/tmp目录下\n[root@a ~]# vim ip.txt \nsanchuang@192.168.0.31:2233\nsanchuang@192.168.0.54:2233\n[root@a ~]# pscp.pssh -h ip.txt pscptest /tmp\n[1] 17:41:31 [FAILURE] sanchuang@192.168.0.54:2233 Exited with error code 1\n[2] 17:41:31 [SUCCESS] sanchuang@192.168.0.31:2233\n============================================================================================\n\n示例13:fping 批量ping(前提ssh可以连接)\n--------------------------------------------------------------------------------------------\n#注:批量ping 使用fping命令\n[root@a ~]# yum install fping -y\n[root@a ~]# fping -g 192.168.0.1/24\t\t# 注:-g 根据网段去ping\n192.168.0.1 is alive\n……\n192.168.0.254 is unreachable\n[root@a ~]# fping -f ip.txt \t\t\t# 注:-f根据文件指定ip去ping\n192.168.0.31 is alive\n192.168.0.54 is alive\n[root@a ~]# vim ip.txt \n192.168.0.31\n192.168.0.54\n```\n\n\n\n---\n\n## 三. ssh服务补充\n\n### 3.1 ssh\n\n> ssh --> secure shell\n>\n> 作用:远程登录和操作远程的服务器 --> 信息加密 --> 非常安全的远程登录协议\n>\n> \\#注:远程登录远程操控 省成本\n>\n> ssh协议 属于**应用层**的协议\n>\n> Linux:openssh --> centos7/8自带\n>\n> Windows\t没有ssh协议\n\n\n\n### 3.2 命令\n\n> 命令:\n>\n> ​\t\tssh\n>\n> ​\t\tscp\t\t\t\t# 注:远程copy\n>\n> ​\t\tsftp\n>\n> ​\t\tssh-keygen\n>\n> ​\t\tssh-copy-id\n\n\n\n### 3.3 登录方式\n\n> 登录方式:\n>\n> ​\t\tXshell\t\t\t\t# 注:不开源\n>\n> ​\t\tputty\t\t\t\t # 注:开源\n>\n> ​\t\tsecureCRT\t\t# 注:开源\n>\n> \n>\n> 1. 用户名和密码\n>\n> ​\t\t/etc/passwd\t\t# 注:放用户名\n>\n> ​\t\t/etc/shadow\t\t# 注:放密码\n>\n> 2. 密钥\n>\n> ​\t\t公钥和私钥\n>\n> ​\t\tpublic key --> 公开\t\t# 注:给别人\n>\n> ​\t\tprivate key\t\t\t\t\t # 注:自己所有\n\n\n\n### 3.4 安全加固措施\n\n> 安全加固措施:\n>\n> 1. 修改端口号 22\n>\n> ​\tnmap\t\t\t # 注:端口扫描\n>\n> ​\tnc\t\t\t\t # 注:端口扫描\n>\n> 2. 禁用root\n>\n> su\t\t\t\t# 注:su 切换到root\n>\n> 3. 密码复杂性\n>\n> 4. 启用密钥\t\t # 注:禁止密码认证\n>\n> 5. 打补丁 或者 安装最新版本的ssh软件\n>\n> 6. iptables防火墙\n>\n> \n>\n> \\#注:免密通道(密钥登录)\n\n\n\n### 3.5 免密通道\n\n> 免密通道:\n>\n> ​\t\t单向信任\t\t\t\t# 注:把密钥给其他主机\n>\n> ​\t\t双向信任\t\t\t\t# 注:双方互给公钥\n>\n> \n>\n> \\#注:一般用root用户,为了安全起见用普通用户\n\n\n\n### 3.6 ansible\n\n> ansible:自动化运维的工具:批量管理和操作\n>\n> \\#注:ansible批量管理 批量部署的软件;底层用的ssh协议,推荐建立免密通道\n>\n> \\#注:ansible软件 用Python写的\n\n\n\n### 3.7 日志文件:/var/log/secure\n\n```bash\n日志文件:/var/log/secure\n[root@cPen_centos8 ssh]# vim /etc/ssh/sshd_config \n# Logging\n#SyslogFacility AUTH\nSyslogFacility AUTHPRIV\t\t# 注:日志类型 认证类型 \tAUTHPRIV 设置\n#LogLevel INFO\n\n日志文件:\n\t/var/log/secure\n[sanchuang@cPen_centos8 ~]$ ps aux|grep rsyslog\t\t\t# 注:外包日志的进程\n```\n\n\n\n```bash\nssh将自己的日志功能外包给rsyslog服务去帮它记录日志\n\n[sanchuang@cPen_centos8 ~]$ vim /etc/rsyslog.conf \n# The authpriv file has restricted access.\nauthpriv.* /var/log/secure\n```\n\n\n\n### 3.8 ssh服务登录不了,如何排除?\n\n> ssh服务登录不了,如何排除?\n>\n> 1. 检测网络是否通畅\n>\n> ping\n>\n> 2. 检测ssh服务是否启动,检查端口,selinux\n>\n> 3. ssh的配置:是否禁用root,是否禁用密码认证\n>\n> 4. 检查防火墙iptables\n>\n> ​ service firewalled stop\n>\n> 5. 黑白名单\t\t\t\t # 注:centos6、7里面用,8里面没有\n\n\n\n### 3.9 ssh免密通道\n\n> ssh免密通道\n>\n> 1. 生成密钥对\n>\n> ​\tssh-keygen\n>\n> ​\tssh-keygen -t ecdsa\n>\n> 2. 上传公钥\n>\n> ​ ssh-copy-id -i id_ecdsa.pub [root@192.168.0.35](mailto:root@192.168.0.35)\n>\n> ​ ssh-copy-id -p 2299 -i id_ecdsa.pub [root@192.168.0.35](mailto:root@192.168.0.35)\n>\n> 3. 远程连接\n>\n> ​ ssh -p '2299' 'root@192.168.0.39'\n\n\n\n```bash\n免密通道的建立步骤:\n[root@localhost .ssh]# ssh-keygen -t ecdsa\n[root@localhost .ssh]# ssh-copy-id -p 2299 -i id_ecdsa.pub root@192.168.0.39\n[root@localhost .ssh]# ssh -p '2299' 'root@192.168.0.39'\n\nknown_hosts:存放我们曾经ssh连接过的机器的公钥\n```\n\n\n\n```bash\nscp\t就是在2台机器之间底层使用ssh协议来拷贝文件或者文件夹\n[root@cPen_centos8 ssh]# ssh root@192.168.0.24\t\t\t\t\t\t# 注:远程登录\n[root@cPen_centos8 ssh]# ssh root@192.168.0.24 df -Th\t\t\t\t# 注:远程执行命令\n[root@cPen_python ssh]# scp echo.sh root@192.168.0.35:/root\t\t\t# 注:传文件 (源文件 远程)\n[root@cPen_python ssh]# scp -r /boot root@192.168.0.35:/root\t\t# 注:传文件夹\n[root@cPen_python ssh]# scp -r root@192.168.0.35:/etc/passwd\t\t# 注:拿文件夹\n[root@cPen_python ssh]# ssh root@192.168.0.35 bash /root/echo.sh feng zhang wang\nscp\t就是在2台机器之间底层使用ssh协议来拷贝文件或者文件夹\n---------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_centos8 ssh]# getenforce \t\t\t\t# 注:查看selinux\nDisabled\n[root@cPen_centos8 ssh]# setenforce 0\t\t\t\t# 注:临时关闭selinux\nsetenforce: SELinux is disabled\n---------------------------------------------------------------------------------------------------------------------------------\n[sanchuang@cPen_centos8 ~]$ ifdown ens33\n[sanchuang@cPen_centos8 ~]$ ifup ens33\n#注:禁用root用户登录后,本地可以用root用户登录\n```\n\n\n\n---\n\n","tags":["Linux","SSH"],"categories":["Linux"]},{"title":"20_Linux基础-ssh服务2","url":"/posts/46092.html","content":"## 一. 公钥认证排错\n\n1、确保公钥正确\n\n2、确保~/.ssh/authorized_keys文件权限为600\n\n3、确保家目录以及.ssh目录权限为755以下权限,即属组和其他人没有7的权限\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@cPen_web .ssh]# ssh -vvv wy@192.168.0.30\t\t# 注:看ssh登录时的详细信息\n#注:B机器下操作\n[wy@cPen_web .ssh]$ vim authorized_keys\t\t\t\t# 注:把A机器的公钥粘过去\n[wy@cPen_web .ssh]$ chmod 600 authorized_keys \n[wy@cPen_web home]$ chmod 755 wy\t\t\t\t\t# 注:公钥认证家目录其他人权限不能太高\n[wy@cPen_web ~]$ chmod 755 .ssh\t\t\t\t\t\t# 注:给.ssh也是755 权限\n```\n\n\n\n---\n\n## 二. 登录方式\n\n```bash\n[root@cPen_web .ssh]# ssh wy@192.168.0.30\n[root@cPen_web .ssh]# ssh 192.168.0.30 -l wy\n[root@cPen_web .ssh]# ssh 192.168.0.30 -l wy -p 22\t# 注:指定用户,指定端口(默认22号端口)\n[root@cPen_web .ssh]# ssh -vvv 192.168.0.30 wy\t\t# 注:查看登录过程的详细信息\n…………\ndebug1: Trying private key: /root/.ssh/id_dsa\ndebug3: no such identity: /root/.ssh/id_dsa: No such file or directory\ndebug1: Trying private key: /root/.ssh/id_ecdsa\ndebug3: no such identity: /root/.ssh/id_ecdsa: No such file or directory\ndebug1: Trying private key: /root/.ssh/id_ed25519\ndebug3: no such identity: /root/.ssh/id_ed25519: No such file or directory\ndebug1: Trying private key: /root/.ssh/id_xmss\ndebug3: no such identity: /root/.ssh/id_xmss: No such file or directory\n…………\n#注:默认会去寻找~/.ssh/id_rsa,然后再找id_dsa等等...\n#注:rsa dsa ecdsa 加密算法\n---------------------------------------------------------------------------------------------------------------------------------\n#注:不接任何用户名,会以A机器上的当前用户去登录B机器上的同名用户(不管B机器有没有这个用户)\t(没有就登录失败)\n[sanchuang@cPen_web ~]$ ssh 192.168.0.30\nAre you sure you want to continue connecting (yes/no/[fingerprint])? yes\nsanchuang@192.168.0.30's password: \n[sanchuang@cPen_web ~]$ \n----------------------------------\n#注:登录时默认会去寻找家目录下的~/.ssh/id_rsa去进行认证,所有尽量不要在生成key的时候将它的默认路径更改\n```\n\n\n\n---\n\n## 三. 登录验证原理 - 密码登录\n\n**1、密码登录**\n\n​\t\tclient向server发送登陆请求,server将自己的公钥发送给client\n​\t\tclient使用这个公钥,将密码进行加密,发送给server\n​\t\tserver用私钥解密登陆密码,验证合法性\n​\t\tserver返回验证结果给client\n\n\n\n这个流程有一个问题,怎么保证收到的公钥就是目标server的公钥?(中间人攻击)\n如果一个攻击者中途拦截了client的登录请求,发送自己的公钥给client,client端就会用攻击者的公钥进行数据加密,攻击者接收到信息后,用自己的私钥就可以解密了,这就窃取了client的登陆信息了\n\n\n\n为了解决这个问题,client端第一次登录的时候,会进行一个公钥确认\n\n\n\n确认server服务端的这个host主机摘要,确认成功之后就会将server端的pubkey保存在~/know_hosts里面\n以后每次连接都会验证这个know_hosts里的key和收到的pubkey是否一致\n\n\n\nserver主机的pubkey保存在/etc/ssh/目录下,默认使用ssh_host_ecdsa_key.pub\n\n\n\n**#注:SSH基于公钥加密的技术**\n\n> ![image-20220824115204565](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241152622.png)\n>\n> \\#注:第一步A机器向B机器发送登录请求(还没有道输入密码的阶段)\n>\n> \\#注:B机器接收到A机器的请求之后,把B机器的公钥发送给A机器\n>\n> \\#注:A机器拿到公钥之后,用公钥对密码进行加密(密码是密文,不能让别人知道)\n>\n> \\#注:A机器把加好密的这一串密文发给B\n>\n> \\#注: B机器收到来此A机器的机密之后的密码,用私钥解密,得到passwd,再与/etc/shadow密码进行比较验证是否通过\n>\n> \\#注:B机器向A机器返回登陆结果(成功或者失败)\n>\n> **#注:密码登录涉及公钥加密,ssh整个都设计公钥加密(无论是密码登录或公钥登录)**\n>\n> \\#注:没有保证第3方人攻击\n>\n> \n>\n> \\#注:公钥加密私钥解密、私钥加密公钥解密(为了区分后面+.pub)\n>\n> \\#注:成对存在成对加解密\n\n\n\n```bash\n#注:第一次登录机器时,一般会要输入yes(是否信任B主机),然后把key放到know_hosts里面\nA机器下\n[root@cPen_web .ssh]# ssh 192.168.0.30 -l wy -p 22\n………………\nAre you sure you want to continue connecting (yes/no/[fingerprint])? yes\n………………\n[root@cPen_web .ssh]# cat known_hosts \n192.168.0.30 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBO+Xv/RYitaOHx0iyAbcOXLIPZEn75xh94pJ2L+MWOV/V3YRezYCgHJSwAJm5N9ceqtYCKoXUL3cCJeuGiiDH0A=\nB机器下\n[root@cPen_web .ssh]# cd /etc/ssh\t\t\t\t\t# 注:ssh服务的配置文件\n[root@cPen_web ssh]# ls\nmoduli sshd_config ssh_host_ecdsa_key.pub ssh_host_ed25519_key.pub ssh_host_rsa_key.pub\nssh_config ssh_host_ecdsa_key ssh_host_ed25519_key ssh_host_rsa_key\n[root@cPen_web ssh]# cat ssh_host_ecdsa_key.pub \t# 注:默认使用ssh_host_ecdsa_key.pub\necdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBO+Xv/RYitaOHx0iyAbcOXLIPZEn75xh94pJ2L+MWOV/V3YRezYCgHJSwAJm5N9ceqtYCKoXUL3cCJeuGiiDH0A= \n#注:A机器保存的key就是B机器/etc/ssh/ssh_host_ecdsa_key.pub下面的\n#注:A机器生成的公钥就是B机器/etc/ssh/ssh_host_ecdsa_key.pub下面的\n```\n\n\n\n第一次登录 输入yes的原因:信任它\n-#注:为了增加安全性,第一次连接B主机的时候,都会进行一个主机确认(yes)\n-#注:输入yes表示,是可信任主机,那就是将主机的pubkey保存在~/.ssh/known_hosts里面,以后每次连接都会验证接收的key是否和know_hosts里一直,不一致,会登录异常\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n-#注:A机器向B机器发送请求登录\n-#注:B机器向A机器返回公钥\n-#注:如果A机器向B机器发送请求的时候,被C给拦截了\n-#注:C就伪造一下,把它的公钥发送给A\n-#注:A把密文用C的公钥加密发送给B,c就可以拿自己的密钥解密信息,不安全\n-#注:只能自己确认(人为确认)接收的公钥是否是B机器的,输入yes,know_hosts就是自己信任的主机,把B主机的公钥保存到know_hosts里面\n-#注:后续都会拿know_hosts里面 这个公钥和B发送的公钥进行比较(密钥不一致时会提示 登录失败不受信任)\n\n-#注:这个key是属于主机的key,验证这台主机的\n-#注:公钥登录的key属于用户的,是验证用户的key\n\n\n\n---\n\n## 四. 登录验证原理 - 公钥认证登录\n\n2、公钥认证登陆\n\n​\t\tclient端生成公钥对,将公钥追加在server端的~/.ssh/authorized_keys(1行1个公钥)\n​\t\t发送登录请求,server收到请求之后,生成随机字符串发送给client\n​\t\tclient用自己的私钥对字符串进行加密,发送给server\n​\t\tserver收到加密字符串之后用公钥解密,比较解密出的字符串和之前生成的字符串是否一致\n​\t\t返回结果给client\n\n\n\n-#注:公私钥对是成对存在的,一个用于加密,一个用于解密,具体哪个为私钥,哪个为公钥就看使用者自己管理\n\n\n\n注意:非对称加密计数\n\t\t**使用公钥进行加密,私钥解密,基本用于数据加密**\n\t\t**使用私钥加密公钥解密,用于认证**(对数据加密性没有要求,拿到就拿到)\n\n\n\n> ![image-20220824115746442](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241157484.png)\n>\n> -#注:第一步在A机器上生成公钥对\n> -#注:B主机将A主机的公钥写入B主机用户的~/.ssh/authorized_keys里面\n> -#注:A主机向B机器发送登录请求\n> -#注:B机器收到请求之后,会生成一个随机字符串。把这个随机字符串发送给A机器\n> -#注:A机器收到随机字符串后,用私钥加密\n> -#注:A机器将加密之后的字符串发送给B机器\n> -#注:B机器拿到A机器的加密字符串之后,用公钥解密,再比较解密之后的字符串和生成的字符串是否一致。\n> -#注:B机器再返回结果\n>\n> -#注:ABC3台机器,A上面的公钥在BC上都有,C也能公钥解密,得到字符串(对数据加密性没有要求,拿到就拿到)\n\n\n\n---\n\n## 五. 总结\n\n### 5.1 SSH服务介绍\n\n**远程Shell应用程序**\n\n- 允许用户在远程机器上执行任意命令 \n- 让标准输出在本地\n- 早期明文远程协议:telnet\n \n\n**SSH(Secure Shell,安全的外壳)**\n\n- 为客户机提供安全的Shell环境,用于远程管理 \n- 默认端口:TCP `22`\n \n\n**SSH基于公钥加密(非对称加密)技术**\n\n- 数据加密传输\n- 客户端和服务器的身份验证\n\n\n\n### 5.2 公钥加密体系\n\n**公钥(Public Key)和私钥(Private Key) **\n\n- 公钥和私钥是成对生成的,这两个密钥互不相同,两个密钥可以互相加密和解密\n- 不能根据一个密钥而推算出另外一个密钥\n- 公钥对外公开,私钥只有私钥的持有人才知道\n- 私钥应该由密钥的持有人妥善保管\n\n**根据实现的功能不同,可以分为数据加密和数字签名**\n\n\n\n---\n\n## 六. 数据加密\n\n**发送方使用接收方的公钥加密数据 **\n**接收方使用自己的私钥解密数据**\n\n> ![image-20220824132431228](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241324278.png)\n\n\n\n**数据加密能保证所发送数据的机密性**\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n> -#注:数据加密 主要是为了保障 接收方的数据安全性\n>\n>-#注:把A机器的公钥发送给B机器\n> -#注:B用A机器的公钥对传输内容进行加密,然后把信息发送给A机器\n> -#注:将加密内容发送给A机器,此时只有A机器有权限获取里面的内容\n> \n>-#注:数据加密 主要是为了保障 接收方的数据安全性\n> -#注:不能保障收到的数据一定是B机器发过来的\n> \n><img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241325586.png\" alt=\"image-20220824132542539\" style=\"zoom:80%;\" />\n\n\n\n---\n\n## 七. 数字签名\n\n**发送方**\n\n- 对原始数据执行HASH算法得到摘要值 \n- 发送方用自己私钥加密摘要值\n- 将加密的摘要值与原始数据发送给接收方\n\n> ![image-20220824132704531](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241327579.png)\n\n\n**数字签名保证数据完整性、身份验证和不可否认**\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n> -#数据签名\n> -#注:如何保障收到的数据一定是B机器发过来的\n> -#注:(A机器上要有B机器的公钥,B机器也要有A机器的公钥)\n> -#注:A机器公钥给B机器\n> -#注:B机器公钥给A机器\n> -#注:B机器向A机器发送数据:B机器先用自己的私钥对摘要信息(hash,一般是data的hash散列值 做信息的摘要信息,验证信息-完整值)进行加密生成签名。B机器再用A机器的公钥对信息内容和签名进行加密,发送给A机器\n> -#注:A机器收到B机器的密文数据后,用自己的私钥进行解密。得到解密后的明文后,用B机器的公钥来解密B机器生成的签名\n>\n> -#注:数据签名 验证发送方的数据安全(验证发送方是不是我想要的发送方)\n>\n> <img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241328958.png\" alt=\"image-20220824132809916\" style=\"zoom:80%;\" />\n\n\n\n---\n\n## 八. SSH身份验证过程\n\n> ![image-20220824133013889](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241330947.png)\n\n\n\n---\n\n## 九. 电子邮件数字签名过程\n\n> ![image-20220824133104520](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241331576.png)\n\n\n\n---\n\n## 十. OpenSSH\n\n**OpenSSH**\n\n- 官方站点:http://www.openssh.com\n- 主要软件包:openssh-server、openssh-clients \n- 服务名:`sshd`\n- 服务端主程序:**/usr/sbin/sshd** \t\t\t\t\t # 注:都是可执行的脚本\n- 客户端主程序:**/usr/bin/ssh**\t\t\t\t\t\t # 注:都是可执行的脚本\n- 服务端配置文件:/etc/ssh/`sshd_config` \n- 客户端配置文件:/etc/ssh/`ssh_config`\n\n\n\n-#注:xshell就是模拟ssh的客户端\n-#注:linux yum下下来的包基本都是rpm包\n\n\n\n```bash\n示例1:查看命令属于哪个包下载的\n---------------------------------------------------------------------------------------------------------------------------------\nssh是通过openssh下载的\n[root@cPen_web ~]# which ssh\n/usr/bin/ssh\n[root@cPen_web ~]# rpm -qf /usr/bin/ssh\nopenssh-clients-8.0p1-4.el8_1.x86_64\n[root@cPen_web ~]# yum list |grep openssh\n===============================================================================\n\n示例2:启动sshd服务的实际上是执行行的服务启动脚本文件 /usr/sbin/sshd(真正执行服务的脚本)\n[root@cPen_web ~]# rpm -qf /usr/sbin/sshd\nopenssh-server-8.0p1-4.el8_1.x86_64\n[root@cPen_web ~]# service sshd restart\t\t\t# 注:service 守护进程 帮它去管理服务\nRedirecting to /bin/systemctl restart sshd.service\n[root@cPen_web ~]# \n#注:守护进程可以帮助管理,想关闭或打开。自己管理的话,很难,要手动的kill 或者 先kill再起来\n===============================================================================\n\n示例3:直接执行脚本/usr/sbin/sshd 启动服务\n---------------------------------------------------------------------------------------------------------------------------------\n#如果服务起来,会有22号端口属于listen监听状态\n[root@cPen_web ~]# service sshd stop\n[root@cPen_web ~]# lsof -i:22\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nsshd 1709 root 5u IPv4 37939 0t0 TCP cPen_web:ssh->192.168.0.42:54537 (ESTABLISHED)\nsshd 2185 root 5u IPv4 50589 0t0 TCP cPen_web:ssh->192.168.0.42:57389 (ESTABLISHED)\n[root@cPen_web ~]# /usr/sbin/sshd\n[root@cPen_web ~]# lsof -i:22\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nsshd 1709 root 5u IPv4 37939 0t0 TCP cPen_web:ssh->192.168.0.42:54537 (ESTABLISHED)\nsshd 2185 root 5u IPv4 50589 0t0 TCP cPen_web:ssh->192.168.0.42:57389 (ESTABLISHED)\nsshd 2282 root 4u IPv4 52306 0t0 TCP *:ssh (LISTEN)\t\t# 注:处于监听状态\nsshd 2282 root 6u IPv6 52308 0t0 TCP *:ssh (LISTEN)\n===============================================================================\n\n示例4:直接启动vsftpd服务端\n---------------------------------------------------------------------------------------------------------------------------------\n#注:vsftpd是服务端,ftp是客户端\n[root@cPen_web ~]# vsftpd\t\t\t\t# 注:启动vsftpd服务端(可以直接启动)\n#注:查看服务是否起来(4种)\n[root@cPen_web ~]# pidof vsftpd\n2297\n[root@cPen_web ~]# ps -ef |grep vsftpd\nroot 2297 1 0 14:50 ? 00:00:00 vsftpd\nroot 2300 2186 0 14:51 pts/1 00:00:00 grep --color=auto vsftpd\n[root@cPen_web ~]# netstat -auplt |grep vsftpd\ntcp6 0 0 [::]:ftp [::]:* LISTEN 2297/vsftpd \n[root@cPen_web ~]# lsof -i:21\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nvsftpd 2297 root 3u IPv6 52524 0t0 TCP *:ftp (LISTEN)\n```\n\n\n\n---\n\n## 十一. SSH服务端配置文件\n\n**/etc/ssh/sshd_config**\n\n- 重启sshd服务生效\n \n\n修改了配置文件端口号,启动不起来,原因是selinux是enforcing状态需要修改\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n-#注:一般配置文件都是以#开头的注释行\n-#注:只有root用户有权限修改它\n\n\n\n```bash\n示例1:过滤出有效行\n--------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_web ~]# grep -v -E \"^#|^$\" /etc/ssh/sshd_config \t# 注:-E支持扩展正则 ; -v不显示\nHostKey /etc/ssh/ssh_host_rsa_key\nHostKey /etc/ssh/ssh_host_ecdsa_key\nHostKey /etc/ssh/ssh_host_ed25519_key\n……………………\nSubsystem\tsftp\t/usr/libexec/openssh/sftp-server\n===============================================================================\n\n示例2:vim /etc/ssh/sshd_config\n--------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_web ~]# vim /etc/ssh/sshd_config \n#Port 22\t\t\t\t\t\t\t# 注:默认端口号\n#AddressFamily any\t\t\t\t\t# 注:ip地址 (ipv4\\ipv6) any 任何\n#ListenAddress 0.0.0.0\t\t\t\t# 注:本机上面的所有ip地址\n#ListenAddress ::\t\t\t\t\t# 注:ipv6\n===============================================================================\n\n示例3:ipv6地址\n--------------------------------------------------------------------------------------------------------------------------------\nIPv6的地址长度为128位,是IPv4地址长度的4倍。于是IPv4点分十进制格式不再适用,采用十六进制表示。\n#注:以: 冒号分隔\n===============================================================================\n\n示例4:网络连接失败 排错\n--------------------------------------------------------------------------------------------------------------------------------\n1、ping通 确保网络是联通的\n2、确保服务是起来的\n[C:\\~]$ telnet 192.168.0.29 2233\t\t\t\t\t\t\n1端口没起,2防火墙\n[C:\\~]$ telnet 192.168.0.29\nConnecting to 192.168.0.29:23...\nConnecting to 192.168.0.29:2233...\t\t\t\t\nConnection established.\nTo escape to local shell, press 'Ctrl+Alt+]'.\nSSH-2.0-OpenSSH_8.0\n===============================================================================\n\n示例5:配置文件常用配置详解\n--------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_web ~]# vim /etc/ssh/sshd_config \n#Port 22\nPort 2233\t\t\t\t\t\t# 注:修改默认监听端口(默认22端口)\n#AddressFamily any\nListenAddress 192.168.0.29\t\t# 注:设置本机监听ip地址,默认为0.0.0.0(表示在本机任意ip地址上监听)\nPermitRootLogin no\t\t\t\t# 注:禁止root用户登录(no 不予许root用户登录,默认为yes)\n#PubkeyAuthentication yes\t\t# 注:是否开启公钥认证(默认开启)\nAuthorizedKeysFile .ssh/authorized_keys\t# 注:配置公钥认证的文件(这个文件可以改 没必要)\n\t\t\t\t\t\t\t\t\t\t\t\t# 注:前面的家目录没有写\nPasswordAuthentication no\t\t# 注:是否开启密码认证,默认为yes\n# WARNING: 'UsePAM no' is not supported in Red Hat Enterprise Linux and may cause several\nUsePAM yes\t\t\t\t\t\t# 注:使用pam认证(一般为yes不用改它)(pam帮我们进行认证,而不是ssh)\n#UseDNS yes\t\t\t\t\t\t# 注:是否将客户端主机名解析成ip,可以将其设置为no\n\t\t\t\t\t\t\t\t# 注:此过程不顺利的话,会非常的慢,会影响登录认证的速度,可以将其设置为no\n#注:一般来说不会开启密码认证\n#注:一般来说一个机器不允许root用户登录,一般来说给用户加sudo权限,用超级用户登录\n#注:pam是linux下面的pam模块,认证模块。我们登陆进来后,pam帮我们做的密码/密码认证,身份认证状态检验\n#注:pam认证模块 --> 配置路径 /etc/pam.d/\t\t这个目录下面存放的是每个需要认证的服务的配置,文件名就是服务名\n#注:DNS --> 域名解析服务。网络中使用ip地址通信。域名最终都要解析成ip的\n#注:DNS域名解析服务。主机名也可以使用DNS解析 \t(比如cPen_centos8)\n#注:如果在DNS范畴之内,可以通过主机名来访问这台主机,或者通过ip地址来访问\n-----------------------------------------------------------------------------------\n[root@cPen_centos8 ~]# visudo\nsanchuang ALL=(ALL) NOPASSWD:ALL\n[root@cPen_python ~]# service sshd restart\t\t\t# 注:重启服务后22号端口已有的连接还在\n-------------------------------------------------------------------------------------\n#注:主机B登录\n[root@cPen_web ~]# ssh 192.168.0.29 -p 2233\t\t\t# 注:指定端口2233\n#注:已经连接了的端口,即使改了端口,也不会有影响(只要不关闭窗口)\n#注:修改配置文件只是在磁盘上进行修改,对于正在运行的程序,需要把配置加载到磁盘上(重启、reload、kill -1)\n#注:修改完配置文件后,root用户 和 密码登录 登录不上去了(禁止使用密码登录)\n--------------------------------------------------------------------------------------------\n#注:修改配置文件并重启服务时 PermitRootLogin no\n#注:B机器root用户登录不上了\n[root@cPen_web ~]# ssh 192.168.0.29 -p 2233\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic).\n===============================================================================\nPasswordAuthentication no\t\t# 注:是否开启密码密码认证,默认为yes\n\n示例6:物理机上 公钥登录(sanchuang用户登录)\n--------------------------------------------------------------------------------------------------------------------------------\n#注:ssh生成公钥:(xshell菜单栏)工具 --> 新建用户密钥生成向导 --> 下一步(一直) --> 保存公钥pub key:id_rsa_2048.pub\n#注:把pub key复制到sanchuang用户下面去\n[sanchuang@cPen_web .ssh]$ vim authorized_keys\n………………\n[sanchuang@cPen_web .ssh]$ chmod 600 authorized_keys \n[sanchuang@cPen_web .ssh]$ chmod 755 /home/sanchuang\n#注:物理机(xshell)生产一对密钥对,放在虚拟机上\n#注:物理机上生成的key,在物理机上登,对物理机进行验证\n#注:属性 --> 用户身份验证 --> 方法:Public Key ; 用户名:sanchuang ; 用户密钥:id_rsa_2048(刚才生成的密钥)\n#注:这个key是物理机上的key,key粘到哪个用户下,就以哪个用户登录。在物理机上生成密钥对,要登你的虚拟机,使用xshell生成和管理密钥对,需要登录虚拟机的sanchuang用户,把物理机的pub key赋给sanchuang用户家目录下~/.ssh/authorized_keys,使用物理机去登。在物理机上生成的key,在物理机上登,sanchuang保存的是物理机的key,只能对物理机进行验证\n\n#注:连接不成功的话,设置selinux 关掉(setenforce 0)。修改端口需要添加selinux的规则,一般来说不会去添加它的规则,而是把它关掉\n#注:连不上的话,把iptables也关掉(iptables -F)\n===============================================================================\n\n示例7:ssh命令登陆\n--------------------------------------------------------------------------------------------------------------------------------\nssh命令登陆\n\t-l\t指定登陆的用户名\n\t-p\t指定server的端口\n\t-i\t指定私钥文件,默认会在~/.ssh/去找私钥\n\t-o\t接特定设置选项\n\t#无序输入yes,自动保存hostkey\n\tssh -o StrictHostKeyChecking=no 192.168.0.132 -p 223\n\t#注:脚本里这样写 无序输入yes\n===============================================================================\n\n示例8:修改完成之后重新加载配置的方法(sshd_config)\n#注:ssh起来后(默认会读磁盘里ssh配置文件)放到内存去运行\n--------------------------------------------------------------------------------------------------------------------------------\n#注:修改完成之后重新加载配置的方法(sshd_config)\n[root@cPen_web ~]# kill -1 2282\n[root@cPen_web ~]# kill -HUP 2282\n[root@cPen_web ~]# service sshd restart\t# 注:重新启动服务\n[root@cPen_web ~]# service sshd reload\t# 注:重新加载配置\n===============================================================================\n\n示例9:man 5 查看配置文件帮助文档\n--------------------------------------------------------------------------------------------------------------------------------\nman 1\t普通的命令\nman 5\t查看配置文件的帮助文档\n[root@cPen_web .ssh]# man 5 /etc/ssh/sshd_config \t# 注:man 5 查看配置文件帮助文档\n===============================================================================\n\n示例10:UsePAM yes\n--------------------------------------------------------------------------------------------------------------------------------\nUsePAM yes\t\t\t\t\t\t# 注:使用pam认证(一般为yes不用改它)\n#注:pam是linux下面的pam模块,认证模块。我们登陆进来后,pam帮我们做的密码/密码认证,身份认证状态检验\n模块文件:/etc/pam.d/\t\t\t # 注:存放路径;用于认证的模块,linux可插入认证模块\n--------------------------------------------------------------------------------------------\n[root@cPen_python ~]# cd /etc/pam.d/\t# 注:里面是pam的配置\n[root@cPen_python pam.d]# ls\t\t\t# 注:里面全是认证的模块;每一个服务一个文件\nchfn fingerprint-auth passwd postlogin runuser-l smtp.postfix sudo-i systemd-user\nchsh fingerprint-auth-ac password-auth postlogin-ac smartcard-auth sshd su-l vlock\nconfig-util login password-auth-ac remote smartcard-auth-ac su system-auth vmtoolsd\ncrond other polkit-1 runuser smtp sudo system-auth-ac vsftpd\n===============================================================================\n\n示例11:hostname -f 查看主机名全称\n--------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_centos8 pam.d]# hostname -f\ncPen_centos8\n===============================================================================\n\n示例12:解析出百度的ip\n--------------------------------------------------------------------------------------------------------------------------------\n[root@cPen_centos8 pam.d]# host www.baidu.com\n[root@cPen_centos8 pam.d]# ping www.baidu.com\n```\n\n\n\n---\n\n## 十二. 练习\n\n**修改端口为2233**\n**禁止root用户登录**\n**禁止密码登录**\n**创建管理员用户sanchuang,给sanchuang所有sudo权限**\n**在Windows机器上生成密钥对,后续A,B两台虚拟机器都使用公钥认证进行登陆**\n**\\*\t注意关闭防火墙和selinx**\n\t\t\tiptables -F\n\t\t\tgetenforce 0 --> 或者修改配置文件 /etc/selinux/config --disabled,永久修改需要重启机器\n\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n-#注:**不是错误,使用service sshd restart命令实际上是执行/bin/systemctl restart sshd.service命令**\n\n```bash\n[root@cPen_python ~]# service sshd restart\nRedirecting to /bin/systemctl restart sshd.service\t\t# 注:使用这个命令去执行\n\n#注:练习 具体操作如上\n```\n\n\n\n---\n\n## 十三. ssh-agent管理密钥\n\n> ![image-20220824134452001](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241344042.png)\n>\n> ssh-agent管理密钥 一个代理程序,帮助我们管理私钥\n> 配置: xshell--> 主机属性--》ssh --》勾选 使用xagent进行身份验证 ;勾选 使用代理转发\n\n\n\n```bash\n[sanchuang@mysql-binary .ssh]$ ssh-add id_rsa\t\t# 注:添加主机密钥给agent管理\n#注:把虚拟机上面的key也交给给ssh-agent去管理\n\n[sanchuang@mysql-binary .ssh]$ ssh-add -l\t\t\t# 注:查看agent管理了哪些密钥\n2048 SHA256:eJz1xcOJnntAP/R0w1if7oEaukIbiwh0vmtp9Q605ls (RSA)\n```\n\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n-#注:ssh-agent的概念:帮你管理密钥的,默认情况下ssh-agent开在物理机上的。ssh-agent就是一个中间商,保存管理密钥的。在xshell里面开启了ssh-agent之后,从A机器登录到B机器,它会先取看一下A机器root家目录下面有没有公私钥,没有的话 会从ssh-agent里面捞取它的公私钥\n-#注:B机器没有A机器的公钥,它会去找ssh-agent里面管理的那个公钥对(中间商),`最后认证是拿物理机的key去做认证的`,因为物理机里面跑了1个ssh-agent,管理了物理机的pubkey,物理机的pubkey可以登录A又可以登录B,满足的条件是物理机能够登录到B\n-#注:再来一台主机C,想要从A调到C,先决条件是C要有物理机的pubkey,C对物理机授了权,然后物理机的key又由ssh-agent去管理,就可以从A主机跳到C主机。(家目录下面没有私钥生成,就去找ssh-agent管理的密钥对,只要C有物理机的公钥,就都可以登录了)\n\n-#注:这个服务是xshell的,只能通过xshell里面才能进行这一系列操作(xshell管理ssh-agent)\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n> -#注:(xshell菜单栏)文件 --> 打开(下拉) --> 属性(右键) --> SSH --> 允许Xagent进行身份验证(勾上);允许代理转发(勾上)\n>\n> ![image-20220824134713614](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241347670.png)\n>\n> -#注:在B机器上勾上(现在要在A机器上登录B机器)\n\n\n\n.--------------------------------------------------------------------------------------------------------------------------\n\n\\#注:物理机上面有2个虚拟机 A、B,物理机使用xshell去连接A和B。刚在在A、B上都创建了sanchuang用户,并且把物理机的pub key都给了A、B两台机器的sanchuang用户。现在,在A机器上想要连接B机器的sanchuang用户,应该怎么做?B机器上没有A机器的key\n\n\\#注:答:把A的key给B(在A机器上生成自己的key,这样的话太麻烦了)\n\n \n\n\\#注:用户加的是哪一台的pubkey,就是允许哪一台的主机登录,加的authorized_keys是为哪一台机器授权\n\n\\#注:A、B机器2台主机之间进行通讯的话,有1个本地的概念,它会在本地用户的家目录下面去找key;物理机没有这个概念,因为它是通过xshell(ssh的客户端,图形界面的ssh命令)去连接的,它通过xshell去管理它的key\n\n\n\n```bash\n示例:A机器上登录到B机器\n--------------------------------------------------------------------------------------------\n#注:前提确保 Windows可以免密码登录到A、B机器\n[sanchuang@cPen_python ~]$ ssh 10.122.148.108 -p 2233\nLast login: Sun Nov 15 19:59:00 2020 from 10.122.38.250\n[sanchuang@cPen_centos8 ~]$ \n```\n\n\n\n---\n\n## 十四. 其他总结\n\n### 14.1 SSH服务端配置文件\n\n**SSH登录使用的用户名**\n\n- 服务器中的本地系统用户的帐号名\n\n**SSH登录的用户验证方式**\n\n- 密码验证:使用服务器中系统帐号对应的密码 \n- 密钥对验证:使用客户机中生成的公钥、私钥\n\n**SSH客户端文件通常无需修改**\n\n\n\n### 14.2 SSH客户端\n\n**使用ssh命令远程登录**\n\n- 方式1: ssh 用户名`@`服务器地址 \n- 方式2: ssh `-l` 用户名 服务器地址 \n- 方式3: ssh\t服务器地址\n\n**客户机使用第一次连接服务器时**\n\t\t[root@localhost ~]# `ssh root@10.10.10.1`\n\n\n\n### 14.3 known_hosts文件\n\n**客户机使用ssh第一次连接服务器时**\n\n- 将服务器上sshd守护进程的公钥复制到本地 \n- 存放到本地~/.ssh/known_hosts文件中\n- 每行存放一台服务器的公钥 \n- `用来验证服务器的身份`\n\n\n\n**公钥验证服务器的具体细节**\n\n> ![image-20220824135229894](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241352942.png)\n>\n> ![image-20220824135239974](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241352022.png)\n\n\n\n### 14.4 密钥方式\n\n**SSH的公钥认证流程**\n\n> ![image-20220824135318183](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241353236.png)\n\n\n\n**公钥验证客户端的具体细节**\n\n> ![image-20220824135336623](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241353669.png)\n>\n> ![image-20220824135415658](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241354706.png)\n\n\n\n**SSH公钥认证的基本实现步骤**\n\n- **1、在客户机创建密钥对**\n - `ssh-keygen -t rsa`\t指定rsa算法\n - 设置保护私钥文件的密码\n - 在`~/.ssh`下生成两个文件\n - `id_rsa`是用户的私钥\n - `id_rsa.pub`是用户的公钥\n\n- **2、将公钥文件上传至服务器**\n\n - 上传到服务器~/.ssh/authorized_keys文件 \n\n - 文件中每行保存一个用户的公钥\n\n - `scp ~/.ssh/id_rsa.pub` \n\n `root@10.10.10.1:~/.ssh/authorized_keys`\n\n\n\n### 14.5 SSH客户端\n\n**使用scp命令远程复制文件/目录**\n\n- 方式1: scp 用户名@服务器地址:源文件 目标路径 \n- 方式2: scp 本地文件 用户名@服务器地址:目标路径 \n- 若复制的是目录,则需添加“-r”选项\n\n**使用sftp命令从服务器下载文件**\n\n- 格式:sftp 用户名@服务器地址\n\n\n\n### 14.6 通过SSH运行服务器中的窗口程序\n\n**运行服务器中的图形程序是SSH的重要应用**\n\n- ssh命令需要在图形界面虚拟终端下运行\n- 命令格式:`ssh -X username@sshserver`\n\n> ![image-20220824135823639](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241358685.png)\n\nxlock是运行在SSH服务器中,而显示在SSH客户机中的窗口程序\n\n\n\n### 14.7 SSH客户端应用\n\n**使用图形客户端软件 SecureCRT**\n\n- 主要用途:基于SSH协议远程登录以便管理服务器 \n- 下载地址:http://www.vandyke.com/\n\n\n**使用图形客户端软件 WinSCP**\n\n- 主要用途:基于sftp、scp或ftp的方式下载/上传数据 \n- 下载地址:http://winscp.net/\n\n\n\n### 14.8 SSH访问控制\n\n**SSH使用TCP Wrappers实现访问控制 **\n\n\n\n**主要配置文件**\n\n- /etc/hosts.allow\n- /etc/hosts.deny\n\n> ![image-20220824140053190](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208241400235.png)\n\n\n\n**TCP Wrappers可以控制哪些服务**\n\n- 受super daemon(xinetd)管理的服务 \n- 支持libwrap.so模块的服务\n\n\n**TCP Wrappers的访问控制原则**\n\n- 首先检查 hosts.allow 文件,若找到相匹配的策略,则允许访问\n- 否则继续检查 hosts.deny 文件,若找到相匹配的策略,则拒绝访问\n- 如果两个文件中都没有相匹配的策略,则允许访问\n\n\n\n---","tags":["Linux","SSH"],"categories":["Linux"]},{"title":"19_Linux基础-ssh服务1","url":"/posts/33033.html","content":"## 一. 练习\n\n1、编写脚本,实现批量新增用户,用户名以user开头,具体新增用户数量随用户输入,并且为每个用户设置随机密码(密码长度为12位随机字符组成),记录创建的用户与密码,保存到/tmp/user文件中。\n\n\n2、如何实现两个字符串的拼接,两个整数求和,以及5除以3,保留2位小数\n\n\n3、如何计算本机有多少个用户以及多少个普通用户?\n\n\n4、如何去除字符串中所有空格?\n\n\n5、备份/var/log/nginx/access.log日志,每五分钟备份一次,并且以2020-11-15_10_05-access.log.tar.gz方式命名。将日志文件备份文件放到/nginx/目录下。\n\n\n6、查找/etc/目录下10天以内3天以前修改过的文件,并将这些文件记录到/tmp/etc_log文件中\n\n\n\n### 1.1 编写脚本,实现批量新增用户,用户名以user开头,具体新增用户数量随用户输入,并且为每个用户设置随机密码(密码长度为12位随机字符组成),记录创建的用户与密码,保存到/tmp/user文件中\n\n**题目1:编写脚本,实现批量新增用户,用户名以user开头,具体新增用户数量随用户输入,并且为每个用户设置随机密码(密码长度为12位随机字符组成),记录创建的用户与密码,保存到/tmp/user文件中。**\n\n```bash\n示例1\n---------------------------------------------------------------------\nread -p \"请输入你要添加的用户个数:\" num1\nfor i in `seq $num1` # 注:循环多少次\ndo\n id user$i &>/dev/null\n a=`echo $?` # 注:上条命令返回值 0 成功 非0 失败\n str1=`date +%s+%N | md5sum|head -c 4` # 注:%s时间戳\n if [ $a -eq 0 ] ;then\n echo \"该用户已存在,不进行新建操作\"\n break\n else\n useradd user$str1$i &>/dev/null\n b=`echo $?`\n if [ $b -eq 0 ];then\n echo \"创建成功\"\n passwd1=`mkpasswd -l 12` # 注:mkpasswd 生成随机12位密码串\n echo $passwd1 |passwd user$str1$i --stdin &>/dev/null # 注:--stdin 密码从标准输入里面来\n echo \"user$str1$i:$passwd1\" >>/tmp/user\n else\n echo \"创建失败\"\n fi\n fi\ndone\n---------------------------------------------------------------------\n[root@cPen_web lianxi]# date +%s+%N\t\t# 注:引用纳秒的概念,防止用户名 重复\n1605251515+012657467\n[root@cPen_web lianxi]# man date\n %% a literal %\n %a locale's abbreviated weekday name (e.g., Sun)\t# 注:Sun\n %A locale's full weekday name (e.g., Sunday)\t\t# 注:Sunday\n %s seconds since 1970-01-01 00:00:00 UTC\t\t\t# 注:时间戳 从1970年1月1号到现在的秒数\n %N nanoseconds (000000000..999999999)\t\t\t# 注:纳秒 1纳秒=十亿分之一秒\n[root@cPen_web ~]# date +%s+N | md5sum|head -c 4\n2b13[root@cPen_web ~]# \n\n示例2\n---------------------------------------------------------------------\nread -p \"输入新增用户数:\" num\nfor i in `seq $num`\ndo\n useradd user$i &>/dev/null\n passwd=`mkpasswd -l 12`\n echo $passwd |passwd user$i --stdin &>/dev/null\n echo \"用户名:user$i\" \"密码:$passwd\" &>>/tmp/user\ndone\n```\n\n\n\n### 1.2 如何实现两个字符串的拼接,两个整数求和,以及5除以3,保留2位小数\n\n**题目2:如何实现两个字符串的拼接,两个整数求和,以及5除以3,保留2位小数**\n\n数值运算:https://blog.csdn.net/weixin_34408624/article/details/92598137\n#注:挨在一起写实现2个字符串拼接\n\n```bash\n示例\n---------------------------------------------------------------------\n[root@cPen_web ~]# a=abc\n[root@cPen_web ~]# b=def\n[root@cPen_web ~]# echo $a$b\t\t# 注:字符串拼接\nabcdef\n[root@cPen_web ~]# echo abc$a\nabcabc\n[root@cPen_web ~]# a=3\n[root@cPen_web ~]# b=4\n[root@cPen_web ~]# echo $(($a+$b))\n7\n#注:1个括号默认是字符串拼接 不会进行数值运算\n[root@cPen_web ~]# a=123\t\t\t# 注:默认都是str类型\n[root@cPen_web ~]# a=\"123\"\n[root@cPen_web ~]# a='123'\n------------------------------------------------------------\n[root@cPen_web ~]# a=123\n[root@cPen_web ~]# b=4\n[root@cPen_web ~]# echo $(( $a > $b ))\n1\t\t\t\t\t\t\t\t\t\t\t# 注:正确返回1\n[root@cPen_web ~]# echo $(( $a < $b ))\n0\t\t\t\t\t\t\t\t\t\t\t# 注:错误返回0\n[root@cPen_web ~]# expr $a + $b\t\t\t\t# 注:expr命令 进行数值运算\n127\n[root@cPen_web ~]# echo $(( $a + $b ))\t\t# 注:2个圆括号实现整数运算\n127\n[root@cPen_web ~]# echo $[ $a + $b ]\t\t# 注:中括号实现整数运算\n127\n[root@cPen_web ~]# let c=$a+$b\t\t\t\t# 注:let 也可以实现整数运算\n[root@cPen_web ~]# echo $c\t\t\t\t\t# 注:let只能复制 不能直接赋值\n127\n#注:整数运算:4种方法\n[root@cPen_web ~]# expr $a + $b\n[root@cPen_web ~]# echo $(( $a + $b ))\n[root@cPen_web ~]# echo $[ $a + $b ]\n[root@cPen_web ~]# let c=$a+$b\t\t\t\t# 注:let只能复制 不能直接赋值\n数值运算:https://blog.csdn.net/weixin_34408624/article/details/92598137\n------------------------------------------------------------------------\n#注:小数运算\necho \"scale=3;5/3\"|bc\t\t\t\t\t\t# 注:3表示保留3位小数 5/3\n[root@cPen_web ~]# echo \"scale=3;5/3\"|bc\t# 注:确保主机上装了bc\n1.666\n[root@cPen_web lianxi]# echo $((5/3))\n1\n[root@cPen_web lianxi]# echo |awk '{printf 5/3}'\t\t# 注:awk默认保留5位小数\n1.66667[root@cPen_web lianxi]# \n[root@cPen_web lianxi]# echo |awk '{printf \"%.2f\",5/3}'\t# 注:保留2位小数\n1.67[root@cPen_web lianxi]# \n数值运算:https://blog.csdn.net/weixin_34408624/article/details/92598137\n```\n\n\n\n### 1.3 如何计算本机有多少个用户以及多少个普通用户?\n\n**题目3:如何计算本机有多少个用户以及多少个普通用户?**\n\n```bash\n示例\n---------------------------------------------------------------------\n#3、如何计算本机有多少个用户以及多少个普通用户?\nwc -l /etc/passwd\t\t\t\t\t\t\t\t\t# 注:本机有多少用户\nawk -F\":\" '$3>=1000{print $1}' /etc/passwd |wc -l\t# 注:本机有多少普通用户\n#注:普通用户uid>1000\n```\n\n\n\n### 1.4 如何去除字符串中所有空格?\n\n**题目4:如何去除字符串中所有空格?**\n\n```bash\n示例\n---------------------------------------------------------------------\nstr=\"s t r i n g\"\necho $str |tr -d \" \"\t\t\t\t\t\t\t# 注:-d删除指定字符\n```\n\n\n\n### 1.5 备份/var/log/nginx/access.log日志,每五分钟备份一次,并且以2020-11-15_10_05-access.log.tar.gz方式命名。将日志文件备份文件放到/nginx/目录下\n\n**题目5:备份/var/log/nginx/access.log日志,每五分钟备份一次,并且以2020-11-15_10_05-access.log.tar.gz方式命名。将日志文件备份文件放到/nginx/目录下。**\n\n\\#注:确保crontab打开\n\n```bash\n示例\n---------------------------------------------------------------------\n[root@cPen_web ~]# crontab -e\t\t\t\t\t# 注:计划任务里命令最好写绝对路径\n*/5 * * * * tar czf /nginx/$(date +%Y-%m-%d_%H_%M-access.log.tar.gz) /var/log/nginx/access.log \n```\n\n\n\n### 1.6 查找/etc/目录下10天以内3天以前修改过的文件,并将这些文件记录到/tmp/etc_log文件中\n\n**题目6:查找/etc/目录下10天以内3天以前修改过的文件,并将这些文件记录到/tmp/etc_log文件中**\n\n```bash\n示例\n---------------------------------------------------------------------\n[root@cPen_web ~]# find /etc -type f -mtime -10 -mtime +3 \t\t# 注:注意 是查找的文件\n/etc/dnf/modules.d/python27.module\n/etc/selinux/config\n/etc/vsftpd/vsftpd.conf\n/etc/dconf/db/site\n/etc/dconf/db/local\n/etc/dconf/db/distro\n[root@cPen_web ~]# stat /etc/selinux/config \t\t\t\t\t# 注:stat看文件的原信息\n………………\n最近访问:2020-11-13 10:14:37.388001468 +0800\n最近更改:2020-11-05 15:12:05.484883965 +0800\n最近改动:2020-11-05 15:12:05.485883965 +0800\n[root@cPen_web lianxi]# find /etc -type f -mtime -10 -mtime +3 &>/tmp/etc_log \n```\n\n\n\n---\n\n## 二. 练习\n\n**请用shell写出一个简单的猜拳游戏,枚举值(0石头、1剪刀、2布),有两位选手分别是rob1、rob2,他们的出拳方式由系统自动枚举,并连续猜十盘,最后给出十盘的结果**\n\n```bash\n示例1:判定各种情况 if语句\n---------------------------------------------------------------------\n#!/bin/bash\necho \"猜拳游戏开始啦!!!\"\necho \"今天我们的两位对手是rob1和rob2\"\npingju=0\nrob1_win=0\nrob2_win=0\nfor i in `seq 10`\ndo\n a=`echo $[RANDOM%3]`\n b=`echo $[RANDOM%3]`\n case $a in\n 0)\n c=bor1出的是石头\n ;;\n 1)\n c=bor1出的是剪刀\n ;;\n 2)\n c=bor1出的是布\n ;;\n esac\n case $b in\n 0)\n d=bor2出的是石头\n ;;\n 1)\n d=bor2出的是剪刀\n ;;\n 2)\n d=bor2出的是布\n ;;\n esac\n if (($a==$b));then\n echo -e \"$c\\n$d \\n他们战平了\"\n pingju=$[$pingju+1]\n continue\n fi\n if [[ $a -eq 1 || $b -eq 1 ]];then # 注:如果1方出布\n if [[ $a -eq 0 || $b -eq 0 ]];then # 注:如果1方出拳头\n if (($a>$b));then\n echo -e \"$c\\n$d,rob2获胜\"\n rob2_win=$[$rob2_win+1]\n continue\n else\n echo -e \"$c\\n$d,rob1获胜\"\n rob1_win=$[$rob1_win+1]\n continue\n fi\n fi\n fi\n if (($a>$b));then\n echo -e \"$c\\n$d,rob1获胜\"\n rob1_win=$[$rob1_win+1]\n else\n echo -e \"$c\\n$d,rob2获胜\"\n rob2_win=$[$rob2_win+1]\n fi\n\ndone\n\necho \"rob1获胜次数$rob1_win,rob2获胜次数$rob2_win,平局次数$pingju\n============================================================================================\n\n示例2:使用减法\n#注:if语句的使用\n---------------------------------------------------------------------\nfor i in `seq 10`\ndo\n rob1=$(($RANDOM%3))\n echo rob1=$rob1\n rob2=$(($RANDOM%3))\n echo rob2=$rob2\n if [ $rob1 -eq $rob2 ]\n then\n echo \"平局\"\n elif [ $(($rob1-$rob2)) -eq -1 ] || [ $(($rob1-$rob2)) -eq 2 ] # 注:rob1赢的情况\n then\n echo \"rob1 win\"\n else\n echo \"rob2 win\"\n fi\ndone\n============================================================================================\n\n示例3\n---------------------------------------------------------------------\nr1_win=0\nr2_win=0\nequal=0\nfor i in `seq 10`\ndo\n echo -ne \"第$i盘\\t\"\n rob1_res=$(($RANDOM%3))\n rob2_res=$(($RANDOM%3))\n if [[ $(($rob1_res - $rob2_res)) = -1 ]]; then echo -ne \"rob1胜\\t\" &&r1_win=$(($r1_win + 1)); fi\n if [[ $(($rob1_res - $rob2_res)) = 2 ]]; then echo -ne \"rob1胜\\t\" &&r1_win=$(($r1_win + 1)); fi\n if [[ $(($rob2_res - $rob1_res)) = -1 ]]; then echo -ne \"rob2胜\\t\" &&r2_win=$(($r2_win + 1)); fi\n if [[ $(($rob2_res - $rob1_res)) = 2 ]]; then echo -ne \"rob2胜\\t\" &&r2_win=$(($r2_win + 1)); fi\n if [[ $(($rob1_res - $rob2_res)) = 0 ]]; then echo -ne \"平局\\t\" && equal=$(($equal + 1)); fi\n [[ $rob1_res = 0 ]] && echo -ne \"rob1:石头\\t\"\n [[ $rob1_res = 1 ]] && echo -ne \"rob1:剪刀\\t\"\n [[ $rob1_res = 2 ]] && echo -ne \"rob1:布\\t\\t\"\n [[ $rob2_res = 0 ]] && echo \"rob2:石头\"\n [[ $rob2_res = 1 ]] && echo \"rob2:剪刀\"\n [[ $rob2_res = 2 ]] && echo \"rob2:布\"\ndone\necho \"rob1胜场:$r1_win\"\necho \"rob2胜场:$r2_win\"\necho \"平局场数:$equal\"\n\n示例4:生成1个随机数 3以内 不包括3\n---------------------------------------------------------------------\n#注:生成1个随机数 3以内 不包括3\n[root@cPen_web lianxi]# echo $[RANDOM%3]\n2\n[root@cPen_web lianxi]# echo $[RANDOM%3]\n1\n[root@cPen_web lianxi]# echo $[RANDOM%3]\n0\n```\n\n\n\n---\n\n**SSH服务**\n\n## 三. SSH服务介绍\n\n**远程Shell应用程序**\n\n- 允许用户在远程机器上执行任意命令 \n- 让标准输出在本地\n- 早期明文远程协议:telnet\n\n\n\n**SSH(Secure Shell,安全的外壳)**\n\n- 为客户机提供安全的Shell环境,用于远程管理 \n- 默认端口:TCP `22`\n\n\n\n**SSH基于公钥加密(非对称加密)技术**\n\n- 数据加密传输\n- 客户端和服务器的身份验证\n\n\n\n\\#注:23号端口是明文的,已经淘汰了\n\n.--------------------------------------------------------------------------------------------------------------\n\n**ssh是什么?**\n\n​\t\tssh --> secure shell\n\n​\t\tremote login program -- 远程登陆模式\n\n​\t\t对数据进行加密传输的服务,主要用在远程登陆\n\n\\#注:把数据放到加密好了的壳里面,是安全的协议\n\n.--------------------------------------------------------------------------------------------------------------\n\nssh协议是应用层协议,根据ssh协议实现的服务叫ssh服务\n\nssh服务主要在HP-UX,LINUX,AIX,UNIX系统上都有(类UNIX系统上),Windows上没有\n\n\\#注:ftp协议也是应用层的协议,根据协议实现的服务叫ftp服务\n\n.--------------------------------------------------------------------------------------------------------------\n\n**ssh常见的2种登陆方式:**\n\n1、密码登陆\n\n2、密钥登陆(免密码登录)\t\t\t# 注:不需要密码\n\n\n\n\\#注:想要登录到那台主机,1、需要知道那台主机ip,2、允许登录,3、网络跟它联通,可以访问到那台主机上\n\n\\#注:ssh服务默认端口 22号端口 可以去更改\n\n.--------------------------------------------------------------------------------------------------------------\n\n#注:`/etc/services` **可以查看常用服务的默认端口号**\n\n```bash\n[root@cPen_web lianxi]# less /etc/services \nssh 22/tcp # The Secure Shell (SSH) Protocol\nssh 22/udp # The Secure Shell (SSH) Protocol\n#注:一般来说ssh都是使用tcp去传输的\n```\n\n.--------------------------------------------------------------------------------------------------------------\n\n\\#注:因为它所有的数据都是进行加密的,所以说它是安全的shell\n\n\\#注:2台主机之间进行数据交互 都会牵扯到 **数据包的传输**\n\n\\#注:对别的服务发起一个请求,其实就是相当于发送了1个包给它,这里包里面带有请求\n\n\\#注:普通情况下不给它加密的话,信息是明文的,是不安全的;ssh服务**对数据进行加密**,只有a主机和b主机知道解密的方式,其他人不知道\n\n\\#注:安装好系统后(最小安装),一般来说自带ssh服务,一般来说启动系统它会自动起来\n\n.--------------------------------------------------------------------------------------------------------------\n\n```bash\n示例:查看ssh服务是否启动\n---------------------------------------------------------------------------------\n1、查看进程\n[root@cPen_web lianxi]# ps ef |grep ssh\t\t\t# 注:进程名叫sshd\n2、pidof sshd\t\t\t\t\t\t\t\t\t# 注:判定某个服务是否存在pid\n[root@cPen_web lianxi]# pidof sshd\t\t\t\t# 注:服务起来的话必定会有1个pid\n2545 2543 2542 2538 2537 2536 909\n#服务起来后必定会有1个pid\n3、查看网络连接监听状态 netstat\n#注:yum install net-tools\n[root@cPen_web lianxi]# netstat -atpl |grep ssh\t\t# 注:a 所有 ;t tcp ;p 端口\n[root@cPen_web lianxi]# netstat -atpln |grep ssh\ntcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 909/sshd \n#注:listen状态 在监听中,表示别人可以里来连接我了\ntcp 0 0 192.168.0.21:22 192.168.0.42:58697 ESTABLISHED 2536/sshd: root [pr \n#注:ESTABLISHED表示已经建立连接了,可以进行数据交换了;\ntcp 0 36 192.168.0.21:22 192.168.0.42:58698 ESTABLISHED 2537/sshd: root [pr \ntcp6 0 0 :::22 :::* LISTEN 909/sshd \n\n#注:0.0.0.0:22表示在本机所有ip上监听22端口(别人可以通过所有的ip来访问)。如果把它监听到192.168.0.135/24上,那别人只能通过135这个地址来访问我\n#注:listen状态 在监听中;表示服务起来了 在监听状态,表示别人可以来连接我了\n#注:establish表示有1个客户端连接我了(已经建立连接的状态)\n#注:0.0.0.0:*表示允许任意ip,任意端口客户端来连接\t(*代表任意端口客户端)\n#注:0.0.0.0:22第1种表示本机上所有的ip\t\t\t(本机上的)\n#注:0.0.0.0:* 表示允许任意ip,任意端口客户端来连接\t(外部客户端的任意端口)(*代表任意端口客户端)\n------------------------------------------------------------------------------------------------------\n#注:本地回环地址代表本地,测试网卡是否ok \t127.0.0.1/8 本地回环地址\n#注:网卡实际地址\t192.168.0.21/24\n#注:别人不可以通过127.0.0.1来访问,因为127.0.0.1代表本地,每一台机器都有一个127.0.0.1本地回环地址,别人通过127.0.0.1来访问,仅仅只是访问的自己\n\n4、lsof -i:22\t\t\t\t#注:查看有没有listen状态的监听 ; establish表示连接建立了\n#注:知道端口后可以查看端口\n#注:lsof -->list open file \t列出打开的文件(全称)\n[root@cPen_web ~]# lsof -i:22\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nsshd 908 root 4u IPv4 27707 0t0 TCP *:ssh (LISTEN)\t\t# 注:listen 监听状态\nsshd 908 root 6u IPv6 27721 0t0 TCP *:ssh (LISTEN)\t\t# 注:ESTABLISHED 建立连接\nsshd 1419 root 5u IPv4 29943 0t0 TCP cPen_web:ssh->10.112.68.22:49959 (ESTABLISHED)\nsshd 1421 root 5u IPv4 29943 0t0 TCP cPen_web:ssh->10.112.68.22:49959 (ESTABLISHED)\n============================================================================================\n示例:增加ip地址\n[root@cPen_web lianxi]# ip a add 192.168.0.144/24 dev ens33\t# 注:增加ip地址\n[root@cPen_web lianxi]# ip add\t\t\t\t\t\t\t\t# 注:最好跟它同网段\n inet 127.0.0.1/8 scope host lo\t\t\t\t\t\t\t# 注:dev ens3 设备 ens33\n inet 192.168.0.21/24 brd 192.168.0.255 scope global dynamic noprefixroute ens33\n inet 192.168.0.144/24 scope global secondary ens33\n============================================================================================\n示例:查看命令属于哪个包\n[root@cPen_web lianxi]# which netstat\t\t\t\t# 注:找到命令的绝对路径\n/usr/bin/netstat\n[root@cPen_web lianxi]# rpm -qf /usr/bin/netstat\t# 注:查看这个绝对路径执行文件属于哪个包\nnet-tools-2.0-0.51.20160912git.el8.x86_64\n```\n\n\n\n---\n\n## 四. 密钥登陆\n\n```bash\n[root@cPen_web ~]# ssh-keygen\t\t\t\t\t# 注:创建密钥对\nGenerating public/private rsa key pair.\t\t\t# 注:rsa算法生成公钥和私钥的钥匙对(钥匙有2把不是同一把)\nEnter file in which to save the key (/root/.ssh/id_rsa): \nEnter passphrase (empty for no passphrase): \nEnter same passphrase again: \nYour identification has been saved in /root/.ssh/id_rsa.\nYour public key has been saved in /root/.ssh/id_rsa.pub.\nThe key fingerprint is:\nSHA256:JZh0IhlTUDkIvuXuv7Iw7zYsoucwfLjpPWrHYN7P63g root@cPen_web\nThe key's randomart image is:\n+---[RSA 2048]----+\n| ..=B=.. |\n| . o+o= |\n| . . o.. . |\n| + o |\n| . . S |\n|.o.. |\n|=o*o. |\n|.=BXBE |\n|=O+*XX+. |\n+----[SHA256]-----+\n[root@cPen_web ~]# \n```\n\n\n\n**加密**\n\n1. **对称加密**\n\n ​\t加解密的钥匙都是同一把\n\n ​\t怎么样安全的保存这个密码,这个密钥在需要加密的机器之间都是共享的\n\n ​\t很难保证这个密钥不被泄漏\n\n2. **非对称加密** \\# 注:加密和解密的钥匙不一样\n\n ​ 生成一对公私钥,私钥自己保管,公钥可以给其他人\n\n ​ 公私钥对是成对存在的,一个用于加密,一个用于解密。具体哪个为私钥,哪个为公钥就看使用者自己管理。\n\n\n\n注意:\n\n​\t\t使用公钥进行加密,私钥解密,基本用于数据加密\n\n​\t\t使用私钥加密公钥解密,用于认证\n\n\n\n```bash\n[root@cPen_web ~]# ssh-keygen\t\t\t\t\t# 注:创建密钥对\nGenerating public/private rsa key pair.\t\t\t# 注:rsa算法生成公钥和私钥的钥匙对(钥匙有2把不是同一把)\nEnter file in which to save the key (/root/.ssh/id_rsa): # 注:存放公私钥的路径,root用户的\nEnter passphrase (empty for no passphrase): \t# 注:设置密钥密码\t# 注:非全局\nEnter same passphrase again: \nYour identification has been saved in /root/.ssh/id_rsa.\t\nYour public key has been saved in /root/.ssh/id_rsa.pub.\nThe key fingerprint is:\nSHA256:JZh0IhlTUDkIvuXuv7Iw7zYsoucwfLjpPWrHYN7P63g root@cPen_web\t# 注:算法hash算法\nThe key's randomart image is:\t\t\t# 注:信息摘要 用的 SHA256 hash算法\n+---[RSA 2048]----+\n| ..=B=.. |\n| . o+o= |\n| . . o.. . |\n| + o |\n| . . S |\n|.o.. |\n|=o*o. |\n|.=BXBE |\n|=O+*XX+. |\n+----[SHA256]-----+\n[root@cPen_web ~]# \n#注:hash算法 任意长度的输入,映射成固定长度的输出\n--------------------------------------------------------------------------------------------\n#注:加密分为2种方式:1、对称加密;2、非对称加密\n#注:对称加密 a机器给b机器传输东西,a机器知道1串密码叫做aa,b机器也知道这个密码叫做aa;a机器对date用aa加密,b机器用aa解密。2个加密解密都用同一个密钥(加密的钥匙A和B都知道)。形式的条件是a和b都知道密钥是什么,且都一样\n#注:问题 不能保证密钥不被被人知道\n\n#注:非对称加密 a机器和b机器进行数据加密传输(进行通讯)。a机器在本地生成1个public和private的钥匙对,a机器生成公钥和私钥都放在a机器上,发送数据时,a机器先把公钥给b(也可以把公钥给c,公钥可以给任何人),但是私钥只有自己a机器才知道。b机器用a机器给的公钥加密,a机器收到后用私钥解密\n唯一能够解密的钥匙 私钥 只有机器a才有,只有机器a才能解密\n\n#注:对于数据信息加密而言,用公钥加密,用私钥解密,只有机器a才能解密\n#注:非对称加密 用于数据加密时,用公钥加密,私钥解密\n```\n\n\n\n---\n\n## 五. ssh配置\n\n**ssh配置**\n\n目录:**/etc/ssh**\t\t\t\t\t\t**# 注:这下面放的都是ssh的配置文件**\n\n```bash\n[root@cPen_web ~]# cd /etc/ssh/ \n[root@cPen_web ssh]# ls\nmoduli sshd_config ssh_host_ecdsa_key.pub ssh_host_ed25519_key.pub ssh_host_rsa_key.pub\nssh_config ssh_host_ecdsa_key ssh_host_ed25519_key ssh_host_rsa_key\n#注:sshd_config 客户端的配置文件\n#注:ssh_config 服务的配置文件\n#注:ssh_host_ecdsa_key ssh_host_ecdsa_key.pub 一对公私钥\n#注:ssh_host_ecdsa_key.pub 公钥 ssh_host_ecdsa_key私钥\n#注:ssh服务起来的时候,它会自动创建1对公私钥\n```\n\n\n\n```bash\n示例:创建的公私钥默认放在/root/.ssh/目录下\n[root@cPen_web ~]# cd .ssh\n[root@cPen_web .ssh]# ls\nid_rsa id_rsa.pub known_hosts\n#注:id_rsa\t\t私钥\n#注:id_rsa.pub\t公钥\n```\n\n\n\n---\n\n## 六. 实现公钥认证(免密码登录)\n\n```bash\n#注:a机器下(生成公钥后)\n[root@cPen_web ~]# cd .ssh\n[root@cPen_web .ssh]# ls\nid_rsa id_rsa.pub known_hosts\n[root@cPen_web .ssh]# cat id_rsa.pub \nssh-rsa\nAAAAB3NhQX......jXDv87iERv/z9XepKCeYqCfF2Dvv0n/g+IeFmzhW0iOppExskimMPGGWcN+7rXWlwaLNTiknmSTl+mFvZV8uIY5DnQXv root@cPen_web\n#注:b机器下\n[root@cPen_web ~]# mkdir .ssh\t\t\t\t\t# 注:没有的话 创建 .ssh文件夹\n[root@cPen_web ~]# cd .ssh/\n[root@cPen_web .ssh]# ls\nknown_hosts\n[root@cPen_web .ssh]# vim authorized_keys\t\t# 注:创建文件authorized_keys\nssh-rsa\t\t\t\t\t\t\t\t\t\t\t# 注:把a机器的公钥粘过去\nAAAAB3NhQX......jXDv87iERv/z9XepKCeYqCfF2Dvv0n/g+IeFmzhW0iOppExskimMPGGWcN+7rXWlwaLNTiknmSTl+mFvZV8uIY5DnQXv root@cPen_web\n[root@cPen_web .ssh]# chmod 600 authorized_keys \t\n#注:给它的权限为600,不要让其他人或者其他组有任何权限\n#注:a机器下\n[root@cPen_web .ssh]# ssh root@10.122.148.108\t\t# 注:使用客户端 以root用户登录\n………………………\nAre you sure you want to continue connecting (yes/no)? yes\n………………………\n[root@cPen_web ~]# \t\t\t\t\t\t\t\t\t# 注:不需要输入密码,就是免密码登录成功\n```\n\n\n\n实现公钥认证,免密码登录\n\nA --> B\t\tA机器要登录到B机器上\n\n1、在A机器上生成公钥对(如果有公钥对,则不需要重新生成),默认会放在当前用户家目录下的.ssh/文件下\n\n生成一个id_rsa(私钥),id_rsa.pub(公钥)\n\n\\#注:如果有了,就不需要重新生成公钥对了,因为会覆盖。默认路径不要改它,改它的意义不大,因为默认在默认路径查找\n\n[root@cPen_web ~]# ssh-keygen\t\t\t# 注:生成,中间一直敲回车,选择默认\n\n2、在B机器上目标用户的家目录下面~/.ssh/authorized_keys文件里将A机器的公钥复制粘贴过来,\n\n没有此文件就创建,并且确保这个文件的权限设为600\n\n3、查看公钥认证是否成功\n\n​\t\t在A机器上执行 ssh root@B机器的ip\n\n​\t\t不需要输入密码就可以登录到B机器,则表示免密码登录成功\n\n\n​\t\t公钥放在B机器的哪个用户下面,就通过哪个用户登录\n\n​\t\t以哪个用户登录,需要看公钥放到B机器的哪个用户下\n\n\n\n```bash\n[root@cPen_web ~]# useradd wy\n[root@cPen_web ~]# su - wy\t\t\t\t\t# 注:su切换不会经过ssh服务\n[wy@cPen_web ~]$ \n\n#注:su切换用户,是不会经过ssh\n#注:ssh是远程登录\nsu 和 su -\t\tsu切换不会切换bash环境(还是原用户的bash环境)\n\t\t\t\t su - 去切换 会切换到wy的bash环境\n```\n\n\n\n**公钥认证排错**\n\n1. 确保公钥正确\n\n2. 确保~/.ssh/authorized_keys文件权限为600\n\n3. 确保家目录以及.ssh目录权限为755以下权限,即属组和其他人没有7的权限\n\n\n\n---\n\n","tags":["Linux","SSH"],"categories":["Linux"]},{"title":"18_Linux基础-用户权限3","url":"/posts/57976.html","content":"## 一. 回顾:/根目录下的 /etc 一般放配置文件\n\n/根目录下的 /etc 一般放配置文件\n\n一个用户的基本组只能有一个,附属组可以有多个;享受的权限是一样的,都是有那个组的权限\n\n\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# useradd sanle10\n[root@sanchuang-linux ~]# id sanle10\nuid=2224(sanle10) gid=2224(sanle10) 组=2224(sanle10)\n[root@sanchuang-linux ~]# less /etc/group\n[root@sanchuang-linux ~]# useradd sanle11 -g sanchuang05 -G sanchuang06\t# 指定基本组、附属组\n[root@sanchuang-linux ~]# id sanle11\nuid=2225(sanle11) gid=1043(sanchuang05) 组=1043(sanchuang05),1044(sanchuang06)\n[root@sanchuang-linux ~]# less /etc/passwd\t\t\t\t\t# 注:存放用户信息\nhello:x:1007:1007::/home/hello:/bin/bash\n# 注:字段2仅仅只是密码占位符,真正的密码放在/etc/shadow\n[root@sanchuang-linux ~]# ls -al /etc/passwd\n-rw-r--r-- 1 root root 4539 11月 12 09:50 /etc/passwd\t\t# 注:任何人都可以访问/etc/passwd\n[root@sanchuang-linux ~]# ls -al /etc/shadow\n---------- 1 root root 4588 11月 12 09:50 /etc/shadow\t\t# 注:权限都为0\n\n[root@sanchuang-linux ~]# useradd sanle13 -c \"create sanle13\"\t# 注:指定用户描述信息\n[root@sanchuang-linux ~]# less /etc/passwd\nsanle13:x:2227:2227:create sanle13:/home/sanle13:/bin/bash\t # 注:字段5用户描述信息\n\n[root@sanchuang-linux tmp]# ls -ld /lianxi\t# 注:查看/lianxi 目录属于哪个用户哪个组\ndrwxr-xr-x. 9 root root 4096 11月 9 09:47 /lianxi\n\n# 普通用户默认只能在自己的家目录下 或 /tmp目录下创建\n\n对个人环境信息做设置\n~/.bash_profile\n~/.bashrc\n\n[root@sanchuang-linux tmp]# id sanle11\nuid=2225(sanle11) gid=1043(sanchuang05) 组=1043(sanchuang05),1044(sanchuang06)\t# 注:基本组sanchuang05\n[root@sanchuang-linux tmp]# su - sanle11\n[sanle11@sanchuang-linux ~]$ touch cc\n[sanle11@sanchuang-linux ~]$ ls -al\n总用量 16\n……………………\n-rw-r--r-- 1 sanle11 sanchuang05 0 11月 12 10:21 cc\t# 注:有效组sanchuang05\n# 注:有效组默认是用户基本组\n[sanle11@sanchuang-linux ~]$ newgrp sanchuang06\t\t\t # 注:修改有效组;临时修改\n[sanle11@sanchuang-linux ~]$ touch dd\n[sanle11@sanchuang-linux ~]$ ls -al\n……………………\n-rw-r--r-- 1 sanle11 sanchuang06 0 11月 12 10:23 dd\t# 注:有效组sanchuang06\n```\n\n\n\n---\n\n## 二. 练习\n\n### 2.1\n\n**题目1**\n\n创建三个用户sx1,sx2,sx3,这三个用户的附属组都是sanle组,创建名为/home/sanle的目录,在该目录中,三个用户可以合作>处理文件。要求恰当修改该目录的权限,以便只允许用户和组能在这个目录中访问、删除、创建文件,其他用户没有任何权限,>三个用户新建的文件只能自己有权限删除,彼此无法删除,而且新建的文件应该被自动分配到sanle的组所有权。\n\n\n\n```bash\n示例\n---------------------------------------------------------------------\n#创建三个用户sx1,sx2,sx3,这三个用户的附属组都是sanle组,创建名为/home/sanle的目录,在该目录中,三个用户可以合作>处理文件。要求恰当修改该目录的权限,以便只允许用户和组能在这个目录中访问、删除、创建文件,其他用户没有任何权限,>三个用户新建的文件只能自己有权限删除,彼此无法删除,而且新建的文件应该被自动分配到sanle的组所有权。\nuseradd -G sanle sx1\nuseradd -G sanle sx2\nuseradd -G sanle sx3\nmkdir /home/sanle\nnewgrp sanle\nmkdir /home/sanle\nchmod 1770 /home/sanle -R\necho \"newgrp sanle\" >> ~/.bashrc\n```\n\n\n\n### 2.2\n\n**题目2** **脚本**\n\n\\---------------------------------------------------------------------\n1、创建用户\n2、删除指定用户\n3、修改指定用户(用户id,用户属组,用户家目录)\n4、删除指定用户\n\n\n\n```bash\n示例1\n---------------------------------------------------------------------\n#!/bin/bash\nmenu(){\n echo \"1、创建用户\"\n echo \"2、删除指定用户\"\n echo \"3、修改指定用户(用户id,用户属组,用户家目录)\"\n echo \"4、删除指定用户\"\n}\n\nadd(){\n read -p \"输入用户名:\" username\t\t\t # 注:接收从键盘的输入\n useradd $username &>/dev/null && echo \"创建成功\" || echo \"创建失败\"\n}\n\ndel(){\n read -p \"输入用户名:\" username\n userdel -r $username &>/dev/null && echo \"删除成功\" || echo \"用户不存在\"\n}\n\nmodify(){\n read -p \"输入用户名:\" username\n id $username &>/dev/null\n if [[ $? = 0 ]]\n then\n read -p \"输入uid:\" uid\t\t\t\t# 注:可以再加3个case 更精细\n read -p \"输入gid:\" gid\n read -p \"输入家目录:\" home\n usermod -u $uid -g $gid -d $home $username 2>/dev/null && echo \"修改成功\" || \"修改失败\"\n else\n echo \"用户不存在\"\n fi\n}\n\nwhile :\ndo\n menu\n read -p \"请输入1-4:\" option\n case $option in\n 1)\n add\n ;;\n 2)\n del\n ;;\n 3)\n modify\n ;;\n 4)\n del\n ;;\n *)\n echo \"输入不合法\"\n esac\ndone\n\n示例2:一次性添加多个变量\n---------------------------------------------------------------------------------------------------------------------------------\nmod(){\n\tread -p \"请输入(用户id,用户属组,用户家目录):\" userid usergroup userhome username\n usermod -u $userid -g $usergroup -d $userhome $username &> /dev/null && echo \"修改成功\" || echo \"修改失败\"\t\n}\n\n示例3:精密选择(推荐)\n---------------------------------------------------------------------------------------------------------------------------------\n#!/bin/bash\n\nmenu(){\n echo \"1、创建用户\"\n echo \"2、删除指定用户\"\n echo \"3、修改指定用户(用户id,用户属组,用户家目录)\"\n}\nmenu2(){\n echo \"1、修改用户id\"\n echo \"2、修改用户属组\"\n echo \"3、修改用户家目录\"\n\n}\n\nadd(){\n read -p \"输入用户名:\" username\n id $username &>/dev/null &&echo \"用户已存在\" || useradd $username &>/dev/null && echo \"创建成功\" || echo \"创建失败\"\n}\n\ndel(){\n read -p \"输入用户名:\" username\n id $username &>/dev/null || echo \"用户不存在\" && userdel -r $username &>/dev/null && echo \"删除成功\" || echo \"删除失败\"\n}\n\nmodify(){\n read -p \"输入用户名:\" username\n if id $username &>/dev/null\n then\n\tmenu2\n\tread -p \"请输入:\" choice2\n\tcase $choice2 in\n\t1)\n\t read -p \"输入uid:\" uid\n\t usermod -u $uid $username &>/dev/null && echo \"修改成功\" || echo \"修改失败\"\n\t;;\n\t2)\n\t read -p \"输入gid:\" gid\n\t usermod -g $gid &>/dev/null && echo \"修改成功\" || echo \"修改失败\"\n\t;;\n\t3)\n\t read -p \"输入家目录:\" home\n\t usermod -d $home $username &>/dev/null && echo \"修改成功\" || echo \"修改失败\"\n\t;;\n\t*)\n\techo \"输入不合法\"\n\tesac\n else\n echo \"用户不存在\"\n fi\n}\n\nwhile true\ndo\n menu\n read -p \"请输入(按q退出):\" choice\n case $choice in\n 1)\n add\n ;;\n 2)\n del\n ;;\n 3)\n modify\n ;;\n q)\n\tbreak\n\t;;\n *)\n echo \"输入不合法\"\n esac\ndone\n```\n\n\n\n---\n\n## 三. ACL的使用\n\n**ACL(Access Control List)**\t\t\t\t\t\t# 注:**访问控制列表(允许哪些人可以/不可以访问)**\n\n- 一个文件/目录的访问控制列表,可以针对任意指定的 用户/组使用权限字符分配rwx权限\n\n\n\n**设置ACL:setfacl指令**\n\n- 格式: `setfacl 选项 规则 文件`\n\n**常用选项**\n\n- `-m`:新增或修改ACL中的规则\n- `-b`: 删除所有ACL规则\n- -x: 删除指定的ACL规则\n\n\n\n**查看ACL:getfacl指令**\n\n- 格式:`getfacl 文件`\n\n\n\n**设置ACL:setfacl指令**\n\n- 格式: `setfacl 选项 规则 文件`\n\n**常用规则**\n\n- 格式:`类型`:`特定的用户或组`:`权限`\n- `user:(uid/name):(perms)` \t 指定某位使用者的权限\n- `group:(gid/name):(perms)` \t指定某一群组的权限\n- `other::(perms)` \t\t\t\t 指定其它使用者的权限\n- `mask::(perms)`\t\t\t\t 设定有效的最大权限\n\n\n\n**注意**\n\n- user、group、other、mask简写为:u , g , o , m \n- perms使用rwx\n\n\n\n#注:acl访问控制列表,工作中和云计算都比较常见\n\n\n\n```bash\n示例1:查看文件acl\n---------------------------------------------------------------------------------------------------------------------------------\n#注:对权限精准把控\n[root@localhost ~]# getfacl win-utf-2.txt \t# 注:查看文件acl规则\n# file: win-utf-2.txt\t\t\t\t\t\t# 注:get file acl\n# owner: root\t\t\t\t\t\t\t\t# 注:初始的规则\n# group: root\nuser::rw-\ngroup::r--\nother::r--\n[root@localhost ~]# ls -la win-utf-2.txt \n-rw-r--r--. 1 root root 0 10月 27 11:42 win-utf-2.txt\n[root@localhost ~]# \n===============================================================================\n\n示例2:对sanchuang用户有读写执行权限\n#注:针对特殊用户\n---------------------------------------------------------------------------------------------------------------------------------\n[root@localhost ~]# setfacl -m u:sanchuang:rwx win-utf-2.txt \t# 注:对sanchuang用户有rwx权限\n[root@localhost ~]# getfacl win-utf-2.txt \t\t\t\t# 注:u也可以写成 user 一般简写\n# file: win-utf-2.txt\t\t\t\t\t\t\t# 注:注意普通用户对/root目录没有操作权限\n# owner: root\n# group: root\nuser::rw-\nuser:sanchuang:rwx\t\t\t\t\t\t\t\t# 注:对sanchuang用户有rwx权限\ngroup::r--\nmask::rwx\nother::r--\n[root@localhost ~]# ls -la win-utf-2.txt \t\t# 注:权限多了个+\n-rw-rwxr--+ 1 root root 0 10月 27 11:42 win-utf-2.txt\n===============================================================================\n\n示例3:对组有读写执行的权利\n#注:针对特定组\n---------------------------------------------------------------------------------------------------------------------------------\n[root@localhost ~]# setfacl -m g:sanchuang5:rw win-utf-2.txt \n[root@localhost ~]# ls -la win-utf-2.txt \t\t# 注:set file acl\n-rw-rwxr--+ 1 root root 0 10月 27 11:42 win-utf-2.txt\n[root@localhost ~]# getfacl win-utf-2.txt \n# file: win-utf-2.txt\n# owner: root\n# group: root\nuser::rw-\nuser:sanchuang:rwx\ngroup::r--\ngroup:sanchuang5:rw-\t\t\t\t\t\t\t# 注:对组有读写执行的权利\nmask::rwx\nother::r--\n===============================================================================\n\n示例4:设置有效的最大权限\n#注:针对mask设置有效权限\n---------------------------------------------------------------------------------------------------------------------------------\n#注:设定有效的最大权限为r\n#注:设置的权限在mask之下(天花板)\n[root@localhost ~]# setfacl -m m::r win-utf-2.txt\t\t# 注:设置有效的最大权限\n[root@localhost ~]# getfacl win-utf-2.txt \n# file: win-utf-2.txt\n# owner: root\n# group: root\nuser::rw-\nuser:sanchuang:rwx\t\t#effective:r--\t\t\t\t\t# 注:即使sanchuang的权限是rw,但是有效最大权限是r\ngroup::r--\ngroup:sanchuang5:rw-\t\t#effective:r--\nmask::r--\nother::r--\n#注:指明了有效最大权限后;用户sanchuang即使有读写的权限,用户sanchuang5最大权限仅仅指为读\n#注:即使设置了用户sanchuang rw权限,但是mask设置为r,也只有r的权限\n```\n\n\n\n---\n\n## 四. ACL类型\n\n**ACL类型**\n\n- 存取型ACL(Access ACL):文件或目录 \n- `预设型ACL(Default ACL):只能对目录`\n\n**预设型ACL(Default ACL)**\n\n- 格式:`setfacl –m default`:类型:特定的用户或组:权限 \n \t\t\t`setfacl –m d`:类型:特定的用户或组:权限\n- 设置了预设型ACL的目录,**其下的所有文件或者子目录就都具有了主目录的ACL权限,并且子目录也同样有预设的ACl权限**\n\n\n\n#注:只能对目录设置预设型\n\n\n\n```bash\n示例 设置预设ACL\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux lianxi]# mkdir cc_test\n[root@sanchuang-linux lianxi]# getfacl cc_test/\n# file: cc_test/\n# owner: root\n# group: root\nuser::rwx\ngroup::r-x\nother::r-x\n[root@sanchuang-linux lianxi]# setfacl -m d:u:sanle10:rw cc_test/\t # 注:对文件进行预设型acl设置\n[root@sanchuang-linux lianxi]# getfacl cc_test/\n# file: cc_test/\n# owner: root\n# group: root\nuser::rwx\ngroup::r-x\nother::r-x\ndefault:user::rwx\t\t\t\t\t\t\t\t# 注:新增的参数\ndefault:user:sanle10:rw-\ndefault:group::r-x\ndefault:mask::rwx\ndefault:other::r-x\n[root@sanchuang-linux lianxi]# cd cc_test/\n[root@sanchuang-linux cc_test]# touch aa\t\t# 注:新建的文件会继承预设的acl设置\n[root@sanchuang-linux cc_test]# getfacl aa\n# file: aa\n# owner: root\n# group: root\nuser::rw-\nuser:sanle10:rw-\t\t\t\t\t\t\t\t# 注:新建的文件会继承预设的acl设置\ngroup::r-x\t\t\t#effective:r--\nmask::rw-\nother::r--\n#注:预设之前已经创建的文件 不会继承预设的acl设置\n```\n\n\n\n---\n\n## 五. 练习\n\n1、新建三个组 shuiguo, mifeng, shaokao\n\n2、新建3个用户,pingguo属于shuiguo组,jingshi属于mifen组,yueyang属于shaokao组\n\n3、在根目录下新建目录food,将/etc/passwd文件复制到food目录下\n\n4、设置权限,passwd文件能被shuiguo组读写,jingshi这个用户读写执行,yueyang这个用户不能进行任何操作\n\n\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n#1\n[root@sanchuang-linux lianxi]# groupadd shuiguo\n[root@sanchuang-linux lianxi]# groupadd mifen\n[root@sanchuang-linux lianxi]# groupadd shaokao\n#2\n[root@sanchuang-linux lianxi]# useradd -g shuiguo pingguo\n[root@sanchuang-linux lianxi]# useradd -g mifen jingshi\n[root@sanchuang-linux lianxi]# useradd -g shaokao yueyang\n#3\n[root@sanchuang-linux lianxi]# mkdir /food\n[root@sanchuang-linux lianxi]# cp /etc/passwd /food\n[root@sanchuang-linux lianxi]# cd /food\n#4\n[root@sanchuang-linux food]# setfacl -m g:shuiguo:rw passwd \n[root@sanchuang-linux food]# setfacl -m u:jingshi:rwx passwd \n[root@sanchuang-linux food]# setfacl -m u:yueyang:--- passwd\t\t\t# 注:没有任何权限\n[root@sanchuang-linux food]# getfacl passwd \n# file: passwd\n# owner: root\n# group: root\nuser::rw-\nuser:jingshi:rwx\nuser:yueyang:---\ngroup::r--\ngroup:shuiguo:rw-\nmask::rwx\nother::r--\n```\n\n\n\n---\n\n## 六. 权限的继承和拒绝\n\n一个用户属于某个组会继承这个组的权限。\n\n​\t\t1.主要组\n​\t\t2.次要组\n\n\n\n用户的主要组(有效组)属于某个组,会继承这个组的权限,如果是附属组属于某个组,也会继承。\n\n- newgrp\n\n\n\n拒绝权限高于一切 ---》针对用户\n\n\n\n一个组允许,一个组拒绝 ---》允许\n\n\n\n---\n\n## 七. sudo授权\n\n**sudo授权**\n\n- **Linux里root用户权限最大**\n\n​\t\t\t关机、重启系统、配置IP地址、格式化磁盘、mount等\n\n- **普通用户权限非常小**\n- **如何让普通用户也具有一定的权限?**\n\n​\t\t\t给root用户分忧\n\n- **如果能授权,那么是授权给用户还是组?**\n\n\n\n\\#注:sudo授权给部分普通用户使用root用户的权限\n#注:**sudo --> 授权给普通用户取执行命令的**\n#注:sudo配置文件 /etc/sudoers\n`#注:有一个日志文件会记录下被授权者执行的所有命令\t/var/log/secure`\n\n#注:**第一个ALL表示允许任何终端、机器访问sudo,一般就表示本机**\n#注:**第二个ALL表示sudo命令可以允许以任何用户身份去执行**\n#注:**第三个ALL表示可以执行任何命令**\n\n**授权日志:有一个日志文件会记录下被授权者执行的所有命令\t/var/log/secure**\n**查看日志,知道授权命令的执行情况**\n[root@cali ~]# tailf /var/log/secure\n\n\n\n```bash\n示例1:生成随机密码\n#注:生成随机密码的工具\tmkpasswd\nhttps://www.cnblogs.com/shijunxian/archive/2020/05/26/12961543.html\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux food]# yum install expect -y\n[root@sanchuang-linux bin]# mkpasswd -l 15 -d 3 -c 4 -C 4 -s 2\nwjp4[HC]hx6mSO6\n===============================================================================\n\n示例2:sudo配置文件 /etc/sudoers\n#注:授权给某些用户执行某些命令\n#注:编辑/etc/sudoers授权并验证\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux bin]# less /etc/sudoers\n………………\n## Syntax:\n##\n## user MACHINE=COMMANDS\t\t………………\n## Allow root to run any commands anywhere \nroot ALL=(ALL) ALL\t\t\t\t\t# 注:ALL表示当前这个机器\n#注:1、允许root用户执行这条命令 ; 2、ALL表示当前这个主机,(ALL)表示允许用户以哪个用户的权限设置 ; 3、ALL表示所有命令(在这个机器上面可以有任何用户的命令)\n\n#注:第一个ALL表示允许任何终端、机器访问sudo,一般就表示本机\n#注:第二个ALL表示sudo命令可以允许以任何用户身份去执行\n#注:第三个ALL表示可以执行任何命令\n===============================================================================\n\n示例3:编辑配置文件/etc/sudoers 给用户颁布权限\n#注:编辑配置文件 可以使用vim 也可以使用visudo 使用visudo不需要接文件名\n#注:推荐使用visodu去编辑/etc/sudoers,它会检测语法;vim去编辑不会检测\n#注:对于用户sanle有本地host所有权限\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux bin]# visudo\t\t\t# 注:使用visudo不需要接文件名\n## Allow root to run any commands anywhere\nroot ALL=(ALL) ALL\nsanle ALL=(ALL) ALL\t\t\t\t\t\n#注:表示sanle用户,可以在这台主机上执行任何用户的任何命令,但是使用sudo执行时需要输入sanle用户的密码\n#注:不设置NOPASSWD 第1次输入密码后 密码有时效性\n[root@sanchuang-linux bin]# su - sanle\t\t# 注:切换到sanle用户\n[sanle@sanchuang-linux ~]$ sudo passwd wy\t\t# 注:前面+sudo 能进行任何操作\n我们信任您已经从系统管理员那里了解了日常注意事项。\n总结起来无外乎这三点:\n #1) 尊重别人的隐私。\n #2) 输入前要先考虑(后果和风险)。\n #3) 权力越大,责任越大。\n[sudo] sanle 的密码:\t\t\t\t\t\t# 注:需要输入sanle用户 密码\n[root@sanchuang-linux bin]# visudo \n## Allow root to run any commands anywhere\nroot ALL=(ALL) ALL\nsanle ALL=(ALL) NOPASSWD:ALL\t\n#注:表示sanle用户,可以在这台主机上执行任何用户的任何命令,无需输入sanle的密码\n[sanle@sanchuang-linux ~]$ sudo passwd wy\n更改用户 wy 的密码 。\n新的 密码:\t\t\t\t\t\t\t\t\t# 注:不需要验证原密码\n===============================================================================\n\n示例4:给用户/组颁布权限\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux bin]# visudo \n## Allow root to run any commands anywhere\nroot ALL=(ALL) ALL\nsanle ALL=(ALL) NOPASSWD:ALL\t\n#注:表示sanle用户,可以在这台主机上执行任何用户的任何命令,无需输入sanle的密码\n%sanchuang5 ALL=(ALL) NOPASSWD:ALL\t\t\n#注:表示sanchuang5这个组的用户,在这台主机上可以执行任何用户的任何命令,无需输入密码\n\n#注:对于sanchuang5这个组赋予以任何用户执行任何权限\n#注:组里的所有成员也会拥有这个权限\n===============================================================================\n\n示例5 对于指定的命令去授权\n---------------------------------------------------------------------------------------------------------------------------------\n[sanle@sanchuang-linux ~]$ which chown\n/usr/bin/chown\n[sanle@sanchuang-linux ~]$ which passwd\n/usr/bin/passwd\n[root@sanchuang-linux cc_test]# visudo\nroot ALL=(ALL) ALL\nsanle ALL=(ALL) NOPASSWD:ALL\n%sanchuang5 ALL=(ALL) NOPASSWD:ALL\nwy ALL=(ALL) /usr/bin/chown,/usr/bin/passwd\t\t# 注:接命令的绝对路径\n#注:表示wy用户在这台主机上,拥有chown,passwd命令执行授权,命令路径写命令的绝对路径\n[wy@sanchuang-linux ~]$ sudo chmod 777 aa\n我们信任您已经从系统管理员那里了解了日常注意事项。\n总结起来无外乎这三点:\n #1) 尊重别人的隐私。\n #2) 输入前要先考虑(后果和风险)。\n #3) 权力越大,责任越大。\n[sudo] wy 的密码:\t\t\t\t\t\t\t\t\t\t\t # 注:验证密码后可以修改\n[wy@sanchuang-linux ~]$ sudo passwd wy2\n更改用户 wy2 的密码 。\n新的 密码:\n===============================================================================\n\n示例6:授权日志 /var/log/目录下 secure文件\n#注:有一个日志文件会记录下被授权者执行的所有命令\t/var/log/secure\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux cc_test]# cd /var/log/\n[root@sanchuang-linux log]# less secure\t\t\t\t\nuid=0 tty=/dev/pts/2 ruser=wy rhost= user=wy\nNov 12 16:43:26 sanchuang-linux sudo[2424]: pam_unix(sudo:auth): conversation failed\nNov 12 16:43:26 sanchuang-linux sudo[2424]: pam_unix(sudo:auth): auth could not identify password for [wy]\nNov 12 16:43:26 sanchuang-linux sudo[2424]: wy : command not allowed ; TTY=pts/2 ; PWD=/home/wy ; USER=root\n ; COMMAND=/bin/chmod 777 aa\n===============================================================================\n\n示例7\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux bin]# ls -ld /bin/passwd\n-rwsr-xr-x. 1 root root 33600 4月 7 2020 /bin/passwd\n#注:s位 普通用户有设置密码的权限,但是没有为他人设置密码的权限,且密码需要满足密码复杂度\n```\n\n\n\n---\n\n## 八. 练习\n\nyum install net-tools -y\n授予bailongma用户:useradd、userdel、passwd\n授予baigujing用户:ip、ping、ifconfig、route\n授权yutujing用户:poweroff、reboot\n\n \n\n\\#注:授权不会检测系统里有该用户\n\n\n\n```bash\n示例1\n---------------------------------------------------------------------------------------------------------------------------------\n[wy@sanchuang-linux ~]$ which useradd\t\t\t\t# 注:查找命令的绝对路径\n/usr/sbin/useradd\n………………………………\n[wy@sanchuang-linux ~]# visudo\nroot ALL=(ALL) ALL\nbailongma ALL=(ALL) /usr/sbin/useradd,/usr/sbin/userdel,/usr/bin/passwd\nbaigujing ALL=(ALL) /usr/sbin/ip,/usr/bin/ping,/usr/sbin/ifconfig,/usr/sbin/route\nyutujing ALL=(ALL) /usr/sbin/poweroff,/usr/sbin/reboot\n===============================================================================\n\n示例2:(ALL) 可以不写\n---------------------------------------------------------------------------------------------------------------------------------\n[wy@sanchuang-linux ~]# visudo\nroot ALL=(ALL) ALL\nbailongma ALL=/usr/sbin/useradd,/usr/sbin/userdel,/usr/bin/passwd\t\t# 注:(ALL) 可以不写\nbaigujing ALL=/usr/sbin/ip,/usr/bin/ping,/usr/sbin/ifconfig,/usr/sbin/route\nyutujing ALL=/usr/sbin/poweroff,/usr/sbin/reboot\n===============================================================================\n\n示例3:定义别名\n--------------------------------------------------------------------------------------------\n[wy@sanchuang-linux ~]# visudo\n#定义命令别名\nCmnd_Alias NETWORK = /usr/sbin/ip,/usr/bin/ping,/usr/sbin/ifconfig,/usr/sbin/route\nCmnd_Alias SHUT = /usr/sbin/poweroff,/usr/sbin/reboot\nCmnd_Alias USER = /usr/sbin/useradd,/usr/sbin/userdel,/usr/bin/passwd\n\nbailongma ALL=USER,NETWORK\nbaigujing ALL=NETWORK\nyutujing ALL=SHUT\n------------------------------------------------------------------------\n[baigujing@sanchuang-linux ~]$ sudo ip a add 192.168.0.144/24 dev ens33 #注:为网卡增加ip地址\n[sudo] baigujing 的密码:\t\t\t\t\t\t\t\t# 注:ip命令权限的使用\n[baigujing@sanchuang-linux ~]$ ip add\n………………\n inet 192.168.0.26/24 brd 192.168.0.255 scope global dynamic noprefixroute ens33\n inet 192.168.0.144/24 scope global secondary ens33\n………………\n------------------------------------------------------------------------\n#注:为网卡增加ip地址(1个网卡可以有多个ip地址)\n[wy@sanchuang-linux ~]$ ip a add 192.168.0.144/24 dev ens33\n```\n\n\n\n---\n\n## 九. SELinux介绍\n\n- **SELinux是什么?有什么用? **\n- **如何查看SELinux是否开启?**\n\n​\t\t\tgetenforce\n\n- **如何关闭和开启SELinux?**\n\n​\t\t\t临时\n​\t\t\t\t\tsetenforce\n​\t\t\t永久\n​\t\t\t\t\t修改配置文件\n​\t\t\t\t\tvim /etc/selinux/config \n​\t\t\t\t\tvim /etc/sysconfig/selinux \n​\t\t\t\t\t重新启动系统\n\n- **SELinux在企业里使用多吗?**\n\n\n\n.---------------------------------------------------------------------------------------------------------------------------------------------------------------------\n\n```bash\nSELinux是什么?\n·SELinux是一个linux系统里的一个安全方面的子系统,用来提升linux的整体的安全级别。是一种访问控制体系,进程只能访问那些在他的任务中所需要文件。(控制进程可以访问哪些允许访问的资源)\n\n·操作系统有两类访问控制:自主访问控制(DAC)和强制访问控制(MAC)。\n\n·标准Linux安全是一种DAC,SELinux为Linux增加了一个灵活的和可配置的的MAC。\n\n·DAC(Discretionary Access Control)自主访问控制\n\n·工作原理:\n\n·MAC(Mandatory Access Control)―――强制访问控制 ---》selinux\n\n·工作原理:\n\n·哪些进程能访问哪些类型的文件,都有安全策略\n```\n\n\n\n```bash\n永久修改\n#注:这是链接文件\t/etc/sysconfig/selinux -> /etc/selinux/config\n[root@cali log]# vim /etc/sysconfig/selinux\nSELINUX=disabled\n\n临时配置\n临时配置,重新启动系统会失效\n0--》Permissive 宽容模式\n1--》Enforcing\t 强制执行模式 \n[root@cali selinux]# setenforce 0 \n[root@cali selinux]# getenforce \nPermissive\n[root@cali selinux]#\n[root@cali selinux]# setenforce 1 \n[root@cali selinux]# getenforce \nEnforcing\n[root@cali selinux]#\n```\n\n\n\n```bash\n·进程控制 :控制哪些进程能访问哪些文件,因为它对进程和文件进行了分类,制定了策略,策略里规定了哪些类型的进程能操作哪些类型的文件。\n\n·服务异常不能访问--》通过网络不能访问\n·1.考虑iptables防火墙是否开启 \n·2.考虑selinux安全机制是否开启\n\n·iptables 是外层的安全策略防火墙\n·selinux是linux内部的安全策略机制防火墙\n```\n\n\n\n```bash\n博客链接:https://blog.csdn.net/yanjun821126/article/details/80828908\n\nSELinux\n是内核集成的一个安全相关的子系统,可以让系统更加的安全\n内核版本2.6以上支持\n\n#注:查看内核版本 uname -r\n[root@sanchuang-linux bin]# uname -r\n4.18.0-193.el8.x86_64\n\n安全增强型 Linux(Security-Enhanced Linux)简称 SELinux,它是一个 Linux 内核模块,也是 Linux 的一个安全子系统。\n\nSELinux 的作用\nSELinux 主要作用就是最大限度地减小系统中服务进程可访问的资源(最小权限原则)。\n\nDAC:\n在没有使用 SELinux 的操作系统中,决定一个资源是否能被访问的因素是:某个资源是否拥有对应用户的权限(读、写、执行)\n这种权限管理机制的主体是用户,也称为自主访问控制(DAC)\n\nMAC:\n在使用了 SELinux 的操作系统中,决定一个资源是否能被访问的因素除了上述因素之外,还需要判断每一类进程是否拥有对某一类资源的访问权限。\n这种权限管理机制的主体是进程,也称为强制访问控制(MAC)\n\n默认情况下SElinux属于关闭状态(disable)\t服务访问不了基本是设置了SElinux\n```\n\n\n\n```bash\n示例:临时修改\n--------------------------------------------------------------------------------------------\n#注:临时修改 关机重启后失效\n#注:临时配置,重新启动系统会失效\n#注:0 --》Permissive 宽容模式\n#注:1 --》Enforcing 强制执行模式\n[root@sanchuang-linux ~]# getenforce \t\t\t# 注:获取当前selinux的模式\nDisabled\n[root@sanchuang-linux ~]# setenforce 0\t\t\t# 注:0宽容模式\t\t临时生效\nsetenforce: SELinux is disabled\n[root@sanchuang-linux ~]# setenforce 1\t\t\t# 注:1强制模式(一定要遵循SELinux规则)\nsetenforce: SELinux is disabled\n#注:0|1 Permissive|Enforcing 宽容模式|强制执行模式\n\n============================================================================================\n示例:永久生效 修改配置文件\n#注:配置文件:/etc/selinux/config\n[root@sanchuang-linux ~]# vim /etc/selinux/config\n# enforcing - SELinux security policy is enforced.\n# permissive - SELinux prints warnings instead of enforcing.\n# disabled - No SELinux policy is loaded.\nSELINUX=disabled\t\t# 注:指定工作模式\n#注:修改之后生效,需要重启电脑\n```\n\n\n\n---\n\n","tags":["Linux","权限"],"categories":["Linux"]},{"title":"17_Linux基础-用户权限2","url":"/posts/14777.html","content":"## 一. 练习:批量创建n个用户\n\n批量创建n个用户\n\n用户名以sanchuang开头,sanchuang\n\n指定家目录/lianxi/user\n\n\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n[root@localhost ~]# seq -w 10\t\t\t# 注:-w 同等长度输出\n01\n02\n………………\n09\n10\n[root@sanchuang-linux ~]# vim create_user2.sh\n#!/bin/bash\nnum=$1 # 注:$1外面 接收参数,改名字 见名知义\n[ -d /lianxi/user ] || mkdir /lianxi/user # 注:-d判断目录是否存在,-f判断普通文件是否存在\nfor i in `seq -w $num`\t\t\t\t\t\t # 注:mkdir /lianxi/user 就可以了,不要加上用户名目录\ndo\t\t\t\t# 注:判断是否存在,如果前面为真不做任何事情,如果为假就执行mkdir…\n useradd -d /lianxi/user/sanchuang$i sanchuang$i\ndone\n[root@sanchuang-linux ~]# bash create_user2.sh 12\nuseradd:用户“sanchuang01”已存在\nuseradd:用户“sanchuang02”已存在\n………………\nuseradd:用户“sanchuang10”已存在\nuseradd:用户“sanchuang12”已存在\n[root@sanchuang-linux ~]# cd /lianxi/user\n[root@sanchuang-linux user]# ls\nsanchuang01 ………… sanchuang10 sanchuang12\n[root@sanchuang-linux user]# cd\n[root@sanchuang-linux ~]# bash create_user2.sh 20\nuseradd:用户“sanchuang01”已存在\nuseradd:用户“sanchuang02”已存在\n………………\nuseradd:用户“sanchuang12”已存在\nuseradd:用户“sanchuang13”已存在\n[root@sanchuang-linux ~]# cd /lianxi/user\n[root@sanchuang-linux user]# ls\nsanchuang01 ………… sanchuang18 sanchuang20\n```\n\n\n\n---\n\n## 二. 一般情况下普通用户只能在家目录下或者/tmp目录下创建文件或者文件夹\n\n**一般情况下普通用户只能在家目录下或者/tmp目录下创建文件或者文件夹**\n\n\\#注:/tmp目录是一个临时目录,一般存放临时性的东西\n\n\\#注:(如:程序运行中需要记录的一些东西,程序结束后把/tmp目录下的东西删掉)\n\n\n\n```bash\n[root@sanchuang-linux ~]# su - sanchuang\n上一次登录:五 11月 6 17:09:41 CST 2020pts/2 上\n[sanchuang@sanchuang-linux ~]$ ls -ld /\ndr-xr-xr-x. 38 root root 4096 11月 5 15:12 /\n[sanchuang@sanchuang-linux ~]$ ls -ld /etc\ndrwxr-xr-x. 90 root root 8192 11月 7 15:00 /etc\n[sanchuang@sanchuang-linux ~]$ ls -ld ./\t\t\t\t# 注:家目录下 创建文件或者文件夹\ndrwxrwxrwx. 4 sanchuang sanchuang 122 11月 6 17:10 ./\n[sanchuang@sanchuang-linux ~]$ ls -ld /tmp\t\t\t# 注:/tmp目录下 创建文件或者文件夹\ndrwxrwxrwt. 12 root root 264 11月 7 10:36 /tmp\n\n#注:chmod 自己是属主的时候,才可以修改权限\n```\n\n\n\n---\n\n## 三. chmod\n\n**chmod使用,必须是文件的属主,才能改动文件的读写执行权限(root除外)**\n\n\\#注:chmod使用 用户必须是文件的属主才能修改(即使是文件属组里的成员也没有权限去修改文件)\n\n\\#注:root用户除外\n\n\n\n```bash\n示例:su切换用户时 加- 不加- 区别\n[root@sanchuang-linux chenpeng]# su - sanchuang11\t\t# 注:加 - 会自动切换到到家目录下\n上一次登录:六 11月 7 15:10:51 CST 2020pts/0 上\n[sanchuang11@sanchuang-linux ~]$ exit\n注销\n[root@sanchuang-linux chenpeng]# su sanchuang11\t\t\t# 注:不加 - 会在当前目录下\n[sanchuang11@sanchuang-linux chenpeng]$ \n```\n\n\n\n---\n\n## 四. 设置文件/目录的归属\n\n**设置文件/目录的归属**\n\n### 4.1 chown命令\n\n**chown命令**\t\t\t\t # 注:用来改变文件的属主和属组\n\n- 必须是**root**\t\t\t\t# 注:chown 只能root去更改\n- 用户和组必须存在\n- 格式:\t`chown 属主 文件`\n `chown :属组 文件 `\n `chown 属主:属组 文件`\n\n\n\n```bash\n示例:chown 修改文件的属主和属组\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux tmp]# ls -al sanchuang_log \t\t\t\t\t\t# 注:属主 sanchuang ; 属组 sanchuang\n-rw-rw-r-- 1 sanchuang sanchuang 673 11月 7 15:19 sanchuang_log\n[root@sanchuang-linux tmp]# chown sanchuang10 sanchuang_log \t\t\t# 注:修改属主 sanchuang10\n[root@sanchuang-linux tmp]# ls -al sanchuang_log \n-rw-rw-r-- 1 sanchuang10 sanchuang 673 11月 7 15:19 sanchuang_log\n[root@sanchuang-linux tmp]# chown :sanchuang9 sanchuang_log \t\t\t# 注:修改属组 sanchuang9\n[root@sanchuang-linux tmp]# ls -al sanchuang_log \n-rw-rw-r-- 1 sanchuang10 sanchuang9 673 11月 7 15:19 sanchuang_log\n[root@sanchuang-linux tmp]# chown sanchuang2:sanchuang sanchuang_log \t# 注:即改属主又改属组\n[root@sanchuang-linux tmp]# ls -al sanchuang_log \n-rw-rw-r-- 1 sanchuang2 sanchuang 673 11月 7 15:19 sanchuang_log\n\n#注:属主和属组不可以随便更改\n#注:数字随便改,没有限制 没有强制性的检查\n#注:改字符串形式的名字 会检查一下\n[root@sanchuang-linux tmp]# chown xixi:haha sanchuang_log \t\t# 注:修改 字符串会检查\nchown: 无效的用户: “xixi:haha”\n[root@sanchuang-linux tmp]# chown 6666:6666 sanchuang_log \t\t# 注:数字没有限制\n[root@sanchuang-linux tmp]# ls -al sanchuang_log \n-rw-rw-r-- 1 6666 6666 673 11月 7 15:19 sanchuang_log\n```\n\n\n\n### 4.2 chgrp命令\n\n**chgrp命令**\t\t\t\t**# 注:修改属组(不常用)**\n\n- 格式:\t`chgrp 属组 文件`\n- 必须是root或者是文件的所有者 \n- 必须是新组的成员\n\n**常用命令选项**\n\n- `-R`:递归修改指定目录下所有文件、子目录的归属\n\n\n\n```bash\n示例:chgrp命令 修改属组\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux tmp]# chgrp sanchuang5 sanchuang_log \t\t# 注:只修改属组\n[root@sanchuang-linux tmp]# ls -al sanchuang_log \n-rw-rw-r-- 1 6666 sanchuang5 673 11月 7 15:19 sanchuang_log\n```\n\n\n\n### 4.3 可以执行的用户\n\n**可以执行的用户**\n\n> ![image-20220817035817124](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208170358168.png)\n\n\n\n操作\t\t\t 可以执行的用户\n\nchmod \t\t root和文件所有者\n\nchgrp \t\t root和文件所有者(必须是组成员)\n\nchown \t\t 只有root\n\n\\#注:chgrp修改属组 文件所有者 必须是想要**修改的组**里的**组成员**\n\n\n\n---\n\n## 五. 默认权限\n\n- 在内核级别,文件的初始权限666 \n- 在内核级别,文件夹的初始权限777\n- 用umask命令控制默认权限,临时有效\n\n\n\n```bash\n[root@localhost ~]# umask 0022\n[root@localhost ~]# umask -S u=rwx,g=rx,o=rx \n[root@localhost ~]# umask 077 \n[root@localhost ~]# umask 0077\n不推荐修改系统默认umask\n\n# 注:umask规定默认创建文件或者文件夹的权限有多大\n============================================================================================\n[sanchuang9@sanchuang-linux ~]$ ls -ld dd\t\t\t\t\t # 注:新建的文件dd\n-rw-rw-r-- 1 sanchuang9 sanchuang9 0 11月 7 15:48 dd\t\t# 注:权限644\n============================================================================================\n```\n\n\n\n### 5.1 /etc/profile下面有umask的设置\n\n**/etc/profile下面有`umask`的设置**\n\n**系统环境设置 /etc/profile**\t\t\t\t# 注:**/etc/profile下面有umask的设置**\n\n\\#注:判断uid是否大于199,并且当前用户的 用户名和组名 相等的时候 umask 是 002\n\n\\#注:用户名和组名不一样时 umask 是022\n\n\n\n```bash\n[sanchuang9@sanchuang-linux ~]$ less /etc/profile\t# 注:/etc/profile下面有umask的设置\nif [ $UID -gt 199 ] && [ \"`/usr/bin/id -gn`\" = \"`/usr/bin/id -un`\" ]; then\n umask 002\t\t\t# 注:如果uid大于199 执行 id -gn 命令 group_name ;id -un user_name\nelse\t\t\t\t\t# 注:判定uid是否大于199,并且group_name=user_name\n umask 022\t\t\t# 注:用户名和组名一样时 umask 是002 ; 用户名和组名不一样时 是 002\nfi\n--------------------------------------------------------------------------------------------\n#注:新建文件的权限是666-umask,新建目录的权限是777-umask\n#注:使用umask设置文件的权限,因为每次登陆shell都会加载系统的环境,会运行/etc/profile,所以会设置它的umask\n\n#注:id -gn 获取当前用户组名\n#注:id -un 获取当前用户名\n#uid大于199,并且当前用户的group_name和user_name名字相同的时候 umask是002\n#剩下的时候 umask是022\n\n·在内核级别,文件的初始权限666 \n·在内核级别,文件夹的初始权限777\n·用umask命令控制默认权限,临时有效\n\numask为002 则表示新建文件的默认权限为664,新建文件的文件夹权限为775\numask为022 则表示新建文件的默认权限为644,新建文件的文件夹权限为755\n\n# 注:666 - umask\n\t 777 - umask\n============================================================================================\n示例:id -gn 获取当前用户组名; id -un 获取当前用户名\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux tmp]# /usr/bin/id -gn\nroot\n[root@sanchuang-linux tmp]# /usr/bin/id -un\nroot\n[root@sanchuang-linux tmp]# id -gn\t\t\t# 注:当前所在用户组名\nroot\n[root@sanchuang-linux tmp]# id -un\t\t\t# 注:当前所在用户名\nroot\n============================================================================================\n示例:判断2个字符串是否相等 可以用1个等号\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux tmp]# [ \"a\" = \"b\" ] || echo \"ok\"\t\t# 注:判断字符串相同 可以用一个等于号\nok\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:条件为假 输出ok\n[root@sanchuang-linux tmp]# [ \"a\" = \"b\" ] && echo \"ok\"\t\t# 注:条件为真 输出ok\n[root@sanchuang-linux tmp]# [ \"a\" = \"a\" ] && echo \"ok\"\nok\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux tmp]# su - sanchuang\t# 注:用户名和组名一样时\n[sanchuang@sanchuang-linux ~]$ umask \n0002\t\t\t\t\t\t\t\t\t# 注:用户名和组名一样时 umask 是002\n[sanchuang@sanchuang-linux ~]$ id -gn\t# 注:第一位0是粘滞位 002是umask\nsanchuang\n[sanchuang@sanchuang-linux ~]$ id -un\nsanchuang\n\n[root@localhost ~]# su - b1\t\t\t\t# 注:用户名 和 组名不一样时\n[b1@localhost ~]$ id\nuid=1204(b1) gid=1001(cali) 组=1001(cali),200(tech)\n[b1@localhost ~]$ id -un\nb1\n[b1@localhost ~]$ id -gn\ncali\n[b1@localhost ~]$ umask \t\t\t\t# 注:用户名和组名不一样时 umask是022\n0022\n[b1@localhost ~]$ touch gg\n[b1@localhost ~]$ ls -ld gg\t\t\t\t# 注:新建文件的权限是644权限\n-rw-r--r--. 1 b1 cali 0 11月 8 16:27 gg\n[b1@localhost ~]$ umask 422\t\t\t\t# 注:临时设置umask为422\t(临时修改)\n[b1@localhost ~]$ mkdir test\t\t\t# 注:新建文件夹的权限是 355(777-umask)\n[b1@localhost ~]$ ls -ld test/\nd-wxr-xr-x. 2 b1 cali 6 11月 8 16:49 test/\t# 注:目录权限355 写执行 读执行 读执行\n============================================================================================\n示例:临时设置umask\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux tmp]# umask 422\t\t\t# 注:临时更改umask\n[root@sanchuang-linux tmp]# touch hh\n[root@sanchuang-linux tmp]# ls -ld hh\n--w-r--r-- 1 root root 0 11月 7 16:02 hh\t # 注:文件 权限是244 写读读\n============================================================================================\n示例:umask -S 查看文件目前默认权限是多少\n[sanchuang9@sanchuang-linux ~]$ umask -S\t\t# 注:查看文件目前默认权限是多少\nu=rwx,g=rwx,o=rx\t\t\n============================================================================================\n示例:想要修改某个用户的umask,永久修改\n--------------------------------------------------------------------------------------------\n#注:在家目录下的.bashrc下添加umask设置\t\t永久修改\n#注:/etc/profile,/etc/bashrc系统配置 基本上不要更改(不要想着改全局配置)\n[sanchuang9@sanchuang-linux ~]$ vim /home/sanchuang9/.bashrc\numask=002\n[sanchuang9@sanchuang-linux ~]$ exit\n注销\n[root@sanchuang-linux tmp]# su - sanchuang9\n上一次登录:六 11月 7 16:07:40 CST 2020pts/0 上\n[sanchuang9@sanchuang-linux ~]$ umask\t\t# 注:umask变成002了\n0002\n[sanchuang9@sanchuang-linux ~]$ bash\t\t# 注:执行到新bash里面去 umask也是002\n[sanchuang9@sanchuang-linux ~]$ umask\n0002\n```\n\n\n\n---\n\n## 六. 练习\n\n### 6.1 新建文件夹/pem,复制/etc/hosts文件到pem目录下\n\n```bash\n1、新建文件夹/pem,复制/etc/hosts文件到pem目录下\n[root@sanchuang-linux pem]# mkdir /pem\n[root@sanchuang-linux pem]# cp /etc/hosts /pem\n```\n\n\n\n### 6.2 修改hosts文件的权限为,属主有读写执行,组有读写执行,其他人没有任何权限\n\n```bash\n2、修改hosts文件的权限为,属主有读写执行,组有读写执行,其他人没有任何权限\n[root@sanchuang-linux pem]# chmod 750 /pem/hosts \n[root@sanchuang-linux pem]# ls -al /pem/hosts \n-rwxr-x--- 1 root root 158 11月 7 16:20 /pem/hosts\n```\n\n\n\n### 6.3 新建/pem2目录,修改权限为任何人都有读写执行的权限\n\n```bash\n3、新建/pem2目录,修改权限为任何人都有读写执行的权限\n[root@sanchuang-linux pem]# mkdir /pem2\n[root@sanchuang-linux pem]# chmod 777 /pem2\n[root@sanchuang-linux pem]# chmod 777 /pem2 -R\t\t# 注:连带下面所有的子文件\n```\n\n\n\n### 6.4 修改/pem2目录权限为属主有读写执行的权限,其他任何人都没有权限\n\n```bash\n4、修改/pem2目录权限为属主有读写执行的权限,其他任何人都没有权限\n[root@sanchuang-linux pem]# chmod 700 /pem2 \n```\n\n\n\n### 6.5 修改/pem2任何人都没有任何权限\n\n```bash\n5、修改/pem2任何人都没有任何权限\n[root@sanchuang-linux pem]# chmod 000 /pem2 \n```\n\n\n\n### 6.6 复制/etc/passwd和/etc/shadow文件到/pem目录下,查看复制之后的权限是否一致,如何保持权限一致\n\n```bash\n6、复制/etc/passwd和/etc/shadow文件到/pem目录下,查看复制之后的权限是否一致,如何保持权限一致\n[root@sanchuang-linux pem]# cp /etc/{passwd,shadow} /pem\n[root@sanchuang-linux pem]# ls -al /pem\n--w-r--r-- 1 root root 3964 11月 7 16:23 passwd\n---------- 1 root root 4201 11月 7 16:23 shadow\n```\n\n\n\n### 6.7 cp -a 保留文件的属性(包括权限、时间、用户、组)\n\n**`cp -a` 保留文件的属性(包括权限、时间、用户、组)**\n\n```bash\n[root@sanchuang-linux pem]# cp /home/sanchuang9/.viminfo /tmp/viminfo\t# 注:cp过来 属主、属组发生改变\n[root@sanchuang-linux pem]# ls -al /tmp/viminfo \n--w------- 1 root root 1622 11月 7 16:30 /tmp/viminfo\n[root@sanchuang-linux pem]# ls -al /tmp/viminfo \t\t\t\t\t\t# 注:cp-a选项 属主、属组、权限、创建时间都没变\n-rw------- 1 sanchuang9 sanchuang9 1622 11月 7 16:11 /tmp/viminfo\n```\n\n\n\n---\n\n## 七. 文件或目录的隐藏属性\n\n**chattr命令:设置文件的隐藏属性**\n\n- 格式:`chattr [+-=] [ai] 文件或目录`\t\t# 注:+、-、= 分别表示 增加、去除、设置参数\n\n**常用命令选项**\n\n- `-R`:递归修改\n- `-a`:可以增加文件内容,但不能修改和删除\n- `-i`:锁定保护文件\n\n\n**lsattr命令:查看文件的隐藏属性**\n\n- 格式:lsattr [Rda] 文件或目录\n\n**常用命令选项**\n\n- `-R`:递归修改\n- `-d`:查看目录\n\n\n#注:**普通用户设置不了文件的隐藏属性;root用户才能设置**\n\n\n\n```bash\n示例1:chattr +i hosts 锁定保护文件\n# 注:root用户也不能去修改它\n--------------------------------------------------------------------------------------------\n#注:不能更改文件(不能删 不能加 不能移动)\n[root@sanchuang-linux pem]# chattr +i hosts\t\t# 注:设置锁定保护文件;将它不能更改\n[root@sanchuang-linux pem]# mv hosts{,.bak}\t\t# 注:不能移动(即使是root用户)\nmv: 无法将'hosts' 移动至'hosts.bak': 不允许的操作\t\n[root@sanchuang-linux pem]# ls -al hosts \t\t# 注:ls -al命令 无法查看隐藏属性\n-rwxr-x--- 1 root root 158 11月 7 16:20 hosts\n[root@sanchuang-linux pem]# lsattr hosts\t\t# 注:lsattr 才能 查看文件隐藏属性 i\n----i--------------- hosts\t\t\t\t\t\t# 注:多了1个i属性\n[root@sanchuang-linux pem]# chattr -i hosts\t\t# 注:去除属性 去除锁定\n[root@sanchuang-linux pem]# lsattr hosts\n-------------------- hosts\t\t\t\t\t\t# 注:i隐藏属性没了\n#注:不能删,加,移动(root用户也不能)\n============================================================================================\n示例2:chattr +a hosts 可以增加文件内容,但不能修改和删除\n# 注:可以使用重定向去增加文件内容,但不能去修改和删除\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux pem]# chattr +a hosts\t\t# 注:可以增加文件内容,但是无法修改和删除\n[root@sanchuang-linux pem]# lsattr hosts\n-----a-------------- hosts\t\t\t\t\t\t# 注:多了a属性\n[root@sanchuang-linux pem]# vim hosts \t\t\t# 注:不可以修改\n[root@sanchuang-linux pem]# echo \"aaaa\" >> hosts \t# 注:可以追加\n[root@sanchuang-linux pem]# cat hosts \n127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4\naaaa\n[root@sanchuang-linux pem]# rm -rf hosts \t\t\t# 注:不可以删除\nrm: 无法删除'hosts': 不允许的操作\n#注:不能修改,只能追加,不能删除\n#注:有时候无论什么情况都不想让它更改 +a属性\n============================================================================================\n示例3:chattr +i /etc/passwd\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux pem]# chattr +i /etc/passwd\t\t# 注:设置以后就创建不了用户\n[root@sanchuang-linux pem]# lsattr /etc/passwd\t\t\t# 注:查看隐藏属性\n----i--------------- /etc/passwd\t\t\t\t\t\t# 注:隐藏属性i\n[root@sanchuang-linux pem]# useradd sanchuang21\t\t\t# 注:无论什么用户,设置了隐藏属性,基本没戏了\nuseradd:无法打开 /etc/passwd\n[root@sanchuang-linux pem]# chattr -i /etc/passwd\t\t# 注:解锁\n============================================================================================\n示例4:普通用户设置不了文件的隐藏属性\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# su - sanchuang\n[sanchuang@localhost ~]$ touch aa\n[sanchuang@localhost ~]$ chattr +i aa\t\t\t\t\t# 注:普通用户设置不了文件的隐藏属性\nchattr: 不允许的操作 while setting flags on aa\n```\n\n\n\n---\n\n## 八. 文件的正常权限\n\n> ![image-20220817041614445](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208170416487.png)\n>\n> \n\n```bash\n#注:正常文件的权限是读写执行\n[root@sanchuang-linux pem]# ls -ld /tmp\ndrwxrwxrwt. 12 root root 4096 11月 7 16:30 /tmp\t\t# 注:t 文件的特殊权限\n```\n\n\n\n---\n\n## 九. 文件的特别权限\n\n#注:**set位权限设置**\n\n> ![image-20220817041733623](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208170417672.png)\n\n\n\n**SET位权限**\n\n**主要用途:**\n\n- 为**可执行**(有 x 权限的)文件设置,权限字符为“s”\t\t# 注:**以前的x位变成s位**\n- 其他用户执行该文件时,将拥有属主或属组用户的权限\n\n**SET位权限类型**:\n\n- SUID:表示对属主用户增加SET位权限\n- SGID:表示对属组内的用户增加SET位权限\n\n\n\\# 注:用在可执行文件\n\\# 注:suid sgid 对应文件而言\n\n\n\n```bash\n示例:/bin/passwd\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# which passwd\n/bin/passwd\n[root@localhost ~]# ls -ld /bin/passwd \n-rwsr-xr-x. 1 root root 27856 4月 1 2020 /bin/passwd\n#注:普通用户以root用户的身份,间接更新了shadow文件中自己的密码\n[root@localhost ~]# su - sanchuang\n[sanchuang@localhost ~]$ passwd sanchuang\t\t\t\t# 注:不能更改密码 其他权限没到位\npasswd:只有根用户才能指定用户名。\n\n#注:s位 这个权限基本不会颁布,必须在有可执行文件下才能生效\n#注:这个权限设置 所有人全部给,不能精确到某个用户\n\n示例:SET位权限设置\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux pem]# ls -ld /pem\nd-wxr-xr-x 2 root root 47 11月 7 16:42 /pem\t\t\t\t# 注:只有root用户有写的权限\n#注:让/pem有普通用户创建、写入的权限?\n1.设置/pem的权限为777\n2.设置mkdir SUID的权限\n[root@sanchuang-linux sbin]# which mkdir\n/usr/bin/mkdir\n[root@sanchuang-linux sbin]# ls -ld /usr/bin/mkdir \t\t\n-rwxr-xr-x. 1 root root 195192 4月 10 2020 /usr/bin/mkdir\t# 注:没有设置s属性\n[root@sanchuang-linux sbin]# chmod u+s /bin/mkdir\t \t# 注:让普通用户执行mkdir时以root(属主)权限去运行\n[root@sanchuang-linux sbin]# ls -ld /usr/bin/mkdir \t\t# 注:变成s位了\n-rwsr-xr-x. 1 root root 195192 4月 10 2020 /usr/bin/mkdir\n[root@sanchuang-linux sbin]# su - sanchuang9\n上一次登录:六 11月 7 16:09:48 CST 2020pts/0 上\n[sanchuang9@sanchuang-linux ~]$ cd /pem\n[sanchuang9@sanchuang-linux pem]$ ls\nhosts passwd shadow\n[sanchuang9@sanchuang-linux pem]$ mkdir aa \t\t\t\t# 注:普通用户有写的权限了\n[sanchuang9@sanchuang-linux pem]$ ls -ld /pem\nd-wxr-xr-x 3 root root 57 11月 7 16:59 /pem\n[sanchuang9@sanchuang-linux pem]$ touch dd\t\t\t\t# 注:touch没有这个权限\ntouch: 无法创建 'dd': 权限不够\n[sanchuang9@sanchuang-linux pem]$ exit\n注销\n[root@sanchuang-linux sbin]# chmod u-s /bin/mkdir\n[root@sanchuang-linux sbin]# ls -ld /bin/mkdir \n-rwxr-xr-x. 1 root root 195192 4月 10 2020 /bin/mkdir\n# 注:s位基本不会给\n# 注:s位不要轻易的颁布它,会对用户进行影响\n```\n\n\n\n---\n\n## 十. 粘滞位权限(Sticky)\n\n**粘滞位权限(Sticky)**\n\n**主要用途:**\n\n- 为公共目录(例如,权限为777的)设置,权限字符为“`t`”\t\t# 注:**t 粘滞位标记字符**\n- 用户不能删除该目录中其他用户的文件\n \n\n\\# 注:一般作用于文件夹\n\\# 注:粘滞位对于文件夹而言\n\n\n\n```bash\n示例1\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux sbin]# ls -ld /tmp\ndrwxrwxrwt. 12 root root 4096 11月 7 16:30 /tmp\t# 注:/tmp目录 任何用户 都有读写执行权限\n#注:因为粘滞位权限,用户在/tmp目录下只能创建自己的,删除自己的\n#注:一般作用于文件夹\n#注:sanchuang10用户不能删除sanchuang用户创建的文件\n==============================================================================================================\n示例2:chmod 777 /pem 普通用户可以操作/pem这一层目录下的文件或者文件夹及子文件\n# 注:777权限,不同用户可以相互删除文件\n# 注:设置粘滞位后,只能删除自己创建的文件\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# chmod 777 /pem\t\t\t\t# 注:把/pem文件夹权限改为777\n[root@sanchuang-linux ~]# ls -ld /pem\t\t\t\t\t# 注:所有用户都有对/pem读写执行的权限 包括创建、删除\ndrwxrwxrwx 3 root root 74 11月 7 17:10 /pem\n[root@sanchuang-linux ~]# su - sanchuang9\t\t\t\t# 注:普通用户有创建的权限\n上一次登录:六 11月 7 17:07:17 CST 2020pts/2 上\n[sanchuang9@sanchuang-linux ~]$ touch /pem/sanchuang9\t# 注:普通用户有创建的权限\n[root@sanchuang-linux ~]# su - sanchuang\n[sanchuang@sanchuang-linux ~]$ rm -rf /pem/sanchuang9\t# 注:普通用户有删除的权限\n#注:用户可以删除其他用户创建的文件\n==============================================================================================================\n示例3:粘滞位 t\n# 注:设置粘滞位后,只能删除自己创建的文件\n[sanchuang9@sanchuang-linux tmp]$ ls -ld /tmp\ndrwxrwxrwt. 13 root root 4096 11月 7 17:07 /tmp\t\t\t# 注:/tmp目录设置了1个粘滞位\n[sanchuang9@sanchuang-linux ~]$ touch /tmp/sanchuang9\n[sanchuang9@sanchuang-linux ~]$ exit\n[root@sanchuang-linux ~]# su - sanchuang\n上一次登录:日 11月 8 19:05:55 CST 2020pts/3 上\n[sanchuang@sanchuang-linux ~]$ rm -rf /tmp/sanchuang9\t# 注:因为设置了1个粘滞位\nrm: 无法删除'/tmp/sanchuang9': 不允许的操作\t\t\t\t# 注:用户只能在/tmp目录下创建 删除自己的\n#注:粘滞位的作用\n#注:·为公共目录(例如,权限为777的)设置,权限字符为“t”\n#注:·用户不能删除该目录中其他用户的文件\n#注:一般作用于文件夹\n```\n\n\n\n---\n\n## 十一. 设置SET位、粘滞位权限\n\n**设置SET位、粘滞位权限**\n\n**使用权限字符**\n\n- `chmod ug±s 可执行文件...`\t\t\t# 注:设置set位\n- `chmod o±t 目录名...`\t\t\t\t # 注:设置粘滞位\n\n**使用权限数字**\n\n- `chmod mnnn 可执行文件...`\n- **m为4时,对应SUID,2对应SGID,1对应粘滞位,可叠加**\t\t# 注:m为4 为2 set位\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ls -ld /tmp\ndrwxrwxrwt. 13 root root 4096 11月 7 17:07 /tmp\t\t# 注:/tmp目录设置了粘滞位,权限为1777\n#注:/tmp目录设置了粘滞位,第1位是1\n============================================================================================\n示例:设置粘滞位\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# chmod 1777 /pem\n[root@sanchuang-linux ~]# ls -ld /pem\ndrwxrwxrwt 3 root root 74 11月 7 17:10 /pem\t\t\t# 注:粘滞位 t 之前 x 的位置\n#注:普通情况下不需要使用粘滞位、set位的时候,用3个数字就可以了\n-----------------------------------------------------------------\n[root@sanchuang-linux ~]# ls -ld /bin/mkdir \n-rwxr-xr-x. 1 root root 195192 4月 10 2020 /bin/mkdir\n[root@sanchuang-linux ~]# chmod 4755 /bin/mkdir\t\t# 注:设置为SET位SUID权限\n[root@sanchuang-linux ~]# ls -ld /bin/mkdir \n-rwsr-xr-x. 1 root root 195192 4月 10 2020 /bin/mkdir\n[root@sanchuang-linux ~]# chmod 755 /bin/mkdir\t\t# 注:改回来\n[root@sanchuang-linux ~]# ls -ld /bin/mkdir \n-rwxr-xr-x. 1 root root 195192 4月 10 2020 /bin/mkdir\n```\n\n\n\n---\n\n","tags":["Linux","权限"],"categories":["Linux"]},{"title":"16_Linux基础-文件&目录权限及归属","url":"/posts/5637.html","content":"## 一. 文件/目录的权限\n\n**文件/目录的权限**\n\n**访问权限**\n\n- `可读(read)`:允许查看文件内容、显示目录列表\t\tr\n- `可写(write)`:允许修改文件内容,允许在目录中新建、移动、删除文件或子目录\tw\n- `可执行(execute)`:允许运行程序、切换目录\t\tx\n\n**归属(所有权)**\n\n- `文件拥有者(owner)`:拥有该文件或目录的**用户帐号**\t\t# 注:**属主**\n- `属组(group)`:拥有该文件或目录的**组帐号**\t\t\t\t # 注:**属组**\n- `其它人(others)`:除了属主和属组的**其他人**\t\t\t\t # 注:**其他**\n\n\n\n#注:区分是对于文件而言还是对于目录而言\n\n```bash\nls -al 查看当前目录下面文件或者文件夹的详细信息,包括文件的权限\nls -ld 查看当前目录\n```\n\n\n\n```bash\n示例1:查看文件权限 ls -al\n# 注:第三列属主 第四列属组\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ls -al\t\t\t\t#注:查看文件权限\n总用量 668\n-rw-r--r--. 1 root root 211 9月 18 10:31 '!'\ndr-xr-x---. 21 root root 12288 11月 6 15:16 .\n[root@sanchuang-linux ~]# ls -al zuoye.sh \t\t# 注:查看单个文件权限\n-rw-r--r--. 1 root root 1212 10月 29 20:20 zuoye.sh\n[root@sanchuang-linux ~]# ls -al /home\t\t\t# 注:查看/home目录下所有文件的权限\n总用量 18348\ndrwxr-xr-x. 43 root root 4096 11月 6 15:36 .\ndr-xr-xr-x. 38 root root 4096 11月 5 15:12 ..\n[root@sanchuang-linux ~]# ls -al *.sh\t\t\t# 注:查看文件权限\n-rw-r--r--. 1 root root 0 9月 25 09:35 backup_log.sh\n-rw-r--r--. 1 root root 41 10月 28 20:27 file_test.sh\n\n示例2:查看目录权限 ls -ld /home\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ls -ld /home\t\t\t# 注:查看/home 目录的权限\ndrwxr-xr-x. 43 root root 4096 11月 6 15:36 /home\n```\n\n\n\n---\n\n## 二. 文件/目录的权限\n\n```bash\n[root@localhost ~]# ls -ld first.py \n-rw-r--r--. 1 root root 1097 10月 13 10:20 first.py\n文件类型 访问权限 所有者 属组\n```\n\n> ![image-20220816204743513](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208162047554.png)\n\n\n\n```bash\n示例:drwxr-xr-x\n--------------------------------------------------------------------------------------------\n第一列:表示文件类型与权限\n\t第一个字符\n -\t普通文件 file\n d\t表示目录\n s\t表示socket文件\t\t\t# 注:socket(套接字) 进程之间通信的一种方式。\n p\t管道文件 pipe\n c\t字符设备文件\ttty\n b\t块设备文件\t 磁盘(disk)\t# 注:跟硬件相关的块设备文件一般放在 /dev下面\n l\t链接文件\t\t\t\t# 注:/usr/bin/目录下 有大量 链接文件\n\n #权限 r 可读 w 可写 x 可执行\n ·第2-第4个字符\n \t 表示属主的权限\n ·第5-第7个字符\n \t 表示属组的权限\n ·后三个\n\t 表示其他人的权限\n--------------------------------------------------------------------------------------------\n敲的所有命令都是在PATH环境变量路径下查找\n\n创建链接文件\n# 注:ln -s 源文件 目标文件\t\tsymbolic adj. 象征的;符号的;使用符号的\n[root@sanchuang-linux bin]# ln -s python3.6 python\t\t\t# 注:-s创建软链接\n[root@sanchuang-linux bin]# ln -s python3.6 /root/python\t# 注:可以在绝对路径下创建链接文件\n#注:链接文件/root/python 放在了/root目录下\nwhich查看命令的绝对路径\n[root@sanchuang-linux bin]# which mkdir\n/usr/bin/mkdir\n[root@sanchuang-linux bin]# mv /usr/bin/mkdir /usr/bin/mkdirbak\t# 注:修改名字后 命令找不到了\n[root@sanchuang-linux bin]# mkdir\n-bash: mkdir: 未找到命令\n[root@sanchuang-linux bin]# mkdirbak /tmp/mkdir\n[root@sanchuang-linux bin]# mv /usr/bin/mkdirbak /usr/bin/mkdir\t# 注:改回来\n\n/usr/bin/下有大量链接文件\n[root@sanchuang-linux tmp]# cd /usr/bin/\t\t\t\t\t\t# 注:/usr/bin/下有大量链接文件\n[root@sanchuang-linux bin]# ls -al python2\t\t\t\t\t\t# 注:链接文件\nlrwxrwxrwx. 1 root root 9 6月 5 11:38 python2 -> python2.7\n[root@sanchuang-linux bin]# ls -al python3\t\t\t\t\t\t# 注:链接文件\nlrwxrwxrwx. 1 root root 25 9月 18 15:47 python3 -> /etc/alternatives/python3\n```\n\n\n\n---\n\n## 三. socket(套接字)\n\n> \\#注:socket(套接字) 进程之间通信的一种方式,通常用于不同主机不同进程之间的通信方式(网络编程)\n>\n> ftp有vsftpd的服务,vsftpd服务端服务起来了开启21号端口。ftp客户端要想连接这个服务,ftp客户端需要开启一个随机端口去连接21号端口,进行网络传输。通过网络指定某种特定协议,进行网络连接。\n>\n> 开启一个vsftpd,会产生一个socket文件\n>\n> 开放了端口基本上都会有一个socket文件\n>\n> \n\n```bash\n[root@localhost mail]# cd /data/mysql\n[root@localhost mysql]# ls -al\nsrwxrwxrwx 1 mysql mysql 0 10月 7 12:04 mysql.sock\t\t# 注:s socket文件 (粉色)\n```\n\n\n\n---\n\n## 四. Linux内核五大子系统\n\n**Linux内核五大子系统:**\n\n- 1、文件系统\n- 2、内存管理\n- 3、进程通信\n- 4、进程调度\n- 5、网络接口\n\n\n\n---\n\n## 五. 进程\n\n**进程是系统进行资源分配的基本单位,不同进程之间资源是互相隔离的**\n\n**进程之间通信(常见的5种):**\n\n1. 管道\n2. 信号\t(kill -9)\n3. 共享内存\n4. socket套接字\n5. 消息队列\n\n\n\n```bash\n示例1:管道\t\t\t\t#注:管道是进程之间通信的一种方式\n示例\n[root@sanchuang-linux ~]# cat /etc/passwd |grep sanchuang\t# 注:通过管道把前进程的输出赋给后进程的输入\nsanchuang:x:1005:1005::/home/sanchuang:/bin/bash\n#注:适用于相同主机不同进程\n--------------------------------------------------------------------------------------------\n示例2:信号\t\t\t\t\n示例:kill -9 pid\n[root@sanchuang-linux ~]# kill -l\n 1) SIGHUP\t 2) SIGINT\t 3) SIGQUIT\t 4) SIGILL\t 5) SIGTRAP\n 6) SIGABRT\t 7) SIGBUS\t 8) SIGFPE\t 9) SIGKILL\t10) SIGUSR1………………\n[root@sanchuang-linux ~]# ps -ef |grep nginx\nroot 5868 5691 0 16:29 pts/0 00:00:00 grep --color=auto nginx\n[root@sanchuang-linux ~]# kill -9 2868\t\t\t\t\t# 注:发送9这个信号给1209进程\n--------------------------------------------------------------------------------------------\n示例3:共享内存\n#注:A、B之间创建了一片新的内存空间,可以一起去拿\n#注:适用于相同主机不同进程\n--------------------------------------------------------------------------------------------\n示例4:socket套接字\n#注:用于不同主机之间不同进程 网络通信\n--------------------------------------------------------------------------------------------\n示例5:消息队列\n#注:相当于排队的 1,2,3,4,5,6\n#注:AB共享的内存空间里,A产生的B去获取。A产生1,B取出来,1从A里出去\n```\n\n\n\n---\n\n## 六. /根目录下\n\n**/etc\t存放配置文件**\n**/dev\t存放设备文件**\t\t# 注:**硬件相关的 磁盘、网卡、socket**\n/root\t\t\t\t\t\t\t\t # 注:root用户家目录\n/home\t\t\t\t\t\t\t # 注:存放普通用户的家目录文件\n\n\n\n```bash\n[root@sanchuang-linux ~]# cd /dev\n[root@sanchuang-linux dev]# ls -al\ncrw-rw-rw- 1 root tty 5, 0 11月 6 11:32 tty\t\t# 注:字符设备文件\ttty\ncrw--w---- 1 root tty 4, 0 11月 5 15:12 tty0\ncrw--w---- 1 root tty 4, 1 11月 6 14:28 tty1\nbrw-rw---- 1 root disk 8, 0 11月 5 15:12 sda\t\t# 注:块设备文件\t磁盘\n```\n\n\n\n## 七. 可执行权限\n\n```\n第一列第二到第十个字符\n #权限 r 可取 w 可写 x 可执行\n 第2-第4个字符\n \t 表示属主的权限\n 第5-第7个字符\n \t 表示属组的权限\n 后三个\n\t 表示其他人的权限\n```\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ls -al men_test.sh \n-rw-r--r--. 1 root root 0 10月 30 16:26 men_test.sh\n[root@sanchuang-linux ~]# bash men_test.sh \t# 注:使用bash解释器去执行(生成一个新的bash)\n[root@sanchuang-linux ~]# sh men_test.sh \t# 注:使用sh解释器去执行(生成一个新的sh)\n[root@sanchuang-linux ~]# . men_test.sh\t\t# 注:使用当前bash去执行,会继承当前环境变量\n#注:相当于当前bash,当前环境\n[root@sanchuang-linux ~]# ./men_test.sh \t# 注:权限不够,本身没有可执行权限\n-bash: ./men_test.sh: 权限不够\t\t\t\t # 注:有可执行权限的文件 可以直接./men_test.sh执行\n```\n\n\n\n---\n\n## 八. Shell文件执行方式\n\n> **Shell文件执行方式(3种)**\n> #注:**shell里面可执行文件后缀没有要求 不一定非要.sh结尾**\n\n\n\n```bash\n[root@sanchuang-linux ~]# vim test_aa.sh\necho \"testaa...\"\necho $a\necho $b\n[root@sanchuang-linux ~]# a=1\n[root@sanchuang-linux ~]# b=2\n[root@sanchuang-linux ~]# . test_aa.sh \t# 注:使用当前bash去执行test_aa.sh,会继承当前 shell 的 环境变量\ntestaa...\t\t\t\t\t\t\t\t# 注:用.会继承当前bash里的一切变量\n1\n2\n[root@sanchuang-linux ~]# bash test_aa.sh \t# 注:创建一个新的bash环境去执行命令\ntestaa...\t\t\t\t\t\t\t\t\t# 注:新bash环境中没有定义a、b变量\n\t\t\t\t\t\t\t\t\t\t\t# 注:没有输出父bash的a、b\n\t\t\t\t\t\t\t\t\t\t\t# 注:没有获取到a、b\n[root@sanchuang-linux ~]# sh test_aa.sh \t\t# 注:创建一个新的sh环境去执行命令\ntestaa...\n\t\t\t\t\t\t\t\t\t\t\t# 注:没有输出\n\n[root@sanchuang-linux ~]# ./test_aa.sh \t\t# 注:执行文件本身,看文件本身有没有执行权限\n-bash: ./test_aa.sh: 权限不够\t\t\t\t # 注:直接执行当前目录下的这个文件 需要可执行权限\n# 注:其他的方式不一定需要可执行权限\n\n总结\n. test_aa.sh\t\t\t不需要可执行权限\t当前bash进程执行\nbash test_aa.sh\t\t\t不需要可执行权限\t新的bash进程运行\nsh test_aa.sh\t\t\t不需要可执行权限\t新的bash进程运行\n./test_aa.sh\t\t\t需要可执行权限\t新的bash进程运行\n```\n\n\n\n---\n\n## 九. chmod命令\n\n**chmod命令**\t# 注:**修改文件的访问权限**\n\n**格式1**:`chmod [ugoa] [+-=] [rwx] 文件或目录...`\n\n- **u、g、o、a 分别表示**\n \t\tu属主、g属组、o其他用户、a所有用户\n\n- **+、-、= 分别表示**\n \t\t+增加、-去除、=设置权限\n\n- **rwx**\n \t\t对应的权限字符\n\n**常用命令选项**\n\n- `-R`:递归修改指定目录下所有文件、子目录的权限\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# chmod u+x men_test.sh \t\t# 注:对属主+可执行权限\n[root@sanchuang-linux ~]# ls -al men_test.sh \n-rwxr--r--. 1 root root 0 10月 30 16:26 men_test.sh\t\t# 注:可执行文件 都是绿的\n#注:可执行文件\t都是绿的\n#注:socket文件\t都是粉的\n[root@sanchuang-linux ~]# ./men_test.sh \t\t\t\t# 注:可以直接执行了\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux lianxi]# chmod a-x sc -R\t\t# 注:-R递归,把该目录和该目录下的所有子文件都去除可执行权限\n[root@sanchuang-linux lianxi]# chmod a+x sc -R\t\t# 注:所有用户增加可执行权限\n============================================================================================\n#注:根目录只有root用户能用\n[root@sanchuang-linux ~]# ls -ld /\ndr-xr-xr-x. 38 root root 4096 11月 5 15:12 /\n============================================================================================\n[root@mysql-binary ~]# chmod u+x group_member.sh \n[root@mysql-binary ~]# ./group_member.sh sanchuang5\t\t# 注:添加了可执行权限后可以 ./运行\nsanchuang5,sanchuang11,sanchuang13,sanchuang10,sanchuang12\n```\n\n\n\n---\n\n## 十. chmod命令\n\n**chmod命令**\t# 注:**修改文件的访问权限**\n\n**格式2**:`chmod nnn 文件或目录...`\t\t\t\t # 注:nnn表示3位八进制数\n\n权限项\t 读\t写\t执行\t\t读\t写\t执行\t\t读\t写\t执行\n\n字符表示\t r\tw\tx\t\t r\tw\tx\t\t r\tw\tx\n\n数字表示\t 4\t2\t1\t\t 4\t2\t1\t\t 4\t2\t1\n\n权限分配\t 文件所有者\t\t 文件所属组\t\t 其他用户\n\n> ![image-20220816210259355](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208162102394.png)\n\n\n\n**常用命令选项**\n\n- `-R`:递归修改指定目录下所有文件、子目录的权限\n\n\n#注:root用户基本上无论有没有权限,它都可以使用\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# chmod 777 sc \t\t\t\t# 注:都有读写执行的权限\n[root@sanchuang-linux ~]# chmod 700 sc \t\t\t\t# 注:属主有读写执行的权限\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux home]# ls -ld sanchuang\t\t# 注:查看目录权限 ls -ld\ndrwx------. 4 sanchuang sanchuang 122 11月 6 17:10 sanchuang\n[root@sanchuang-linux home]# chmod 777 /home/sanchuang\t\t# 注:都有读写执行的权限\n[root@sanchuang-linux home]# ls -ld sanchuang\ndrwxrwxrwx. 4 sanchuang sanchuang 122 11月 6 17:10 sanchuang\n[root@sanchuang-linux home]# chmod 777 /home/sanchuang -R\t# 注:-R:递归修改指定目录下所有文件、子目录的权限\n[root@sanchuang-linux home]# ls -ld sanchuang\ndrwxrwxrwx. 4 sanchuang sanchuang 122 11月 6 17:10 sanchuang\n#注:用户的家目录下(如/home/sanchuang)授予所有对象读写执行权限,会造成普通用户sanchuang无法进行远程登录\n\n示例:root用户基本上无论有没有权限,它都可以使用\n[root@sanchuang-linux ~]# ls -ld /etc/shadow\n---------- 1 root root 4201 11月 7 12:04 /etc/shadow\n[root@sanchuang-linux ~]# vim /etc/shadow\n```\n\n\n\n---\n\n## 十一. 一般情况下普通用户只能在家目录下或者/tmp目录下创建文件或者文件夹\n\n**一般情况下普通用户只能在家目录下或者/tmp目录下创建文件或者文件夹**\n\n#注:/tmp目录是一个临时目录,一般存放临时性的东西(如:程序运行中需要记录的一些东西,程序结束后把/tmp目录下的东西删掉)\n\n```bash\n[root@sanchuang-linux ~]# su - sanchuang\n上一次登录:五 11月 6 17:09:41 CST 2020pts/2 上\n[sanchuang@sanchuang-linux ~]$ ls -ld /\ndr-xr-xr-x. 38 root root 4096 11月 5 15:12 /\n[sanchuang@sanchuang-linux ~]$ ls -ld /etc\ndrwxr-xr-x. 90 root root 8192 11月 7 15:00 /etc\n[sanchuang@sanchuang-linux ~]$ ls -ld ./\t\t\t\t# 注:家目录下 创建文件或者文件夹\ndrwxrwxrwx. 4 sanchuang sanchuang 122 11月 6 17:10 ./\n[sanchuang@sanchuang-linux ~]$ ls -ld /tmp\t\t\t\t# 注:/tmp目录下 创建文件或者文件夹\ndrwxrwxrwt. 12 root root 264 11月 7 10:36 /tmp\n\n#注:chmod 自己是属主的时候,才可以修改权限\n```\n\n\n\n---\n\n## 十二. chmod\n\n**chmod**\t# 注:**修改文件的归属权限**\n\n**chmod使用,必须是文件的属主,才能改动文件的读写执行权限(root除外)**\n\n\n\n```bash\n[root@sanchuang-linux chenpeng]# su - sanchuang11\t\t# 注:加 - 会自动到家目录下\n上一次登录:六 11月 7 15:10:51 CST 2020pts/0 上\n[sanchuang11@sanchuang-linux ~]$ exit\n注销\n[root@sanchuang-linux chenpeng]# su sanchuang11\t\t\t# 注:不加 - 会在当前路径下\n[sanchuang11@sanchuang-linux chenpeng]$ \n```\n\n\n\n---\n\n","tags":["Linux","权限"],"categories":["Linux"]},{"title":"15_Linux基础-用户与组2","url":"/posts/43746.html","content":"## 一. 练习\n\n### 1.1 如何知道一个用户是否在linux系统里存在?\n\n```bash\n1、如何知道一个用户是否在linux系统里存在?\ncat /etc/passwd\n或者 id命令\n```\n\n\n\n### 1.2 如何禁用一个用户登陆linux系统\n\n```bash\n2、如何禁用一个用户登陆linux系统\n使用usermod -L 锁定用户\nusermod -s /sbin/nologin root\n```\n\n\n\n### 1.3 如何知道一个用户属于哪些组\n\n```bash\n3、如何知道一个用户属于哪些组\n使用id命令查看\n使用groups命令查看\n查看/etc/group里用户所属的组\n```\n\n\n\n### 1.4 如何知道哪些用户现在已经登录在linux里? 哪些用户曾经登陆过linux系统?\n\n```bash\n4、如何知道哪些用户现在已经登录在linux里? 哪些用户曾经登陆过linux系统?\n使用w命令查看用户登录情况\n使用last命令查看曾经登录过的用户\n示例:w who 看当前登录的用户\n#注:w看的更详细些\n[root@localhost ~]# w\n 09:37:40 up 8:32, 5 users, load average: 0.00, 0.01, 0.05\nUSER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\nroot tty1 四09 6:28 0.09s 0.09s -bash\nroot pts/3 192.168.136.1 09:29 4.00s 0.05s 0.03s w\n[root@localhost ~]# who\nroot tty1 2020-11-05 09:31\nroot pts/3 2020-11-06 09:29 (192.168.136.1)\n```\n\n\n\n### 1.5 如何给用户重新设置密码\n\n```bash\n5、如何给用户重新设置密码\npasswd\n```\n\n\n\n### 1.6 linux的root密码忘记了怎么办\n\n```bash\n6、linux的root密码忘记了怎么办\n\t 进入单用户模式\n 1、开机,按任意键停住启动界面,然后选择对应的内核,按 e 进行编辑\n 2、找到linux16这一行,在最后输入 rd.break\n 3、按 Ctrl-x 启动,然后按照以下操作破解 root 密码\n示例:忘记root用户密码怎么办?\n答:进入单用户模式\n```\n\n​\t\thttps://blog.csdn.net/qq_37960324/article/details/84589565\n​\t\thttps://www.cnblogs.com/jsjrj01/p/10301603.htm\n\n\n\n### 1.7 如何将已经登录在系统里的用户踢出去?并且防止它再次登陆?\n\n```bash\n7、如何将已经登录在系统里的用户踢出去?并且防止它再次登陆?\n1.踢出可疑的root登录用户,马上修改密码 \n2.sshd---》/etc/hosts.deny hosts.allow -->ip \n3./etc/ssh/sshd_config -->DenyUsers -->用户\n```\n\n\n\n### 1.8 怎么把普通用户变成root用户\n\n```bash\n8、怎么把普通用户变成root用户\n1.(不推荐)修改 /etc/passwd 文件,找到要修改的普通用户,把用户ID修改为 0\n2.sudo 权限\n```\n\n\n\n### 1.9\n\n```bash\n· 创建目录/tech/cali和/tech/sanle,分别用于保存个项目组中用户帐号的宿主目录;\n· 为两个项目组添加组帐号cali、sanle,GID号分别为1001、1002;为技术部添加组帐号tech,GID号为200;\n· 添加2个用户,分别为b1、b2,要求他们的基本组是cali,附加组是tech,宿主目录均使用/tech/cali目录中与帐号同名的文件夹(例如b1用户的宿主目录/tech/cali/b1);其中b2用户帐号设置2012-12-31日后失效;\n· 添加2个用户,分别为a1、a2,要求他们的基本组是sanle,附加组是tech;宿主目录均使用/tech/sanle目录中与帐号同名的文件夹(例如a1用户的宿主目录/tech/cali/a1) ;其中a2用户帐号登录的shell为/bin/ksh\n所有新建用户密码都是123456;\n\n1、mkdir -p /tech/cali /tech/sanle\n2、groupadd -g 1001 cali \n groupadd -g 1002 sanle\n groupadd -g 200 tech\n3、useradd -g cali -G tech -d /tech/cali/b1 b1\n useradd -g cali -G tech -d /tech/cali/b2 -e 2020-11-6 b2\n4、useradd -g sanle -G tech -d /tech/sanle/a100 a1\n useradd -g sable -G tech -d /tech/sanle/a200 -s /bin/ksh a2\n5、echo 123456|passwd a1 --stdin\n echo 123456|passwd a2 --stdin\n----------------------------------------------------------------\n示例:过期账户不能登录\n-----------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# useradd -e \"2012-11-22\" sanle3\t# 注:过期账户不能登录\n[root@sanchuang-linux ~]# su - sanle3\t\t\t\t\t\t# 注:可以切换,不能登录\n[sanle3@sanchuang-linux ~]$ \n```\n\n\n\n---\n\n## 二. /etc/group文件\n\n**/etc/group文件**\n\n#注:/etc 存放配置文件的地方\n\n**/etc/group文件**\t\t\t# 注:可以查看**哪些账户的次要组是**\n\n组帐号:\n\n- 主要组(私有组)\n- 次要组(附属组)\n\nGID:(Group Identify,组标识号)\n\n\n**Linux组帐号**\n\n- 主要组(私有组)\n\n与用户相关的默认组,在/etc/passwd文件的第四个字段定义\n\n- 次要组(附属组)\n\n用户可以同时属于其他的组,在/etc/group文件的第四个字段定义\n\n`用户的主要组的名称和GID相关`\n\n\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# useradd -g sanchuang4 -G sanchuang5 sanchuang10\n[root@sanchuang-linux ~]# useradd -g sanchuang4 -G sanchuang5 sanchuang12\n[root@sanchuang-linux ~]# useradd -g sanchuang5 -G sanchuang4 sanchuang13\n[root@sanchuang-linux ~]# cat /etc/group\nsanchuang4:x:1100:sanchuang13\t\t\t\t\t# 注:只显示次要组的组成员列表\nsanchuang5:x:1200:sanchuang10,sanchuang12\t\t# 注:只显示次要组的组成员列表\n#注:组账号名:sanchuang5;GID:1200;组成员列表sanchuang10,sanchuang12\n#注:只显示次要组的组成员列表\n===========================================================================================================\n示例:怎样查看一个组里有哪些用户\n---------------------------------------------------------------------------------------------------------------------------------\n#注:联系2个文件 /etc/passwd /etc/group\n[root@sanchuang-linux ~]# awk -F: '/sanchuang5/{print $3,$4}' /etc/group\t\n1200 sanchuang10,sanchuang12\t\t\t\t# 注:模糊匹配,匹配包含sanchuang5的行\n[root@sanchuang-linux ~]# awk -F: '$1==\"sanchuang5\"{print $3,$4}' /etc/group\t# 注:加引号\n1200 sanchuang10,sanchuang12\t\t\t\t# 注:精确匹配\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# vim group_member.sh\n#!/bin/bash\ngroup_name=$1 #注:组名作为参数\n#/etc/group获取它的GID和成员列表\ngroup_msg=`awk -F: -v group_awk=$group_name '$1==group_awk{print $3,$4}' /etc/group`\necho $group_msg #注:-v选项 向awk传递shell变量 指定外部$group_name赋给awk内部变量 运行的时候用自定义的变量\n[root@sanchuang-linux ~]# sh group_member.sh sanchuang5\n1200 sanchuang10,sanchuang12\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a='1200 sanchuang10,sanchuang12'\n[root@sanchuang-linux ~]# s1=(a b c d e)\n[root@sanchuang-linux ~]# s2=($a)\t\t\t# 注:转化为数组\n[root@sanchuang-linux ~]# echo $s2\n1200\n[root@sanchuang-linux ~]# echo $s2[@]\n1200[@]\n[root@sanchuang-linux ~]# echo ${s2[@]}\t\t# 注:获取数组里全部元素\n1200 sanchuang10,sanchuang12\n[root@sanchuang-linux ~]# echo ${#s2[@]}\t# 注:获取数组长度\n2\n[root@sanchuang-linux ~]# echo ${#s2}\t\t# 注:获取第一个元素 字符的长度\n4\n[root@sanchuang-linux ~]# echo ${s2[0]}\t\t# 注:获取数组里第一个元素\n1200\n[root@sanchuang-linux ~]# echo ${s2[1]}\t\t# 注:获取数组里第二个元素\nsanchuang10,sanchuang12\n-----------------------------------------\ngroup_name=$1 #注:组名作为参数\n#/etc/group获取它的GID和成员列表\ngroup_msg=`awk -F: -v group_awk=$group_name '$1==group_awk{print $3,$4}' /etc/group`\n#注:-v选项 向awk传递shell变量 指定外部$group_name赋给awk内部变量 运行的时候用自定义的变量\n#注:获取数组里第一个元素\ngroup_lst=($group_msg) #注:转变成数组\ngroup_id=${group_lst[0]}\t\t# 注:gid\ngroup_user_1=${group_lst[1]}\t# 注:该组(次要组)成员\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# vim group_member.sh\n#!/bin/bash\n \ngroup_name=$1 #注:组名作为参数\n#/etc/group获取它的GID和成员列表\ngroup_msg=`awk -F: -v group_awk=$group_name '$1==group_awk{print $3,$4}' /etc/group`\n#注:-v选项 向awk传递shell变量 指定外部$group_name赋给awk内部变量 运行的时候用自定义的变量\n#注:获取数组里第一个元素\ngroup_lst=($group_msg) #注:转变成数组\ngroup_id=${group_lst[0]}\ngroup_user_1=${group_lst[1]}\n#注:获取/etc/passwd 主要组 成员;tr \"\\n\" \",\" 指定分隔符为,;过滤出 $4==group_id 的行\ngroup_user_2=`awk -F: -v group_id=$group_id '$4==group_id{print $1}' /etc/passwd|tr \"\\n\" \",\"`\necho $group_user_2$group_user_1\t\t# 注:直接拼接 不需要加“+”号\n[root@sanchuang-linux ~]# sh group_member.sh sanchuang5\nsanchuang13,sanchuang10,sanchuang12\n--------------------------------------------------------\n[root@sanchuang-linux ~]# cat /etc/passwd\nsanchuang13:x:1034:1200::/home/sanchuang13:/bin/bash\t# 注:gid 位置 $4\n===========================================================================================================\n总结:查看组中有哪些成员\n#shell与awk参数传递:\nhttps://blog.csdn.net/imzoer/article/details/8738581\n[root@sanchuang-linux ~]# cat group_member2.sh\n#!/bin/bash\n\ngroup_name=$1\ngroup_msg=`awk -F: -v group_awk=$group_name '$1==group_awk{print $3,$4}' /etc/group`\ngroup_lst=($group_msg)\t\t\t# 注:awk -v 选项 定义参数,把变量传递给awk\ngroup_id=${group_lst[0]}\t\t# 注:()括起来 把字符变成一个数组,默认以空格分割,获取1,2元素\ngroup_user_1=${group_lst[1]}\ngroup_user_2=`awk -F: -v group_id=$group_id '$4==group_id{print $1}' /etc/passwd| tr \"\\n\" \",\"`\necho $group_user_2$group_user_1\t\t\t\t\t\t# 注:把换行符换成逗号\n[root@sanchuang-linux ~]# sh group_member2.sh sanchuang5\nsanchuang13,sanchuang10,sanchuang12\n\n--------------------------------------------------------------------------------------------\n命令行\n[root@sanchuang-linux ~]# less /etc/group\nsanchuang5:x:1200:sanchuang10,sanchuang12\n[root@sanchuang-linux ~]# awk -F: '$1==\"sanchuang5\"{print $3}' /etc/group\n1200\t\t\t\t\t\t\t\t\t# 注:加引号,表示一个字符串\n[root@sanchuang-linux ~]# awk -F: '$1==\"sanchuang5\"{print $3,$4}' /etc/group\n1200 sanchuang10,sanchuang12\t\t\t# 注:组id\t附属组的成员\n[root@sanchuang-linux ~]# awk -F: '$4==1200{print $1}' /etc/passwd\nsanchuang13\t\t\t\t\t\t\t\t# 注:获取的是 为主要组时 成员的用户名(默认换行分割)\ngroup_user_2=`awk -F: -v group_id=$group_id '$4==group_id{print $1}' /etc/passwd| tr \"\\n\" \",\"`\n#注:把换行符换成逗号\n--------------------------------------------------------------------------------------------\n字符串截取\t\t\t\t# 注:不准确,gid可能5位\n[root@sanchuang-linux ~]# result=`awk -F: '$1==\"sanchuang5\"{print $3,$4}' /etc/group`\n[root@sanchuang-linux ~]# echo ${result:0:4}\n1200\n[root@sanchuang-linux ~]# echo ${result#* }\nsanchuang10,sanchuang12\n[root@sanchuang-linux ~]# echo ${result:5}\nsanchuang10,sanchuang12\n[root@sanchuang-linux ~]# echo ${result%% *}\n1200\n---------------------------\n字符串截取:\n#字符串操作\nline=`head -n1 /etc/passwd`\necho \"字符串为:$line\"\necho '字符串为:$line'\necho \"截取前4个字符:\"\necho ${line:0:4}\necho \"截取后9个字符:\"\necho ${line:0-9}\necho \"从倒数第九个字符开始截取4个字符\"\necho ${line:0-9:4}\necho \"从左向右截取最后一个:后的字符\"\necho ${line##*:}\necho \"从左向右截取第一个:后的字符\"\necho ${line#*:}\necho \"从右向左截取最后一个:后的字符\"\necho ${line%%:*}\necho \"从右向左截取第一个:后的字符\"\necho ${line%:*}\necho \"字符串长度\"\necho ${#line}\n--------------------------------------------------------------------------------------------\nfor循环获取\n[root@sanchuang-linux lianxi]# vim user.sh\nresult=`awk -F: '$1==\"sanchuang5\"{print $3,$4}' /etc/group`\nfor i in $result\ndo\n echo $i\ndone\n[root@sanchuang-linux lianxi]# bash user.sh \n1200\nsanchuang10,sanchuang12\n[root@sanchuang-linux ~]# result=`awk -F: '$1==\"sanchuang5\"{print $3,$4}' /etc/group`\n------------------------------------------------------------\n[root@sanchuang-linux ~]# for i in $result; do echo $i; done\n1200\nsanchuang10,sanchuang12\n```\n\n\n\n---\n\n## 三. group操作\n\n### 3.1 groupadd groupdel\n\n**groupadd命令**\n\n格式:`groupadd [-g GID]\t组帐号名`\n\n**groupdel命令**\n\n格式:`groupdel 组帐号名`\n\n\n\n```bash\n示例:groupadd groupdel\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# groupadd -g 5000 sanle\t# 注:创建gid为5000的sanle组\n[root@sanchuang-linux ~]# less /etc/group\t\t\t#↑注:添加组账号sanle\nsanle:x:5000:\n[root@sanchuang-linux ~]# groupdel sanle\t\t\t# 注:删除组账号sanle\n[root@sanchuang-linux ~]# less /etc/group\t\t\t# 注:没有了\n```\n\n\n\n### 3.2 groupmod newgrp\n\n**groupmod命令**\n\n- 用途:设置组名和组id\n- 格式:`groupmod [选项]...\t组帐号名`\n\n**常用命令选项**\n\n- -n:修改组名\n- -g:修改组id\n\n**newgrp改变有效组**\n\n- 用户必须是要改变组的成员\n\n\n**有效组:(用的很少)**\n\t\t新建文件或者文件夹的时候,使用的gid\n\t\tgid使用哪个组,哪个就是有效组\n\n当前用户新建文件或者文件夹的时候,默认使用的gid对应的组 就是有效组\n\n\n\n```bash\n示例:newgrp改变有效组\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux lianxi]# ll\t\t\t\t# 注:ll查看目录详细信息\n-rw-r--r--. 1 root root 86 9月 25 14:23 abcd.txt\n-rw-r--r--. 1 root root 158 9月 25 09:47 backup_log.sh\n#注:第一个root是文件的 属主\n#注:第二个root是文件的 属组\n---------------------------------------------------\n[root@sanchuang-linux lianxi]# newgrp sanchuang4\n[root@sanchuang-linux lianxi]# touch aa\n[root@sanchuang-linux lianxi]# ll\n-rw-r--r-- 1 root sanchuang4 0 11月 6 11:25 bb\t\t# 注:属组发生改变\n---------------------------------------------------\n[root@sanchuang-linux lianxi]# su - sanchuang10\n[root@sanchuang-linux lianxi]# touch cc\n[sanchuang10@sanchuang-linux ~]$ ll\n总用量 0\n-rw-r--r-- 1 sanchuang10 sanchuang4 0 11月 6 11:27 cc\n[sanchuang10@sanchuang-linux ~]$ newgrp sanchuang\t# 注:普通用户想切换有效组,有效组里面必须有这个普通用户\n密码:\nnewgrp: failed to crypt password with previous salt: 无效的参数\n#注:普通用户想切换有效组,有效组里面必须有这个普通用户\n```\n\n\n\n### 3.3 Linux组帐号\n\n**Linux组帐号**\n\n- 主要组(私有组)\n\n与用户相关的默认组,在/etc/passwd文件的第四个字段定义\n\n- 次要组(附属组)\n\n用户可以同时属于其他的组,在/etc/group文件的第四个字段定义\n\n`用户的主要组的名称和GID相关`\n\n\n\n---\n\n## 四. gpasswd命令\n\n**gpasswd命令**\n\n- 用途:设置组帐号密码(极少用)、添加/删除组成员 \n- 格式:`gpasswd [选项]... 组帐号名`\n\n\n\n```bash\n示例:删除组成员root\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# gpasswd -d root market\n正在将用户“root”从“market”组中删除\n\n示例:设置组账号密码\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# gpasswd sanchuang\n正在修改 sanchuang 组的密码\n新密码:\n请重新输入新密码:\n[root@sanchuang-linux ~]# \n```\n\n\n\n---\n\n## 五. linux加密\n\nLinux加密\n\n默认采用sha512算法\n\n采用哈希算法--》散列值求取\n\n​\t\t把任意长度的输入,映射成固定长度的输出,该输出就是散列值\n\n​\t\t是一种单向加密技术\n\n\nhash算法:md5 sha1 sha2 sha256 sha512\n\n\n**如何判定密码正确?**\n\n\\# 注:把输入的密码用同样的方式进行加密,再判定输入的密文和文件里的密文是否一致\n\n\n\n```python\n示例:md5sum\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# echo \"123456\"|md5sum \t# 注:md5sum也是一种哈希算法\nf447b20a7fcbf53a5d5be013ea0b15af -\t\t\t\t# 注:无论给的是 都会返回特点长度的输出\n[root@sanchuang-linux ~]# echo \"123456xyzzzzz\"|md5sum \t# 注:单向加密的算法\nbcdd6694d1ece311bd7bd668da54b9b9 -\n[root@sanchuang-linux ~]# echo \"xxxxxxxxxxxxxxxxxxxxxxxx\"|md5sum\n7373d8394616d74ba2c42402266ae3aa -\n\n[root@sanchuang-linux tmp]# md5sum douban\t\t# 注:对文件进行加密\n816ba8dd29e68f3450d8748096227d42 douban\t\t# 注:对任意文件的输入,都会有对应长度的输出\n[root@sanchuang-linux tmp]# md5sum sucai8\n9a44802fc09e1b84dc94740c40aa6450 sucai8\n\n示例:撞库 加盐\n--------------------------------------------------------------------------------------------\n#注:撞库\n[root@sanchuang-linux ~]# echo \"123456\"|md5sum\t\t# 注:加密字符串相同,输出的散列值相同\nf447b20a7fcbf53a5d5be013ea0b15af -\n[root@sanchuang-linux ~]# echo \"123456\"|md5sum\nf447b20a7fcbf53a5d5be013ea0b15af -\n#注:加盐\t\t# 注:提高密码安全性\n[root@sanchuang-linux ~]# echo \"123456xndfoaei242\"|md5sum\t# 注:xndfoaei242 盐值\n15465f7aa2929cca95ed7efb97ffeba0 -\n\n示例\n--------------------------------------------------------------------------------------------\nroot:$6$i4J5vzOUIMpchLRj$nTCbYWgA5cpv34Set6R2ZmC1AYYHGHnQafNbA9fkFsTR0E9GG1BJP5o3OTMuC4kGUqsomCI/G8FdEVELI/aeq0::0:99999:7:::\n\n密码字段:$加密算法id$盐值$真正的密文\n加密底层使用内核的crypt函数实现\n\npython实现(sha512)\n>>> import crypt\n>>> crypt.crypt('123456','$6$i4J5vzOUIMpchLRj')\t# 注:$加密算法id$盐值,密文和上面相同\n'$6$i4J5vzOUIMpchLRj$nTCbYWgA5cpv34Set6R2ZmC1AYYHGHnQafNbA9fkFsTR0E9GG1BJP5o3OTMuC4kGUqsomCI/G8FdEVELI/aeq0'\t\t# 注:与上面的密文一样\n-----------------------------------------\n$6 \t\t\t\t\t\t代表sha512算法\n$i4J5vzOUIMpchLRj \t\t盐值\n$nTCbYWgA5cpv……aeq0 \t真正的密文\n\n哈希算法用途:用来判定文件md5值是否改变\n```\n\n\n\n---\n\n## 六. /etc/login.defs文件\n\n**/etc/login.defs文件**\n\n- 对账户初始的属性设置\n- 设置普通用户的UID和GID范围等\n\n\n\n```bash\n示例\n[root@sanchuang-linux ~]# vim /etc/login.defs \nMAIL_DIR /var/spool/mail\t\t# 注:设置默认地址\nPASS_MAX_DAYS 99999\t\t\t\t# 注:密码的过期天数\nPASS_MIN_DAYS 0\nPASS_MIN_LEN 5\nPASS_WARN_AGE 7\nUID_MIN 1000\n```\n\n\n\n---\n\n## 七. useradd命令在后台到底做了哪些工作?\n\n> **useradd命令在后台到底做了哪些工作?**\n>\n> ![image-20220813013242770](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208130132822.png)\n\n\n\n---\n\n## 八. /etc/skel/*文件\n\n**/etc/skel/*文件**\n\n- 新建用户帐号时,复制到用户宿主目录中\n\n**主要控制用户初始配置文件**\n\n- `bash_profile`:\t用户**每次登录**时执行\n- `bashrc`:\t\t\t 每次进入**新的Bash**环境时执行\n- `bash_logout`:\t用户每次**退出登录**时执行\n- `bash_history` : 记录存放**上次注销前**使用的历史命令\n\n*登陆的时候:*\n\t\t.bash_profile\n\t\t~/.bash_profile --> ~/.bashrc --> **/etc/bashrc**\n\n**进入新bash环境**:\n\t\t~/.bashrc --> **/etc/bashrc**\n\n\\--------------------------------------------------------------------------------------------\n\n#注:**登录的时候都会执行 .bash_profile**\n\n#注:登录的时候都会执行 .bashrc\t\t\t# 注:**.bash_profile里面调用了.bashrc**\n\n#注:登录的时候 **先执行.bash_profile,.bash_profile里面调用了.bashrc**\n\n#注:进入了一个**新的bash环境,执行.bashrc**\n\n#注:到**新bash环境下,执行了.bashrc,不执行.bash_profile。登录时执行.bash_profile**\n\n\n\n**用户环境设置**\n\n#注:/etc/bashrc 系统用户的环境设置,别名设置,其他的函数\n\n/etc/bashrc 相当于全局配置,此文件只能root用户修改\t# 注:/etc/bashrc 只有root用户才能修改\n\n~/.bashrc 个人配置,个性化配置,自己家目录下有权限修改\t# 注:家目录下的.bashrc文件\n\n**/etc/profile**\t系统全局用户环境配置\n\n**~/.bash_profile**\t个人配置\n\n\n原因:\n\n全局配置,影响所有用户。\n\n家目录下配置,影响当前用户。\n\n\n\n**/etc/目录下的环境配置修改,属于全局配置,家目录下属于个人用户配置**\n\n\n\n```bash\n示例:家目录下配置\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# less .bash_profile \n# .bash_profile\nif [ -f /etc/bashrc ]; then\t\t# 注:判断有没有 /etc/bashrc,有就在当前执行/etc/bashrc\n . /etc/bashrc\t\t\t# 注:/etc/bashrc 执行初始化的用户环境设置\nfi\t\t\t\t\t\t\t\t# 注:用. 去执行,. 代表当前bash\nPATH=$PATH:$HOME/bin\n\nexport PATH\n\n[root@localhost ~]# less .bashrc \n# .bashrc\nalias rm='rm -i'\nalias cp='cp -i'\nalias mv='mv -i'\nif [ -f /etc/bashrc ]; then\n . /etc/bashrc\t\t\t\t\t# 注:最终执行的是这个文件\nfi\n[root@sanchuang-linux ~]# which ls\t\t# 注:ls执行的是/usr/bin/ls,通过PATH环境变量从前往后找\nalias ls='ls --color=auto'\n\t/usr/bin/ls\n\n============================================================================================\n示例:/etc/skel/*文件\n#注:新建用户帐号时,复制到用户宿主目录中\n[root@sanchuang-linux ~]# cd /etc/skel/\n[root@sanchuang-linux skel]# ls -al\n总用量 24\ndrwxr-xr-x. 2 root root 62 9月 16 13:23 .\ndrwxr-xr-x. 90 root root 8192 11月 6 15:15 ..\n-rw-r--r--. 1 root root 18 11月 9 2019 .bash_logout\n-rw-r--r--. 1 root root 141 11月 9 2019 .bash_profile\n-rw-r--r--. 1 root root 312 11月 9 2019 .bashrc\n\n============================================================================================\n示例:.bash_history 记录存放上次注销前使用的历史命令\n.bash_history 存放当前用户的命令历史,第一次登录用户,操作命令的时候,不会生成此文件\n第一次登陆退出后会自动将内存里的历史记录写到.bash_history文件里\n\n[root@sanchuang-linux ~]# history\t\t\t\t#注:history只是查看当前用户的命令历史\n\n#注:用户退出时,命令历史才会写入.bash_history\n#注:新建用户时,不会生成.bash_history文件,只有退出后 再次登录 才会生成.bash_history文件\n#注:不是所有的命令都写入history,不是很准确\n\n[root@sanchuang-linux ~]# cat .bash_history \t# 注:在当前用户的家目录下查看.bash_history文件\n```\n\n\n\n---\n\n## 九. 每次登录或退出sanchuang的时候,打印日志到/tmp/sanchuang_log\n\n**每次登录或退出sanchuang的时候,打印日志到/tmp/sanchuang_log**\n\n```bash\n步骤\n1.在sanchuang用户下,修改.bash_profile文件,添加\t\t# 注:因为每次登陆都会先执行这个文件\nnow_date=`date`\necho $now_date\"login...\" >> /tmp/sanchuang_log\n2.在sanchuang用户下,修改.bash_logout文件,添加\t\t\t# 注:因为每次退出时都会执行这个文件\nnow_date=`date`\necho $now_date\"logout...\" >> /tmp/sanchuang_log\n3.监控文件变化,新增末尾行\t\t\t\t\t\t\t\t# 注:经常用 tail -f 监控文件\n$ tail -f /tmp/sanchuang_log\t# 注:tail -f监控文件末尾的变化(新增的末尾行)\n```\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux log]# su - sanchuang\t\t\t\t\t# 注:普通用户 在自己的家目录下操作\n上一次登录:五 11月 6 14:59:23 CST 2020pts/1 上\n[sanchuang@sanchuang-linux ~]$ vim ~/.bash_profile \t\t\t# 注:家目录下的.bash_profile操作\nnow_date=`date`\necho $now_date\"login...\" >> /tmp/sanchuang_log\n[sanchuang@sanchuang-linux ~]$ tail -f /tmp/sanchuang_log\t# 注:tail -f监控文件末尾的变化\n2020年 11月 06日 星期五 15:05:26 CSTlogin...\n[sanchuang@sanchuang-linux ~]$ vim ~/.bash_logout \nnow_date=`date`\necho $now_date\"logout...\" >> /tmp/sanchuang_log\n[sanchuang@sanchuang-linux ~]$ tail -f /tmp/sanchuang_log\t# 注:tail -f监控文件末尾的变化\n2020年 11月 06日 星期五 15:05:26 CSTlogin...\n2020年 11月 06日 星期五 15:07:33 CSTlogout...\n```\n\n\n\n---\n\n## 十. Shell启动配置文件的区别\n\n**Shell启动配置文件的区别**\n\n- **/etc/profile**:\t\t 配置全局环境变量,影响所有用户\n- **~/.bash_profile** :\t 配置个人环境,影响一个用户\n- **/etc/bashrc** :\t 配置全局的别名或者shell选项,影响所有用户\n- **~/.bashrc **:\t\t 配置个人别名或者shell选项,影响一个用户\n\n\n\n---\n\n## 十一. .bash_history\n\n**.bash_history** \n\n存放当前用户的命令历史,第一次登录用户,操作命令的时候,不会生成此文件\n\n第一次登陆退出后会自动将内存里的历史记录写到.bash_history文件里\n\n\n\n---\n\n## 十二. bash的启动脚本初始化\n\n> **bash的启动脚本初始化**\n>\n> ![image-20220813014441823](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208130144863.png)\n>\n> ![image-20220813014453858](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202208130144897.png)\n\n\n\n---\n\n## 十三. 用户和组账户查询\n\n**用户和组账户查询**\n\n**id命令**\n\n- 用途:查询用户身份标识 \n- 格式:id [用户名]\n\n**who、w、users命令**\n\n- 用途:查询已登录到主机的用户信息\n\n**groups命令**\n\n- 用途:查询用户所属的组\t\t# 注:返回用户所属的 基本组和附加组\n\n**last、lastlog命令使用**\n\n\n\n```bash\n示例:w who\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# w\t\t# 注:看的是你以哪个用户登录进来,而不是当前你切换到的用户\n 15:26:24 up 6:11, 6 users, load average: 0.00, 0.01, 0.05\nUSER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\nroot tty1 - 四15 58:07 0.07s 0.07s -bash\t\t# 注:tty真实终端\nroot pts/0 192.168.0.42 14:28 0.00s 0.18s 0.01s w\t\t # 注:远程登录pts虚拟终端\nroot pts/1 192.168.0.42 14:28 12:24 0.07s 0.01s -bash\n#注:真实终端FORM为空\n#注:虚拟终端显示的是物理机的ip地址\n#注:WHAT当前环境做的事情\n#注:15:26:24 当前时间\n#注:6:11\t\t开机总时间\n#注:6 users\t登录用户数量\n#注:load average\t cpu平均负载,数值越大,机器越繁忙\n--------------------------------------------------------------\n[root@sanchuang-linux ~]# who\t\t\t# 注:看的没有w详细\nroot tty1 2020-11-05 15:13\nroot pts/0 2020-11-06 14:28 (192.168.0.42)\nroot pts/1 2020-11-06 14:28 (192.168.0.42)\n------------------------------------------------------------------\n[root@sanchuang-linux ~]# users\t\t\t# 注:查看当前有哪些用户登录\nroot root root root root root\n---------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# groups sanchuang10\t# 注:显示用户所属的基本组和附加组\nsanchuang10 : sanchuang4 sanchuang5\n[root@sanchuang-linux ~]# id sanchuang10\nuid=1032(sanchuang10) gid=1100(sanchuang4) 组=1100(sanchuang4),1200(sanchuang5)\n--------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# last\t\t# 注:查看之前有哪些用户登录过\nroot tty1 Wed Sep 16 13:41 - 13:41 (00:00)\nroot pts/0 192.168.136.1 Wed Sep 16 13:29 - 13:40 (00:11)\nreboot system boot 4.18.0-193.el8.x Wed Sep 16 13:26 - 13:42 (00:15)\n[root@sanchuang-linux ~]# lastlog \t# 注:查看每一个用户的最近登录状态\n用户名 端口 来自 最后登陆时间\nroot pts/0 五 11月 6 15:18:46 +0800 2020\nbin **从未登录过**\nshutdown **从未登录过**\n```\n\n\n\n---\n\n## 十四. 终端设备名称\n\n**终端设备名称**\n\n​\t\t名称\t\t\t 设备\n\n​\t\t**ttyn\t\t\t 虚拟控制台**\n\n​\t\t**pts/n\t\t 伪终端**\n\n​\t\t**:0\t\t\t X服务器**\n\n\n\n---","tags":["Linux","用户与组"],"categories":["Linux"]},{"title":"14_Linux基础-用户与组1","url":"/posts/10588.html","content":"## 一. 练习\n\n```bash\n示例1\n---------------------------------------------------------------------------------------------------------------------------------\nmenu(){\n echo \"1、监控内存使用情况,如果内存使用率大于百分之80,给予提醒\"\n echo \"2、扫描局域网ip,检查哪些ip地址正在使用\"\n echo \"3、监控文件/etc/passwd是否被修改,每隔5分钟监控一次\"\n echo \"4、监控nginx进程是否存在,不存在就给予相应提醒\"\n}\n\noption_1(){\n total=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f2`\n #free=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f4`\n used=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f3`\n used_rate=`echo \"scale=4;$used/$total\" |bc`\n #used_1=`echo \"$total*0.8\"|bc `\n result=` echo \"$used_rate>0.8\"|bc `\n #echo $result\n if (( $result == 1 ))\n then\n echo -e \"\\e[31m使用率超过80%,请及时对内存扩容,以免不必要的损失\\e[0m\"\n else\n echo \" nothing to do\"\n fi\n}\n\noption_2(){\n for ip in `seq 255`\n do\n ( ip_full=192.168.0.$ip\n ping -c 1 $ip_full &>/dev/null && echo $ip_full >>up.txt || echo $ip_full >>down.txt\n ) & # 注:放到后台子进程执行\n done\nwait # 父进程等待子进程执行完成之后再退出\n}\n\noption_3(){\n check_num=`diff /etc/passwd /lianxi/passwd |wc -l`\n [[ check_num -eq 0 ]] && echo \"文件未被修改\" || echo \"文件已被修改\"\n}\n\noption_4(){\n pidof nginx && echo \"nginx is running\" || echo \"nginx is down\"\n}\n\nmenu\nread -p \"请输入你的选择:\" option\ncase $option in\n1)\n option_1\n ;;\n2)\n option_2\n ;;\n3)\n option_3\n ;;\n4)\n option_4\n ;;\n*)\n echo \"请输入1-4\"\nesac\n示例2:重复选择\n--------------------------------------------------------------------------------------------\n重复选择\nwhile : \ndo\ndone\n\necho \"#########################\"\necho \"1.查看内存使用率\"\necho \"2.扫描局域网ip\"\necho \"3.查看文件是否被修改\"\necho \"4.查看nginx进程\"\necho \"5.退出\"\necho \"#########################\"\n\nwhile : \ndo\n\tread -p \"请输入你的选择:\" options\n\tcase $options in\n\t1)\n\t/root/shell/mem.sh\n\t;;\n\t2)\n\t/root/shell/scan_ip.sh\n\t;;\n\t3)\n\t/root/shell/passwd_test.sh\n\t;;\n\t4)\n\t/root/shell/ngnix_test.sh\n\t;;\n\t5)\n\techo \"退出\"\n\texit\n\t;;\n\t*)\n\techo \"1-4\"\n\tesac\ndone\n--------------------------------------------------------------------------------------------\n示例3:使用awk获取\ncase $options in\n\n1)\n\tmemory_monitor(){\n\t\ttotal=`free -m |grep Mem |awk '{print $2}'`\n\t\tused=`free -m |grep Mem |awk '{print $3}'`\n\t\tuse_rate=`echo \"scale=2;$used/$total\" |bc`\n\t\tresult=`echo \"$use_rate>0.8\" |bc`\n\t\tif(( $result == 1 ))\n\t\tthen\n\t\t\techo \"内存使用率大于80%!!!\"\n\t\telse\n\t\t\techo \"内存使用状态良好!\"\n\t\tfi\n\t}\n\tmemory_monitor\n\t;;\n```\n\n\n\n---\n\n## 二. user group 用户与组\n\n### 2.1 常见命令\n\nid 查看\nuseradd 创建\nuserdel 删除\npasswd 创建用户密码\nsu 切换用户\n**usermod 更改用户信息**\n\n\n\n### 2.2 为什么要引入这个用户和组?\n\n> 1、安全性\n>\n> 2、权限管理\n>\n> 3、资源管控\n>\n> \n>\n> 对文件的访问,读写可以管控\n>\n> 对进程的管理 --> 谁可以管理\n\n\n\n### 2.3 用户和组\n\n> 每个用户有一个唯一的UID\n> 每个组也有一个唯一的GID\n>\n> 一个用户可以属于不同组\n> 一个组可以有不同用户\t\t\t\t\t\t# 注:多对多的关系\n>\n> 用户和组 --> 权限资源管控\n> 用户加入组,就可以有这个组的权限\n> 默认情况下,创建用户,会添加一个和用户同名的组\n>\n> \n\n```bash\n[root@sanchuang-linux ~]# id chenpeng\t\t\t# 注:id查看用户和组信息\nuid=1030(chenpeng) gid=1030(chenpeng) 组=1030(chenpeng)\t\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# useradd sanchuang\n[root@localhost ~]# id sanchuang\nuid=1000(sanchuang) gid=1000(sanchuang) 组=1000(sanchuang)\n[root@localhost ~]# less /etc/passwd\n[root@localhost ~]# less /home/sanchuang/\n[root@localhost ~]# passwd sanchuang\n更改用户 sanchuang 的密码 。\n新的 密码:\n无效的密码: 密码少于 8 个字符\n重新输入新的 密码:\npasswd:所有的身份验证令牌已经成功更新。\n[sanchuang@localhost ~]$ \t\t# 注:登录后默认位置为用户家目录(使用用户sanchuang登录)\n[root@localhost ~]# less /etc/shadow\t\t\t# 注:shadow存放的是用户的密码信息\n[root@localhost ~]# less /etc/shadow\nshadow shadow- \n[root@localhost ~]# less /etc/passwd\npasswd passwd- \n[root@localhost ~]# diff /etc/passwd /etc/passwd-\t# 注:passwd-备份文件,每次都会少一个最新的操作\n21d20\t\t\t\t\t\t\t\t\t\t\t\t# 注:可以回滚上一个版本\n< sanchuang:x:1000:1000::/home/sanchuang:/bin/bash\n[root@localhost ~]# diff /etc/shadow /etc/shadow-\t# 注:shadowd-备份文件,每次都会少一个最新的操作\n21d20\t\t\t\t\t\t\t\t\t\t\t\t# 注:可以回滚上一个版本\n< sanchuang:$6$dKQsah/D$6sm6owwvDEnVs8BclDWQZ7meYSaMf5Y7AofxzxwxO0PPrvzqHHVCer1G656iY2gE.sUOarUl9beKi2usYdATQ1:18571:0:99999:7:::\n[root@localhost ~]# less /etc/group\t\t\t\t\t# 注:存放组信息\n[root@localhost ~]# less /etc/gshadow\t\t\t\t# 注:存放组密码信息\n\n[root@localhost ~]# cd /home/sanchuang/\t\t\t\t# 注:新建用户,有三个隐藏文件\n[root@localhost sanchuang]# ls\n[root@localhost sanchuang]# ls -al\t\t# 注:新建用户帐号时,从 /etc/skel 目录中复制而来\n总用量 12\ndrwx------. 2 sanchuang sanchuang 62 11月 5 10:25 .\ndrwxr-xr-x. 3 root root 23 11月 5 10:25 ..\n-rw-r--r--. 1 sanchuang sanchuang 18 4月 1 2020 .bash_logout\n-rw-r--r--. 1 sanchuang sanchuang 193 4月 1 2020 .bash_profile\n-rw-r--r--. 1 sanchuang sanchuang 231 4月 1 2020 .bashrc\n[root@localhost sanchuang]# cd /etc/skel/\t\t\t# 注:模板,拷贝一份过去\n[root@localhost skel]# ls -al\n总用量 24\ndrwxr-xr-x. 2 root root 62 10月 6 16:33 .\ndrwxr-xr-x. 77 root root 8192 11月 5 10:27 ..\n-rw-r--r--. 1 root root 18 4月 1 2020 .bash_logout\n-rw-r--r--. 1 root root 193 4月 1 2020 .bash_profile\n-rw-r--r--. 1 root root 231 4月 1 2020 .bashrc\n\n\n[root@localhost skel]# less /etc/login.defs\t\t# 注:关于账户的设置信息\n# Min/max values for automatic uid selection in useradd\n#\nUID_MIN 1000\t\t\t\t\t# 注:最多可以创建59000个用户\nUID_MAX 60000\n# System accounts\nSYS_UID_MIN 201\nSYS_UID_MAX 999\nCREATE_HOME yes\t\t\t\t\t\t\t\t\t# 注:创建家目录\nENCRYPT_METHOD SHA512\t\t\t\t\t\t\t\t# 注:指定用什么方式加密用户密码\n\n\n[root@localhost skel]# ls /etc/group\t\t\t\t# 注:组也有备份文件\ngroup group- \n[root@localhost skel]# ls /etc/gshadow\ngshadow gshadow- \n\n[root@localhost spool]# cd /var/spool/mail/\t\t\t# 注:邮件目录\n[root@localhost mail]# ls\t\t\t\t\t\t\t# 注:/var/spool/mail/ 下创建一个同名的文件\nsanchuang\n\n[sanchuang@localhost ~]$ less /etc/shadow\t\t\t# 注:普通用户没有权限查看 /etc/shadow存放密码信息\n/etc/shadow: 权限不够\t\t\t\t\t\t\t\t # 注:只有root用户可读\n```\n\n\n\n### 2.4 用户创建牵扯到哪些文件\n\n**账户信息相关文件**\n\n- /etc/passwd --> 存放用户相关信息的\n- /etc/shadow --> 存放用户密码\n \n- /etc/passwd- 和 /etc/shadow- 这是/etc/passwd 和 /etc/shadow的备份文件,总是比原文件少一次操作\n\n\n\n**组相关文件**\n\n- /etc/group --> 存放组信息的\n\n- /etc/gshadow --> 存放组密码的\n \n- /etc/group- 和 /etc/gshadow- 备份文件\n\n\n\n**用户环境默认设置**\n\n- 创建用户时,会拷贝/etc/skel/下的文件到用户的家目录\n\n\n\n**用户的家目录**\n\n- 默认情况下会在/home目录下创建一个同名文件夹\n\n\n\n**用户默认属性设置文件**\n\n- /etc/login.defs\n\n\n\n**邮件目录**\n\n- /var/spool/mail/ 下创建一个同名的文件\n\n\n\n### 2.5 /etc/passwd 文件详解\n\n```bash\n[root@localhost mail]# cat /etc/passwd\nroot:x:0:0:root:/root:/bin/bash\nbin:x:1:1:bin:/bin:/sbin/nologin\nsanchuang:x:1000:1000::/home/sanchuang:/bin/bash\n·使用:分隔\n·字段1:用户名\n·字段2:密码占位符,通常为“x”或者“*”(因为这个文件谁都可读,所以真正的密码存放在/etc/shadow)\n·字段3:用户id\t\t\t\t\t\t\t# 注:-u指定\n·字段4:用户所属基本组id\t\t\t\t\t # 注:-g指定基本组\n·字段5:用户描述信息\t\t\t\t\t\t # 注:新建用户没有 没有设置一般没有 (-c选项)\n·字段6:家目录\t\t\t\t\t\t\t# 注:家目录的绝对路径\t\t\t(-d选项)\n·字段7:登录shell的信息\n```\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# ls -ld /etc/shadow\n----------. 1 root root 2330 11月 5 20:51 /etc/shadow\t\t# 注:普通用户/组 无法读取执行\n[root@localhost ~]# ls -ld /etc/passwd\n-rw-r--r--. 1 root root 2006 11月 5 20:51 /etc/passwd\n\n#注:通过yum安装的 配置文件一般放在/etc 下\n```\n\n\n\n### 2.6 练习:找出系统中uid大于1000的用户,显示出它的名字,UID,家目录,shell\n\n**找出系统中uid大于1000的用户,显示出它的名字,UID,家目录,shell**\n\n```bash\n[root@sanchuang-linux ~]# awk -F: '$3>1000{print $1,$3,$6,$7}' /etc/passwd\nchenpeng 1030 /home/chenpeng /bin/bash\n\n#注:使用cat和直接使用awk消耗内存差不多\n#注:语法:awk 选项 ‘模式+动作’ 文件\t\t# 注:不接模式的话 全文截取\n```\n\n\n\n### 2.7 练习:找出/etc/passwd中有几种shell信息\n\n**找出/etc/passwd中有几种shell信息**\n\n\n\n### 2.8 useradd详解\n\n```bash\nShell设置\n[root@sanchuang-linux ~]# awk -F: '{print $7}' /etc/passwd |sort|uniq\t\t# 注:排序去重\n/bin/bash\t\t# 注:系统默认用户的shell环境信息 --> 正常使用的shell\n/bin/sync\t\t# 注:将内存里的缓存刷新到磁盘 --> 类似于Python中fp.flush()\n/sbin/halt\t\t# 注:登陆就关机\n/sbin/nologin\t# 注:用户不能登录(不允许登录)\n/sbin/shutdown\t# 注:登陆就关机\n```\n\n\n\n```bash\n--------------------------------------------------------------------------------------------\n#注:关机至强最会执行以下sync,将内存里的缓存刷新到磁盘\n[root@localhost ~]# sync\n--------------------------------------------------------------------------------------------\n#注:使用which命令查看命令的绝对路径\n[root@localhost ~]# which sync\n/usr/bin/sync\n敲sync会按照PATH变量的路径下向下找下去\n执行一个/bin/bash 就会到我们现在的终端环境了\n```\n\n\n\n---\n\n## 三. 用户和组的关系\n\n- 每个账户有一个唯一的UID\n\n- 每个组也有一个唯一的GID\n\n- 多个账户可以属于同一个组\n\n<img src=\"https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220812074315487.png\" alt=\"image-20220812074315487\" style=\"zoom:80%;\" />\n\n\n\n---\n\n## 四. 用户和组的相关文件\n\n**和账户相关文件**\n\n- /etc/passwd、/etc/shadow\n\n\n\n**和组相关文件**\n\n- /etc/group、/etc/gshadow\n\n\n\n**账户宿主目录中文件来源**\n\n- 新建用户帐号时,从 `/etc/skel` 目录中复制而来\t\t\t# 注:**初始化用户家目录**\n\n\n\n**默认账户的属性文件**\n\n- /etc/login.defs\n\n\n\n**用于保存用户的帐号基本信息**\n\n- 文件位置:`/etc/passwd`\n- 每一行对应一个用户的帐号记录\n \n- 字段1:用户帐号的名称\n- 字段2:用户密码字串或者密码占位符“`x`”\n- 字段3:用户帐号的UID号\n- 字段4:所属基本组帐号的GID号\n- 字段5:用户描述信息\n- 字段6:家目录\n- 字段7:登录Shell信息\n\n\n\n---\n\n## 五. 用户和组的相关文件\n\n**用户账户:**\n\n- 超级用户`root`\n- 程序用户\n- 普通用户\n\n**UID (User Identity,用户标识号)**\n\n- 超级用户root的UID为`0`\n- 程序用户的UID`1-999`\n- 普通用户的UID大于等于`1000`\n\n\n\n---\n\n## 六. 添加与删除用户\n\n**useradd命令**\n\n- 格式:`useradd\t[选项]...\t用户名`\n\n\n\n**常用命令选项**\n\n- `-u:指定 UID 标记号`\n- `-d`:指定宿主目录,缺省为 `/home/用户名`\n- `-e`:指定帐号失效时间\n- `-g`:指定用户的基本组名(或GID号)\n- `-G`:指定用户的附加组名(或GID号)\n- -M:不为用户建立并初始化宿主目录\n- `-s`:指定用户的登录Shell\n- -c:用户注释描述信息\n- -r:\t新建系统用户,不会有新建家目录\n\n\n\n#注:每次新建用户,uid都会在上一个用户uid基础上+1\n#注:默认新建用户从1001开始\n\n\n\n**Shell设置**\n\n```bash\n/bin/bash\t\t\t# 注:系统默认用户的shell环境信息 --> 正常使用的shell\n/bin/sync\t\t\t# 注:将内存里的缓存刷新到磁盘 --> 类似于Python中fp.flush()\n/sbin/halt\t\t\t# 注:登陆就关机\n/sbin/nologin\t\t# 注:用户不能登录,ssh和su都不能登陆\n/sbin/shutdown\t\t# 注:登陆就关机\n```\n\n\n\n```bash\n示例:-s /sbin/nologin\n--------------------------------------------------------------------------------------------\n#注:本机用来跑服务的,不能登录\n[root@localhost mail]# useradd -s /sbin/nologin sanchuang2\n[root@localhost mail]# echo 123456|passwd sanchuang2 --stdin\n更改用户 sanchuang2 的密码 。\npasswd:所有的身份验证令牌已经成功更新。\n[root@localhost mail]# ssh sanchuang2@192.168.136.136\t#注:ssh 登录本机sanchuang2\n……………………………………\nAre you sure you want to continue connecting (yes/no)? yes\nWarning: Permanently added '192.168.136.136' (ECDSA) to the list of known hosts.\nsanchuang2@192.168.136.136's password: \nThis account is currently not available.\t# 注:提示用户不可达,因为sanchuang2的Shell是nologin,不能直接登录\nConnection to 192.168.136.136 closed.\n[root@localhost ~]# su - sanchuang2\t\t\t# 注:不能切换\n上一次登录:四 11月 5 11:49:14 CST 2020从 192.168.136.136pts/2 上\nThis account is currently not available.\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# usermod -s /bin/bash sanchuang2\t\t# 注:usermod -s 更改用户的shell信息\n[root@localhost ~]# cat /etc/passwd|grep sanchuang2\nsanchuang2:x:1001:1001::/home/sanchuang2:/bin/bash\n```\n\n\n\n### 练习:显示出系统中uid大于1000并且用户名包含sanchuang的用户信息(用户名,用户Id,用户家目录)\n\n**显示出系统中uid大于1000并且用户名包含sanchuang的用户信息(用户名,用户Id,用户家目录)**\n\n```bash\n[root@localhost ~]# awk -F: '$3>1000{print $1,$3,$6}' /etc/passwd\nsanchuang2 1001 /home/sanchuang2\n方法1\n[root@localhost ~]# awk -F: '$3>1000{print $1,$3,$6}' /etc/passwd |grep sanchuang\nsanchuang2 1001 /home/sanchuang2\n方法2\n[root@localhost ~]# awk -F: '$3>1000 && $1 ~ /sanchuang/{print $1,$3,$6}' /etc/passwd\nsanchuang2 1001 /home/sanchuang2\t\t\t# 注:$1 ~ /sanchuang/ 匹配sanchuang\n```\n\n\n\n---\n\n## 七. 进程\n\n> 进程:正在运行中的程序\n>\n> 程序:代码集合,放在磁盘上的\n>\n> \n>\n> 进程是计算机进行资源分配的基本单位\n>\n> 进程的组成核心:进程控制块(PCB)\n>\n> PCB一般包括\n>\n> 1、pid\t进程唯一标识符\n>\n> 2、有效用户信息 -euid,egid(通常情况下就是uid,gid)\t\t\t# 注:就是进程属于哪个用户\n>\n> 3、程序的状态\n>\n> 4、程序的优先级\n>\n> 5、程序的上下文\n\n\n\n---\n\n## 八. Python中使用os模块查看当前进程的用户信息\n\n**Python中使用os模块查看当前进程的用户信息**\n\n```python\n>>> import os\n>>> os.geteuid()\t\t\t\t\t# 注:获取当前进程用户的用户uid信息\n0\t\t\t\t\t\t\t\t\t# 注:为0的都是root用户 root用户的uid\n>>> os.getuid()\t\t\t\t\t\t# 注:通常情况下,uid和euid都是一样的\n0\n--------------------------------------------------------------------------------------------\n普通用户导入 os模块\n[sanchuang2@localhost ~]$ python3\n>>> import os\n>>> os.geteuid()\n1001\n>>> os.getuid()\n1001\n[sanchuang2@localhost ~]$ id sanchuang2\nuid=1001(sanchuang2) gid=1001(sanchuang2) 组=1001(sanchuang2)\n```\n\n\n\n---\n\n## 九. ftp协议(文件传输协议)\n\n### 9.1\n\n> vsftpd服务与本地用户\n>\n> ftp的服务 做文件传输的,上传或下载一个文件到指定的地方\n>\n> ftp是一个文件传输服务,主要用于上传和下载文件,实现文件共享\n>\n> \n>\n> 匿名用户和本地用户都可以登录ftp服务,它们登录进去之后只能操作家目录下的文件或者文件夹\n>\n> 三种用户:\n>\n> 1、匿名用户\n>\n> 2、本地用户\t\t\t\t# 注:ftp传输可以使用linux本地用户;ssh登录也可以用本地用户\n>\n> 3、虚拟用户\n>\n> \n\n```bash\n============================================================================================\n1、服务安装\n[root@sanchuang-linux ~]# yum install vsftpd\n--------------------------------------------------------------------------------------------\n2、启动服务\n[root@sanchuang-linux ~]# service vsftpd restart\nRedirecting to /bin/systemctl restart vsftpd.service\n[root@sanchuang-linux ~]# ps -ef |grep vsftp\t\t\t# 注:默认root用户启动\nroot 3377 1 0 14:51 ? 00:00:00 /usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf\nroot 3379 3184 0 14:52 pts/1 00:00:00 grep --color=auto vsftp\n--------------------------------------------------------------------------------------------\n3、安装客户端\n#注:centos8里vsftpd服务默认不允许匿名用户登录\n\t使用匿名用户(ftp)登录的话,修改/etc/vsftpd/vsftpd.conf里的配置 anonymous_enable=YES\n#注:修改完配置文件重启vsftpd服务\n\n登录上去之后,默认读取系统中ftp这个用户的家目录文件\n-----------------------------------------------------\n[root@sanchuang-linux ~]# yum install lftp -y\t\t\t# 注:lftp是vsftpd的客户端\n[root@sanchuang-linux ~]# yum install ftp\t-y\t\t\t# 注:ftp也是vsftpd的客户端\n#注:这两个都是ftp的客户端\n============================================================================================\n[root@sanchuang-linux ~]# lftp ftp@192.168.0.27\t\t# 注:以ftp用户去登录程序\n密码: \t\t\t\t\t\t\t\t\t\t\t # 注:ftp是默认用户\n[root@localhost ~]# ftp 192.168.136.136\t\t\t\t# 注:登录ftp服务\n………………………………\nName (192.168.136.136:root): ftp\t\t\t\t\t# 注:匿名用户ftp登录\n331 Please specify the password.\nPassword:\t\t\t\t\t\t\t\t\t\t\t# 注:回车\n230 Login successful.\n………………………………\nftp> \n============================================================================================\n[root@sanchuang-linux ~]# cat /etc/passwd\nftp:x:14:50:FTP User:/var/ftp:/sbin/nologin\t\t\t# 注:vsftpd的匿名用户,公共用户\n#注:/var/ftp ftp这个用户的家目录文件\n============================================================================================\n[root@sanchuang-linux ~]# vim /etc/vsftpd/vsftpd.conf \t# 注:Centos8中开启匿名用户允许登录\nanonymous_enable=YES\t\t\t\t\t\t\t\t\t# 注:centos7不用设置\n#注:修改完配置文件重启vsftpd服务\n============================================================================================\n登录上去之后,默认读取系统中ftp这个用户的家目录文件\n/var/ftp\n-----------------------------------------------------\n[root@localhost ~]# cd /var/ftp/\n[root@localhost ftp]# ls\npub\n[root@localhost ftp]# cd pub\n[root@localhost pub]# ls\t\t\t\t\t# 注:/var/ftp/pub/下为空\n[root@localhost pub]# touch aa bb\t\t\t# 注:创建文件aa bb\n--------------------------------------------------------------------------------------------\nftp> ls\t\t\t\t\t\t\t\t\t\t# 注:当前路径 /var/ftp\n…………………………\ndrwxr-xr-x 2 0 0 26 Nov 05 07:20 pub\nftp> cd pub\n…………………………\nftp> ls\t\t\t\t\t\t\t\t\t\t# 注:显示出文件aa bb\n…………………………\n-rw-r--r-- 1 0 0 0 Nov 05 07:20 aa\n-rw-r--r-- 1 0 0 0 Nov 05 07:20 bb\n226 Directory send OK.\n--------------------------------------------------------------------------------------------\nftp> get aa\t\t\t\t\t\t\t\t\t# 注:下载文件\nlocal: aa remote: aa\n…………………………\nftp> !ls\t\t\t\t\t\t\t\t\t# 注:查看当前所在系统命令有哪些文件\naa\t addstr.py\nftp> !pwd\t\t\t\t\t\t\t\t\t# 注:查看当前所在系统命令路径\n/root\n#注:匿名用户不能上传\n============================================================================================\n[root@localhost ~]# ftp 192.168.136.136\nName (192.168.136.136:root): sanchuang\t\t# 注:本地用户sanchuang登录\nPassword:\n230 Login successful.\t\t\t\t\t\t# 注:230 代表登录成功\n--------------------------------------------------------------------------------------------\nftp> put first.py \t\t\t\t\t\t\t# 注:上传文件\nlocal: first.py remote: first.py\t\t\t# 注:匿名用户不能上传\n…………………………\n1097 bytes sent in 0.0157 secs (69.83 Kbytes/sec)\nftp> ls\n…………………………\n-rw-r--r-- 1 1000 1000 1097 Nov 05 07:34 first.py\n226 Directory send OK.\n============================================================================================\n[root@localhost pub]# less /etc/services \t\t# 注:# less /etc/services 查看默认端口号\nftp 21/tcp\t\t\t\t\t\t\t# 注:ftp服务默认是21号端口\nftp 21/udp fsp fspd\n```\n\n\n\n### 9.2 匿名用户和本地用户都可以登录ftp服务,它们登录进去之后只能操作家目录下的文件或者文件夹\n\n**匿名用户和本地用户都可以登录ftp服务,它们登录进去之后只能操作家目录下的文件或者文件夹**\n\n**三种用户:**\n1、**匿名用户**\t# 注:匿名用户 ftp ; 无需密码 ; 家目录 /var/ftp ; ftp也是系统的本地用户,系统自动创建ftp用户,nologin,可以通过ftp登录\n2、**本地用户**\t# 注:就是linux系统上的用户 ; ftp登录之后在本地用户家目录下\n3、**虚拟用户**\t# 注:建立出一个虚拟的用户,映射到本地用户\n\n#注:/etc/passwd 第6个字段 是用户的家目录\n#注:看用户的家目录 看/etc/passwd文件\n\n\n\n### 9.3 ftp常用命令\n\n**ftp常用命令**\n\n> ftp常用命令:\n> 上传文件:**put**\t\t\t\t# 注:匿名用户不能上传\n> 下载文件:**get**\n> 查看:**ls**\n> 切换路径:**cd**\n\n\n\n### 9.4* ftp的2种工作模式\n\n**ftp的2种工作模式**(面试)\n\n**问的时候:总结(要提到端口号)**\n\n主动模式和被动模式都会开启21号端口进行连接\n\n区别是数据连接的方式\n\n主动模式:服务器主动开启20号端口去和客户机主动建立数据连接,传输数据\n\n被动模式:客户机拿到随机开放端口后向服务器进行一个数据传输,客户端向这个随机端口去建立连接,进行数据传输\n\n> **一**、**主动模式**(**默认**情况下是主动模式)\n>\n> 1、客户端登录时请求ftp服务器 命令连接端口(21号端口)\n>\n> 2、21号端口返回信息登录成功或者登录失败\n>\n> 3、登录成功后客户端请求传输数据(对21号端口发起一个请求),开启一个随机端口\n>\n> 4、服务器主动开启它的20号端口去把它的数据传递给客户端的随机端口\n>\n> 服务器主动开启20号端口,向客户机主动发送数据\n>\n> \n>\n> **二**、**被动模式**\n>\n> 1、客户端登录时请求ftp服务器 开启 命令连接端口(21号端口)\n>\n> \\#注:21号端口都是用来做命令连接的\n>\n> 2、21号端口返回信息登录成功或者登录失败\n>\n> 3、客户机请求数据传输(客户机向服务器请求数据传输时,向服务器发送一个pasv命令,告诉服务器端要以被动模式取接收命令。这时服务器端就开放一个端口,可以指定范围,返回给客户机,把这个端口号返回给客户端)\n>\n> 4、收到服务器开放端口号\n>\n> 5、开始连接服务器端口,进行数据传输(和5555号端口建立连接)\n>\n> 假设开放的是5555,服务器就会把5555端口起来,端口处于监听状态,别人就可以连接过来,就可以和这个主机建立连接,就可以通过5555号端口传递数据\n>\n> \\#注:被动模式需要配置,默认主动模式\n> \n>\n>\n> 无论主动模式,还是被动模式,21号端口都必须起来\n>\n> 主动模式20号端口起来,被动模式20号端口不一定起来\n> \n>\n>\n> \\#注:数据请求和命令请求不是同一个端口的\n>\n> ![image-20220812080812262](https://dlvr.cpen.top/gh/mycpen/image_bed/image/image-20220812080812262.png)\n\n\n\n---\n\n## 十. usermod userdel\n\n### usermod\n\n**usermod命令**\n\n格式:`usermod\t[选项]...\t用户名`\n\n**常用命令选项**\n\n- -l:更改用户帐号的登录名称\n- -L:锁定用户账户\n- -U:解锁用户账户\n- 以下选项与useradd命令中的含义相同\n\n​\t\t\t-u、-d、-e、-g、-G、-s\n\n\n\n### userdel\n\n**userdel命令**\n\n- 格式:`userdel [-r] 用户名 `\n- **添加 -r 选项时,表示连用户的宿主目录一并删除**\t\t# 注:**建议接上**\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# useradd stu01 \n[root@localhost ~]# ls -ld /home/stu01/\ndrwx------ 2 stu01 stu01 4096 09-09 12:38 /home/stu01/ \n[root@localhost ~]# userdel -r stu01\t\t\t\t# 注:删除用户帐号stu01\n[root@localhost ~]# ls -ld /home/stu01/ \nls: /home/stu01/: 没有那个文件或目录\n```\n\n\n\n---\n\n## 十一. useradd\n\n**useradd命令**\n\n- 格式:`useradd\t[选项]...\t用户名`\n\n**常用命令选项**\n\n- `-u:指定 UID 标记号`\n- `-d`:指定宿主目录,缺省为 `/home/用户名`\n- `-e`:指定帐号失效时间\n- `-g`:指定用户的基本组名(或GID号)\t\t# 注:基本组只能有一个\n- `-G`:指定用户的附加组名(或GID号)\t# 注:附加组可以用很多个 无论基本组/附加组 用户都可以获得所有权限\n- -M:不为用户建立并初始化宿主目录\n- `-s`:指定用户的登录Shell\n- -c:用户注释描述信息\n- -r: 新建系统用户,不会有新建家目录\n\n\n\n---\n\n## 十二. 用户\n\n### 12.1\n\n**用户账户:**\n\n- 超级用户`root`\t\t\t\t\t\t# 注:拥有最高权限\n- 程序用户\t\t\t\t\t\t\t # 注:程序运行过程中需要使用的用户\n- 普通用户\t\t\t\t\t\t\t # 注:手动创建的用户\n\n**UID (User Identity,用户标识号)**\n\n- 超级用户root的UID为`0`\n- 程序用户的UID `1-999`\n- 普通用户的UID大于等于`1000`\n\n\n\n```bash\n示例:mysql uid\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# id mysql\nuid=1000(mysql) gid=1000(mysql) 组=1000(mysql)\n[root@localhost ~]# id sanchuang2\nuid=1001(sanchuang2) gid=1001(sanchuang2) 组=1001(sanchuang2)\n\n示例\n--------------------------------------------------------------------------------------------\n#注:默认情况不指定uid 在上一个用户前+1\n[root@localhost ~]# useradd -u 1100 chenpeng1\t\t\t# 注:指定用户id\n[root@localhost ~]# id chenpeng1\nuid=1100(chenpeng1) gid=1100(chenpeng1) 组=1100(chenpeng1)\n[root@localhost ~]# useradd -u 1101 -g 1100 chenpeng2\t# 注:指定用户id、基本组\n[root@localhost ~]# id chenpeng2\t\t\t\t\t\t# 注:在chenpeng1这个组里面\nuid=1101(chenpeng2) gid=1100(chenpeng1) 组=1100(chenpeng1)\n\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# usermod -u 1200 chenpeng2\t\t\t# 注:修改用户id\n[root@localhost ~]# id chenpeng2\nuid=1200(chenpeng2) gid=1100(chenpeng1) 组=1100(chenpeng1)\n\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# useradd -d /var/log/sanchuang6 sanchuang6\t# 注:指定用户家目录\n[root@localhost ~]# cd /var/log/sanchuang6/\n[root@localhost sanchuang6]# ls\n[root@localhost sanchuang6]# less /etc/passwd\nsanchuang6:x:1201:1201::/var/log/sanchuang6:/bin/bash\t\t\t# 注:第6列 用户家目录\n\n示例:指定附加组\n--------------------------------------------------------------------------------------------\n[root@localhost sanchuang6]# useradd -g chenpeng1 -G sanchuang,sanchuang2 sanchuang7\n[root@localhost sanchuang6]# id sanchuang7\nuid=1202(sanchuang7) gid=1100(chenpeng1) 组=1100(chenpeng1),1000(sanchuang),1001(sanchuang2)\n#注:基本组chenpeng1 附属组 sanchuang sanchuang2\n#注:-g指定基本组 -G指定附加组\n============================================================================================\n·-c:用户注释描述信息\n/etc/passwd 第5列可以查看描述信息\n```\n\n\n\n### 12.2 userdel 删除用户\n\n**userdel命令**\n\n格式:`userdel [-r] 用户名 `\n\n添加 -r 选项时,表示连用户的宿主目录一并删除\n\n```bash\n示例1\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# useradd stu01 \n[root@localhost ~]# ls -ld /home/stu01/\ndrwx------ 2 stu01 stu01 4096 09-09 12:38 /home/stu01/ \n[root@localhost ~]# userdel -r stu01\t\t\t\t\t\t# 注:删除用户帐号stu01\n[root@localhost ~]# ls -ld /home/stu01/ \nls: /home/stu01/: 没有那个文件或目录\n\n示例2\n--------------------------------------------------------------------------------------------\n[root@localhost sanchuang6]# userdel sanchuang7\n[root@localhost sanchuang6]# less /etc/passwd\t\t\t\t# 注:删除了\n[root@localhost sanchuang6]# cd /home/sanchuang7\t\t\t# 注:没删\n[root@localhost sanchuang7]# ls /var/spool/mail/sanchuang7\t# 注:没删\n/var/spool/mail/sanchuang7\n```\n\n\n\n---\n\n## 十三. usermod 用户修改\n\nusermod命令\n\n格式:`usermod\t[选项]...\t用户名`\n\n常用命令选项\n\n- -l:更改用户帐号的登录名称\n- -L:锁定用户账户\n- -U:解锁用户账户\n- 以下选项与useradd命令中的含义相同\n -u、-d、-e、-g、-G、-s\n\n\n\n```bash\n示例:-L:锁定用户账户\n--------------------------------------------------------------------------------------------\n#注:锁上之后不能密码登录\n#注:本质就是在shadow密码前面加一个!号,使得登录的时候密码验证失败\n[root@localhost sanchuang7]# id sanchuang6\nuid=1201(sanchuang6) gid=1201(sanchuang6) 组=1201(sanchuang6)\n[root@localhost sanchuang7]# usermod -L sanchuang6\t\t# 注:锁定用户账户\n[root@localhost sanchuang7]# less /etc/shadow\t\t\t# 注:密码密文前面加了1个感叹号\nchenpeng2:!$6$P3yFUy.H$UOfUIbl8V3h1ng4J/OdVV1aWc3Cx3s5bldkysl33aDyrigsgK0VQ3nzrC4mojDNotpE9w61NbVQmZFqDDRfpl.:18571:0:99999:7:::\n[root@localhost sanchuang7]# diff /etc/shadow /etc/shadow-\n25c25\n< chenpeng2:!$6$P3yFUy.H$UOfUIbl8V3h1ng4J/OdVV1aWc3Cx3s5bldkysl33aDyrigsgK0VQ3nzrC4mojDNotpE9w61NbVQmZFqDDRfpl.:18571:0:99999:7:::\n---\n> chenpeng2:$6$P3yFUy.H$UOfUIbl8V3h1ng4J/OdVV1aWc3Cx3s5bldkysl33aDyrigsgK0VQ3nzrC4mojDNotpE9w61NbVQmZFqDDRfpl.:18571:0:99999:7:::\n#注:sha512加密技术 密文 明文\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# ssh chenpeng2@192.168.0.188\nchenpeng2@192.168.0.188's password: \t\t\t\t\t# 注:锁上之后不能密码登录\nPermission denied, please try again.\n…………………………\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\n```\n\n\n\n---\n\n## 十四. /etc/shadow\n\n**用于保存密码字串、密码有效期等信息**\n\n- 文件位置:`/etc/shadow`\t\t\t\t # 注:存放用户密码的文件,只能root用户查看\n- 每一行对应一个用户的密码记录\n\n\n\n- 字段1:用户帐号的名称\n- `字段2:加密的密码字串信息`\t\t\t # 注:字段2就是存放密码的字段存放的密码是加密的 密文,sha512算法加密\n- 字段3:上次修改密码的时间\n- 字段4:密码的最短有效天数,默认值为0\n- 字段5:密码的最长有效天数,默认值为99999\n- 字段6:提前多少天警告用户口令将过期,默认值为7\n- 字段7:在密码过期之后多少天禁用此用户\n- 字段8:帐号失效时间,默认值为空\n- 字段9:保留字段(未使用)\n\n\n\n---\n\n## 十五. passwd\n\n**passwd命令**\n\n- 格式:`passwd [选项]... 用户名`\n\n**常用命令选项**\n\n- -d:清空用户的密码,使之无需密码即可登录\n- -l:锁定用户帐号\n- -S:查看用户帐号的状态(是否被锁定)\n- -u:解锁用户帐号\n- --stdin:接收别的命令stdout做为stdin标准输入设置密码\n\n`root用户可以修改所有用户密码,不要求复杂性`\n\n`普通用户只能改自己的密码,要求复杂性`\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost sanchuang7]# passwd -d sanchuang6\t\t# 注:清空用户密码\n清除用户的密码 sanchuang6。\npasswd: 操作成功\n[root@localhost sanchuang7]# useradd sanchuang5\t\t\t# 注:注册 未给密码\n[root@localhost mail]# less /etc/shadow\nsanchuang6::18571:0:99999:7:::\t\t\t\t\t\t\t# 注:清除用户密码,密码字段为空\nsanchuang5:!!:18571:0:99999:7:::\t\t\t\t\t\t# 注:未给密码 密码字段默认2个感叹号\n\n#usermod和passwd锁定账户都是修改账户的shadow加密字段信息,使他们登录的时候密码匹配不上,达到一个锁定状态\n#usermod -L 加一个!号\t\t\t\t# 注:锁定用户在shadow密码字段前加一个!号\n#passwd -l \t加两个!号\t\t\t\t# 注:锁定用户在shadow密码字段前加两个!号\n#注:查看用户有没有设置密码 看/etc/shadow信息\n\n示例:usermod -L 和 passwd -l\t锁定用户\n--------------------------------------------------------------------------------------------\n[root@localhost mail]# useradd chen001\n[root@localhost mail]# useradd chen002\n[root@localhost mail]# useradd chen003\n[root@localhost mail]# echo 123456|passwd chen001 --stdin\n[root@localhost mail]# echo 123456|passwd chen002 --stdin\n[root@localhost mail]# echo 123456|passwd chen003 --stdin\n[root@localhost mail]# usermod -L chen002\t\t\t\t# 注:chen002做 usermod -L 操作\n[root@localhost mail]# passwd -d chen003\t\t\t\t# 注:chen003做 passwd -d 操作\n清除用户的密码 chen003。\npasswd: 操作成功\n[root@localhost mail]# less /etc/shadow\nchen001:$6$y……k1q.yk8U1gOGp/:18571:0:99999:7:::\nchen002:!$6$u……YF0.:18571:0:99999:7:::\nchen003::18571:0:99999:7:::\n-------------------------------------------------------------------------\n[root@localhost ~]# ssh chen003@192.168.136.136\t\t\t# 注:登录不上去\nchen003@192.168.136.136's password: \n…………\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\n[root@localhost ~]# ssh chen002@192.168.136.136\t\t\t# 注:登录不上去\nchen002@192.168.136.136's password: \n…………\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).\n[root@localhost ~]# ssh chen001@192.168.136.136\t\t\t# 注:没做操作的 远程登录成功\nchen001@192.168.136.136's password: \n[chen001@localhost ~]$ \n```\n\n\n\n---\n\n## 十六. /etc/group\n\n**/etc/group**\n\n​\t字段一:组名\n\n​\t字段二:密码字段\n\n​\t字段三:组id\n\n​\t字段四:存放是当前组为附属组时,有哪些用户\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# less /etc/group\ntech:x:200:b1,b2,a1,a2\n```\n\n\n\n---\n\n","tags":["Linux","用户与组"],"categories":["Linux"]},{"title":"13_Linux基础-SHELL命令-wc-diff-patch-bc-awk","url":"/posts/9132.html","content":"## 一. 回顾\n\n### sort\n\n**sort**\n\n```\n格式:sort 选项 文件\n-n\t按数值进行排序\n-r\t降序排序\n-k\t指定排序的列\n-t\t指定分隔符\n-u\t去重\n```\n\n\n\n### uniq\n\n**uniq**\n\n```\n格式:uniq 选项 文件\n-c\t统计每列在文本中出现的次数\n-u\t仅显示出现一次的行\n-d\t仅显示重复出现的行\n```\n\n\n\n### cut\n\n**cut**\n\n```\n格式:cut 选项 提取范围 文件\n-d\t指定分隔符\n-f\t指定显示的特定字段\n-c\t指定特定字符\n```\n\n\n\n### 文本三剑客\n\n```\ngrep 过滤 通用的正则表达式分析程序\ngrep [选项]... 模式 目标文件\n-i\t不区分大小写\n-v\t反转查找,不显示包含指定字符的行\n-o\t显示匹配的内容,并且换行显示\n-n\t显示出过滤出来的行的行号\n-r\t递归查找指定目录下所有的文件(包括其子目录)\n-E\t支持更多的正则扩展表达式\n```\n\n\n\n### 正则表达式\n\n```\n^aa\t以aa开头的行\nAa$\t以aa结尾的行\n```\n\n\n\n### 通配符\n\n```\n*\t表示匹配前一项任意次\n?\t表示匹配前一次0次或1次\n+\t表示匹配前一项一次到多次\n.\t(占位符)表示除换行符之外的任意字符\n{n,m}\t\t匹配n到m次\n{,n}\t\t匹配0次到n次\n{m,}\t\t匹配m次以上\n```\n\n```\n[]集合表示\n[a-zA-Z]\n[0-9]\n[^a]\t\t表示不取a\n```\n\n\n\n```bash\n示例\n---------------------------------------------------------------------------------------------------------------------------------\n# grep -E \"a.*c\" grep_test.txt \t\t\t\t# 注:.* 匹配前一项 . 0次或任意次\n# grep -E \"a*c\" abc.txt --color=auto\t\t# 注:* 匹配前一项 a 0次或任意次\n# grep -E \"a+c\" abc.txt --color=auto\t\t# 注:+ 匹配前一项 a 1次或多次\n```\n\n\n\n---\n\n## 二. wc\n\nwc(字数统计)命令\n\n格式:`wc\t[选项]...\t目标文件...`\n\n- **-l:统计行数**\n- **-w:统计字数 (前后都是空白的一组字符)**\n- **-c:统计字符数(可见和不可见的字符)**\n\n注:wc文本操作命令,可以直接接文本,不需要用cat\n\n\n\n```bash\n[root@sanchuang-linux ~]# cat wc_test.txt \na b c\naa bb cc\nxyz\n1234\naa-bb\n\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# wc -l wc_test.txt \t# 注:统计行数\n5 wc_test.txt\n[root@sanchuang-linux ~]# wc -w wc_test.txt \t# 注:统计字数\n9 wc_test.txt\n[root@sanchuang-linux ~]# wc -c wc_test.txt \t# 注:统计字符数\n30 wc_test.txt\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cat wc_test.txt|wc -c\t\t# 写法2:cat\n30\n[root@sanchuang-linux ~]# wc -c < wc_test.txt \t\t# 写法3:重定向\n30\n```\n\n\n\n---\n\n## 三. diff\n\ndiff命令\n\n- 比较两个文件之间的差异\n- 输出结果为两个文件的不同之处\n\ndiff命令的输出格式\n\n- 标准diff\n- `-u`:会将不同的地方放在一起,紧凑易读\n- -r: 递归比较目录下的所有文件\n\n利用diff命令生成补丁\n\n- `diff -u test1 test2 > test.patch`\n\n\n\n```bash\n[root@sanchuang-linux ~]# cat diff_1_test.txt\naa\nbb\ncc\nxx\n[root@sanchuang-linux ~]# cat diff_2_test.txt\naa\nbb\nxx\n\n示例1\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# diff diff_1_test.txt diff_2_test.txt \n3d2\t\t\t\t\t\t\t# 注:3d2 文件1个第3行 需要删除 就会和 文件2相同\n< cc\t\t\t\t\t\t# 注:文件1 中的cc\n============================================================================================\n\n[root@sanchuang-linux ~]# cat diff_1_test.txt\naa\nbb\ncc\nxx\ngg\n[root@sanchuang-linux ~]# cat diff_2_test.txt\naa\nbb\ndd\nxx\nee\n\n示例2\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# diff diff_1_test.txt diff_2_test.txt \n3c3\t\t\t\t\t\t\t\t\t\t\t# 注:第3行\n< cc\t\t\t\t\t\t\t\t\t\t# 注:文件1 中的cc\n---\n> dd\t\t\t\t\t\t\t\t\t\t# 注:文件2 中的dd\n5c5\t\t\t\t\t\t\t\t\t\t\t# 注:第5行\n< gg\t\t\t\t\t\t\t\t\t\t# 注:文件1 中的gg\n---\n> ee\t\t\t\t\t\t\t\t\t\t# 注:文件2 中的ee\n--------------------------------------------------------------------------------------------\n============================================================================================\n\n示例3:-u:会将不同的地方放在一起,紧凑易读\n[root@sanchuang-linux ~]# diff -u diff_1_test.txt diff_2_test.txt \n--- diff_1_test.txt\t2020-10-30 11:50:45.784010843 +0800\n+++ diff_2_test.txt\t2020-10-30 11:51:11.475010836 +0800\n@@ -1,5 +1,5 @@\n aa\n bb\n-cc\t\t\t\t\t\t\t\t\t\t\t# 注:理解为 左 - 右 +\n+dd\t\t\t\t\t\t\t\t\t\t\t# 注:或者理解为 左边 -cc +dd 就和右边相同\n xx\n-gg\n+ee\n```\n\n\n\n---\n\n## 四. patch\n\npatch命令:\n\n- 用途:用来打补丁修补文件\n- 格式:`patch\t[选项]\t原始文件 < 补丁文件`\n- `-p`N: N表示忽略N层路径\n- `-R`: 还原到老版本\n\n注意事项\n\n- 如果打多个补丁,注意先后顺序 \n- 打补丁前不要修改源文件\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# yum install patch\n[root@sanchuang-linux ~]# diff diff_1_test.txt diff_2_test.txt \t\n3c3\t\t\t\t\t\t\t# 注:差异内容\n< cc\n---\n> dd\n5c5\n< gg\n---\n> ee\n\n#注:差异文件又叫补丁文件\n#注:生成的是文件1的补丁文件\n[root@sanchuang-linux ~]# diff -u diff_1_test.txt diff_2_test.txt > diff_test.patch # 注:1的补丁\n[root@sanchuang-linux ~]# cat diff_test.patch \t\t#注:补丁文件\n--- diff_1_test.txt\t2020-10-30 11:50:45.784010843 +0800\n+++ diff_2_test.txt\t2020-10-30 11:51:11.475010836 +0800\n@@ -1,5 +1,5 @@\n aa\n bb\n-cc\n+dd\n xx\n-gg\n+ee\n[root@sanchuang-linux ~]# patch diff_1_test.txt < diff_test.patch \t# 注:打补丁\npatching file diff_1_test.txt\n[root@sanchuang-linux ~]# cat diff_1_test.txt \t\t\t\t\t\t# 注:打补丁\naa\nbb\ndd\nxx\nee\n[root@sanchuang-linux ~]# cat diff_2_test.txt \t\t# 注:文件1、2内容相同\naa\nbb\ndd\nxx\nee\n```\n\n\n\n---\n\n## 五. grep -A\\\\-B\n\n-A:找到匹配行以及后几行\n\n-B:输出匹配行以及前几行\n\n```bash\n示例\n[root@localhost ~]# grep -A 3 quit /etc/passwd\t\t# 注:找到匹配行以及后几行\n[root@localhost ~]# grep -B 3 quit /etc/passwd\t\t# 注:输出匹配行以及前几行\n```\n\n\n\n---\n\n## 六. free -g\n\n**看内存使用率 free -g**\n\n```bash\n[root@sanchuang-linux ~]# free -g\t\t# 注:看内存使用率 ,-g单位G , -m单位M\n total used free shared buff/cache available\nMem: 1 0 1 0 0 1\nSwap: 1 0 1\n[root@sanchuang-linux ~]# free -m\n total used free shared buff/cache available\nMem: 1800 272 1101 8 426 1363\nSwap: 2047 0 2047\n```\n\n\n\n---\n\n## 七. 编写脚本\n\n```bash\n实现以下功能\n1、监控内存使用情况,如果内存使用率大于百分之80,给予提醒\n\ttotal free 使用率\n2、扫描局域网ip,检查哪些ip地址正在使用\n\tping -c 1\t\t# 注:发送1个包\n3、监控文件/etc/passwd是否被修改,每隔5分钟监控一次\n\tdiff\n\tmd5sum\t# md5值,文件的唯一标识\n4、监控nginx进程是否存在,不存在就给予相应提醒\n\tpidof nginx\n```\n\n\n\n```bash\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# md5sum abc.txt \t\t\t# 注:md5值\n2416b02c3d9d753f48cf49dbb5f1de94 abc.txt\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# pidof nginx\t\t\t\t# 注:显示指定程序的进程号\n12767 12766 12765\n```\n\n\n\n### 7.1 监控内存使用情况,如果内存使用率大于百分之80,给予提醒\n\n​\t\ttotal free 使用率\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n#!/bin/bash\nfunction mem(){\n total=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f2`\n #free=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f4`\n used=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f3`\n used_rate=`echo \"scale=4;$used/$total\" |bc`\n #used_1=`echo \"$total*0.8\"|bc `\n result=` echo \"$used_rate>0.8\"|bc `\n echo $result\n if (( $result == 1 ))\n then\n echo -e \"\\e[31m使用率超过80%,请及时对内存扩容,以免不必要的损失\\e[0m\"\n else\n echo \" nothing to do\"\n fi\n}\nmem\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# bash mem_test.sh\n0\n nothing to do\n============================================================================================\n知识点7.1.1 bc 命令\n菜鸟教程:https://www.runoob.com/linux/linux-comm-bc.html\nbc 命令是任意精度计算器语言,通常在linux下当计算器用\n[root@localhost ~]# yum install bc -y\n[root@sanchuang-linux ~]# used=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f3`\n[root@sanchuang-linux ~]# total=`free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f2`\n[root@sanchuang-linux ~]# echo \"scale=2;$used/$total\" |bc\t# 注:保留2位小数\n.16\n[root@sanchuang-linux ~]# echo \"scale=3;$used/$total\" |bc\t# 注:保留3位小数\n.165\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# free -m|grep -i mem|tr -s \" \"|cut -d \" \" -f2 # 注:-i 不区分大小写\n1800\n[root@sanchuang-linux ~]# use_rate=`echo \"scale=4;$used/$total\" |bc`\n[root@sanchuang-linux ~]# echo \"$use_rate>0.8\"|bc\t# 注:为假返回0\n0\n[root@sanchuang-linux ~]# echo \"0.7>0.8\"|bc\t\t\t# 注:为假返回0\n0\n[root@sanchuang-linux ~]# echo \"0.9>0.8\"|bc\t\t\t# 注:为真返回1\n1\t\t# 注:这返回的应该是布尔值0假1真,而不是命令执行失败的值。$?都为0 ,命令执行成功\n############################################################################################\n知识点7.1.2 小数的运算\n小数的运算:\n1、可以使用bc\n[root@sanchuang-linux ~]# echo \"scale=3;1/3\"|bc\t\t# 注:保留3位小数\n.333\n[root@sanchuang-linux ~]# echo \"0.7>0.8\"|bc\t\t\t# 注:不成立返回0\n0\n[root@sanchuang-linux ~]# echo \"0.9>0.8\"|bc\t\t\t# 注:成立返回1\n1\n\n2、awk 选项\n语法:awk 选项 ‘模式+动作’ 文件\n常用选项:\n-F\t指定分隔符\n\n内置变量\nNR\tawk里表示每一行的行号\nNF\tawk的列号\n\n模式\n\n示例\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# free -m\n total used free shared buff/cache available\nMem: 3770 195 3274 11 300 3348\nSwap: 2047 0 2047\n[root@localhost ~]# free -m|awk 'NR==2{print $2}'\t\t# 注:打印第二行 第2个变量\n3770\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:NR 行号 , $2 第2个变量\n[root@localhost ~]# free -m|awk 'NR==2{print $3}'\t\t# 注:打印第二行 第3个变量\n194\n============================================================================================\n[root@sanchuang-linux ~]# free -m|awk '/Mem/{print $3/$2}'\t\t# 注:计算小数,过滤出Mem\n0.156111\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:过滤出Mem 这1行\n[root@sanchuang-linux ~]# free -m|awk '/Mem/{printf \"%.2f\\n\", $3/$2}'\t# 注:保留2位的浮点数\n0.16\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:\\n换行输出\n```\n\n\n\n### 7.2 扫描局域网ip,检查哪些ip地址正在使用\n\n​\t\tping -c 1\t\t# 注:发送1个包\n\n```bash\n方法1\n--------------------------------------------------------------------------------------------\nscan_ip(){\n for ip in `seq 255`\n do\n ( ip_full=192.168.0.$ip\n ping -c 1 $ip_full &>/dev/null && echo $ip_full >>up.txt || echo $ip_full >>down.txt\n ) &\t# 注:放到后台子进程执行\n done\nwait # 父进程等待子进程执行完成之后再退出\n}\nscan_ip\n\n方法2\n--------------------------------------------------------------------------------------------\nscan_ip(){\n for ip in 192.168.0.{1..255}\t\t\t\t\t# 注:1-255可以这么写\n do\n ( \n ping -c 1 $ip &>/dev/null && echo $ip >>up.txt || echo $ip >>down.txt\n ) & \n done\nwait #注:作用:父进程等待子进程执行完成之后再退出\n}\nscan_ip\n注:后台进程\n命令 &\t 产生子bash进程去执行命令的任务\nwait\t\t父进程等待子进程结束之后再退出\n============================================================================================\n\n[root@sanchuang-linux ~]# ip=45\n[root@sanchuang-linux ~]# ip_full=192.168.0.$ip\t\t\t# 注:shell 字符串的拼接\n[root@sanchuang-linux ~]# echo $ip_full \n192.168.0.45\n[root@sanchuang-linux ~]# top\t\t\t\t\t\t\t# 注:查看cpu\n```\n\n\n\n### 7.3 监控nginx进程是否存在,不存在就给予相应提醒\n\n​\t\tpidof nginx\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\ncheck_nginx(){\n pidof nginx && echo \"nginx is running\" || echo \"nginx is down\"\n #if [[ $? -eq 0 ]]\n #then\n # echo \"nginx is running\"\n #fi\n}\ncheck_nginx\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# pidof nginx\n12767 12766 12765\n[root@sanchuang-linux ~]# echo $?\t\t\t\t\t# 注:返回值为0表示成功\n0\n```\n\n\n\n### 7.4 监控文件/etc/passwd是否被修改,每隔5分钟监控一次\n\n​\t\tdiff\n\n​\t\tmd5sum\t# md5值,文件的唯一标识\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\ncheck_monitor(){\n check_num=`differ /etc/passwd /lianxi/passwd |wc -l`\n [[ check_num -eq 0 ]] && echo \"文件未被修改\" || echo \"文件已被修改\"\n}\ncheck_monitor\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cp /etc/passwd /lianxi/passwd\ncp:是否覆盖'/lianxi/passwd'? y\n[root@sanchuang-linux ~]# diff /etc/passwd /lianxi/passwd\n[root@sanchuang-linux ~]# echo $?\t# 注:即使文件不被修改,返回也为0 (理解为命令执行成功)\n0\t\t\t\t\t\t\t\t\t# 注:所以不能直接用类三元运算 去判断\n[root@sanchuang-linux ~]# diff /etc/passwd /lianxi/passwd\n[root@sanchuang-linux ~]# diff /etc/passwd /lianxi/passwd|wc\n 0 0 0\n[root@sanchuang-linux ~]# diff /etc/passwd /lianxi/passwd|wc -l\n0\n#注:判定依据 diff 是否输出内容\n\t没有输出内容,wc -l 行数为0,说明文件未被修改\n#注:文件是否被修改,想到diff命令\n```\n\n\n\n---\n\n","tags":["Linux","Shell"],"categories":["Linux"]},{"title":"12_Linux基础-SHELL命令-sort-uniq-cut-grep-正则表达式-通配符","url":"/posts/61496.html","content":"## 一. 回顾\n\n**回顾1 shell常用命令**\n\n```\n获取命令的返回输出结果\t\n1.` `,反引号\t line=`ls`\n2.$()\t\t\tline=$(ls)\n```\n\n```\nseq 类似于python里的range\n主要生产一组有序数字序列\n-s 指定分隔符\n-w 指定同等宽度输出\n```\n\n\n\n---\n\n## 二. sort\n\n**sort命令**\n\n- 默认按每行的第一个字符排序\n- -n:按**整数**进行排序-->默认是**升序**\n- -r:**递减**排序(注:降序)\n- -u:去重\n\n`指定排序键`\n\n- 指定按哪一列数据进行排序\n- -k:指定哪一列为排序键 \n- `cat tt | sort -n -k4`\n\n`指定字段分隔符`\n\n- -t:指定字段分割符(默认是空白) \n- `sort -t: -n -k3 /etc/passwd`\t\t\t# 注:指定分隔符为 :\n\n\n\n**sort是一个排序命令**\n\n- **默认按照每行第一个首字符进行排序**\n - **英文根据a-z的顺序进行排序,如果第一个字母相同,就比较第二个字母,依次类推**\n - **中文根据首个字符的拼音的首字母进行排序**\n\n\n\n```bash\n示例1:cat sort_test.txt |sort\n---------------------------------------------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cat sort_test.txt \t\t\t# 注:显示文本内容\n中文 456 1xx 123\nabc bcd 3yy dd\nAac XYZ 2zz\n三创 xixi\n[root@sanchuang-linux ~]# cat sort_test.txt |sort\t\t# 注:对整个文本进行排序\n三创 xixi\n中文 456 1xx 123\nAac XYZ 2zz\nabc bcd 3yy dd\n--------------------------------------------------------------------------------------------\n>>> ord(\"三\")\t\t\t\t\t\t\t# python中的ord()函数查看万国码编码\n19977\t\t\t\t\t\t\t\t\t# 注:sort不是按编码排序\n>>> ord(\"中\")\n20013\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# locale\t\t# 注:查看编码格式\nLANG=zh_CN.UTF-8\nLC_CTYPE=\"zh_CN.UTF-8\"\nLC_NUMERIC=\"zh_CN.UTF-8\"\nLC_TIME=\"zh_CN.UTF-8\"\nLC_COLLATE=\"zh_CN.UTF-8\"\nLC_MONETARY=\"zh_CN.UTF-8\"\nLC_MESSAGES=\"zh_CN.UTF-8\"\nLC_PAPER=\"zh_CN.UTF-8\"\nLC_NAME=\"zh_CN.UTF-8\"\nLC_ADDRESS=\"zh_CN.UTF-8\"\nLC_TELEPHONE=\"zh_CN.UTF-8\"\nLC_MEASUREMENT=\"zh_CN.UTF-8\"\nLC_IDENTIFICATION=\"zh_CN.UTF-8\"\nLC_ALL=\n============================================================================================\n示例2:cat sort_test.txt |sort -k 2\t指定哪一列为排序键\n[root@sanchuang-linux ~]# cat sort_test.txt |sort -k2\t\t# 注:指定第二列进行排序\n中文 456 1xx 123\nabc bcd 3yy dd\n三创 xixi\nAac XYZ 2zz\n[root@sanchuang-linux ~]# cat sort_test.txt |sort -k 3\t # 注:指定第三列进行排序\n三创 xixi\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:空白在前面\n中文 456 1xx 123\t\t\t\t\t\t\t\t\t\t\t# 注:1\nAac XYZ 2zz\t\t\t\t\t\t\t\t\t\t\t # 注:2\nabc bcd 3yy dd\t\t\t\t\t\t\t\t\t\t\t # 注:3\n============================================================================================\n示例3:英文根据a-z的顺序进行排序,如果第一个字母相同,就比较第二个字母\n[root@sanchuang-linux ~]# cat sort_test.txt \n中文 456 1xx 123\naac bcd 3yy dd\nAac XYZ 2zz\n三创 xixi\nXyz cde\nBbc Abc\nbbc xxx\nABC\nabc\n[root@sanchuang-linux ~]# cat sort_test.txt |sort\t\t\t# 注:不是按照编码排序\n三创 xixi\n中文 456 1xx 123\naac bcd 3yy dd\nAac XYZ 2zz\nabc\nABC\nBbc Abc\nbbc xxx\nXyz cde\n```\n\n\n\n### sort -n\n\n**sort -n 按数字进行排序**\n\n```bash\n[root@sanchuang-linux ~]# a=123\t\t\t\t\t\t# 注:a表示的是字符\n[root@sanchuang-linux ~]# b=234\n[root@sanchuang-linux ~]# echo $a+$b\t\t\t\t# 注:字符串的拼接\n123+234\n[root@sanchuang-linux ~]# echo $(($a+$b))\t\t\t# 注:需要用2个括号进行数字的相加\n357\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cat aa.txt \n123\n23\n4\n234\n[root@sanchuang-linux ~]# cat aa.txt |sort\t\t\t# 注:默认情况按首个字母字符串进行排序\n123\n23\n234\n4\n[root@sanchuang-linux ~]# cat aa.txt |sort -n\t\t# 注:sort -n 按数值大小进行排序\n4\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:默认升序\n23\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:-n 数字排序比较\n123\n234\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cat aa.txt |sort -n -r\t# 注:数字、倒序 排序,效果相同\n[root@sanchuang-linux ~]# cat aa.txt |sort -nr\t\t# 注:数字、倒序 排序,效果相同\n234\n123\n23\n4\n```\n\n\n\n### -t 指定列数的分隔符\n\n**指定列数的分隔符\t\t`# head -n7 /etc/passwd |sort -k6 -t :`**\n\n​\t**默认分隔符为空白字符**\n\n​\t**使用 -t 指定列数的分隔符**\n\n```bash\n[root@sanchuang-linux ~]# head -n7 /etc/passwd |sort\t\t# 注:取前7行 排序\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nroot:x:0:0:root:/root:/bin/bash\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nsync:x:5:0:sync:/sbin:/bin/sync\n[root@sanchuang-linux ~]# head -n7 /etc/passwd |sort -k2\t# 注:sort -k2指定第2列为排序键\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nbin:x:1:1:bin:/bin:/sbin/nologin\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\nroot:x:0:0:root:/root:/bin/bash\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nsync:x:5:0:sync:/sbin:/bin/sync\n[root@sanchuang-linux ~]# head -n7 /etc/passwd |sort -k6 -t :\t\t\t# *注:-t : 指定分隔符为 :\nbin:x:1:1:bin:/bin:/sbin/nologin\nroot:x:0:0:root:/root:/bin/bash\nsync:x:5:0:sync:/sbin:/bin/sync\ndaemon:x:2:2:daemon:/sbin:/sbin/nologin\nshutdown:x:6:0:shutdown:/sbin:/sbin/shutdown\nadm:x:3:4:adm:/var/adm:/sbin/nologin\nlp:x:4:7:lp:/var/spool/lpd:/sbin/nologin\n[root@sanchuang-linux ~]# head -n7 /etc/passwd |sort -k6 -t : -r\t\t# 注:-r 倒序\n```\n\n\n\n---\n\n## 三. 练习:找出内存使用率最高的5个进程\n\n**找出内存使用率最高的5个进程**\n\n```bash\nps aux|sort -n -k4 -r|head -5\t\t注:推荐\n注:内存使用率 %MEM\n[root@sanchuang-linux ~]# ps aux|tail -n +2|sort -nr -k4 |head -5\nroot 960 0.0 2.0 221572 38096 ? S 08:31 0:00 /usr/libexec/sssd/sssd_nss --uid 0 --gid 0 --logger=files\nroot 930 0.0 1.7 425416 31480 ? Ssl 08:31 0:01 /usr/libexec/platform-python -Es /usr/sbin/tuned -l -P\npolkitd 890 0.0 1.2 1625936 23856 ? Ssl 08:31 0:00 /usr/lib/polkit-1/polkitd --no-debug\nroot 891 0.0 0.9 391216 18088 ? Ssl 08:31 0:00 /usr/sbin/NetworkManager --no-daemon\nroot 954 0.0 0.8 219700 15416 ? S 08:31 0:00 /usr/libexec/sssd/sssd_be --domain implicit_files --uid 0 --gid 0 --logger=files\n--------------------------------------------------------------------------------------------\n#ps aux|tail -n +2|sort -nr -k4 |head -5\n注:tail -n +2 显示从第2行到末尾(可加可不加)\n注:sort -nr -k4 -n按数字排序,-r倒序,-k4指定第4列为排序键\n注:head -5 取前5行\n```\n\n\n\n---\n\n## 四. uniq\n\n**uniq命令的使用(去重)**\n\nuniq --> unique唯一的\n去重相邻的行\n**先排序,再去重**\n**-c 统计重复出现的次数**\n**-u 显示只出现1次的行**\n**-d 显示重复出现的行**\n\n\n\n```bash\n============================================================================================\n示例1:去重相邻的行\n[root@sanchuang-linux ~]# cat uniq_test.txt\n123 abc\nabc 123\n45\n46\n45\n45\n47\n47\n48\n47\n[root@sanchuang-linux ~]# cat uniq_test.txt |uniq\t\t# 注:去重相邻的行\n123 abc\nabc 123\n45\n46\n45\n47\n48\n47\n[root@sanchuang-linux ~]# cat uniq_test.txt |sort -n |uniq\t# 注:先排序,再去重\nabc 123\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:一般来说,先排序,再去重\n45\n46\n47\n48\n123 abc\n--------------------------------------------------------------------------------------------\n示例1.1 # cat uniq_test.txt |sort -nu\n[root@sanchuang-linux ~]# cat uniq_test.txt |sort -n -u\t\t# 注:sort -u 也可以去重\n[root@sanchuang-linux ~]# cat uniq_test.txt |sort -nu\t\t# 注:效果一样\nabc 123\n45\n46\n47\n48\n123 abc\n============================================================================================\n示例2:-c 统计重复出现\n[root@sanchuang-linux ~]# cat uniq_test.txt |sort -n |uniq -c # 注: -c 统计重复出现的次数\n 1 abc 123\n 3 45\n 1 46\n 3 47\n 1 48\n 1 123 abc\n============================================================================================\n示例3:-u显示只出现1次的行\n[root@sanchuang-linux ~]# cat uniq_test.txt |sort -n |uniq -u\t# 注:-u显示只出现1次的行\nabc 123\n46\n48\n123 abc\n============================================================================================\n示例4:-d 显示重复出现的行\n[root@sanchuang-linux ~]# cat uniq_test.txt |sort -n |uniq -d\t# 注:-d 显示重复出现的行\n45\n47\n```\n\n\n\n---\n\n## 五. 练习:统计120000行 频率前十的ip\n\n**统计120000行 频率前十的ip**\n\n```bash\n[root@sanchuang-linux ~]# cat ips.txt |sort |uniq -c|sort -nr |head\n#注1:第一个sort 把相同的ip段放在一起\n#注2:uniq -c统计次数\n#注:第二个sort -nr 对前面的次数+ip 进行逆序\n#注:head 默认取前十个\n```\n\n\n\n```bash\n注 :sort -c 用于统计ip地址的访问\n[root@localhost ~]# yum install nginx\n[root@sanchuang-linux ~]# nginx\n[root@sanchuang-linux ~]# lsof -i:80\t\t\t# 注:nginx起来了\nCOMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME\nnginx 12765 root 9u IPv4 60060 0t0 TCP *:http (LISTEN)\nnginx 12765 root 10u IPv6 60061 0t0 TCP *:http (LISTEN)\nnginx 12766 nginx 9u IPv4 60060 0t0 TCP *:http (LISTEN)\nnginx 12766 nginx 10u IPv6 60061 0t0 TCP *:http (LISTEN)\nnginx 12767 nginx 9u IPv4 60060 0t0 TCP *:http (LISTEN)\nnginx 12767 nginx 10u IPv6 60061 0t0 TCP *:http (LISTEN)\n[root@sanchuang-linux ~]# iptables -F\t\t\t# 注:关闭防火墙\n\n[root@sanchuang-linux ~]# cd /var/log\t\t\t# 注:/var/log放日志\n[root@sanchuang-linux log]# cd nginx\n[root@sanchuang-linux nginx]# pwd\n/var/log/nginx\n[root@sanchuang-linux nginx]# ls\naccess.log error.log\t\t\t\t\t\t\t# 注:日志文件\n```\n\n\n\n---\n\n## 六. 练习:统计web服务器访问前十的用户\n\n**统计web服务器访问前十的用户(注:通过ip判断)**\n\n```bash\n#注:nginx查看访问次数最多的3个ip(笔试题常见)\n#cat access.log |awk '{print $1}'|sort|uniq -c|sort -nr|head -3\n[root@sanchuang-linux nginx]# head access.log \n192.168.0.42 - - [29/Oct/2020:12:01:01 +0800] \"GET / HTTP/1.1\" 200 4057 \"-\" \"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3823.400 QQBrowser/10.7.4307.400\" \"-\"\n………………\t\t\t\t\t\t# 注:awk命令 提取文本第一列数据 ip地址\n[root@sanchuang-linux nginx]# cat access.log |awk '{print $1}'\n192.168.0.42\t\t\t\t# 注:默认以空格为分隔符,打印第一列$1\n192.168.0.42\n192.168.0.42\n192.168.0.42\n192.168.0.42\n192.168.0.193\n192.168.0.193\n192.168.0.193\n192.168.0.193\t\t\t\t# 注:awk命令 提取文本第一列数据 ip地址\n[root@sanchuang-linux nginx]# cat access.log |awk '{print $1}'|sort|uniq -c|sort -nr|head -3\n 5 192.168.0.42\t\t# 注:统计前3的访问量\n 4 192.168.0.193\n```\n\n\n\n---\n\n## 七. cut\n\n**cut命令**\n\n- 从文本文件或者文本流中提取文本列\n- `cut -选项 提取范围 文本文件`\n\n\\-----------------------------------\n\n**常见选项**\n\n- -c:从指定提取范围中提取字符\n- -f:从指定提取范围中提取字段\n- -d:指定分隔符,默认分隔符为tab键\n\n\\-----------------------------------\n\n**提取范围**\n\n`n:第n项`\n\n`n-:第n项到行尾`\n\n`-m:行首到第m项 `\n\n`n,m:第n项和第m项 `\n\n`n-m:第n项到第m项`\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# w\t\t\t\t\t# 注:w 当前用户登录情况\n 14:45:33 up 4:12, 5 users, load average: 0.00, 0.00, 0.03\nUSER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\nroot tty1 - 三22 15:49 0.08s 0.08s -bash\nroot pts/0 192.168.0.42 14:29 3.00s 0.02s 0.01s w\nroot pts/1 192.168.0.42 14:29 15:35 0.00s 0.00s -bash\nroot pts/3 192.168.0.42 09:48 4:56m 0.03s 0.03s -bash\nroot pts/4 192.168.0.42 09:50 2:37m 0.52s 0.52s -bash\n[root@sanchuang-linux ~]# who\t\t\t\t# 注:w 看到更详细点\nroot tty1 2020-10-28 22:15\nroot pts/0 2020-10-29 14:29 (192.168.0.42)\nroot pts/1 2020-10-29 14:29 (192.168.0.42)\nroot pts/3 2020-10-29 09:48 (192.168.0.42)\nroot pts/4 2020-10-29 09:50 (192.168.0.42)\n方法1\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# w |tr -s \" \"|cut -d\" \" -f 1,2,4\n 14:50:31 4:17,\t\t\t\t\t\t\t\t\t# 注:默认分隔符为tab键,所有要压缩 \nUSER TTY LOGIN@\t\t\t\t\t\t\t\t\t# 注:再指定分隔符为空格\nroot tty1 三22\t\t\t\t\t\t\t\t # 注:加tr -s \" \"\nroot pts/0 14:29\nroot pts/1 14:29\nroot pts/3 09:48\nroot pts/4 09:50\n方法2\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# w |awk '{print $1,$2,$4}'\t\t# 注:awk 默认分隔符是空白字符\n14:51:28 up 5\t\t\t\t\t\t\t\t\t\t # 注:打印第1、2、4列\nUSER TTY LOGIN@\nroot tty1 三22\nroot pts/0 14:29\nroot pts/1 14:29\nroot pts/3 09:48\nroot pts/4 09:50\n```\n\n\n\n### 以冒号作为分隔符 截取用户名、用户Id、用户属组\n\n**以冒号作为分隔符 截取用户名、用户Id、用户属组**\n\n```bash\n写法1\n[root@sanchuang-linux ~]# cat /etc/passwd|cut -d\":\" -f 1,3,5\t\n写法2(推荐)\n[root@sanchuang-linux ~]# cut -d \":\" -f 1,3,5 /etc/passwd\t# 注:截取1,3,5列\n#注:文本操作命令,可以直接操作文本,不需要用到cat\n```\n\n\n\n### 取值范围\n\n**取值范围**\n\n```bash\n[root@sanchuang-linux ~]# cut -d \":\" -f 1,3,5 /etc/passwd\t# 注:截取1,3,5列\n[root@sanchuang-linux ~]# cut -d \":\" -f 1-5 /etc/passwd\t\t# 注:截取1-5列\n[root@sanchuang-linux ~]# cut -d \":\" -f 3- /etc/passwd\t\t# 注:截取第3列--列尾\n[root@sanchuang-linux ~]# cut -d \":\" -f -3 /etc/passwd\t\t# 注:截取前3列\n============================================================================================\n-c:从指定提取范围中提取字符\n示例\n[root@sanchuang-linux ~]# echo abcdefg |cut -c 2\t\t# 注:截取第2个字符\nb\n[root@sanchuang-linux ~]# echo abcdefg |cut -c 2-5\t\t# 注:截取2--5个字符\nbcde\n[root@sanchuang-linux ~]# echo abcdefg |cut -c 5-\t\t# 注:截取第5到末尾字符\nefg\n```\n\n\n\n---\n\n## 八. 练习\n\n**练习**\n\n```\n1统计access.log中排名前三的ip\n2显示/boot目录下面所有的文件大小(包括子目录中的文件),并且由小到大排序\n3统计/etc/passwd中每种shell使用的次数(降序排序)\n4统计一下/etc/passwd中sbin这个单词出现了多少次\n5只显示ens33的ip地址\n```\n\n\n\n```bash\n============================================================================================\n示例1:1统计access.log中排名前三的ip\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cut -d \"-\" -f 1 access.log |sort|uniq -c|sort -nr|head -n3\n 7 192.168.0.42 \n 6 192.168.0.193 \n 5 192.168.0.38 \n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cut -d \" \" -f1 access.log |sort|uniq -c\n 6 192.168.0.193\n 5 192.168.0.21\n 5 192.168.0.32\n 5 192.168.0.37\n 5 192.168.0.38\n 7 192.168.0.42\n[root@sanchuang-linux ~]# cut -d \" \" -f1 access.log |sort|uniq -c|sort -nr\n 7 192.168.0.42\n 6 192.168.0.193\n 5 192.168.0.38\n 5 192.168.0.37\n 5 192.168.0.32\n 5 192.168.0.21\n[root@sanchuang-linux ~]# cut -d \" \" -f1 access.log |sort|uniq -c|sort -nr|head -3\n 7 192.168.0.42\n 6 192.168.0.193\n 5 192.168.0.38\n============================================================================================\n示例2:2显示/boot目录下面所有的文件大小(包括子目录中的文件),并且由小到大排序\n方法1\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# du -ak /boot |sort -n \t\t# 注:以k为字节\n4\t/boot/.bashrc\n4\t/boot/efi/EFI/centos\n4\t/boot/grub2/device.map\n4\t/boot/grub2/grubenv\n4\t/boot/grub2/i386-pc/adler32.mod\n4\t/boot/grub2/i386-pc/all_video.mod\n4\t/boot/grub2/i386-pc/aout.mod\n\n方法2\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ll -R|grep root|tr -s \" \"|cut -d \" \" -f 5,9|sort -n\n0 1214.txt\n0 12244.txt\n0 1224.txt\n0 12456.txt\n0 20\n0 20\n0 2020-09-24-18_25_03.txt\n\n方法3\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ll -R|grep root|awk '{print $5,$9}'|sort -n\n0 1214.txt\n0 12244.txt\n0 1224.txt\n0 12456.txt\n0 20\n0 20\n0 2020-09-24-18_25_03.txt\n0 abcd.txt\n============================================================================================\n示例3:3统计/etc/passwd中每种shell使用的次数(降序排序)\n[root@sanchuang-linux ~]# cut -d : -f7 /etc/passwd |sort|uniq -c|sort -nr\n 31 /bin/bash\n 19 /sbin/nologin\n 1 /sbin/shutdown\n 1 /sbin/halt\n 1 /bin/sync\n============================================================================================\n示例4:4统计一下/etc/passwd中sbin这个单词出现了多少次\n方法1\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# grep -o sbin /etc/passwd\nsbin\nsbin\n………………\nsbin\nsbin\n[root@sanchuang-linux ~]# grep -o sbin /etc/passwd|wc -l\n25\n\n方法2\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cat /etc/passwd|tr \":\" \"\\n\"|grep sbin|wc -l\n25\t\t\t\t\t\t# 注:将: 换成 换行符 同一行换到不同的行去\n============================================================================================\n示例5:5只显示ens33的ip地址\n#ip a |grep ens33|grep inet|tr -s \" \"|cut -d \" \" -f3|cut -d\"/\" -f1\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# ip a |grep ens33\n2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000\n inet 192.168.0.34/24 brd 192.168.0.255 scope global dynamic noprefixroute ens33\n[root@sanchuang-linux ~]# ip a |grep ens33|grep inet|tr -s \" \"|cut -d \" \" -f3\n192.168.0.34/24\n[root@sanchuang-linux ~]# ip a |grep ens33|grep inet|tr -s \" \"|cut -d \" \" -f3|cut -d\"/\" -f1\n192.168.0.34\n```\n\n\n\n---\n\n## 九. awk指定分隔符 -F\n\n**awk指定分隔符 -F**\n\n```bash\n[root@sanchuang-linux ~]# awk -F\":\" '{print $1}' /etc/passwd\nroot\nbin\ndaemon\nadm\nlp\nsync\n…………………………\n```\n\n\n\n---\n\n## 十. grep\n\n**grep命令**\n\n文本三剑客 ==> awk grep sed\nhttps://www.cnblogs.com/end/archive/2012/02/21/2360965.html\ngrep 过滤 通用的正则表达式分析程序\n\t\t**grep、egrep、fgrep**\n\t\t**做匹配来过滤的**\n\n\n\n用途:在文件中查找并显示包含指定字符串的行 格式:`grep [选项]... 模式 目标文件` \n\n#注:**模式pattern --》模板**\n\n​\t\t **可以接受一个正则表达式**\n\n\n\n`-i`:查找时忽略大小写\n\n`-v`:反转查找,输出与模式不相符的行\n\n-n:显示符合模式要求的行号\n\n-r:递归搜索所有文件\n\n`-o`:只显示匹配的内容\n\n`-E`:支持更多的元字符(支持扩展正则)\n\n-A:找到匹配行以及后几行\n\n-B:输出匹配行以及前几行\n\n模式\n\n`^…. :以什么开头,整行以什么开头`\n\n`…..$ :以什么结尾,整行以什么结尾`\n\n \n\n注:grep 是文本操作命令,可以直接操作文本\n\n\n\n```bash\n=====================================================================\n示例1:-v:反转查找,输出与模式不相符的行\n---------------------------------------------------------------------\n[root@sanchuang-linux ~]# grep -v “#” /etc/yum.repos.d/centos.repo \n# 注:不输出包含# 的行\n============================================================================================\n\n示例2:-i 查找时忽略大小写\n---------------------------------------------------------------------\n[root@sanchuang-linux ~]# cd /etc/ssh/\n[root@sanchuang-linux ssh]# pwd\n/etc/ssh\n[root@sanchuang-linux ssh]# grep -i \"port\" /etc/ssh/sshd_config \t\t# 注:查找时忽略大小写\n# If you want to change the port on a SELinux system, you have to tell\n# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER\n#Port 22\n# WARNING: 'UsePAM no' is not supported in Fedora and may cause several\n#GatewayPorts no\n============================================================================================\n\n示例3:忽略大小写,并显示查找到的行号\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ssh]# grep -i -n \"port\" /etc/ssh/sshd_config \t\t# 注:显示符合模式要求的行号\n13:# If you want to change the port on a SELinux system, you have to tell\n15:# semanage port -a -t ssh_port_t -p tcp #PORTNUMBER\n17:#Port 22\n102:# WARNING: 'UsePAM no' is not supported in Fedora and may cause several\n108:#GatewayPorts no\n============================================================================================\n\n示例4:-r 递归搜索所有文件\n注:子目录以及子子目录下面查找\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ssh]# grep \"xxxxx\" * -r \t\t\t\t# 注:当前目录所有目录及子目录文件下的 递归查找\n[root@sanchuang-linux ssh]# grep \"GET\" /var/log/nginx -r \t# 注:nginx目录下面 递归查找\n/var/log/nginx/error.log:2020/10/29 12:01:02 [error] 12767#0: *2 open() \"/usr/share/nginx/html/favicon.ico\" failed (2: No such file or directory), client: 192.168.0.42, server: _, request: \"GET /favicon.ico HTTP/1.1\", host: \"192.168.0.34\", referrer: \"http://192.168.0.34/\"\n/var/log/nginx/error.log:2020/10/29 12:01:58 [error] 12767#0: *2 open() \"/usr/share/nginx/html/favicon.ico\" failed (2: No such file or directory), client: 192.168.0.42, server: _, request: \"GET /favicon.ico HTTP/1.1\", host: \"192.168.0.34\"\n--------------------------------------------------------------------------------------------\n#递归查找/var/log/nginx下的所有文件(包括其下面子目录里的文件)\n[root@mysql-binary nginx]# grep \"GET\" /var/log/nginx -r\n```\n\n\n\n---\n\n## 十一. 正则表达式\n\n**正则表达式**\n\n`^aa 表示以aa开头的行`\n`aa$ 表示以aa结尾的行`\n\n```\n[] 表示一个字符集\n[a-z] 从a - z 中取一个\n[^a-z] 不取a-z的字符\ngrep ^[^a-zA-Z0-9_] grep_test.txt 显示不以字母、数字、下划线开头的行\n```\n\n\n\n```bash\n示例1:不输出以#开头的行\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux yum.repos.d]# grep -v ^# centos.repo\n[root@sanchuang-linux yum.repos.d]# grep -v ^# centos.repo|grep -v ^$ # 注:不输出空白行\n注:不输出空白行 grep -v ^$\n 不输出以#开头的行 grep -v ^#\n============================================================================================\n\n示例2:过滤出grep_test.txt中,不以#号开头的行 和 非空白行\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# cat grep_test.txt\n#aaa\naaa#bbb\n\n456\n#\n789\n[root@sanchuang-linux chenpeng]# grep -v ^# grep_test.txt # 注:过滤出不以#号开头的行\naaa#bbb\n\n456\n789\n\n#方法1\n[root@sanchuang-linux chenpeng]# grep -v ^# grep_test.txt |grep -v ^$\t# 注:过滤出空白行\naaa#bbb # 注:如果是空白字符 不会被过滤\n456\n789\n\n#方法2\n过滤出grep_test.txt中 不以#开头的行和非空白行\n[root@sanchuang-linux chenpeng]# grep -v -E \"^#|^$\" grep_test.txt \naaa#bbb # 注:-E 正则表达式 ,| 或者 , -v 不显示\n456 # 注:-E:支持更多的元字符(支持扩展正则)\n789\n```\n\n\n\n---\n\n## 十二. [] 表示一个字符集(正则表达式)\n\n**[] 表示一个字符集(正则表达式)**\n\n```bash\n[root@localhost chenpeng]# cat grep_test.txt \nabc\nadc\nAbdc\nac\na1c\naxy\naxc\n123\n777\n示例1:过滤出abc adc\n--------------------------------------------------------------------------------------------\n[root@localhost chenpeng]# grep a[bd]c grep_test.txt # 注:取字符集[bd]里面的其中1个\nabc\nadc\n[root@sanchuang-linux chenpeng]# grep a[a-z]c grep_test.txt # 注:取出a-z中的1个字符\nabc # 注:ac 没有被过滤,必须有1个字符放在这里\nadc # 注:[a-z] 表示 从a - z 中取一个\naxc\n[root@sanchuang-linux chenpeng]# grep a[0-9]c grep_test.txt # 注:取出0-9中的1歌字符\na1c\n--------------------------------------------------------------------------------------------\n\n示例2:[^a-z] 不取a-z的字符\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# grep a[^a-z]c grep_test.txt # 注:^取反,ac之间不取a-z的字符\na1c\n\n示例3:取出不以字母开头的行\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# grep ^[^a-zA-Z] grep_test.txt # 注:不以a-zA-Z开头的行\n11c\n123 # 注:中间接空格 表示 包括空格\n777\n注:grep ^[a-zA-Z] grep_test.txt 以字母开头的行\n============================================================================================\n示例4:显示不以字母、数字、下划线开头的行\n写法1\n[root@sanchuang-linux chenpeng]# grep ^[^a-zA-Z0-9_] grep_test.txt\n写法2\n[root@sanchuang-linux chenpeng]# grep -v ^[a-zA-Z0-9_] grep_test.txt\n#注:显示不以字母、数字、下划线开头的行\n```\n\n\n\n---\n\n## 十三. 通配符(正则表达式)\n\n**通配符(正则表达式)**\n\n```\n* 代表匹配前一个项任意次\n? 代表匹配前一个项0次或者1次\n+ 代表匹配前一个项一次到多次\n. 占位符 除\\n之外的任意字符\n{n,m} 匹配前一项n到m次\negrep 等同于 grep -E\nfgrep 不支持任何正则,普通文本过滤\n```\n\n\n\n```bash\n示例1:* ? + .\n--------------------------------------------------------------------------------------------\n#注:匹配的都是前面这个字符\n[root@localhost ~]# cat grep_test.txt \nalc\naxxc\nac\n[root@localhost ~]# grep -E a.?c grep_test.txt # 注:-E 支持更多正则扩展\nalc # 注:. 占位符(注=一定要有1个字符)\nac # 注:.? 表示a和c之间.可以出现0次到1次\n[root@localhost ~]# grep -E a.*c grep_test.txt # 注:.* 表示a和c之间可以有任意个.(任意个字符)\nalc # 注:egrep 等同于 grep -E\naxxc\nac\n[root@localhost ~]# grep -E a.c grep_test.txt # 注:. 表示a和c之间只有1个字符\nalc\n[root@localhost ~]# grep -E a.+c grep_test.txt # 注:代表前一个字符.出现1个到多个\nalc\naxxc\n\n示例2:{ }\n--------------------------------------------------------------------------------------------\n#注:匹配的都是前面这个字符\n[root@localhost ~]# egrep \"a.{1}c\" grep_test.txt # 注:指定 . 出现1次\nalc\n[root@localhost ~]# egrep \"a.{1,2}c\" grep_test.txt # 注:指定 . 出现1次到2次\nalc\naxxc\n\n示例3:{ }\n--------------------------------------------------------------------------------------------\n[root@localhost ~]# cat grep_test.txt \nalc\naxxc\nac\nayy1c\naddddddc\n[root@localhost ~]# egrep \"a.{1,5}c\" grep_test.txt # 注:前1项 . 出现1次到5次\nalc\naxxc\nayy1c\n\negrep 等同于 grep -E\nfgrep 不支持正则,普通文本过滤\n```\n\n\n\n---\n\n## 十四. 练习:grep 正则表达式\n\n**grep 正则表达式**\n\n1、进入/lianxi目录,复制/etc/passwd到当前目录下,然后对passwd进行操作\n\n2、查找出当前passwd文件中以ftp或者mail开头的行,输出到屏幕\n\n```bash\ngrep -E \"^ftp|^mail\" passwd\negrep \"^ftp|^mail\" passwd\n```\n\n3、查找出当前passwd文件中不以r、m、f开头的行\n\n```bash\ngrep -v -E \"^r|^m|^f\" passwd\ngrep ^[^rmp] passwd\n```\n\n4、查找出当前passwd中以bash结尾的行\n\n```bash\ngrep bash$ passwd\n```\n\n5、查找出/etc/login.defs文件中的有效行(不显示空行和注释行,以#号开头的行)\n\n```bash\ngrep -v -E \"^#|^$\" /etc/login.defs\n```\n\n6、查找出/var/log/messages 文档中有15个字母的单词\n\n```bash\ngrep -E \"[^a-zA-Z][a-zA-Z{15}][^a-zA-Z]\" /var/log/message # 注:左右不是单词,中间15个字母\ngrep -E \"\\b[a-zA-Z{15}]\\b\" /var/log/message # 注:\\b自动匹配单词的边界\n```\n\n7、查找出/etc/passwd文件里用户名包含liu同时使用bash的用户\n\n```bash\ngrep liu /etc/passwd|grep bash$|cut -d\":\" -f1\n```\n\n8、查找出/etc/ssh/sshd_config里的有效行\n\n```bash\ngrep -v -E \"^#|^$\" /etc/ssh/sshd_config\n```\n\n9、查找出/etc/ssh/sshd_config 文件里包含连续2个字符的行\n\n```bash\ngrep -E \"(.)\\1\" /etc/ssh/sshd_config \ngrep -E \"(.)\\1\" # 注:.除了换行的任意一个字符 \\1前面这个组在\\1这里又出现一次(一模一样) \n```\n\n10、查找出包含特殊字符的行\n\n```bash\ngrep -E \"[^0-Z]\" grep_test.txt\n```\n\n11、查找出不包含数字的行\n\n```bash\ngrep -v \"[0-9]\" abc.txt\n```\n\n12、查找出/var/log/secure里的ip地址\n\n```bash\ncut -d \" \" -f11 /var/log/secure|grep -E \"\\..\"|sort|uniq 注:\\.转义 第二个. 表示任1字符\n```\n\n\n\n```bash\n--------------------------------------------------------------------------------------------\ngrep -E \"((([0-9])|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))\\.){3}(([0-9])|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))\" ip_test.txt\n============================================================================================\nip地址匹配:\n Ipv4 0-255 4个 192.168.1.0\n注:匹配ip地址\n[root@sanchuang-linux ~]# grep -E \"((([0-9])|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))\\.){3}(([0-9])|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))\" ip_test.txt\n192.168.0.1\n192.168.1.255\n172.0.0.1\n\n((([0-9])|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))\\.){3}(([0-9])|([1-9][0-9])|(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]))\n#括号括起来表示一个组\n\n分析\n0-255\n0-9 个位数\n[1-9][0-9] 十位数\n(1[0-9][0-9])|(2[0-4][0-9])|(25[0-5]) 百位数\n```\n\n\n\n---\n\n","tags":["Linux","Shell"],"categories":["Linux"]},{"title":"11_Linux基础-SHELL入门2","url":"/posts/35184.html","content":"## 一. 练习:用户 增删改查\n\n**脚本 编写一个脚本,实现如下功能**\n\n```\n====================\n1.增加用户并设置密码\n2.删除用户\n3.查看用户\n4.退出\n====================\n输入的指定不是1-4,给提示给予提醒,并且如果不输入退出的话,可以循环添加。\n按1  增加用户,并且设置密码 \tuseradd  passwd\n按2  删除用户    \t\t\t userdel -r \n按3  查看用户   \t\t\t\t id \n按4  退出       \t\t\t exit\n=====================================================================\n```\n\n\n\n```bash\n示例1:\n--------------------------------------------------------------------------------------------\nmenu(){\t\t\t\t\t\t\t\t\t#(注:函数)\necho \"====================\"\necho \"1.增加用户并增加密码\"\necho \"2.删除用户\"\necho \"3.查看用户\"\necho \"4.退出\"\necho \"====================\"\nread -p \"请选择您所需要的服务:\" ser\n}\n-------------------------------------------------\ncreate_user(){\t\t\t\t\t\t\t#(注:函数)\n read -p \"创建用户名:\" user1\n id $user1 &>/dev/null && echo \"用户已存在!\" && return\t#(注:退出函数,接return)\n useradd $user1 &>/dev/null\t\t\t\t#(注:导入黑洞文件)\n id $user1 &>/dev/null || return \t#(注:用户已存在 用Id 判断比较好。返回值非0可能是命令执行错误)\n read -s -p \"设置密码:\" passwd1\t\t\t#(注:-s密码隐藏)\n echo $passwd1|passwd $user1 --stdin &>/dev/null\n}\n-----------------------------------------------------------\nwhile :\ndo\nmenu\t\t\t\t#(注:调用函数)\ncase $ser in\t\t\t\n1)\n clear\t\t\t#(注:清空屏幕)\n create_user\n ;;\n2)\n# ……………………………………\n4)\n echo “退出!”\n exit\n ;;\n*)\t\t\t\t\t\t\t#(注:表示其他的所有选项,从上至下依次匹配)\n echo “请输入1-4!”\nesac\ndone\n-----------------------------------------------------------------------------------------------------------\n示例2:if 语法\n---------------------------------------------------------------------\n if [\"$options\"==1]||[\"$options\"==2]||[\"$options\"==3]||[\"$options\"==4]\n then\n case $options in\n 1)\n read -p \"请输入用户名:\" username\n if id $username &>/dev/null\n then\n echo \"$username is exist!\"\n else\n read -s -p \"请设置密码:\" password\n useradd $username &>/dev/null\n echo $password | $username --stdin &>/dev/null\n echo -e \"\\n create $username ok!\"\n fi \n ;;\n # ……………………………………………………\n 4)\n echo \"退出!\"\n exit\n esac\n else\n echo \"请输入数字1或2或3或4!\"\n fi\n```\n\n\n\n```bash\n补充:&&可以连接2个命令\n--------------------------------------------------------------------\n&&可以连接2个命令\n[root@sanchuang-linux ~]# id chen222\nuid=1017(chen222) gid=1017(chen222) 组=1017(chen222)\n[root@sanchuang-linux ~]# id chen222 && echo \"chen222存在\"\nuid=1017(chen222) gid=1017(chen222) 组=1017(chen222)\nchen222存在\n[root@sanchuang-linux ~]# id chen222 &>/dev/null && echo \"chen222存在\"\nchen222存在\n\n#注:用户已存在 用id 判断比较好。返回值非0可能是命令执行错误\n```\n\n\n\n---\n\n## 二. 变量\n\n**变量 全局/局部**\n\n### Shell\n\n`Shell中定义的变量 默认全局变量`\n\n```bash\n===========================================================================================\nlocal a=10 局部变量\n示例1:local 局部变量\n--------------------------------------------------------------------------------------------\nfunc01(){\n local a=10\n}\n\nfunc01\t\t\t\t\t\t\t\t#(注:调用函数)\necho $a\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# sh aaa.sh \n\t\t\t\t\t\t\t\t\t#(注:为空。局部变量)\n============================================================================================\n示例2:默认全局变量\n--------------------------------------------------------------------------------------------\nfunc01(){\n a=10\n}\n\nfunc01\t\t\t\t\t\t\t\t#(注:调用函数)\necho $a\n[root@sanchuang-linux chenpeng]# sh aaa.sh \n10\t\t\t\t\t\t\t\t\t#(注:全局变量)\n```\n\n\n\n### Python\n\n`Python定义的变量 默认局部变量`\n\n```python\n===========================================================================================\nglobal a 全局变量\n示例1:global a 全局变量\n--------------------------------------------------------------------------------------------\ndef func01():\n global a \t\t\t\t#(注:全局变量)\n a = 10\n\nfunc01()\nprint(a)\n[root@sanchuang-linux ~]# python3 python_hanshu.py \n10\n============================================================================================\n示例2:默认局部变量 只能在函数体内使用的变量\n--------------------------------------------------------------------------------------------\ndef func01():\n a = 10\n\nfunc01()\nprint(a)\n\n[root@sanchuang-linux ~]# python3 python_hanshu.py \nTraceback (most recent call last):\n File \"python_hanshu.py\", line 5, in <module>\n print(a)\nNameError: name 'a' is not defined\t\t\t\t#(注:局部变量)\n```\n\n\n\n### Shell函数里传参(位置变量)\n\nshell函数里传参(位置变量)\n\n```bash\n示例:\n--------------------------------------------------------------------------------------------\nShell里传参\nfunc01(){\n a=100\n echo \"$1 $2 $3\"\t\t\t\t\t\t#(注:函数的参数 [位置变量])\n}\nfunc01 第一个参数 第二个参数 第三个参数\t\t#(注:调用参数)\necho $a\n```\n\n\n\n### Python里传参\n\npython里传参\n\n```python\n示例:python里传参\n--------------------------------------------------------------------------------------------\ndef func01(x,y):\n global a\n a = 10\n\nfunc01(1,2)\nprint(a)\n```\n\n\n\n---\n\n## 三. test\n\n**test判断 等同于[]**\n\n```bash\n示例:test\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# a=123\n[root@sanchuang-linux chenpeng]# b=123\n[root@sanchuang-linux chenpeng]# test a==b\n[root@sanchuang-linux chenpeng]# test a==b && echo ok\nok\n```\n\n\n\n---\n\n## 四. 判断方式 [] [[]] (()) test\n\n**判断方式 [] [[]] (()) test**\n\n- (( ))\t判断数字 > < == !=\n- [[ ]]\t判断字符串 或者 -eq -ne -gt -lt 判断数字\n- 有些语法 [ ] 是不支持的,建议使用[[ ]]\n- **test(测试)判断,等同于1个中括号**\n\n```bash\n示例:test\n---------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=123\n[root@sanchuang-linux ~]# b=123\n[root@sanchuang-linux ~]# test a==b && echo ok\nok\n[root@sanchuang-linux ~]# test a==b && echo ok || echo error\nok\n```\n\n\n\n---\n\n## 五. 连接运算\n\n**连接运算**\n\n使用分号(;)实现一行中写多条语句\n\n```bash\n示例:\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# echo \"abc\";echo \"xyz\"\nabc\nxyz\n```\n\n\n\n---\n\n## 六. 函数\n\n### 函数的定义/使用\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\nadd(){\n echo “两数相加为:$(( $num1 + $num2 ))”\n}\nadd\n============================================================================================\n```\n\n\n\n### 函数的传参\n\n```bash\n示例:位置参数传参\n--------------------------------------------------------------------------------------------\nfunc01(){\n a=100\n echo \"$1 $2 $3\"\n}\n\nfunc01 第一个参数 第二个参数 第三个参数\necho $a\n============================================================================================\n·函数内的变量定义 \t 默认为全局变量\n·使用local关键字 \t可以转换为局部变量\n```\n\n\n\n---\n\n## 七. seq\n\n**seq命令**\n\nseq命令 类似于 python中的range函数\n\n用途:**打印出一串有序的数字 **\n\n格式:seq\t`[选项]\t数字范围`\n\n**-s:指定分隔符**\n\n**-w:指定同等宽带输出**\n\n\\----------------------------------------\n\n数字范围的展示:\n\n[start] [step] end\n\nstart 和 step 都是选填的\n\nstep 为正,表示从小到大输出\n\nstep 为负,表示从大到小输出\n\n\n\n```bash\n示例1:[start] [step] end\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# seq 3 -1 1\t\t\t# 注:中间是步长。左右是起始位置\n3\n2\n1\n[root@sanchuang-linux ~]# seq 1 2 6\n1\n3\n5\n[root@sanchuang-linux ~]# seq 1 -2 6\t\t\t# 注:步长为负数时,从1到6没有输出\n[root@sanchuang-linux ~]# seq 6 -2 1\n6\n4\n2\n示例2:# seq 2 5 # seq -w 9 12\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# seq 2 5\n2\n3\n4\n5\n[root@localhost ~]# seq -w 9 12\t\t\t# -w 指定同等宽度输出\n09\n10\n11\n12\n============================================================================================\n补充 获取命令的返回结果\n·使用反引号 ``\n·或者 $()\n示例3:获取/etc/passwd最后一行,赋给一个变量\n[root@sanchuang-linux ~]# tail -n1 /etc/passwd\t\t\t\t# 注:获取最后一行 # tail -n1\nwtc:x:1029:1029::/home/wtc:/bin/bash\n[root@sanchuang-linux ~]# line=`tail -n1 /etc/passwd`\t\t# 注:方法1\n[root@sanchuang-linux ~]# echo $line\nwtc:x:1029:1029::/home/wtc:/bin/bash\n[root@sanchuang-linux ~]# line1=$(tail -n1 /etc/passwd)\t\t# 注:方法2\n[root@sanchuang-linux ~]# echo $line1\nwtc:x:1029:1029::/home/wtc:/bin/bash\n============================================================================================\n示例4:seq命令 类似于 python中的range函数\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# vim seq_test.sh\nfor i in `seq 2 10`\t\t# 注:反引号 执行这个命令,获取命令的返回值\ndo\t\t\t\t\t\t# 注:seq 2 10 包括2,包括10\n echo $i\ndone\n-----------------------------------------------------------------------\nfor i in $(seq 2 10)\t# 注:也表示执行这个命令,获取命令的返回值\ndo\n echo $i\ndone\n[root@sanchuang-linux ~]# bash seq_test.sh \n2\n3\n4\n5\n6\n7\n8\n9\n10\n============================================================================================\n示例5:-s:指定分隔符\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# seq -s \"+\" 10\t\t\t# -s:指定分隔符\n1+2+3+4+5+6+7+8+9+10\t\t\t\t\t\t\t# 注:不搞开头,默认情况下 从1开始,到10\n[root@sanchuang-linux ~]# seq 10\t\t\t\t#注:默认情况下 连接符是 换行符\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n```\n\n\n\n---\n\n## 八. 练习:创建用户\n\n**创建用户(3次重试机会)脚本**\n\n```bash\n示例:seq命令 创建失败 重试\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# vim user_add.sh\n#!/bin/bash\n# 增加\t\t\t\t\t\t\t\t# 注:用户增加的部分\nadd(){\n for i in `seq 3 -1 1`\t\t\t\t# 注:seq 命令类似于pythonrange函数 3 2 1\n do\n echo \"增加用户\"\n read -p \"请输入用户名:\" username\n id $username &>/dev/null && echo \"用户已存在,还有$(( $i - 1))次机会\" && continue\n #if id $username &>/dev/null \n #then\n # echo \"用户已存在,还有$(( $i -1 ))次机会\"\n # continue\n #fi \n #useradd $username &>/dev/null && echo \"创建成功!\" && echo $password | passwd $username --stdin &>/dev/null && break || echo -e \"\\n创建失败!\"\n if useradd $username &>/dev/null\n then\n echo \"创建${username}成功!\"\n read -s -p \"请设置密码:\" password\n echo $password | passwd $username --stdin &>/dev/null\n break\n else\n echo \"创建失败!,还有$(($i-1))次机会!\"\n fi\n done\n}\n# 删除\ndel(){\n echo \"删除用户\"\n read -p \"请输入用户名:\" username\n userdel -r $username &>/dev/null && echo \"删除成功!\" || echo \"用户不存在,删除失败!\"\n}\n# 查看\nseek(){\n echo \"查看用户\"\n read -p \"请输入用户名:\" username\n id $username \n}\necho \"#############################\"\necho \"按1 增加用户,并且设置密码\"\necho \"按2 删除用户\"\necho \"按3 查看用户\"\necho \"按4 退出\"\necho \"#############################\"\nwhile :\ndo\n read -p \"请输入你的选择:\" options\n case $options in\n 1)\n add\n ;;\n 2)\n del\n ;;\n 3)\n seek\n ;;\n 4)\n echo \"退出!\"\n exit\n ;;\n *)\n echo \"请输入指定内容 1-4!\"\n esac\ndone\n```\n\n\n\n---\n\n## 九. 循环获取文件或者命令输出的内容(3种)\n\n### 重定向\n\n```bash\n示例1:重定向 while read a b c\t; < a.txt\n--------------------------------------------------------------------------------------------\n#!/bin/bash\nwhile read a b c\ndo\n echo \"name is $a, sex is $b, age is $c \"\ndone < a.txt\t\t\t\t\t# 注:当前路径下的文件。可以接绝对路径\n============================================================================================\n```\n\n\n\n### 管道符号\n\n```bash\n示例2:管道符号\tcat a.txt | while read a b c\n--------------------------------------------------------------------------------------------\ncat a.txt | while read a b c\ndo \n echo \"name is $a, sex is $b, age is $c \"\ndone\n============================================================================================\n```\n\n\n\n### for循环\n\n```bash\n示例3:for 循环实现(注:使用for循环去做,不太好)\n#for循环默认以空白(空格/回车 制表符)分割\n--------------------------------------------------------------------------------------------\necho \"for 循环实现...........\"\nfor i in `ls`\t\t\t\t\t# i 代表空白输出的每个文件\ndo\n echo $i\ndone\n--------------------------------------------------------------------------------------------\n示例3.2:i代表文件的每一项,以空白分割\n[root@sanchuang-linux ~]# vim file_test.sh\nfor i in `cat a.txt`\ndo\n echo $i\ndone\n[root@sanchuang-linux ~]# bash file_test.sh \nwenyao\nf\n18\nchenpeng\nm\n19\nwtc\nf\n17\n[root@sanchuang-linux ~]# cat a.txt \nwenyao f 18\nchenpeng m 19\nwtc f 17\n示例3.3:for i in `ls -al`\t\t# i代表当前目录下详细信息,i代表以空白分割的每一项\n```\n\n\n\n---\n\n## 十. 练习:找出list.xml中主机为ZF的行然后循环输出ip与区服对应的关系\n\n**找出list.xml中主机为ZF的行然后循环输出ip与区服对应的关系**\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# cat list.xml \n####IP 主机名 区服#########\n127.0.0.1 ZF-1 1 33 49 57\n127.0.0.1 ZF-11 65 67 69\n127.0.0.1 HF-1 22 34 6\n127.0.0.1 HF-11 6 17 36\n127.0.0.1 ZF-12 1 2\n127.0.0.1 HF-1 34 7\n--------------------------------------------------------------------------------------------\n步骤1:首先过滤出ZF所在的行\n[root@sanchuang-linux ~]# vim test6.sh \n#!/bin/bash\t\t\t\t\t\t\t\t\t# 管道| 把输出 作为下一条命令的输入\ncat list.xml |grep ZF |while read ip host qufu\t\t# 首先过滤出ZF所在的行\ndo\t\t\t\t\t\t\t\t\t\t\t# while read 获取内容\n echo \"ip:$ip, qufu:$qufu\"\t\t\t\t\t# 注:参数3整个赋给$qufu\ndone\n[root@sanchuang-linux ~]# cat list.xml | grep ZF\n127.0.0.1 ZF-1 1 33 49 57\n127.0.0.1 ZF-11 65 67 69\n127.0.0.1 ZF-12 1 2\n[root@sanchuang-linux ~]# sh test6.sh \t\t\t# 注:$ip $host $qufu 不一定需要对应\nip:127.0.0.1, qufu:1 33 49 57\t\t\t\t\t# 前两个对应的,把前两个都取了\nip:127.0.0.1, qufu:65 67 69\t\t\t\t\t\t# 后面有的话,就全部是后面的内容\nip:127.0.0.1, qufu:1 2\t\t\t\t\t\t\t# 没有的话就为空(取不到的话就为空)\n--------------------------------------------------------------------------------------------\n步骤2:套个循环\n#!/bin/bash\ncat list.xml |grep ZF |while read ip host qufu\ndo\n for i in $qufu\t\t\t\t\t\t\t\t# 注:套个循环。for循环以空格进行分割\n do\n echo \"ip:$ip, qufu:$i\"\t\t\t\t\t# 注:这里是i。对区服进行循环\n done\ndone\n[root@sanchuang-linux ~]# sh test6.sh \nip:127.0.0.1, qufu:1\nip:127.0.0.1, qufu:33\nip:127.0.0.1, qufu:49\nip:127.0.0.1, qufu:57\nip:127.0.0.1, qufu:65\nip:127.0.0.1, qufu:67\nip:127.0.0.1, qufu:69\nip:127.0.0.1, qufu:1\nip:127.0.0.1, qufu:2\n```\n\n\n\n---\n\n## 十一. 循环获取文件或者命令输出的内容\n\n**循环获取文件或者命令输出的内容**\n\n- for i in 默认 以空白分割 循环获取每个元素\n\n- while read 每次获取整行\n\nwhile read的参数 可以接任意个,默认还是以空白分割\n\n如果参数没有对应获取的值,那参数就为空\n\n如果文件中空白分割的参数大于read接受的参数,那多出的参数都会赋给最后一个read接受的参数\n\n\n\n```\n管道 进制之间通信的一种方式\n```\n\n\n\n---\n\n## 十二. shell中的一维数组\n\n**shell中的一维数组**\n\nshell中的一维数组 使用\n定义:使用`圆括号`,中间以 `空格` 作为分隔符\n博客连接:https://www.cnblogs.com/tangshengwei/p/5446315.html\n\n\n\n```bash\n示例14.1:定义、索取\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=(xx yy zz)\t\t\t# 注:a 是一个数组\n[root@sanchuang-linux ~]# a=(xx yy zz ff)\t\t# 注:a 是一个数组\n[root@sanchuang-linux ~]# echo ${a[0]}\t\t\t# 注:通过索引查找,下标从0开始\nxx\n[root@sanchuang-linux ~]# echo ${a[1]}\t\t\t# 注:通过索引查找\nyy\n[root@sanchuang-linux ~]# echo ${a[3]}\nff\n[root@sanchuang-linux ~]# echo ${a[@]}\t\t\t# 注:${a[@]} 表示它里面的每一个数,@ 取它里面的全部值\nxx yy zz ff\t\t\t\t\t\t\t\t\t\t# 注:$@ 参数列表里面的全部内容\n[root@sanchuang-linux ~]# echo ${a[@]:1:4}\t\t# 注:索取(切片)\nyy zz ff\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=(xx yy zz ff)\n[root@sanchuang-linux ~]# echo $a\t\t\t# 注:echo $a 只取出一位数组里的第一个元素\nxx\n[root@sanchuang-linux ~]# echo ${a[*]}\t\t# 注:${a[*]} 取出一位数组里面的全部内容,效果一样\nxx yy zz ff\n[root@sanchuang-linux ~]# echo ${a[@]}\t\t# 注:${a[@]} 取出一位数组里面的全部内容\nxx yy zz ff\n[root@sanchuang-linux ~]# echo ${a:0:4}\t\t# 注:对字符 xx 进行截取 从0开始\nxx\n[root@sanchuang-linux ~]# echo ${a:1:4}\t\t# 注:对字符 xx 进行截取 从1开始\nx\n[root@sanchuang-linux ~]# echo ${a[*]:1:3}\t# 注:索取,效果一样(切片)\nyy zz ff\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=(1 2 3 4)\n[root@sanchuang-linux ~]# echo ${a[*]:1:3}\t# 注:索取,闭区间(切片)\n2 3 4\n============================================================================================\n获取长度(元素个数)\n#注:$#\t获取参数列表长度\n# echo ${#a[*]}\n# echo ${#a[@]}\n示例14.2:获取一位数组长度(元素个数)\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# echo ${#a[*]}\t\t\t# 注:不能用$a直接获取,因为 $a 代表 里面第一个元素\n4\n[root@sanchuang-linux ~]# echo ${#a[@]}\n4\n[root@sanchuang-linux ~]# echo ${#a}\t\t\t# 注:第一个元素长度\n2\n###########################################################################################\n示例14.3:获取字符串长度 echo ${#b}\n[root@sanchuang-linux ~]# b=abc\n[root@sanchuang-linux ~]# echo ${#b}\n3\n============================================================================================\n修改/删除 元素(shell里面一维数组的修改/删除)\n示例14.4:修改/删除 元素\n[root@sanchuang-linux ~]# echo ${a[*]}\nxx yy zz ff\n[root@sanchuang-linux ~]# a[3]=\"hh\"\t\t\t\t\t# 注:修改元素\n[root@sanchuang-linux ~]# echo ${a[*]}\nxx yy zz hh\t\t\t\t\t\t\t\t\t\t\t# 注:清空数组 unset a\n[root@sanchuang-linux ~]# unset a[3]\t\t\t\t# 注:删除指定元素(下标为3)\n[root@sanchuang-linux ~]# echo ${a[*]}\nxx yy zz\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# echo ${a[*]}\nxx zz\n[root@sanchuang-linux ~]# unset a[1]\t\t\t\t# 注:删除不了\n[root@sanchuang-linux ~]# echo ${a[*]}\nxx zz\n[root@sanchuang-linux ~]# echo ${!a[*]}\t\t\t\t# 注:加! 看元素的下标\n0 2\t\t\t\t# 注:删除后,不会重新分配下标。一开始每个值的下标都一一对应了,不会改\n[root@sanchuang-linux ~]# unset a[2]\t\t\t\t# 注:删除zz元素,unset a[2],下标为2\n[root@sanchuang-linux ~]# echo ${a[*]}\nxx\n[root@sanchuang-linux ~]# \n```\n\n\n\n---\n\n## 十三. linux里 生成随机数\n\n**linux里 生成随机数**\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# echo $RANDOM \t\t# 注:自定义的环境变量\n15386\n[root@sanchuang-linux ~]# echo $RANDOM \n24960\n############################################################################################\n知识点15.2 生成指定范围内的随机数\n示例1:产生10以内的随机数(不含10)\n[root@sanchuang-linux ~]# echo $(($RANDOM % 10)) \n1\n[root@sanchuang-linux ~]# echo $(($RANDOM % 10)) \n8\n[root@sanchuang-linux ~]# echo $(($RANDOM % 10)) \n2\n[root@sanchuang-linux ~]# echo $(($RANDOM % 10)) \n3\n```\n\n\n\n---\n\n## 十四. 练习:编写一个随机抽取同学唱歌的程序,如果唱过了,就不能再次被抽到了\n\n**编写一个随机抽取同学唱歌的程序,如果唱过了,就不能再次被抽到了**\n\n1、编写一个文件,里面存放我们歌手的名字 name.txt\n\n2、随机抽取歌手\t\t\t\t\t\t\t\t# 1.循环抽取 2.抽到了就丢掉\n\n\n\n```bash\n============================================================================================\n#注:使用命令的输出 用``反引号\n#注:把读到的人员名单变成一个数组\n示例\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# vim geshou_test.sh\n#!/bin/bash\n# 将name.txt的内容读取出来\t\t\t\t\t # 注:反引号` ` 把cat命令的输出放到数组里\nsingers=(`cat name.txt`)\t\t\t\t\t# 注:把读取的内容放到数组里面(cat读取)\necho ${singers[@]}\t\t\t# 注:验证是否取出数据\t# 注:相对路径 指当前下的文件\n# 有多少人\ntotal=${#singers[@]}\t\t\t\t\t\t# 首先 获取人数(对singers长度进行统计)\n\nfor i in `seq $total`\t\t\t\t\t\t# 然后循环(for 循环次数,$total 人数进行循环)\ndo\t\t\t\t\t\t\t\t\t\t\t# 注:反引号` ` 命令去执行它\n read -p \"请输入任意键进行抽取\"\t\t\t # 注:read 目的:敲一下键盘 才会接着循环\n # 随机抽取一个人演唱\t\t\t\t# 每次循环都是抽取 新的 列表里面的人数(因为下标问题)\n random_num=$(( $RANDOM % ${#singers[*]} ))\t\t#注:生成随机数,范围0 ~ 一维数组长度\n echo \"随机数为:$random_num\"\t\t\t\t# 注:随机抽取索引/下标\n echo \"有请${singers[$random_num]}献唱一首!大家热烈欢迎!\"\n unset singers[$random_num]\t\t\t\t# 注:把选中的人删除(与python不同的是,删除以后下标不变)\n singers=(`echo ${singers[@]}`)\t\t\t# 注:解决办法 重新赋值,赋值给一个新的一维数组\n echo \"未献唱者具体名单为: ${singers[@]}\"\t # 注:↑也可以使用 singers=(${singers[@]})\ndone\t\t\t\t\t\t\t\t\t\t# 注:↑也可以使用singers= `echo ${singers[@]}`\n[root@sanchuang-linux chenpeng]# cat name.txt \t# 注:↑重新赋值后 下标会变 从0~总长度\nfengcheng\nzhanghuayou\npengyifan\nchenpeng\nxulilin\ntangliangfei\nwangtiancheng\nlixinhai\nliangluyao\n--------------------------------------------------------------------------------------------\n演示\n[root@sanchuang-linux chenpeng]# sh geshou_test.sh \nfengcheng zhanghuayou pengyifan chenpeng xulilin tangliangfei wangtiancheng lixinhai liangluyao\n请输入任意键进行抽取\n随机数为:2\n有请pengyifan献唱一首!大家热烈欢迎!\n未献唱者具体名单为: fengcheng zhanghuayou chenpeng xulilin tangliangfei wangtiancheng lixinhai liangluyao\n请输入任意键进行抽取\n随机数为:2\n有请chenpeng献唱一首!大家热烈欢迎!\n未献唱者具体名单为: fengcheng zhanghuayou xulilin tangliangfei wangtiancheng lixinhai liangluyao\n\n#注:获取命令输出的时候 加``反引号\n```\n\n\n\n---\n\n## 十五. 练习:产生5--10之间随机数\n\n**产生5--10之间随机数**\n\n```bash\n产生5--10之间随机数\n[root@sanchuang-linux chenpeng]# echo $(( $RANDOM % 10 ))\t\t# 注:产生10以内随机数\n3\n[root@sanchuang-linux chenpeng]# echo $(( $RANDOM % 5 +5 ))\t\t# 注:取5以内的随机数 +5\n6\n[root@sanchuang-linux chenpeng]# echo $(( $RANDOM % 5 +5 ))\n8\n--------------------------------------------------------------------------------------------\n50--150之间随机数\n[root@sanchuang-linux chenpeng]# echo $(( $RANDOM % 100 +50 ))\n79 # 注:100是区间绝对值,50是初始值\n--------------------------------------------------------------------------------------------\n150-200之间随机数 # 注:150初始值, 50 + 150 末尾值\n[root@sanchuang-linux ~]# echo $(( $RANDOM % 50 + 150 ))\t# 注:150~200之间\n190\n```\n\n\n\n---\n\n## 十六. tr(替换命令)\n\n**tr命令(替换命令)**\n\ntr命令(主要用来做字符的替换)\t\t\t\t\t # 注:对文本处理常用\n\n- 字符转换工具\n- 只能对`stdin`操作,不能直接对文件操作\t# 注:**只能对标准输入进行操作**\n\n\\----------------------------------------------------\n\n使用tr转换字符\n\n- tr SET1 SET2\n- 用SET2中的字符替换掉SET1中同一位置的字符\n\n**tr -d 删除指定字符**\n**tr -s 压缩相同字符,将连续的指定字符压缩成一个字符**\n\n\n\n```bash\n示例\n--------------------------------------------------------------------------------------------\n示例1:替换\n#注:替换同位置的\n[root@sanchuang-linux chenpeng]# echo 123456| tr 345 xyz\t# 注:把345替换成xyz\n12xyz6\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:只能对标准输入进行操作\n[root@sanchuang-linux chenpeng]# echo 123456| tr 3 xyz\t\t# 注:把3替换成xyz\n12x456\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:只替换了x,对应位置的\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:有几个位置,替换几个字符\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t# 注:替换同位置的\n============================================================================================\n示例2:删除 # echo 123456| tr -d 34\ntr -d 删除指定字符\n[root@sanchuang-linux chenpeng]# echo 123456| tr 3 \"\"\t\t# 注:\"\" 不能为空,它要替换同位置的\ntr: 当不截断设置1 时,字符串2 不能为空\n[root@sanchuang-linux chenpeng]# echo 123456| tr -d 34\t\t# 注:删除接tr -d\n1256\n============================================================================================\ntr -s 压缩相同字符,将连续的指定字符压缩成一个字符\n将连续的指定字符压缩成一个字符\n示例3:tr -s 压缩相同字符\n[root@sanchuang-linux chenpeng]# echo 111223333444445556666| tr -s 34\n11122345556666\t\t\t\t\t\t\t\t\t\t\t\t# 注:当有连续的时候压缩成一个\n[root@sanchuang-linux chenpeng]# echo 11122333344444555666633377744| tr -s 34\n1112234555666637774\t\t\t\t\t\t\t\t\t\t\t# 注:并不是去重\n============================================================================================\n练习4:把环境变量里 : 替换成空格\t\t\t\t\t\t\t\t # 注:关键点 tr不能替换文件内容\n[root@sanchuang-linux chenpeng]# echo $PATH |tr \":\" \" \"\t\t# 注:关键点 tr接收的是标准输入\n/lianxi/sc /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /root/bin /usr/local/nginx/sbin /root/bin /usr/local/nginx5/sbin /root/bin\n============================================================================================\n扩展5:替换文件里的内容,生成一个新文件\n#注:把文件导进来 进行标准输入\n示例:将/etc/passwd里的 :替换成空格\n--------------------------------------------------------------------------------------------\n写法1:cat导入\n[root@sanchuang-linux chenpeng]# cat /etc/passwd |tr \":\" \" \" >/tmp/passwd\n[root@sanchuang-linux chenpeng]# less /tmp/passwd \t\t\t# 注::全变空格了\n写法2:tr接收标准输入 重定向标准输入 tr \":\" \" \" </etc/passwd\n[root@sanchuang-linux chenpeng]# tr \":\" \" \" </etc/passwd >/tmp/passwd2 \n[root@sanchuang-linux chenpeng]# less /tmp/passwd2\t\t\t# 注::全变空格了\n#注:写法2把一个文件导进来,进行标准输入 tr \":\" \" \" </etc/passwd\n============================================================================================\n扩展5.1 重定向标准输入\n[root@sanchuang-linux chenpeng]# wc -l /etc/passwd\t\t\t# 注:wc -l 查看文件行数\n52 /etc/passwd\n示例:重定向标准输入\n[root@sanchuang-linux chenpeng]# wc -l < /etc/passwd\n52\n```\n\n\n\n---\n\n","tags":["Linux","Shell"],"categories":["Linux"]},{"title":"10_Linux基础-SHELL入门1","url":"/posts/30664.html","content":"## 一. 输入输出重定向\n\n**回顾1 输入输出重定向**\n\n输入\n\nread -p “请输入” a\t\t-p 提示 a 赋值给a\n\nread -s 密码隐藏\n\n---\n\n输出\n\n​\t\techo\n\n​\t\t\\# echo -e “abc\\t abc”\t转义字符输出\n\n​\t\tabc\t\tabc\n\n​\t\t\\# echo “abc\\t abc”\n\n​\t\tabc\\t abc\n\n`echo -n 不接换行`\n\n`echo -e 转义字符输出`\n\n\n\n---\n\n## 二. 2个特殊文件\n\n**知识点2 2个特殊文件**\n\n两个特殊文件\n\n·`/dev/null`:过滤标准错误信息\n\n·`/dev/zero`:用来创建指定长度文件\n\n`/dev/null`:黑洞文件,不保存,不输出的信息,就丢到黑洞文件\n\n`/dev/zero`:用来生成指定大小的文件,生成一堆0\n\n---\n\n示例:`/dev/zero`:用来生成指定大小的文件,生成一堆0\n\n`/dev/zero`一般用作生成指定大小的文件,做测试用\n\ndd是一个备份命令,也可以产生一个指定大小的文件\n\nif\t 输入文件 input file\n\nof\t 输出文件 output file\n\nbs\t 输出的数据的单位大小\n\ncount 输出的数据单位数量\n\n示例:\\_\\_\\_\\_\\_\\__\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\__\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\__\\_\n\n```bash\n[root@sanchuang-linux dev]# dd if=/dev/zero of=/tmp/test.dd bs=1M count=5\n记录了5+0 的读入\n记录了5+0 的写出\n5242880 bytes (5.2 MB, 5.0 MiB) copied, 0.00196718 s, 2.7 GB/s\n[root@sanchuang-linux dev]# du -sh /tmp/test.dd \n5.0M\t/tmp/test.dd\nif 从哪里导进来 , of 导出去这个文件 , bs 数据单位大小 , count数据单位数量\n```\n\n\n\n---\n\n## 三. here document\n\n**知识点3 here document**\n\n`here document\t文档就在这里`\n\n<<\n\n生成一个指定内容的文档。\n\n简单脚本中使用\n\n示例:\n\n\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\n\n[root@sanchuang-linux chenpeng]# `cat >here_test.txt <<EOF`\n\\> nihao\n\\> sanchuang\n\\> huanying\n\\> world............\n\\> x y z\n`\\> EOF`\n[root@sanchuang-linux chenpeng]# cat here_test.txt \nnihao\nsanchuang\nhuanying\nworld............\nx y z\n\n\n\n---\n\n**知识点3.2 EOF是文档结束标志 可以自行定义\t(end of file)**\n\n示例:\n\n\\------------------------------------------------------\n\n[root@sanchuang-linux chenpeng]# cat >here_test <<`XYZ`\n\\> nihao\n\\> hello world\n`> XYZ`\n[root@sanchuang-linux chenpeng]# cat here_test\nnihao\nhello world\n\n\n\n---\n\n## 四. tee命令\n\n**知识点4 tee命令**\n\n`tee命令 输出到屏幕也重定向到文件`\n\n示例:\n\n\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\--\\-\\-\n\n[root@sanchuang-linux chenpeng]# echo \"aa\" >test_aa.txt\t#(注:默认不输出到屏幕)\n[root@sanchuang-linux chenpeng]# cat test_aa.txt \naa\n[root@sanchuang-linux chenpeng]# `echo \"bb\" |tee test_bb.txt\t#`(注:屏幕+文件)\nbb\n[root@sanchuang-linux chenpeng]# cat test_bb.txt \nbb\n\n\n\n---\n\n## 五. 清空文件内容\n\n**知识点5 清空文件内容**\n\n[root@sanchuang-linux chenpeng]# `>test_bb.txt`\n[root@sanchuang-linux chenpeng]# `echo > test_bb.txt` #(注:有换行)\n[root@sanchuang-linux chenpeng]# cat test_bb.txt \n\n[root@sanchuang-linux chenpeng]# `echo -n > test_bb.txt `\n[root@sanchuang-linux chenpeng]# cat test_bb.txt \n[root@sanchuang-linux chenpeng]# `:>test_bb.txt `\n[root@sanchuang-linux chenpeng]# cat test_bb.txt \n\n\n\n---\n\n**知识点6 echo**\n\n`echo`\n\n在屏幕上显示一段文字或指定内容\n\n输出变量,输出指定内容\n\n`-e 选项\t转义字符输出`\n\n`-n 选项\t不接换行`\n\n\n\n---\n\n## 六. SHELL入门\n\n`shell入门`\n\nshell 是一个用C语言写的程序,它是用户使用linux的桥梁\n\nshell 脚本 实现自动化 重复性的操作编写脚本完成,减少人工失误\n\n\n\n---\n\n### SHELL的变量\n\n`shell的变量`\n\n1、局部变量 定义在脚本或命令中\n\n2、环境变量 shell启动的程序能访问到的环境变量 env、 echo $PATH\n\n3、shell变量\n\n```bash\n示例:环境变量\n------------------------------------------\n[root@sanchuang-linux chenpeng]# which ls\nalias ls='ls --color=auto'\n\t/usr/bin/ls\t\t\t\t\t\t\t#(注:环境变量)\n[root@sanchuang-linux chenpeng]# echo $PATH\t#(注:环境变量)\n/lianxi/sc:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/nginx/sbin:/root/bin:/usr/local/nginx5/sbin:/root/bin\n示例2:局部变量\n-------------------------------------------\na=1\necho $a\necho ${a}\n```\n\n\n\n---\n\n**知识点8.2 变量名命名规则**\n\n`变量名命名规则:`\n\n由数字、字母、下划线组合,不能以数字开头\n\n不能使用bash中的关键字\n\n \n\n`使用一个定义过的变量,需要在前面加上$符号`\n\n```bash\n示例:\n--------------------------------------------\n[root@sanchuang-linux chenpeng]# echo $PATH\t\t#(注:环境变量)\n/lianxi/sc:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin:/usr/local/nginx/sbin:/root/bin:/usr/local/nginx5/sbin:/root/bin\n```\n\n\n\n---\n\n### SHELL接收参数\n\n**知识点9 shell接收参数**\n\nshell接收\n\n`位置变量 :$1 - $9 ,分别代表参数列表中的 第1 - 9 个参数`\n\n可以重复使用(即脚本里可以出现两个$1)\n\n\n\n---\n\n`预定义变量,系统预留的一些变量:`\n\n$0 当前进程 或者 脚本名称\n\n$! 后台运行的最后一个进程的pid号\n\n$? 上一条命令程序返回值\n\n$* 代表所有参数内容\n\n\\$\\$ 表示当前进程pid号\n\n$# 表示参数个数\n\n$@ 代表所有参数(逐个提取)\n\n\n\n---\n\n`# perror 1`\n\n查看命令的返回值,并且看返回值的**具体含义**\n\n$? 命令返回值为0 表示正常执行\n\n​\t\t不为0 都表示运行错误\n\n```bash\n示例如下:__________________________________\n[root@mysql-binary shell_test]# echo $?\n1\n[root@mysql-binary shell_test]# perror 1\nOS error code 1: Operation not permitted\n```\n\n\n\n---\n\n\n\n`#!/bin/bash\t脚本前最好加上这一行,默认使用什么解释器去执行`\n\n`原因:类unix操作系统,unbuntu、debian、centos每个操作系统的默认bash可能不一样`\n\n\n\n---\n\n**示例1:`位置变量$1、$2` \\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_**\n\n[root@sanchuang-linux shell_test]# cat canshu.sh \n\\#!/bin/bash\n\necho \"########这是$1########\"\t\t#(注:位置变量)\necho \"$1\"\t\t\t\t\t\t\t\t\t\t\t\t\t\t#(注:位置变量)\necho \"########这是$2########\"\t\t#(注:位置变量)\necho \"$2\"\t\t\t\t\t\t\t\t\t\t\t\t\t\t#(注:位置变量)\n[root@sanchuang-linux shell_test]# sh canshu.sh `\"hello\" \"world\"\t#`(注:传了2个参数)\n\\########这是hello########\t\t\t#(注:参数1)\nhello\n\\########这是world########\t\t\t#(注:参数2)\nworld\n\n\n\n---\n\n**示例2:`预定义变量 $0`\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_**\n\n```bash\n[root@sanchuang-linux shell_test]# echo $0\t#(注:$0 当前进程 或者 脚本名称)\n-bash\n[root@sanchuang-linux shell_test]# sh canshu.sh \"hello\" \"world\"\n########这是hello########\nhello\n########这是world########\nworld\ncanshu.sh\t\t\t\t\t\t\t\t\t#(注:$0 当前进程 或者 脚本名称)\n[root@sanchuang-linux shell_test]# cat canshu.sh \n#!/bin/bash\n\necho \"########这是$1########\"\necho \"$1\"\necho \"########这是$2########\"\necho \"$2\"\n\necho \"$0\"\n```\n\n\n\n---\n\n**示例3:`预定义变量 $* $# $@`\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_**\n\n```bash\n[root@sanchuang-linux shell_test]# vim canshu.sh\n#!/bin/bash\n\necho \"########这是$1########\"\necho \"$1\"\necho \"########这是$2########\"\necho \"$2\"\necho \"$0\"\n\necho \"这是所有:$*\"\t\t\t#(注:$* 代表所有参数内容)\necho \"参数#:$#\"\t\t\t#(注:$# 表示参数个数)\necho \"这是@:$@\"\t\t\t#(注:$@ 代表所有参数(逐个提取))\n──────────────────────────────────────────────\n[root@sanchuang-linux shell_test]# sh canshu.sh hello world 2020\t #(注:3个参数)\n########这是hello########\nhello\n########这是world########\nworld\ncanshu.sh\n这是所有:hello world 2020\n参数#:3\n这是@:hello world 2020\n```\n\n\n\n---\n\n**知识点10 python中接收参数 sys模块**\n\npython中\n\nsys模块里面的argv属性。python后面 传过来的参数是一个`列表`,然后获取第一个第二个\n\n```python\n[root@sanchuang-linux ~]# vim canshu.py\nimport sys\n\nprint(sys.argv[1],sys.argv[2])\t\t#(注:1接收参数1,2接收参数2)\nprint(sys.argv[0])\t\t\t\t\t#(注:0是文件名)\n----------------------------------------------------------------------\n[root@sanchuang-linux ~]# python3 canshu.py \"hello\" \"world\"\nhello world\ncanshu.py\n```\n\n\n\n---\n\n### 数据类型\n\n**知识点11 数据类型**\n\n`shell常用数字、字符串、数组`\n\n字符串的定义,可以使用单引号,也可以使用双引号,也可以不用引号\n\n```bash\n示例:字符串的定义__________________\n[root@sanchuang-linux ~]# echo abc\nabc\n[root@sanchuang-linux ~]# a=b\n[root@sanchuang-linux ~]# echo $a\nb\n[root@sanchuang-linux ~]# a=\"b\"\n[root@sanchuang-linux ~]# echo $a\nb\n[root@sanchuang-linux ~]# a='b'\n[root@sanchuang-linux ~]# echo $a\nb\n\n示例:数字的定义_________________\n[root@sanchuang-linux ~]# a=1\n[root@sanchuang-linux ~]# a=2\n```\n\n\n\n---\n\n### 引号区别\n\n**知识点12 引号区别:双引号可以识别变量,单引号不可以识别变量**\n\n引号区别:双引号可以识别变量,单引号不可以\n\n```bash\n[root@sanchuang-linux ~]# head -n1 /etc/passwd\t\t\t#(注:输出passwd第一条)\nroot:x:0:0:root:/root:/bin/bash\n[root@sanchuang-linux ~]# cat /etc/passwd |head -n1\t\t#(注:不建议用这个 2条命令)\nroot:x:0:0:root:/root:/bin/bash\n```\n\n\n\n```bash\n#!/bin/bash\n\n# 字符串操作\nline=`head -n1 /etc/passwd`\t\t#(注:使用反引号``)(注:把命令输出保存在line里面)\necho $line\n---------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# bash test2.sh \nroot:x:0:0:root:/root:/bin/bash\n```\n\n\n\n**示例:双引号可以识别变量,单引号不可以识别变量\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_\\_**\n\n```bash\necho \"字符串为:$line\"\n字符串为:root:x:0:0:root:/root:/bin/bash\n------------------------------------------\necho '字符串为:$line'\n字符串为:$line\n```\n\n\n\n---\n\n### 字符串操作\n\n**知识点13 字符串操作**\n\n```bash\n截取\n截取前4个字符:echo ${line:0:4}\n截取后9个字符 echo ${line:0-9}\n从倒数第九个字符开始截取4个字符 echo ${line:0-9:4}\n从左向右截取最后一个:后的字符 echo ${line##*:}\n从左向右截取第一个:后的字符 echo ${line#*:}\n从右往左截取最后一个:后的字符\techo ${line%%:*}\n从右向左截取第一个:后的字符\techo ${line%:*}\n字符串长度\techo ${#line}\n```\n\n\n\n```bash\n示例:字符串操作_______________________________\n# 字符串操作\n[root@sanchuang-linux chenpeng]# vim test2.sh\nline=`head -n1 /etc/passwd`\necho $line\t\t\t\t#(注:root:x:0:0:root:/root:/bin/bash)\necho \"字符串为:$line\"\t\t#(注:字符串为:root:x:0:0:root:/root:/bin/bash)\n\necho '字符串为:$line'\t\t#(注:字符串为:$line)\n\necho \"截取前4个字符:\"\necho ${line:0:4}\t\t\t#(注:root)\n\necho \"截取后9个字符\"\necho ${line:0-9}\t\t\t#(注:/bin/bash)\n\necho \"从倒数第九个字符开始截取4个字符\"\necho ${line:0-9:4}\t\t\t#(注:/bin)\n\necho \"从左向右截取最后一个:后的字符\"\necho ${line##*:}\t\t\t#(注:/bin/bash)\n\necho \"从左向右截取第一个:后的字符\"\necho ${line#*:}\t\t\t#(注:x:0:0:root:/root:/bin/bash)\n\necho \"从右往左截取最后一个:后的字符\"\necho ${line%%:*}\t\t\t#(注:root)\n\necho \"从右向左截取第一个:后的字符\"\necho ${line%:*}\t\t\t#(注:root:x:0:0:root:/root)\n\necho \"字符串长度\"\necho ${#line}\t\t\t\t#(注:31)\n-----------------------------------------------\n[root@sanchuang-linux chenpeng]# bash test2.sh \nroot:x:0:0:root:/root:/bin/bash\n字符串为:root:x:0:0:root:/root:/bin/bash\n字符串为:$line\n截取前4个字符:\nroot\n截取后9个字符\n/bin/bash\n从倒数第九个字符开始截取4个字符\n/bin\n从左向右截取最后一个:后的字符\n/bin/bash\n从左向右截取第一个:后的字符\nx:0:0:root:/root:/bin/bash\n从右往左截取最后一个:后的字符\nroot\n从右向左截取第一个:后的字符\nroot:x:0:0:root:/root\n字符串长度\n31\n```\n\n\n\n---\n\n**练习13 截取百度网址**\n\n```bash\nline=\"http://www.baidu.com/login\"\n\n# 截取出:login\necho ${line:0-5}\t\t\t\t#(注:取最后5个字符)\necho ${line##*/}\t\t\t\t#(注:从左往右最后一个/后的内容)\n\n# 截取出:www.baidu.com/login\necho ${line##*//}\n\n# 截取出:http://www.baidu.com\necho ${line%/*}\n\n# 截取出:http:\necho ${line%%/*}\n```\n\n\n\n---\n\n### 数值的运算与比较\n\n**知识点14 数值的运算与比较**\n\n数值的运算:\n第一种: `$(( 表达式 ))`\n第二种: `$[ 表达式 ]`\n第三种: `expr 表达式`\n\n注意表达式运算符`左右空格`\n\n```bash\n示例:↓↓↓↓↓↓↓↓↓↓↓↓↓↓\n[root@sanchuang-linux ~]# a=10\n[root@sanchuang-linux ~]# b=20\n[root@sanchuang-linux ~]# $(($a + $b))\n-bash: 30: 未找到命令\n[root@sanchuang-linux ~]# echo $(($a + $b))\n30\n[root@sanchuang-linux ~]# echo $[ $a +$b ]\n30\n[root@sanchuang-linux ~]# expr $a + $b\n30\n[root@sanchuang-linux ~]# expr $a+$b\n10+20\n```\n\n\n\n---\n\n### SHELL结构语句,循环和判断\n\n**知识点15 shell结构语句,循环和判断**\n\n**知识点15.1 for循环**\n\n**for循环**\n\n```bash\n语法1:↓↓↓↓↓↓↓↓\n-----------------------\nfor 变量 in 值1 值2\ndo\n\t循环执行语句\ndone\n=======================================\n语法2:↓↓↓↓↓↓↓\n---------------------------------------\n# for ((i=0;i<3;i++))\nfor ((初始化变量; 结束循环的条件; 运算))\ndo \n\t循环执行的语句\ndone\n```\n\n\n\n---\n\n**知识点15.2 while循环**\n\n**While循环**\n\n```bash\n语法1:↓↓↓↓↓\n---------------------------------------\nwhile read line\ndo \n\t循环执行语句\ndone\n=======================================\n语法2↓↓↓↓↓↓↓↓↓\n---------------------------------------\nwhile [条件(非必选)]:\ndo\n\t循环执行语句\ndone\n=======================================\n注:也支持break,continue\n```\n\n\n\n---\n\n**知识点15 判断**\n\n**知识点15.3 if语句**\n\n**if语句**\n\n```bash\n语法1:↓↓↓↓↓\n-------------------------\nif 条件\nthen\n\t执行语句\nfi\n=========================\n语法2:↓↓↓↓↓\nif 条件\nthen\n\t执行语句\nelse\n\t执行语句\nfi\n==========================\n语法3:↓↓↓↓↓↓\n----------------------\nif [ command ];then\n符合该条件执行的语句\nelif [ command ];then\n符合该条件执行的语句\nelse\n符合该条件执行的语句\nfi\n```\n\n\n\n---\n\n**知识点15.4 case语句**\n\n**case语句**\n\n```bash\n语法:↓↓↓↓↓________________\ncase $变量名 in\n条件1)\n\t执行语句一\n\t;;\n条件2)\n\t执行语句二\n\t;;\n*)\nesac\n```\n\n\n\n---\n\n**练习16**\n\n编写一个shell脚本\n\n接收用户输入的两个数,然后选择要对着两个数进行什么计算,并且输出结果\n\n实现菜单选择\n\n\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\n\n1. add 加法\n\n2. sub 减法\n\n3. mul 乘法\n\n4. exit 退出\n\n\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n\n注:菜单选择用case、服务重启脚本用case\n\n```bash\n示例:↓↓↓↓↓↓↓↓↓_________________________\n[root@sanchuang-linux chenpeng]# vim num_test.sh\n#!/bin/bash\n\nread -p \"请输入数字一:\" num1\nread -p \"请输入数字二:\" num2\n\necho \"================\"\necho \"1.add 加法\"\necho \"2.sub 减法\"\necho \"3.mul 乘法\"\necho \"4.exit 退出\"\necho \"================\"\n\nread -p \"请输入你的选择:\" options\ncase $options in\n1)\n echo \"两数相加为:$(($num1 + $num2))\"\n ;;\n2)\n echo \"两数相减为:$(($num1 - $num2))\"\n ;;\n3)\n echo \"两数相乘为:$(($num1 * $num2))\"\n ;;\n4)\n echo \"退出!\"\n exit\nesac\n-------------------------------------------------------------------------------------------\n整成函数形式\nadd(){\n echo \"两数相加为:$(($num1 + $num2))\"\n}\n\ncase $options in\n1)\n add\t\t\t#(注:需要使用的时候调用)\n ;;\n2)…………………………\n```\n\n\n\n---\n\n### /etc/init.d 服务的启动脚本\n\n**知识点17 /etc/init.d 服务的启动脚本**\n\n**/etc/init.d/ 放着服务的启动脚本**\n\n```bash\n[root@sanchuang-linux chenpeng]# cd /etc/init.d/ \n[root@sanchuang-linux init.d]# ls \nfunctions README \n```\n\n\n\n```bash\n示例:服务重启脚本用case↓↓↓↓↓__________________\ncase $mode in\n\tstart)\n\t\t启动\n\t\t;;\n\tstop)\n\t\t关闭(使用kill命令)\n\t\t;;\n\trestart)\n\t\t关闭\n\t\t启动\n\t\t;;\n\treload)\n\t\t重新加载配置(使用kill -HUP)\n\t\t;;\nesac \n```\n\n\n\n---\n\n### kill\n\n**知识点18 kill**\n\n```bash\nkill 用来删除正在执行中的程序或者工作\nkill 可以将指定的信息发送给程序\n\n# kill -l 可以查看kill信号量\t(kill -L(小写))\n# kill -0 用来检测进程是否存在,当进程不存在时,kill -0 会报错\n# kill -1 pid 重新加载进程(常用)\n# kill -HUP pid 和 kill -1 pid是一样的\n# kill -1 pid 或者 kill -HUP pid 都表示重新加载这个文件\n# kill -9 强制杀死\n# kill -15 正常停止一个进程\nkill 不接信号量的时候,默认为信号15\n除了9号信号,其他信号进程都有权利拒绝执行!\n```\n\n\n\n---\n\n注:重新加载 相当于 加载最新的配置 服务还是正常运行的(连接不会断)\n\n​\t\t重启 服务会断\n\n\n\n```bash\n示例:↓↓↓↓↓↓↓↓↓____________\n[root@sanchuang-linux ~]# kill -l\n 1) SIGHUP\t 2) SIGINT\t 3) SIGQUIT\t 4) SIGILL\t 5) SIGTRAP\n 6) SIGABRT\t 7) SIGBUS\t 8) SIGFPE\t 9) SIGKILL\t10) SIGUSR1\n…………………………\n63) SIGRTMAX-1\t64) SIGRTMAX\t\n```\n\n\n\n---\n\n### SHELL编程 if判断\n\n**知识点19 shell编程 if判断**\n\n**if 判断**\n\n```bash\n示例:↓↓↓↓↓↓____________________________________________________________\n[root@sanchuang-linux ~]# if id wenyao; then echo \"ok\"; else echo \"error\"; fi\nid: “wenyao”:无此用户\nerror\n--------------------------------------------------------\n等同于:↓↓↓↓↓________________________________________________\nif id wenyao; \nthen \n\techo \"ok\"; \nelse \n\techo \"error\"; \nfi\n```\n\n\n\n---\n\n### [ ]\n\n**知识点20 [ ]**\n\n**[ ]表示条件测试**\n\n注意这里的空格很重要。要注意在'['后面和']'前面都必须要有空格。\n\n\n\n---\n\n```bash\n常用判断:\n[ -d FILE ] 如果 FILE 存在且是一个目录则返回为真。\n[ -f FILE ] 如果 FILE 存在且是一个普通文件则返回为真。\n[ -e **** ] 判断文件/文件夹是否存在\n\n字符串判断:\n[ -z STRING ] 如果STRING的长度为零则返回为真,即空是真\n[ -n STRING ] 如果STRING的长度非零则返回为真,即非空是真\n[ STRING1 ]  如果字符串不为空则返回为真,与-n类似\n[ STRING1 == STRING2 ] 如果两个字符串相同则返回为真\n[ STRING1 != STRING2 ] 如果字符串不相同则返回为真\n[ STRING1 < STRING2 ] 如果 “STRING1”字典排序在“STRING2”前面则返回为真。\n[ STRING1 > STRING2 ] 如果 “STRING1”字典排序在“STRING2”后面则返回为真。\n\n数值判断\n[ INT1 -eq INT2 ] INT1和INT2两数相等返回为真 ,=\n[ INT1 -ne INT2 ] INT1和INT2两数不等返回为真 ,<>\n[ INT1 -gt INT2 ] INT1大于INT2返回为真 ,>\n[ INT1 -ge INT2 ] INT1大于等于INT2返回为真,>=\n[ INT1 -lt INT2 ] INT1小于INT2返回为真 ,<\n[ INT1 -le INT2 ] INT1小于等于INT2返回为真,<=\n\n逻辑判断\n[ ! EXPR ] 逻辑非,如果 EXPR 是false则返回为真。\n[ EXPR1 -a EXPR2 ] 逻辑与,如果 EXPR1 and EXPR2 全真则返回为真。\n[ EXPR1 -o EXPR2 ] 逻辑或,如果 EXPR1 或者 EXPR2 为真则返回为真。\n[ ] || [ ] 用OR来合并两个条件\n[ ] && [ ] 用AND来合并两个条件\n```\n\n\n\n---\n\n```bash\n示例:↓↓↓↓↓↓↓↓↓↓↓↓↓\n[root@sanchuang-linux ~]# a=10\n[root@sanchuang-linux ~]# b=20\n[root@sanchuang-linux ~]# if [ $a -gt $b ];then echo \"a>b\";else echo \"a<b\";fi\t#(注:正确)\na<b\n[root@sanchuang-linux ~]# if [ $a > $b ];then echo \"a>b\";else echo \"a<b\";fi\t#(注:出错)\na>b\t\t\t\t\t\t(注:使用2个中括号不出错)\n[root@sanchuang-linux ~]# if [[ $a > $b ]];then echo \"a>b\";else echo \"a<b\";fi\t#(注:正确)\na<b\n\n[root@sanchuang-linux ~]# if [ $a -gt $b ] && [ $a -ne 20 ];then echo \"输出a>b\";else echo \"输出a<b\";fi\n输出a<b\n```\n\n\n\n---\n\n**练习21**\n\n判断当前目录下是否存在文件a,没有的话就创建\n\n有的话输出,输出文件已存在\n\n```bash\n示例:↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\n写法1:\nif [ -f a.txt ];\n then echo \"文件存在\"\nelse\n touch a.txt\nfi\n-------------------------------------------------\n写法2:推荐(类似python的if三元运算符)\n[ -f a.txt ] && echo \"文件已存在\" || touch a.txt\n```\n\n\n\n---\n\n示例2:\n\n编写一个脚本,实现如下功能\n\n\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\n\n1.增加用户并设置密码\n\n2.删除用户\n\n3.查看用户\n\n4.退出\n\n\\=\\=\\=\\==\\=\\=\\=\\=\\=\\==\\=\\=\n\n输入的指定不是1-4,给提示给予提醒,并且如果不输入退出的话,可以循环添加。\n\n按1 增加用户,并且设置密码 useradd passwd\n\n按2 删除用户 userdel -r \n\n按3 查看用户 id \n\n按4 退出 exit\n\n\n\n---\n\n### && ||\n\n**知识点22 类似python的if三元运算符**\n\n**使用&& || 来实现**\n\n·cmd1 && cmd2 如果cmd1执行成 功,或者为真,则执行cmd2\n\n·cmd1 || cmd2 如果cmd1执行不成功,或者为假,则执行cmd2\n\n·cmd1 && cmd2 || cmd3 如果cmd1执行成功,就执行cmd2,不成功就执行cmd3\n\n```bash\n示例:上个练习↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓\n[ -f a.txt ] && echo \"文件已存在\" || touch a.txt\n[[ -f a.txt ]] && echo \"文件已存在\" || touch a.txt\t\t#(注:推荐使用两个中括号)\n\n示例:\n-------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=10\n[root@sanchuang-linux ~]# b=20\n[root@sanchuang-linux ~]# [ $a -gt $b ] && echo \"输出 a>b\"\n[root@sanchuang-linux ~]# [ $a -gt $b ] || echo \"输出 a<b\"\n输出 a<b\n[root@sanchuang-linux ~]# [ $a -gt $b ] && echo \"输出 a>b\" || echo \"输出 a<b\"\n输出 a<b\n```\n\n\n\n---\n\n### [] 、[[]]、 (()) (判断方式)\n\n**知识点23 [] 、[[]]、 (()) (判断方式)**\n\n[ ] 会做单词拆分\n[ ] 很多表示都不是很支持,**建议使用[[ ]]判断(2个中括号)**\n**总结:**\n**`·建议使用`[[ ]]`来比较运算,进行判断`**\n**`·字符串用`[[ ]]\t\t(推荐)**\n**`·数字用比较用`(( ))**\n结论:建议使用[[ ]]来比较运算,进行判断\n\n\n\n```bash\n示例1:if判断时\n-------------------------------------------------------------------------------------------\n[root@sanchuang-linux chenpeng]# name=\"wen yao\"\n[root@sanchuang-linux chenpeng]# [ $name == \"wen yao\" ] && echo \"ok\" || echo \"error\"\n-bash: [: 参数太多\t\t#(注:自动做单词拆分)\nerror\n[root@sanchuang-linux chenpeng]# [[ $name == \"wen yao\" ]] && echo \"ok\" || echo \"error\"\nok\t\t\t\t\t\t\t#(注:推荐使用2个中括号)\n[root@sanchuang-linux chenpeng]# [ \"$name\" == \"wen yao\" ] && echo \"ok\" || echo \"error\"\nok\t\t\t\t\t#(注:使用引号连接在一起,表示一个整体)\n============================================================================================\n\n示例2:数值比较\n-------------------------------------------------------------------------------------------\n[root@mysql-binary shell_test]# echo $a\n10\n[root@mysql-binary shell_test]# echo $b\n20\n[root@mysql-binary shell_test]# [[ $a > $b ]] && echo \"ok\" || echo \"error\"\nerror\n[root@mysql-binary shell_test]# [ $a > $b ] && echo \"ok\" || echo \"error\"\nok\t\t\t\t\t\t\t#(注:出错)\n[root@mysql-binary shell_test]# (( $a == $b )) && echo \"ok\" || echo \"error\" \nerror\n\n示例:\n--------------------------------------------------------------------------------------------\n[root@mysql-binary shell_test]# a=10\n[root@mysql-binary shell_test]# b=20\n[root@mysql-binary shell_test]# [[ $a -eq $b ]] && echo \"ok\" || echo \"eroor\"\neroor\n[root@mysql-binary shell_test]# (( $a -eq $b )) && echo \"ok\" || echo \"eroor\"\n-bash: ((: 10 -eq 20 : 表达式中有语法错误 (错误符号是 \"20 \")\nEroor\n----------------------------------------------------------------------------\n[root@mysql-binary shell_test]# c=102\n[root@mysql-binary shell_test]# b=20\n[root@mysql-binary shell_test]# [[ $c > $b ]] && echo \"ok\" || echo \"eroor\"\neroor\n[root@mysql-binary shell_test]# (( $c > $b )) && echo \"ok\" || echo \"eroor\"\nok\n\n示例3:if条件判断的2种写法\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=10\n[root@sanchuang-linux ~]# b=20\n[root@sanchuang-linux ~]# if [[ $a > $b ]]; then echo \"ok\"; else echo \"error\"; fi\nerror\n[root@sanchuang-linux ~]# [[ $a > $b ]] && echo \"ok\" || echo \"error\"\nerror\n\n示例:字符串比较(( )) 也可以\n--------------------------------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=abc\n[root@sanchuang-linux ~]# b=abc1\n[root@sanchuang-linux ~]# (( $a > $b )) && echo \"ok\" || echo \"error\"\nerror\n[root@sanchuang-linux ~]# a=abc\n[root@sanchuang-linux ~]# b=bac1\n[root@sanchuang-linux ~]# (( $a > $b )) && echo \"ok\" || echo \"error\"\nerror\n[root@sanchuang-linux ~]# a=abc\n[root@sanchuang-linux ~]# b=abc\n[root@sanchuang-linux ~]# (( $a == $b )) && echo \"ok\" || echo \"error\"\nok\n\n结论:建议使用[[ ]]来比较运算,进行判断\n```\n\n\n\n---\n\n### SHELL函数 定义\n\n**知识点24 Shell函数 定义**\n\n```bash\n示例:\nadd() {\n echo \"两数相加为:$(( $num1 + $num2 ))\"\t\t#(注:函数里面的操作内容)\n}\n------------------------------------------------\n调用的时候 add\ncase $options in \n1)\n\tadd\n\t;;\n2)……………………\n--------------------------------------------------------------------------------------------\nadd(){\n echo \"两数相加为:$(($num1 + $num2))\"\n}\n\ncase $options in\n1)\n add\t\t\t#(注:需要使用的时候调用)\n ;;\n2)…………………………\n```\n\n\n\n---\n\n### 判断方式 [] [[]] (()) test\n\n**知识点25 判断方式 [] [[]] (()) test**\n\n- (( ))\t判断数字 > < == !=\n\n- [[ ]]\t判断字符串 或者 -eq -ne -gt -lt 判断数字\n\n- 有些语法 [ ] 是不支持的,建议使用[[ ]]\n\n- test(测试)判断,等同于1个中括号\n\n```bash\n示例:test\n---------------------------------------------------------------------\n[root@sanchuang-linux ~]# a=123\n[root@sanchuang-linux ~]# b=123\n[root@sanchuang-linux ~]# test a==b && echo ok\nok\n[root@sanchuang-linux ~]# test a==b && echo ok || echo error\nok\n```\n\n\n\n---\n\n","tags":["Linux","Shell"],"categories":["Linux"]},{"title":"09_Linux基础-SHELL-标准输入与标准输出-重定向-管道","url":"/posts/5276.html","content":"\n> ```\n> 作业\n> \t编辑文本文件/home/text/file1,分4行输入bbb bbb bbb、 ddd ddd ddd、aaa aaa aaa、ccc ccc ccc。 保存不要退出;\n> \t在末行模式下打开一个新文件/text/file2;\n> \t在file2中输入内容为eee eee eee在这一行内容之后, 将file1的内容读入到file2中,接着在命令模式下按照 abcde的显示顺序调整每行的位置,最后保存退出;\n> \t同时编辑file1和file2,接着从file1切换到file2,然后 再快速切换回来,接着将file2的内容读到file1内容的末尾,显示文件file1内容的行号,复制3到6行到file1 内容的末尾;\n> \t利用替换命令将全文的每行第一个ccc都替换为333;\n> \t将全文中所有aaa都替换为111,撤销行号,最后不保 存退出;\n> ```\n>\n> \n>\n> ```bash\n> [root@sanchuang-linux chenpeng]# mkdir /home/text2\n> [root@sanchuang-linux chenpeng]# cd /home/text2\n> [root@sanchuang-linux chenpeng]# mkdir /text2\n> [root@sanchuang-linux text2]# vim file1\n> :r /text2/file2\n> aaa aaa aaa\n> bbb bbb bbb\n> ccc ccc ccc\n> ddd ddd ddd\n> eee eee eee\n> [root@sanchuang-linux text2]# vim file1 /text2/file2\n> :n\n> :N\n> :set nu\n> :%s/ccc/333\n> :%s/aaa/111/g\n> :set nonu\n> :q!\n> ```\n>\n> \n\n---\n\n> ```bash\n> 练习1:\n> \t1.进入/lianxi目录\n> # cd /lianxi\n> \t2.复制/etc/passwd文件到当前目录下,然后使用vim编辑当前目录下的passwd\n> # cp /etc/passwd . # vim passwd\n> \t3.显示一下行号\n> :set nu\n> \t4.复制第5到10行的内容,粘贴到末尾,删除最后一行的最后一个单词\n> :5 ; 6yy ; G ; p ; dw\n> \t5.删除第9行和第10行\n> :9 ; 2dd\n> \t6.将root改为gen\n> :%s/root/gen/g\n> \t7.删除部分bash字符串\n> :%s/bash//gc\n> \t8.快速到达第5行,然后再跳到第1行,再跳到最后一行\n> :5 ; :1 ; G\n> \t9.剪切第6-7行,粘贴到末尾\n> :6 ; 2dd ; G ; p\n> \t10.退出并且保存\n> :wq\n> \t11.复制/etc/hosts文件到当前目录下,将第1列的ip地址复制,然后粘贴到文件的末尾\n> # /etc/hosts . ; # vim hosts ; ctrl+v ; y ; G ;p\n> ```\n>\n> \n\n\n\n---\n\n## 一. SHELL-标准输入与标准输出\n\n> **学习内容:重定向和文件目录高级操作**\n>\n> ```\n> 知识要点\n> 输入输出重定向\n> 管道及相关配套命令 数据提取及过滤\n> 文件差异对比和补丁生成及打补丁\n> ```\n>\n> \n\n\n\n### 标准输入和标准输出\n\n> **知识点1 标准输入和标准输出**\n>\n> ```\n> ---------------------------\n> 输入输出及重定向\n> 每个进程基本都会打开三个文件描述符\n> 0: 标准输入(从键盘)\n> 1: 标准输出 (输出到屏幕)\n> 2: 标准错误输出 (输出到屏幕)\n> \n> 类型\t\t\t设备文件\t\t文件描述符(fd)\t默认设备\n> 标准输入\t /dev/stdin\t 0\t\t\t 键盘\n> 标准正确输出\t /dev/stdout\t 1\t\t\t\t显示器\n> 标准错误输出\t /dev/stderr\t 2\t\t\t\t显示器\n> -------------------------------------------------------\n> 标准输入(stdin)和标准输出(stdout)\n> ------------------------------------\n> python中 >>>help(print) file=sys.stdout 默认输出到屏幕(标准输出)\n> ------------------------------------------------------------------\n> 进程:正在进行的程序\n> ---------------------\n> 键盘 =》 标准输入 =》 终端程序 =》 标准输出 =》显示器\n> \t\t\t\t\t\t\t标准错误输出 =》显示器\n> ----------------------------------------------------------\n> https://blog.csdn.net/xiaofei0859/article/details/78448493?utm_source=blogxgwz9\n> 每个进程基本都会打开三个文件描述符\n> 0:标准输入\t(从键盘、语音、人脸识别……)\n> 1:标准输出\t(输出到屏幕)\n> 2:标准错误输入(输出到屏幕)\n> ---------------------------\n> 文件描述符:fd 就是每个进程打开的文件\n> ```\n>\n> \n\n\n\n### 文件描述符\n\n> **知识点1.1 文件描述符**\n>\n> ```\n> 文件描述符:\n> linux内核给每个进程都创造一个文件描述符,这个表里记载了这个进程所打开的所有文件,为了方便进程知道自己打开了哪些文件呢,就给每个文件都进行了标号,这个编号就是文件描述符。\n> 此后,所有对文件的操作,就是用该编号。\n> ```\n>\n> \n\n\n\n### linux下面一切皆文件\n\n> **知识点1.2 linux下面一切皆文件**\n>\n> linux下面一切皆文件\n>\n> disk磁盘\n>\n> `/dev目录下面基本都是块设备文件`\n>\n> ```bash\n> [root@sanchuang-linux ~]# cd /dev\n> [root@sanchuang-linux dev]# cd disk\n> [root@sanchuang-linux disk]# ls\n> by-id by-label by-partuuid by-path by-uuid\n> [root@sanchuang-linux disk]# cd ..\n> [root@sanchuang-linux dev]# ls -ld sda1\n> brw-rw----. 1 root disk 8, 1 10月 6 17:16 sda1\n> [root@sanchuang-linux dev]# ls -ld sda2\n> brw-rw----. 1 root disk 8, 2 10月 6 17:16 sda2\n> ------------------------------------------------\n> [root@sanchuang-linux dev]# cd net\n> [root@sanchuang-linux net]# ls\n> tun\n> [root@sanchuang-linux net]# \n> ----------------------------\n> 对文件的操作就是对设备的操作\n> ----------------------------\n> [root@sanchuang-linux ~]# cd /dev\n> [root@sanchuang-linux dev]# ls\n> stderr\n> stdin\n> Stdout\n> fd\n> ……\n> ---------------------------------\n> [root@sanchuang-linux ~]# cd /dev\n> [root@sanchuang-linux dev]# cd fd\n> [root@sanchuang-linux fd]# ls\n> 0 1 2 255 \n> [root@sanchuang-linux fd]# ls -al\n> 总用量 0\n> dr-x------. 2 root root 0 10月 16 10:40 .\n> dr-xr-xr-x. 9 root root 0 10月 16 10:40 ..\n> lrwx------. 1 root root 64 10月 16 10:40 0 -> /dev/pts/6\t#(注:链接的意思,快捷方式 指向\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t/dev/pts/6,标准输入到虚拟终端6)\n> lrwx------. 1 root root 64 10月 16 10:40 1 -> /dev/pts/6\t#(注:标准输出到虚拟终端6)\n> lrwx------. 1 root root 64 10月 16 10:40 2 -> /dev/pts/6\t#(注:标准错误输出到虚拟终端6)\n> lrwx------. 1 root root 64 10月 16 11:24 255 -> /dev/pts/6\n> [root@sanchuang-linux fd]# \n> ---------------------------------------\n> ```\n>\n> \n\n\n\n### 虚拟终端pts 真实终端tty\n\n> **知识点1.3 虚拟终端pts 真实终端tty**\n>\n> [root@sanchuang-linux dev]# cd /dev/`pts`\n> [root@sanchuang-linux pts]# ls\n> 0 1 2 3 4 5 6 ptmx\n> [root@sanchuang-linux pts]# \n>\n> `pts是别人连接到服务器的虚拟终端(远程控制)`。别人远程连接会创建虚拟终端\n>\n> pts虚拟终端\n>\n> ```bash\n> -----------------------------------------------------\n> Linux centos登录——》本地的终端shell环境 真实终端\n> xshell连接\t ——》虚拟终端\n> --------------------------------\n> tty 本地真实终端\n> [root@sanchuang-linux dev]# cd /dev\n> [root@sanchuang-linux dev]# ls\n> tty\n> ```\n>\n> \n\n\n\n### 查看当前linux登陆的用户情况\n\n> **知识点1.4 查看当前linux登陆的用户情况**\n>\n> 查看当前linux登陆的用户情况 # `w`\n>\n> [root@sanchuang-linux dev]# `w`\n> 11:32:52 up 16:23, 4 users, `load average`: 0.00, 0.00, 0.00\n> USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\n> root `tty1` - 0610月20 1:32m 0.60s 0.60s -bash\t`(注:bash环境)`\n> root `pts/1` 192.168.0.26 10:03 25:40 0.21s 0.21s -bash\t\t`(注:bash环境)`\n> root `pts/2` 10.122.155.164 08:52 2:29m 0.16s 0.13s vim -r a\t`(注:删除环境)`\n> root `pts/6` 192.168.0.26 10:40 4.00s 0.09s 0.01s w\t\t`(注:输入w命令环境)`\n>\n> ----------↓解释----------------------------------------------------------------------------\n>\n> USER:登录用户\n>\n> TTY:终端类型 terminal type 面向用户使用的接口\n>\n> ​\t\t`tty1:真实终端`\n>\n> ​\t\t\t\ttty1==>`直接登录进去 操纵的第一个终端`(真实终端)\n>\n> ​\t\t\t\tLinux里最多允许`6个`可以直接登录的终端(即`真实终端tty`)\n>\n> ​\t\t\t\ttty2~tty6 需要的时候使用\n>\n> ​\t\t\t\t`Alt+F1` tty1 回到第一个终端\n>\n> ​\t\t\t\t`Alt+F2` tty2 回到第二个终端\n>\n> ​\t\t`pts/1:虚拟终端`,给别人用的。数量可以有很多个。有远程登录过来的时候,就会创建1个终端\n>\n> FROM:从哪里来\n>\n> WHAT:做什么事\n>\n> load average机器的拼接负载\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\n>\n> [root@sanchuang-linux dev]# w\n> `11:39:04` up 16:29, 4 users, `load average`: 0.00, 0.00, 0.00\n> USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\n> root tty1 - 0610月20 1:38m 0.60s 0.60s -bash\n> root pts/1 192.168.0.26 10:03 31:52 0.21s 0.21s -bash\n> root pts/2 10.122.155.164 08:52 2:35m 0.16s 0.13s vim -r a\n> root pts/6 192.168.0.26 10:40 0.00s 0.09s 0.00s w\n> [root@sanchuang-linux dev]# date\n> 2020年 10月 16日 星期五 `11:39:06` CST\n>\n> \n>\n> load average机器的平均负载\n>\n> \\---------------------------\n\n\n\n### 本地终端(真实终端)的创建、切换\n\n> **知识点1.5 本地终端(真实终端)的创建、切换**\n>\n> Alt+F2\n>\n> 本地最多能登录`6个终端`\n>\n> `Alt+F1~F6` 切换本地登录的终端(真实终端)\n>\n> \\-----------------------------------------\n>\n> Alt+F2、Alt+F6\n>\n> [root@sanchuang-linux dev]# `w`\n> 11:42:06 up 16:32, 6 users, load average: 0.00, 0.00, 0.00\n> USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\n> root `tty1` - 0610月20 1:41m 0.60s 0.60s -bash\n> root pts/1 192.168.0.26 10:03 34:54 0.21s 0.21s -bash\n> root pts/2 10.122.155.164 08:52 2:38m 0.16s 0.13s vim -r a\n> root pts/6 192.168.0.26 10:40 3.00s 0.09s 0.00s w\n> root `tty2` - 11:40 1:50 0.01s 0.01s -bash\n> root `tty6` - 11:41 13.00s 0.01s 0.01s -bash\n\n\n\n### 如何拦截虚拟终端\n\n> **知识点1.6 如何拦截虚拟终端**\n>\n> 如何拦截虚拟终端\t# `kill -9 pid`\n>\n> ```bash\n> -----------------------------------\n> [root@sanchuang-linux dev]# ps aux\n> USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND\n> root 1 0.0 0.7 179304 13536 ? Ss 10月15 0:07 /usr/lib/systemd/systemd --switched-root --system --dese\n> root 1450 0.0 0.2 25588 3996 tty1 Ss+ 10月15 0:00 -bash\n> root 12692 0.0 0.2 34480 4444 ? Ss 04:49 0:00 tmux\n> ……………………………………………………\n> root 13025 0.0 0.2 25588 4048 pts/14 Ss+ 05:14 0:00 -bash\n> root 13046 0.0 0.2 25588 4032 pts/15 Ss+ 05:14 0:00 -bash\n> root 13286 0.0 0.2 25588 3940 pts/0 Ss+ 05:28 0:00 -bash\n> root 13614 0.0 0.2 25588 4016 pts/3 Ss+ 06:23 0:00 -bash\n> root 13635 0.0 0.2 25588 3956 pts/4 Ss 06:23 0:00 -bash\n> root 13657 0.0 0.4 48860 8596 pts/4 S+ 06:24 0:00 vim /home/text/file2\n> [root@sanchuang-linux dev]# kill -9 13046\t(注:杀死pid号13046的进程)\n> ------------------------------------------------------------------------\n> ssh服务 22号端口 有端口肯定有服务\n> 起服务一定要有端口\n> 端口跟服务挂钩\n> \n> Mysql默认端口3306\n> ```\n>\n> \n\n\n\n### 查看服务的默认端口\n\n> **知识点1.7 查看服务的默认端口**\n>\n> 怎样查看服务的默认端口 # `less /etc/services`\n>\n> 查看服务的默认端口\n>\n> ```bash\n> # less /etc/services\n> tcpmux 1/tcp # TCP port service multiplexer\n> tcpmux 1/udp # TCP port service multiplexer\n> rje 5/tcp # Remote Job Entry\n> rje 5/udp # Remote Job Entry\n> …………\n> ```\n>\n> \n\n---\n\n> **知识点1.8 传输层协议 TCP、UDP**\n>\n> 传输层协议 TCP、UDP\n\n\n\n### 杀死连接 限制连接\n\n> **知识点1.9 杀死连接 限制连接**\n>\n> 杀死连接:\n>\n> `ps aux` 查看pts的连接pid\n>\n> 然后使用: `kill -9 xxx`\n>\n> \\-------------------------\n>\n> 限制连接:\n>\n> `iptables` 防火墙\n>\n> 或使用其他ssh相关的限制\n>\n> \\-------------------------\n\n\n\n### /proc目录\n\n> **知识点2.0 /proc目录**\n>\n> /Proc目录 放一些正在运行的程序\n>\n> \\# `ls /proc` 正在运行的程序\n>\n> ```bash\n> [root@sanchuang-linux ssh]# ls /proc\n> ………………………………………………(删了很多)\n> 11 13657 1450 158 171 186 29 508 632 906 999 fb loadavg self zoneinfo\n> 13025 14438 15 168 182 23 40 6 859 982 diskstats kmsg partitions tty\n> ………………………………………………(删了很多)\n> ```\n>\n> \n\n\n\n### 查看进程打开了哪些文件描述符\n\n> **知识点2.1 查看进程打开了哪些文件描述符 proc/1450/fd**\n>\n> 查看进程打开了哪些文件描述符\n>\n> [root@mysql-binary fd]# ls\n>\n> `0 1 2 255`\n>\n> [root@mysql-binary fd]# pwd\n>\n> `/proc/1680/fd`\n>\n> ```bash\n> -----------------------------------------\n> [root@sanchuang-linux ssh]# cd /proc/1450\n> [root@sanchuang-linux 1450]# ls\n> attr comm fd map_files net pagemap schedstat \n> ………………………………(删了很多)\n> [root@sanchuang-linux 1450]# cd fd\n> [root@sanchuang-linux fd]# ls\n> 0 1 2 255 3 4\n> [root@sanchuang-linux fd]# pwd\n> /proc/1450/fd\n> ```\n>\n> \n\n\n\n---\n\n## 二. 重定向\n\n> `重定向:改变标准输入、标准输出的方向就是重定向`\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 类型\t\t\t\t\t\t操作符\t用途\n>\n> 重定向标准`输出`\t>\t\t\t\t将命令的执行结果`输出到指定的文件`中,而不是直接显示在屏幕上\n>\n> ​\t\t\t\t\t\t\t\t\\>>\t\t\t将命令执行的结果`追加输出到指定文件`\n>\n> 重定向标准`输入`\t<\t\t\t\t将命令中`接收输入的途径`由默认的键盘`更改 为指定的文件`\n\n\n\n### echo\n\n> **知识点3.1 echo**\n>\n> `echo -n 不接换行`\n>\n> `echo -e 转义字符输出`\n\n```bash\n[root@sanchuang-linux redirect]# echo \"xxx\"\nxxx\n[root@sanchuang-linux redirect]# echo -n \"xxx\"\nxxx[root@sanchuang-linux redirect]#\n[root@sanchuang-linux redirect]# echo \"xx \\n x1x1\"\nxx \\n x1x1\n[root@sanchuang-linux redirect]# echo -e \"xx \\n x1x1\"\nxx \n x1x1\n[root@sanchuang-linux redirect]# \n---------------------------------\necho -n 不接换行\necho -e 转义字符输出\n```\n\n\n\n### 重定向(改变原来的输出方式)\n\n> **知识点3.2 重定向(改变原来的输出方式)**\n>\n> 重定向(改变原来的输出方式)\n>\n> [root@sanchuang-linux redirect]# `echo \"xxx\" >file.txt`\n> [root@sanchuang-linux redirect]# `cat file.txt`\n> `xxx`\n\n\n\n### 脚本运行 标准错误输出、标准正确输出 (显示)\n\n> **知识点3.3 脚本运行 标准错误输出、标准正确输出 (显示)**\n>\n> 脚本一行一行 \t从上到下执行\n>\n> [root@sanchuang-linux redirect]# vim test.sh\n> [root@sanchuang-linux redirect]# cat test.sh\n> `t`\n> `date`\n> [root@sanchuang-linux redirect]# sh test.sh \n> `test.sh:行1: t: 未找到命令`\n> `2020年 10月 16日 星期五 14:49:40 CST`\n>\n> \\--------------------------------------------\n>\n> 注↑:标注错误输出 、正常输出\n\n\n\n### 重定向\n\n> **知识点3 重定向**\n>\n> `重定向:改变标准输入、标准输出的方向就是重定向`\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 类型\t\t\t\t\t\t操作符\t用途\n>\n> 重定向标准`输出`\t>\t\t\t\t将命令的执行结果`输出到指定的文件`中,而不是直接显示在屏幕上\n>\n> ​\t\t\t\t\t\t\t\t\\>>\t\t\t将命令执行的结果`追加输出到指定文件`\n>\n> 重定向标准`输入`\t<\t\t\t\t将命令中`接收输入的途径`由默认的键盘`更改 为指定的文件`\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 操作如下\n>\n> **知识点3.4 # sh test.sh > test_result.txt**\n>\n> `标准错误输出不会重定向到文件,正确输出会重定向到文件`\n>\n> [root@sanchuang-linux redirect]# vim test.sh\n> [root@sanchuang-linux redirect]# cat test.sh\n> `t`\n> `date`\n> [root@sanchuang-linux redirect]# sh test.sh \n> test.sh:行1: t: 未找到命令\n> 2020年 10月 16日 星期五 14:49:40 CST\n> [root@sanchuang-linux redirect]# sh test.sh `>` test_result.txt\n> test.sh:行1: t: 未找到命令\t\t\t`(注:标准错误输出显示在屏幕上,不重定向到文件)`\n> [root@sanchuang-linux redirect]# cat test_result.txt \n> 2020年 10月 16日 星期五 14:50:32 CST`(注:正确输出会重定向到文件)`\n>\n> \\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\n>\n> `重定向 > 默认只会重定向标准输出`\n\n\n\n### 重定向 标准错误\n\n> **知识点3 重定向 标准错误**\n>\n> `标准错误:通过该设备报告执行出错信息`\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 类型\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t操作符\n>\n> 重定向标准错误\t\t\t\t\t\t\t\t\t\t\t\t 2>\n>\n> ​\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t2>>\n>\n> 重定向`标准输出和标准错误`到`同一个文件`\t\t2>&1 或者>&或者 &>\n>\n> 重定向`标准输出和标准错误`到`不同文件`\t\t\t> 文件1 2 >文件2\t(没教)\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 操作如下\n>\n> **知识点3.5.1 # sh test.sh 2> test_result.txt**\n>\n> \\# sh test.sh `2>` test_result.txt `重定向标准错误`\t`(注:与>效果相反)`\n>\n> 正确输出显示在屏幕上,标准错误输出重定向到文件\n>\n> `只输出了错误的`\n>\n> [root@sanchuang-linux redirect]# sh test.sh `2>` test_result.txt\n> `2020年 10月 16日 星期五 14:52:33 CST`\t(注:正确输出显示在屏幕上)\n> [root@sanchuang-linux redirect]# cat test_result`.txt`\n> `test.sh:行1: t: 未找到命令`\t\t\t\t(注:标准错误输出重定向到文件)\n>\n> \n\n---\n\n> **知识点3.5.2 # sh test.sh &> test_result.txt**\n>\n> \\# sh test.sh `&>` test_result.txt\n>\n> `把正确的错误的都重定向到 文件`\n>\n> [root@sanchuang-linux redirect]# sh test.sh `&>` test_result.txt\n> [root@sanchuang-linux redirect]# cat test_result.txt \n> test.sh:行1: t: 未找到命令\n> 2020年 10月 16日 星期五 14:54:05 CST\n>\n> `与下面效果相同`\n>\n> \n\n---\n\n> **知识点3.5.3 # sh test.sh > test_result.txt 2>&1**\n>\n> \\# sh test.sh `>` test_result.txt `2>&1`\n>\n> `把错误输出重定向向到标准输出`\n>\n> [root@sanchuang-linux redirect]# sh test.sh > test_result.txt `2>&1`\n> [root@sanchuang-linux redirect]# cat test_result.txt \n> test.sh:行1: t: 未找到命令\n> 2020年 10月 16日 星期五 14:55:16 CST\n>\n> `两者效果等同`\n>\n> \n\n---\n\n> **知识点3.5.4 # sh test.sh > test_result.txt 1>&2**\n>\n> \\# sh test.sh `>` test_result.txt `1>&2`\n>\n> `把标准输出重定向错误输出`\n>\n> `*输出到屏幕上 (*注:不重定向到文件)`\n>\n> [root@sanchuang-linux redirect]# sh test.sh > test_result.txt `1>&2`\n> test.sh:行1: t: 未找到命令\t\t\t\t\t\t\t(注:输出到屏幕上)\n> 2020年 10月 16日 星期五 14:56:19 CST\t(注:输出到屏幕上)\n>\n> [root@sanchuang-linux redirect]# cat test_result.txt \n> [root@sanchuang-linux redirect]# \n\n\n\n### 使用重定向清空文件的几种方式\n\n> **知识点3.6 使用重定向清空文件的几种方式**\n>\n> 使用重定向清空文件的几种方式:\n>\n> \\# `>`stdout_test.txt\n>\n> \\# `echo >`stdout_test.txt (注:有空格)\n>\n> \\# `echo \"\"`>stdout_test.txt (注:有空格)\n>\n> \\# `:>`stdout_test.txt\n>\n> \\# `echo -n \"\" >` stdout_test.txt\n>\n> 代码如下\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> [root@sanchuang-linux redirect]# vim stdout_test.txt\n> [root@sanchuang-linux redirect]# `>stdout_test.txt\t(注:清空)`\n> [root@sanchuang-linux redirect]# cat stdout_test.txt\n> [root@sanchuang-linux redirect]# echo \"aaa\"> stdout_test.txt \n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n> aaa\n> [root@sanchuang-linux redirect]# `echo >stdout_test.txt \t\t(注:有空格)`\n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n>\n> [root@sanchuang-linux redirect]# echo \"aaa\">stdout_test.txt \n> [root@sanchuang-linux redirect]# `echo \"\">stdout_test.txt \t(注:有空格)`\n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n>\n> [root@sanchuang-linux redirect]# echo \"aaa\">stdout_test.txt \n> [root@sanchuang-linux redirect]# `:>stdout_test.txt \t(注:清空)`\n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n>\n> [root@sanchuang-linux chenpeng]# `echo -n \"\" > stdout_test.txt\t(注:清空)`\n> [root@sanchuang-linux chenpeng]# cat stdout_test.txt \n> [root@sanchuang-linux chenpeng]# \n>\n> \n\n---\n\n> **知识点3.6.1 # `echo -n \"\"`>stdout_test.txt **\n>\n> \\# `echo -n \"\"`>stdout_test.txt\n>\n> `echo默认情况会接一个换行符 不想换行 接-n`\n>\n> [root@sanchuang-linux redirect]# echo \"aaa\">stdout_test.txt \n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n> aaa\n> [root@sanchuang-linux redirect]# echo \"\">stdout_test.txt\n> [root@sanchuang-linux redirect]# cat stdout_test.txt \t\t`(注:有空格)`\n>\n> [root@sanchuang-linux redirect]# `echo -n \"\">`stdout_test.txt \t`(注:清空,没有空格)`\n> [root@sanchuang-linux redirect]# \n\n\n\n### 重定向 > 与 >>\n\n> **知识点3.7 重定向 > 与 >>**\n>\n> 重定向> 与 >>\n>\n> `>` \t\t是以`覆盖`的方式写入\n>\n> `>>`\t 是以`追加`的方式写入\n>\n> 代码如下\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> [root@sanchuang-linux redirect]# echo `\"aaa\" >` stdout_test.txt \n>\n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n> `aaa`\n> [root@sanchuang-linux redirect]# echo `\"bb\" >>` stdout_test.txt \n> [root@sanchuang-linux redirect]# cat stdout_test.txt \n> `aaa`\n> `bb`\n> [root@sanchuang-linux redirect]# \n\n\n\n### 重定向标准输入 read输入\n\n> **知识点3.8 重定向标准输入 read输入**\n>\n> `重定向标准输入 read输入`\n>\n> (注:用到了tmux)\n>\n> While 循环\n>\n> echo \"`$a $b $c`\"\n>\n\n```bash\n脚本1 3个参数 3个参数\n[root@sanchuang-linux redirect]# cat abc.sh\nwhile read a b c\ndo\n echo \"$a $b $c\"\ndone < f1.txt\n[root@sanchuang-linux redirect]# \n\n(注:窗口1)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# vim f1.txt\n[root@sanchuang-linux redirect]# cat f1.txt\nxx yy zz\naa bb cc\n\n(注:窗口2)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# sh abc.sh\nxx yy zz\naa bb cc\n\n[root@sanchuang-linux redirect]# \n\n(注:窗口3)\n```\n\n\n\n> echo \"`$a -- $b`\"\n>\n\n```bash\n脚本2 2个参数 3个参数\n[root@sanchuang-linux redirect]# vim abc.sh\n[root@sanchuang-linux redirect]# cat abc.sh\nwhile read a b\ndo\n echo \"$a -- $b\"\ndone < f1.txt\n[root@sanchuang-linux redirect]#\n\n(注:窗口1)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# vim f1.txt\n[root@sanchuang-linux redirect]# cat f1.txt \nxx yy zz\naa bb cc\n[root@sanchuang-linux redirect]# \n\n(注:窗口2)\n──────────────────────────────────────────────\n(注:默认空格分割参数,xx 和yy zz)\n[root@sanchuang-linux redirect]# sh abc.sh \nxx -- yy zz\naa -- bb cc\n[root@sanchuang-linux redirect]# \n\n(注:窗口3)\n```\n\n\n\n> echo \"line:`$line`\"\n>\n\n```bash\n脚本3 1个参数 3个参数\n[root@sanchuang-linux redirect]# vim abc.sh\n[root@sanchuang-linux redirect]# cat abc.sh \nwhile read line \ndo\n echo \"line:$line\"\ndone < f1.txt\n[root@sanchuang-linux redirect]# \n\n(注:窗口1)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# vim f1.txt\n[root@sanchuang-linux redirect]# cat f1.txt \nxx yy zz\naa bb cc\n[root@sanchuang-linux redirect]# \n\n(注:窗口2)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# sh abc.sh \nline:xx yy zz\nline:aa bb cc\n[root@sanchuang-linux redirect]# \n\n(注:窗口3)\n```\n\n\n\n> echo \"`$a -- $b -- $c -- $d -- $e`\"\n>\n\n```bash\n脚本4 5个参数 3个参数\n[root@sanchuang-linux redirect]# vim abc.sh\n[root@sanchuang-linux redirect]# cat abc.sh \nwhile read a b c d e \ndo\n echo \"$a -- $b -- $c -- $d -- $e\"\ndone < f1.txt\n[root@sanchuang-linux redirect]# \n\n(注:窗口1)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# vim f1.txt\n[root@sanchuang-linux redirect]# cat f1.txt \nxx yy zz\naa bb cc\n[root@sanchuang-linux redirect]# \n\n(注:窗口2)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# sh abc.sh \nxx -- yy -- zz -- -- \naa -- bb -- cc -- -- \n[root@sanchuang-linux redirect]# \n\n(注:窗口3)\n=================================\n```\n\n\n\n---\n\n> **知识点3.9 上课练习 重定向标准输入 read输入**\n>\n\n```bash\n[root@sanchuang-linux redirect]# vim student_information.sh\n[root@sanchuang-linux redirect]# cat student_information.sh \necho \"========学生信息管理系统===============\"\nwhile read name sex age\ndo\n echo \"==姓名:$name, 性别:$sex, 年龄:$age==\"\ndone < stu_info.txt\necho \"========================================\"\n[root@sanchuang-linux redirect]# \n\n(注:窗口1 tmux)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# cat stu_info.txt\nwenyao 18 f\nfengcheng 78 m\nchenpeng 80 m\n[root@sanchuang-linux redirect]# \n\n(注:窗口2 tmux)\n──────────────────────────────────────────────\n[root@sanchuang-linux redirect]# sh student_information.sh \n========学生信息管理系统===============\n==姓名:wenyao, 性别:18, 年龄:f==\n==姓名:fengcheng, 性别:78, 年龄:m==\n==姓名:chenpeng, 性别:80, 年龄:m==\n========================================\n[root@sanchuang-linux redirect]#\n\n(注:窗口3 tmux)\n```\n\n\n\n---\n\n## 三. SHELL-脚本练习及管道\n\n> **知识点4.0 接受从键盘的输入 管道符号**\n>\n> 脚本 接受从键盘的输入\n>\n> 要求:输入用户名和密码 创建相应的用户\n>\n> 需求分析:接受用户输入\n>\n> ​\t\t\t\t\t创建用户\n>\n> ​\t\t\t\t\t设置密码\n>\n> -----相关知识点----------------------------------\n>\n> 管道符号 `| :上一条命令的输出作为下一条命令的输入`\n>\n> \n>\n> yum list 默认输出到屏幕\n>\n> yum list | grep tmux yumlist的输出 作为grep tmux命令的输入\n\n\n\n---\n\n> ```bash\n> 创建用户 useradd wy\n> [root@sanchuang-linux ~]# useradd wy\n> [root@sanchuang-linux ~]# passwd wy\n> 更改用户 wy 的密码 。\n> 新的 密码:\n> 无效的密码: 密码少于 8 个字符\n> 重新输入新的 密码:\n> passwd:所有的身份验证令牌已经成功更新。\n> ==============================================================\n> 重新给用户wy设置密码\n> [root@sanchuang-linux ~]# echo \"yyyzzz123\" |passwd wy --stdin\n> stdin 标准输入\n> ```\n>\n> \n\n\n\n---\n\n> **\\*4.1 初始脚本1**\n>\n> (注:# passwd在bash中执行时会在中间停止,让用户进行输入密码\n>\n> ​\t\t\\# `为了防止shell停止使用参数--stdin`,让passwd介绍标准输入,echo是标准输出\n>\n> ​\t\t来自:https://blog.csdn.net/qq_31820885/article/details/78100587)\n>\n\n```bash\n[root@sanchuang-linux chenpeng]# vim test.sh\nread -p \"请输入用户名:\" username\nread -p \"请设置密码:\" password\n\nuseradd $username\necho $password | passwd $username --stdin\necho $username\necho $password\n\n[root@sanchuang-linux chenpeng]# sh test.sh\n请输入用户名:cp1\n请设置密码:123456\n更改用户 cp1 的密码 。\npasswd:所有的身份验证令牌已经成功更新。\ncp1\n123456\n[root@sanchuang-linux chenpeng]# id cp1\nuid=1009(cp1) gid=1009(cp1) 组=1009(cp1)\n[root@sanchuang-linux chenpeng]# less /etc/passwd\nroot:x:0:0:root:/root:/bin/bash\n………………\nwy:x:1008:1008::/home/wy:/bin/bash\ncp1:x:1009:1009::/home/cp1:/bin/bash\n```\n\n\n\n> \\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> **\\*4.2 python 与 shell 程序运行出错**\n>\n> python中如果程序运行中出现错误,后续操作会终止\n>\n> shell 中如果出现错误,操作会继续向下执行\n>\n> \n>\n> **\\*4.3 优化脚本2**\n>\n> 用户创建脚本优化:\n>\n> 1.让命令的标准输出和标准错误输出都输出到黑洞文件\n>\n> echo $password | passwd $username --stdin `&>/dev/null`\n>\n> 2.密码隐藏\t`-s`\n>\n> read -s -p \"请设置密码:\" password\n>\n> 3.判断用户是否存在\n>\n> 条件语句:\n>\n> `if 条件 then`\n>\n> ​\t\t`语句体1`\n>\n> `else`\n>\n> ​\t\t`语句体2`\n>\n> `fi`\n>\n> \n>\n> **\\*4.3 优化脚本2**\n>\n\n```bash\n[root@sanchuang-linux chenpeng]# vim test.sh\nread -p \"请输入用户名:\" username\n\nif cat /etc/passwd |grep $username &>/dev/null\nthen\n echo \"$username is exist!\"\nelse\n read -s -p \"请设置密码:\" password\n useradd $username &>/dev/null\n echo $password | passwd $username --stdin &>/dev/null\n echo -e \"\\n create $username ok!\"\nfi\n\n----------------------------------------------------------\n[root@sanchuang-linux chenpeng]# sh test.sh \n请输入用户名:cp1\ncp1 is exist!\n[root@sanchuang-linux chenpeng]# sh test.sh \n请输入用户名:cp8\n请设置密码:\n create cp8 ok!\n[root@sanchuang-linux chenpeng]# \n```\n\n\n\n> **4.3.2 脚本优化3**\n>\n\n```bash\n[root@sanchuang-linux chenpeng]# vim test.sh\nread -p \"请输入用户名:\" username\n\nif cat /etc/passwd |grep $username &>/dev/null\nthen\n echo \"$username is exist!\"\nelse\n read -s -p \"请设置密码:\" password\n useradd $username &>/dev/null\n echo $password | passwd $username --stdin &>/dev/null\n echo -e \"\\n create $username ok!\"\nfi\n \n(tmux 窗口1) \n──────────────────────────────────────────────\n[root@sanchuang-linux chenpeng]# sh test.sh \n请输入用户名:chen5556\nchen5556 is exist!\n[root@sanchuang-linux chenpeng]# sh test.sh \n请输入用户名:chen7778\n请设置密码:\n create chen7778 ok!\n[root@sanchuang-linux chenpeng]# \n\n(tmux 窗口2)\n```\n\n\n\n> **4.3.4 脚本改善 最终版**\n>\n> [root@sanchuang-linux chenpeng]# `id chen5557`\n> uid=1019(chen5557) gid=1019(chen5557) 组=1019(chen5557)\n>\n> \\--------------------------------------------------------\n>\n\n```bash\n[root@sanchuang-linux chenpeng]# vim test.sh\nread -p \"请输入用户名:\" username\n\nif id $username &>/dev/null\nthen\n echo \"$username is exist!\"\nelse\n read -s -p \"请设置密码:\" password\n useradd $username &>/dev/null\n echo $password | passwd $username --stdin &>/dev/null\n echo -e \"\\n create $username ok!\"\nfi\n\n(tmux 窗口1)\n──────────────────────────────────────────────\n[root@sanchuang-linux chenpeng]# sh test.sh \n请输入用户名:chen5556\nchen5556 is exist!\n[root@sanchuang-linux chenpeng]# sh test.sh \n请输入用户名:chen7777\n请设置密码:\n create chen7777 ok!\n[root@sanchuang-linux chenpeng]# \n\n(tmux 窗口2)\n```\n\n\n\n### 查看用户是否存在\n\n> **\\*4.4 查看用户是否存在**\n>\n> [root@sanchuang-linux ~]# `cat /etc/passwd` |grep cp1\n> `cp1`: x:1009:1009::/home/`cp1`:/bin/bash\n\n\n\n### 上一条命令返回值 $?\n\n> **\\*4.5 上一条命令返回值 $?**\n>\n> $? 上一个命令的返回值\n>\n> 上一条命令返回值: 保存在 -->$?\n>\n> 为0是成功\n>\n> 为1是失败\n>\n> `命令返回值为0 表示执行成功`\n>\n> ​\t\t\t\t\t\t`1 执行失败`\n>\n> ​\t\t\t\t\t\t`227 没有这条命令`\n>\n> 命令返回值 $?\n\n\n\n---\n\n> **\\*4.6 命令返回值 不精确的判断用户是否存在**\n>\n> 不精确地判断用户是否存在\n>\n> [root@sanchuang-linux ~]# cat /etc/passwd |`grep cp1`\t(注:不精确地判断用户是否存在)\n> `cp1`: x:1009:1009::/home/`cp1`:/bin/bash\n> [root@sanchuang-linux ~]# echo $?\t(注:为0是成功)\n> 0\n> [root@sanchuang-linux ~]# cat /etc/passwd |grep cp9\n> [root@sanchuang-linux ~]# echo $?\t(注:为1是失败)\n> 1\n>\n> \\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\n>\n> 命令返回值 id\n>\n> [root@sanchuang-linux ~]# `id cp1`\n> `uid`=1009(cp1) `gid`=1009(cp1) `组`=1009(cp1)\n> [root@sanchuang-linux ~]# echo $?\n> `0`\n> [root@sanchuang-linux ~]# id cp9\n> id: “cp9”:无此用户\n> [root@sanchuang-linux ~]# echo $?\n> `1`\n> [root@sanchuang-linux ~]# \n>\n> 上一条命令返回值: 保存在 ——>$?\n>\n> \\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\n>\n> `命令返回值为0 表示执行成功`\n>\n> ​\t\t\t\t\t\t`1 执行失败`\n>\n> ​\t\t\t\t\t\t`227 没有这条命令`\n\n\n\n---\n\n> **\\*4.7 精确的判断用户是否存在 (完善脚本)**\n>\n> 想要精确匹配的话,就把过滤的范围缩小一点:\n>\n> ^wy: 以wy: 开头\n>\n> `^…:以什么开头,整行以什么开头`\n>\n> `…$:以什么结尾,整行以什么结尾`\n>\n> [root@sanchuang-linux ~]# cat /etc/passwd |`grep \"^wy:\"`\n> `wy:` x:1008:1008::/home/wy:/bin/bash\n>\n> [root@sanchuang-linux ~]# useradd wy:\n> useradd:无效的用户名“wy:”\n\n\n\n### wc命令 <重定向标准输入\n\n> **知识点5.1 wc命令 <重定向标准输入**\n>\n> wc(字数统计)命令\n>\n> 格式:`wc\t[选项]...\t目标文件...`\n>\n> `-l:统计行数`\n>\n> `-w:统计字数` (前后都是空白的一组字符)\n>\n> `-c:统计字符数`(可见和不可见的字符)\n>\n> 例:\n>\n> \\# wc /etc/hosts\n>\n> `4` `23` `185` /etc/hosts\n>\n> (* 注:4行,23个单词,185个字节)\n>\n> 代码如下\n>\n> \\---------------------------------------------------------------\n>\n> [root@sanchuang-linux ~]# `wc -l` backup_log.sh (注:查看文件有多少行)\n> 0 backup_log.sh\n> [root@sanchuang-linux ~]# `wc <` backup_log.sh \t(输入重定向)\n> 0 0 0\n> [root@sanchuang-linux ~]# wc backup_log.sh \n> 0 0 0 backup_log.sh\n>\n> [root@sanchuang-linux lianxi]# `wc -l` sshd_config2\t(注:查看文件有多少行)\n> 148 sshd_config2\n> [root@sanchuang-linux lianxi]# `wc <` sshd_config2\t(注:`标准输入 输入重定向`)\n> 148 559 4425\n> [root@sanchuang-linux lianxi]# wc sshd_config2 (注:wc(字数统计)命令)\n> 148 559 4425 sshd_config2\n\n\n\n---\n\n> **知识点5.2 重定向 发信息 echo \"hello brother\" > /dev/pts/22**\n>\n> [root@sanchuang-linux ~]# w\n> 17:20:37 up 19:51, 7 users, load average: 0.00, 0.00, 0.02\n> USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT\n> root tty1 - 0610月20 7:20m 0.60s 0.60s -bash\n> root pts/7 192.168.0.30 14:30 42:37 0.09s 0.00s tmux\n> root pts/21 192.168.0.30 16:48 21.00s 0.14s 0.14s -bash\n> root `pts/22` 192.168.0.30 17:20 0.00s 0.02s 0.01s `w`\n>\n> \\----------------------------------------------------------------------\n>\n> \\# `echo \"hello brother\" > /dev/pts/22`\n>\n> 重定向 发信息\n\n\n\n### xargs 管道符号\n\n> **知识点5.3 xargs 管道符号**\n>\n> xargs 将前面命令的`输出`送给后面的命令`作为参数`使用\n>\n> `xargs 和 管道符号 一般配套使用`\n>\n> \\-------------------------------------------------\n>\n> 在当前路径查看.txt结尾的文件\n>\n> find . -name \"*.txt\"\n>\n> \\------------------------------------\n>\n> 管道 与 xargs\n>\n> 将管道前的输出作为参数赋给后面的命令\n>\n> `find . -name \"*.txt\" | xargs rm -rf`\n>\n> \\--------------------------------------------------------------------------------------\n>\n> 管道与xargs\n>\n> xargs 可以将管道或标准输入(stdin)数据转换成命令行参数,也能够从文件的输出中读取数据。\n>\n> [root@mysql-binary vim_test]# find . -name \"*.sh\" `|xargs ls -al`\n>\n> [root@mysql-binary vim_test]# find . -name \"*.txt\" `| xargs rm -rf`\n>\n> (注:ls -al 看文件详细信息)\n>\n> 代码如下\n>\n> \\------------------------------------------------------------------\n>\n> [root@sanchuang-linux chenpeng]# find . -name \"*.sh\" `|xargs ls -al`\n> -rw-r--r--. 1 root root 77 10月 16 15:30 ./redirect/abc.sh\n> -rw-r--r--. 1 root root 206 10月 16 15:45 ./redirect/student_information.sh\n> -rw-r--r--. 1 root root 300 10月 16 17:15 ./test.sh\n> [root@sanchuang-linux chenpeng]# ls -al test.sh \n> -rw-r--r--. 1 root root 300 10月 16 17:15 test.sh\n\n\n\n---\n\n","tags":["Linux","Shell"],"categories":["Linux"]},{"title":"08_Linux基础-vim-tmux-字符编码","url":"/posts/33007.html","content":"## 一. vim\n\n> 文本编辑器-vim(==编辑文本==)\n\n\n\n> Windows:记事本、word、sublime、pycharm\n>\n> 能编辑音乐、视频、图片?答:不能,==只能编辑文本==\n\n\n\n> Linux:\n>\n> ​\t\tvi(==字符界面==),vim(==字符界面==),gedit(==图形化==)\n>\n> \n>\n> ==unix 都会安装vi==\n>\n> vim 是vi的==加强版==(在vi基础上添加其他功能)\n\n\n\n### vim编辑器作用\n\n> vim编辑器==作用==:\n>\n> ==1、编写脚本、程序==\n>\n> ==2、修改配置文件==\n>\n> ==3、做一些文本处理==\n\n\n\n### vim模式\n\n> vim有三种最常用最基本的模式:命令模式、编辑模式(插入模式)、末行模式、可视模式,替换模式\n>\n> vim有三种最常用最==基本==的模式:\n>\n> ==命令模式==\n>\n> ==编辑模式==\n>\n> ==末行模式==\n>\n> \n>\n> 还有另外两种==不常用==模式:\n>\n> ==视图模式==\n>\n> ==替换模式==\n\n\n\n#### vim命令模式\n\n> ==命令模式:vim a / ESC==\n>\n> ​\t\t==无法编辑==,只允许删除、复制、粘贴、撤销等快捷操作,打开文件时==默认==进行此模式\n>\n> ==yy\t复制==\n>\n> ==p\t粘贴==\n>\n> ==dd\t删除==\n>\n> ==u\t撤销==\n>\n> ==命令模式== 相当于一个==中间==介\n>\n> 每个模式==退出== 都会==回到命令模式==,命令模式可以进入所有模式\n\n\n\n#### vim编辑模式\n\n> 编辑模式 ESC ==i==\n>\n> -- 插入 --\n>\n> ​\t\t插入模式,进行==文本编辑==\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\n>\n> 操作键\t功能\n>\n> ​\t\t==i==\t光标在==当前==位置进入插入模式\n>\n> ​\t\tI\t光标==跳到行首==并进入插入模式\n>\n> ​\t\ta\t光标==后退一格==并进入插入模式\n>\n> ​\t\tA\t光标==退到行尾==并进入插入模式\n>\n> ​\t\t==o==\t在光标所在==行下新起一行==并进入插入模式\n>\n> ​\t\t==O==\t在光标所在==行上新起一行==并进入插入模式\n>\n> ​\t\ts\t==删除==光标==所在字符==并进入插入模式\n>\n> ​\t\tS\t==删除==光标所在==行==并进入插入模式\n\n\n\n#### vim末行模式\n\n> 末行模式 ESC ==:==\n>\n> : \n>\n> 输入命令,设置环境,保存文件,查找替换\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\n>\n> 操作键\t功能\n>\n> ​\t\t==:q==\t如果未对文件做改动则==退出==\n>\n> ​\t\t==:q!==\t==放弃保存==并==退出==\n>\n> ​\t\t==:wq\t保存==当前文件并==退出==\n>\n> ​\t\t==:wq!\t强制保存==当前文件并==退出==\n>\n> ​\t\t==:x\t保存==当前文件并==退出==\n>\n> ​\t\t==:x!\t强制保存==当前文件并==退出==\n>\n> ​\t\t==ZZ\t保存==当前文件并==退出==\n\n\n\n#### vim视图模式\n\n> 视图模式 ESC ==v、V、ctrl+v==\n>\n> -- 可视 行 --\n>\n> ​\t\t选择特定的块文本,进行复制,修改等\n>\n> 小==v==:选择==行指定的部分==\n>\n> 大==V==:选择==整个行==\n>\n> ==Ctrl + v== :选择==块== 插入按I 退出模式进人命令模式(Esc),这个时候就全部加上\n\n\n\n#### vim替换模式\n\n> 替换模式 ESC ==R==\n>\n> -- 替换 --\n>\n> \\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\n>\n> 123 hello456 789\n> xxx helloyyy zzz\n> xxx yyy zzz\n\n\n\n### 练习\n\n> **课堂练习1 插入模式**\n>\n> 123 456\n> 123 4\n> xyz 789\n> 4\n> xyz 789\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\n>\n> 步骤:\n>\n> ==v== 小v 可视模式 visual ---》选择一部分\n>\n> ==y== 按y复制\n>\n> ==o== 按o另起一行,进入插入模式\n>\n> ==P== 再按esc,再p,按p粘贴\n\n\n\n> **课堂练习2**\n>\n> 123 TEST 456 789\n> xxx TEST yyy zzz\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\n>\n> 选择块插入\n>\n> ctrl + v:选择块 \n>\n> 插入按大I \n>\n> ESC 退出模式进入命令模式,这个时候就全部加上\n\n\n\n### vim常用快捷方式\n\n> vim 常用快捷方式\n>\n> vim打开文件:\n>\n> \\# vim e\n> \\# ==vim +5 e==\n>\n> 表示打开文件e,并且==将光标移动到第3行==\n>\n> \\# ==vim +/aa e==\n>\n> 打开文件e,并且==高亮显示aa字符==\n\n\n\n### 退出vim编辑器的方法\n\n> vim保存退出:\n>\n> 操作键\t功能\n>\n> ​\t\t==:q==\t如果未对文件做改动则==退出==\n>\n> ​\t\t==:q!==\t放弃保存并==退出==\n>\n> ​\t\t==:wq==\t==保存==当前文件并==退出==\n>\n> ​\t\t==:wq!==\t==强制保存==当前文件并==退出==\n>\n> ​\t\t==:x==\t==保存==当前文件并==退出==\n>\n> ​\t\t==:x!==\t==强制保存==当前文件并==退出==\n>\n> ​\t\t==ZZ==\t==保存==当前文件并==退出== (注:命令模式退出)\n\n\n\n### 光标移动\n\n> 光标移动:上下左右方向键(k,j,h,l)\n>\n> \\-\\-\\-\\--\\-\\-\\-\\--\\-\\-\\-\\--\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\--\\-\\-\\--\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\--\\-\\-\n>\n> 操作类型\t\t \t操作键\t\t\t\t功能\n>\n> ==光标==方向移动\t ==k,j,h,l==\t\t==上、下、左、右==\n>\n> \\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> ==翻页==\t\t\t Page Down或Ctrl+F\t向==下==翻动一整页内容\n>\n> ​\t\t\t\t\t Page Up或Ctrl+B\t\t向==上==翻动一整页内容\n>\n> \\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> ==行内==快速跳转\t Home键或“^”、数字“0”\t跳转至==行首\t(注:“^”尖符号)==\n>\n> ​\t\t\t\t\t\t\tEnd键或“$”键\t\t\t\t\t跳转到==行尾==\n>\n> \\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> ==行间==快速跳转\t\n>\n> 1G或者gg\t\t\t跳转到文件的==首行==\n>\n> G\t\t\t\t\t\t 跳转到文件的==末尾行==\n>\n> \\#G\t\t\t\t\t\t跳转到文件中的==第#行==\n>\n> (末行模式):40\t跳转到==40行==\n>\n> w\t\t\t\t\t\t ==每个单词==的==首字母==跳转\n>\n> e\t\t\t\t\t\t ==每个单词==的==尾字母==跳转\n\n\n\n### vim设置\n\n> **vim设置**\n>\n> (末行模式):set number\t\t==设置行数==\n>\n> (末行模式):set nonumber \t==取消设置==\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\n>\n> ```vim\n> :set number\n> \n> 1 aa bb cc\n> 2 dd ee ff\n> 1 aa bb cc\n> 2 dd ee ff\n> 3 aa bb cc\n> ```\n\n\n\n### 删除(剪切)、复制、粘贴\n\n> 操作类型\n>\n> 操作键\t\t功能\n>\n> \\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\n>\n> **删除** \t\t(*注:一般==^行首,$行尾==)\n>\n> ==x或d或Del\t删除==光标处的==单个字符==\n>\n> ==dd\t\t\t删除==当前光标==所在行==\n>\n> ==\\#dd\t\t\t删除==从光标处开始的==\\#行内容==\n>\n> d==^==\t\t\t==删除==当前==光标之前到行首==的所有字符\n>\n> d==$==\t\t\t删除当前==光标处到行尾==的所有字符\t\n>\n> d==w==\t\t\t==删除一个单词==(word),以空格、冒号等 符号\n>\n> \\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\n>\n> **复制**\t\n>\n> ==yy\t\t\t复制==当前行==整行==的内容到剪贴板\n>\n> ==\\#yy\t\t\t复制==从光标处开始的==#行==内容\n>\n> \\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\n>\n> **粘贴**\t\n>\n> 小==p==\t\t\t将==缓冲区==中的内容==粘贴==到光标位置处==之后==\n>\n> 大==P\t\t\t粘贴==到光标位置处==之前==\n\n\n\n### 文件内容查找\n\n> 文件内容查找\n>\n> 操作键\t功能\n>\n> ==/==word\t==从上而下==在文件中查找字符串“word”\n>\n> ==?==word\t==从下而上==在文件中查找字符串“word”\n>\n> 小==n==\t\t==定位下一个==匹配的被查找字符串\n>\n> 大==N==\t\t==定位上一个==匹配的被查找字符串\n>\n> (注:/word 和 ?word 不同点:==方向相反==)\n\n\n\n### 取消高亮、设置行数、取消行数设置\n\n```\n取消高亮 :noh\n设置行数:set nu\n取消:set nonu\n```\n\n\n\n---\n\n## 二. vim-tmux及字符编码问题\n\n> **文件内容替换**\n>\n> 文件内容替换(末行模式)\n>\n> 命令\t\t\t\t\t\t功能\n>\n> ==:s /old/new==\t\t\t将==当前行==中查找到的==第一个==字符“old”串==替换==为“new”\n>\n> ==:s /old/new/g==\t\t 将==当前行==中查找到的==所有==字符串“old”==替换==为“new”\n>\n> ==:#,# s==/old/new/==g==\t在==行号“#,#”==范围内替换==所有==的字符串“old”为“new”\n>\n> ==:% s==/old/new/==g==\t 在==整个文件==范围内替换==所有==的字符串“old”为“new” global\n>\n> ==:s== /old/new/==gc==\t\t在替换命令末尾加入==c命令==,将对每个替换动作==提示==用 户进行==确认==\tConfirm\n>\n> ==:%s==/feng//==g==\t\t\t 将==所有==的feng==删除==\n>\n> (注::s/…/… 当前行 第一个str\n>\n> ​\t\t\t:s/…/…/g当前行 所有str\n>\n> ​\t\t\t:#,#s/…/…/g 行号#,# 所有str\n>\n> ​\t\t\t:%s/…/…/g 整个文档 所有str\n>\n> ​\t\t\t:s/…/…/gc 整个文档 所有str 确认提示\n>\n> ​\t\t\t:%s/…//g 整个文档 所有str 删除)\n>\n> (注:s \t —— 替换\n>\n> ​\t\t\t :s\t —— 当前行替换\n>\n> ​\t\t\t\\#,# —— 行号#到#\n>\n> ​\t\t\t%\t —— 整个文档\n>\n> ​\t\t\tg\t —— 所有字符串\n>\n> ​\t\t\tc\t —— 确认提示\n>\n> ​\t\t\t:%s/…//g —— 整个文档 所有str 删除)\n\n\n\n> ==缓存:swp文件==\n>\n> ==编写文件时 1.txt==\n>\n> ==先把1.txt文件拷贝一份,拷贝成.1.txt.swp文件,真正编辑的是这个文件==\n>\n> ==保存时,会将.1.txt.swp覆盖1.txt==\n>\n> \\-------------------------------------------------------------------------------------------\n>\n> **相关操作**\n>\n> 一个终端下# vim 2.txt,另一个终端敲# ls -al,提示如下\n>\n> [root@sanchuang-linux cp]# ==ls -al==\n> 总用量 88\n> -rw-r--r--. 1 root root 4096 10月 15 15:05 ==.2.txt.swp==\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\n>\n> 在另一个终端# vim 2.txt,提示如下\n>\n> ```\n> 发现交换文件 \".2.txt.swp\"\n> 所有者: root 日期: Thu Oct 15 15:05:45 2020\n> 文件名: ~root/cp/2.txt\n> 修改过: 否\n> 用户名: root 主机名: sanchuang-linux\n> 进程 ID: 3129 (仍在运行)\n> 正在打开文件 \"2.txt\"\n> 日期: Thu Oct 15 15:05:22 2020\n> \n> (1) Another program may be editing the same file. If this is the case,\n> be careful not to end up with two different instances of the same\n> file when making changes. Quit, or continue with caution.\n> (2) An edit session for this file crashed.\n> 如果是这样,请用 \":recover\" 或 \"vim -r 2.txt\"\n> 恢复修改的内容 (请见 \":help recovery\")。\n> 如果你已经进行了恢复,请删除交换文件 \".2.txt.swp\"\n> 以避免再看到此消息。\n> \n> 交换文件 \".2.txt.swp\" 已存在!\n> 以只读方式打开([O]), 直接编辑((E)), 恢复((R)), 退出((Q)), 中止((A)): \n> ```\n>\n> \n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\n>\n> :wq 写入时,提示如下\n>\n> ```\n> \"2.txt\" \n> 警告: 此文件自读入后已发生变动!!!\n> 确实要写入吗 (y/n)?\n> ```\n>\n> \n\n\n\n> ==\\* 注意==:进入命令模式,按数字键,之后再进入插入模式的话,会将输入内容按照之前按的数字大小复制成多份\n>\n> (注:步骤\n>\n> ​\t\t\tvim 1.txt ——> 先按数字3 ——> 按i进入插入模式 ——> abc ——> Esc ——> abcabcabc)\n\n\n\n> **打开新文件或读入其他文件内容 && 撤销和另存为**\n>\n> 打开新文件 ==:e== 或 读入其他文件内容 ==:r==\n>\n> 命令\t功能\n>\n> ==:e== ~/install.log\t\t\t==打开==新的==文件==进行==编辑==\n>\n> ==:r== /etc/filesystems\t在==当前文件==中==读入其他文件内容== (注:即追加内容)\n>\n> 撤销和另存为 ==:w==\n>\n> ==:w== /tmp/hello.txt\t把当前文件另存为/tmp目录下的hello.txt\n>\n> \n>\n> ==同时编辑==多个文件\n>\n> \\# ==vim 1.txt 2.txt==\n>\n> ==:n== 编辑上一个\n>\n> ==:N== 编辑下一个\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\n>\n> 例:\n>\n> \\# vim 2.txt\n>\n> ==:e 1.txt==\n>\n> (注:进入1.txt进行编辑)\n>\n> \\-\\-\\-\\-\\-\\-\\-\\--\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\-\\--\n>\n> \\# vim 2.txt\n>\n> ==:r 1.txt==\n>\n> (注:读入1.txt文件的内容。在当前光标下一行插入1.txt文件内容)\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\n>\n> 撤销和另存为 ==:w==\n>\n> 命令\t\t\t\t\t\t 功能\n>\n> ==:w== /tmp/hello.txt\t把当前文件另存为/tmp目录下的hello.txt\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\n>\n> 例:\n>\n> \\# vim 1.txt\n>\n> ==:w /root/cp/test.txt==\n>\n> (注:将文件1.txt另存为在/root/cp/目录下,==改名为test.txt==)\n\n\n\n> **vim的配置(3种)**\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 第一种\n>\n> ==vim设置==:(末行模式) \n>\n> 一次性设置行数:(只在当前编辑时生效)\n>\n> :set number\n>\n> 取消\n>\n> :set nonumber\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 第二种\n>\n> ==全局配置文件==:\n>\n> \\# vim /etc/vimrc\n>\n> \\# cp /etc/vimrc{,.bak} (注:效果等同于 # cp /etc/vimrc /etc/vimrc.bak)\n>\n> ​\t\t\t\t\t\t\t\t\t (* 注↑:备份操作。修改全局配置文件前先备份。出错就回滚)\n>\n> set number\t\t\t\t (注:==设置行数==)\n>\n> set ==showcmd==\t\t\t (注:==显示当前键入命令==)\n>\n> set encoding=utf-8 \t (注:==设置编码==)\n>\n> set tabstop=4\t\t\t (注:==设置tab键的空格数==)\n>\n> \\--------------------------------------------------------------------------------------------\n>\n> 第三种:(只针对当前用户生效)\n>\n> ==编写 ~/.vimrc==\n>\n> [root@sanchuang-linux ~]# vim ==.vimrc==\n>\n> [root@sanchuang-linux ~]# cat .vimrc\n>\n> set number\n>\n> set showcmd \n>\n> set encoding=utf-8\n>\n> set tabstop=4\n\n\n\n### tmux\n\n> ```bash\n> tmux shell里面多屏幕编辑\n> 安装:\n> # yum install tmux -y \n> tmux\n> Ctrl+b 上下左右\n> Ctrl+b shift +"\n> Ctrl+b shift + %\n> Ctrl+b + c 创造新的一页\n> Ctrl+b + p 返回上一页\n> Ctrl+b + n 返回下一页\n> Ctrl+b + x 关闭当前小窗口\t \n> ctrl+d\t关闭\n> Ctrl+b + b + ! \t删除\n> \n> Ctrl+b + d 暂存,保存当前的tmux状态并退出tmux\n> ```\n>\n> \n\n\n\n> tmux:\n>\n> 安装:yum install tmux\n>\n> tmux: \n>\n> 一:敲tmux 进入会话\n>\n> 窗口底部有绿杠表示进入了tmux\n>\n> \\-----------------------------------------------------\\-----------------------------------------------------\n>\n> 左右分屏:先按==ctrl + b==,然后再按shift+==%==号\n>\n> 上下分屏:先按==ctrl + b==, 然后再按shift+==\"==\n>\n> 上下左右移动光标: ==ctrl + b==,再按==上下左右==方向键\n>\n> 删除一个分割: 光标移动到那个分割屏幕,然后按==ctrl +d==\n>\n> 新增一个新的窗口(新增一页):==ctrl+b==,然后按==c==\n>\n> 返回上一页: ==ctrl+b== 然后按==p==\n>\n> 返回下一页: ==ctrl+b== 然后按==n==\n>\n> \\-----------------------------------------------------\\-----------------------------------------------------\n>\n> 保存当前的tmux状态,并退出tmux:\n>\n> 使用: ==ctrl+b== 然后按==d==\n>\n> \\-----------------------------------------------------\\-----------------------------------------------------\n>\n> 查看当前保存的会话状态\n>\n> [root@mysql-binary ~]# ==tmux ls==\n>\n> 0: 2 windows (created Thu Oct 15 16:31:27 2020) [139x22]\n>\n> 1: 2 windows (created Thu Oct 15 16:45:40 2020) [139x22]\n>\n> \\--------------------------------------------------------\\-----------------------------------------------------\n>\n> 进入第一个会话状态:\n>\n> ==tmux a -t 0==\n>\n> \\--------------------------------------------------------\\-----------------------------------------------------\n>\n> ==设置tmux==,跟vim的末行模式很像:\n>\n> 按==ctrl+b== ,然后按==:==(这时窗口底部就会有==黄色==的杠)\n>\n> 设置==同步==: ==ctrl+b== 然后按==:== 然后输入==set synchronize-panes on==\n>\n> ​ \t\t\t\t\t\t\t\t 取消同步==set synchronize-panes off==\n\n\n\n> **tmux终端关闭,执行的程序会继续执行 (\\* tmux的好处)**\n>\n> tmux 终端关闭,不是tmux会话关闭。tmux 终端关闭,那之前执行的程序都会继续执行。\n>\n> 不使用tmux,默认情况下,终端关闭,执行的程序也会关闭。 测试如下\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\==\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> 测试:\n>\n> ==编写脚本:==\n>\n> \\# cat sleep.sh \n> echo \"begin...........\"\n> sleep 100\n> echo \"end.............\"\n>\n> \\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=====\\=\\==\\=\\=\n>\n> ==运行脚本==\n> \\# sh sleep.sh \n> begin...........\n>\n> \\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=====\\=\\==\\=\\=\n>\n> 运行脚本:==(放到后台运行)==\n>\n> \\# sh sleep.sh ==&==\n>\n> \\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=====\\=\\==\\=\\=\n>\n> ==查看进程有没有运行==\n>\n> \\# ==ps -ef |grep sleep==\n> root 13133 13112 0 17:12 pts/6 00:00:00 sh sleep.sh\n> root 13134 13133 0 17:12 pts/6 00:00:00 sleep 100\n> root 13190 13140 0 17:12 pts/16 00:00:00 grep --color=auto sleep\n>\n> \\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=====\\=\\==\\=\\=\n>\n> ==关闭终端之后再重新开启连接,查看进程有没有运行。==\n>\n> 结果:没有运行\n>\n> ……\n>\n> \\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=====\\=\\==\\=\\=\n>\n> ==在tmux下 运行脚本==\n>\n> ……\n>\n> ==tmux关闭后 会话还在,程序还会一直运行==\n>\n> \\# ps -ef |grep sleep\n> root 13278 13003 0 17:17 pts/13 00:00:00 sh sleep.sh\n> root 13279 13278 0 17:17 pts/13 00:00:00 sleep 100\n> root 13284 13140 0 17:17 pts/16 00:00:00 grep --color=auto sleep\n>\n> \\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=====\\=\\==\\=\\=\n\n\n\n### 编码\n\n> **编码**\n>\n> 编码:http://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html\n>\n> \n>\n> 文件编码一般2种方式:==ascii 和 unicode==\n>\n> UTF-8 是 Unicode 的实现方式之一\n>\n> \n>\n> ==转编码==:\n>\n> \\# ==iconv -f== utf-8 ==-t== gbk ==code_test.txt== >==code_test1.txt==\n>\n> ASCII 码 最多能表示256个字,不够用\n>\n> unicode 万国码,每个字给你一个序号\n>\n> UTF-8 是 Unicode 的实现方式之一,规定怎么存储在计算机。\n>\n> (UTF-8对ascii码/英文码友好)\n>\n> \n>\n> ==以什么编码方式存储,就要以什么编码方式解码==\n>\n> \n>\n> utf-8、utf-16\n>\n> \n>\n> 国内编码 gbk、gb2131\n>\n> \\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\n>\n> ==系统语言设置环境:==\n>\n> \\# ==locale==\n>\n> LANG=zh_CN.UTF-8\n>\n> LC_CTYPE=\"zh_CN.UTF-8\"\n>\n> LC_NUMERIC=\"zh_CN.UTF-8\"\n>\n> LC_TIME=\"zh_CN.UTF-8\"\n>\n> LC_COLLATE=\"zh_CN.UTF-8\"\n>\n> LC_MONETARY=\"zh_CN.UTF-8\"\n>\n> LC_MESSAGES=\"zh_CN.UTF-8\"\n>\n> LC_PAPER=\"zh_CN.UTF-8\"\n>\n> LC_NAME=\"zh_CN.UTF-8\"\n>\n> LC_ADDRESS=\"zh_CN.UTF-8\"\n>\n> LC_TELEPHONE=\"zh_CN.UTF-8\"\n>\n> LC_MEASUREMENT=\"zh_CN.UTF-8\"\n>\n> LC_IDENTIFICATION=\"zh_CN.UTF-8\"\n>\n> LC_ALL=\n>\n> \\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\n>\n> ==file code_test.txt \t注:查看文件编码类型==\n>\n> \n>\n> \\# locale 系统语言设置环境\n>\n> \\# file code_test1.txt 看文件编码方式\n>\n> 系统、文件、shell 三者统一 ,不会乱码\n>\n> \\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\n>\n> 上课代码操作:\n>\n> \\# mkdir vim_test\n> \\# cd vim_test/\n> \\# ls\n> \\# rz -E\t(注:将windows code_test.txt文件上传linux)\n> rz waiting to receive.\n> \\# ls\n> code_test.txt\n> \\# vim code_test.txt \n> \\# ==file code_test.txt \t(注:查看文件编码类型)==\n> code_test.txt: UTF-8 Unicode text\n> \\# iconv -f utf-8 -t ==gbk== code_test.txt >code_test1.txt\t(注:转国标码)\n> \\# ==file code_test1.txt==\n> code_test1.txt: ==ISO-8859 text\t(注:国标码)==\n> \\# vim code_test1.txt \t(注:显示乱码)\n> \\# \n>\n> 为什么出现乱码?答:以utf-8的方式打开gbk编码\n>\n> 以什么编码方式存储,就要以什么编码方式解码\n\n\n\n### 总结(xmind)\n\n> ![image-20220504144731448](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205041447906.png)\n>\n> ```bash\n> vim文本编辑器\n> vi,vim\n> vim常见模式\n> \t命令模式\n> \t\t文件打开默认就是命令模式\n> \t\tESC键到达\n> \t编辑模式\n> \t\ta,i,o,s(支持大写)\n> \t末行模式\n> \t\t:\n> \t可视模式\n> \t\tv\n> \t\t\t选中文本指定部分\n> \t\tV\n> \t\t\t选择文本指定行\n> \t\tctrl+v\n> \t\t\t选择文本指定块\n> \t替换模式\n> \t\tR\n> 基本使用\n> \t命令模式\n> \t\t删除\n> \t\t\tx 、d\n> \t\t\tdd\n> \t\t\t5dd\n> \t\t复制\n> \t\t\tyy\n> \t\t\t3yy\n> \t\t粘贴\n> \t\t\tp \n> \t\t撤销\n> \t\t\tu\n> \t\t查找\n> \t\t\t/\n> \t\t光标移动\n> \t\t\t上下左右方向键(k,j,h,l)\n> \t\t\t文件首\n> \t\t\t\tgg\n> \t\t\t文件尾\n> \t\t\t\tG\n> \t\t\t移动到特定行\n> \t\t\t\t5G\n> \t\t\t\t:5\n> \t\t\t行首\n> \t\t\t\thome键\n> \t\t\t\t0\n> \t\t\t\t^\n> \t\t\t行尾\n> \t\t\t\tend键\n> \t\t\t\t$\n> \t\t\t上翻页\n> \t\t\t\tpage up, ctrl+b\n> \t\t\t下翻页\n> \t\t\t\tpagedowm, ctrl+f\n> \t编辑模式\n> \t\ti\n> \t\tI\n> \t\to\n> \t\tO\n> \t\ta\n> \t\tA\n> \t\ts\n> \t\tS\n> \t可视模式\n> \t\t复制y\n> \t\t插入 I\n> \t末行模式\n> \t\t退出和保存\n> \t\t\tq\n> \t\t\tq!\n> \t\t\twq\n> \t\t\twq!\n> \t\t\tx\n> \t\t\tZZ命令模式退出\n> \t\t替换\n> \t\t\t:s/old/new\n> \t\t\t:s/old/new/g\n> \t\t\t:%s/old/new\n> \t\t\t:%s/old/new/g\n> \t\t\t:3,5s/old/new/g\n> \t\t\t:%s/old/new/gc\n> \t\t设置\n> \t\t文件操作\n> \t\t\t:e 编辑新文件\n> \t\t\t:r 导入文件内容\n> \t\t\t:w 另存文件路径\n> \t\t\tvim 1.txt 2.txt\n> \t\t\t\t:n 编辑下一个\n> \t\t\t\t:N 编辑上一个\n> vim常见快捷方式使用\n> \tvim file1 file2 file3\n> \tvim +10 file\n> \tvim +/aa file\n> vim的配置\n> \t临时配置\n> \t\t末行模式\n> \t\t\t:set nu\n> \t全局配置\n> \t\t/etc/vimrc\n> \t用户配置\n> \t\t~/.vimrc\n> tmux\n> \ttmux:\n> 安装:yum install tmux\n> tmux: \n> 一:敲tmux 进入会话\n> 窗口底部有绿杠表示进入了tmux\n> \n> 左右分屏:先按ctrl + b ,然后再按shift+% 号\n> 上下分屏:先按ctrl + b, 然后再按 shift+\"\n> 上下左右移动光标: ctrl + b 再按上下左右方向键\n> 删除一个分割: 光标移动到那个分割屏幕,然后按ctrl +d\n> 新增一个新的窗口(新增一页): ctrl+b 然后按c\n> 返回上一页: ctrl+b 然后按p\n> 返回下一页: ctrl+b 然后按n\n> \n> 保存当前的tmux状态,并退出tmux:\n> 使用: ctrl+b 然后按d\n> \n> 查看当前保存的会话状态\n> [root@mysql-binary ~]# tmux ls\n> 0: 2 windows (created Thu Oct 15 16:31:27 2020) [139x22]\n> 1: 2 windows (created Thu Oct 15 16:45:40 2020) [139x22]\n> \n> 进入第一个会话状态:\n> tmux a -t 0\n> \n> 设置tmux,跟vim的末行模式很像:\n> 按ctrl+b ,然后按: (这时窗口底部就会有黄色的杠)\n> 设置同步: ctrl+b 然后按: 然后输入set synchronize-panes on\n> 取消同步set synchronize-panes off\n> \n> tmux 终端关闭,不是tmux会话关闭。那之前执行的程序都会继续执行。\n> 不使用tmux,默认情况下,终端关闭,执行的程序也会关闭。\n> 文件编码\n> \ticonv -f utf-8 -t gbk file.txt > file2.txt\n> \t查看系统语言环境\n> \t\tlocale\n> \tascii\n> \tunicode\n> \t\tutf-8\n> \t\tutf-16\n> \t\tgbk\n> \t\tgb2132\n> ```\n>\n> \n\n\n\n---\n\n","tags":["Linux","Vim"],"categories":["Linux"]},{"title":"07_Linux基础-计划任务-备份脚本-变量定义和使用","url":"/posts/29955.html","content":"## 一. 计划任务\n\n> 主要内容:周期性的计划任务crontab\n>\n> ==/var/spool/cron/ 统一存放计划任务的目录==\n>\n> ==/var/log/cron\t\t日志文件==\n>\n> ==/etc/cron\t cron.daily/ cron.hourly/ cron.monthly/ cron.weekly/ crontab的顺风车==\n>\n> /etc/crontab\n>\n> ==crontab -l==\n>\n> ==crontab -e==\n>\n> crontab ==-u cali== -e\n>\n> crontab -u cali -l\n>\n> ​\t\t==如何知道计划任务是否执行?==\n>\n> ​\t\t==用户没有登录,计划任务是否执行?答:会执行==\n>\n> ​\t\t==黑客也会去利用计划任务定时执行程序,你如何去检查?==\n>\n> ​\t\t==annacron 将电脑主机因为系统故障关机导致计划任务没有被执行,正常启动后,anacron会去检测没有执行的计划任何,重新执行一次==\n>\n> at 一次性的计划任务\n>\n> ==at 11:45==\n>\n> ==at -l==\n\n\n\n### cron\n\n> 计划任务\n>\n> ​\t1.什么是计划任务? (闹钟)\n>\n> ​\t\t计划什么时候去做什么事情\n\n\n\n> 一次性的计划任务\n>\n> ​\tat\n>\n> 周期性的计划任务\n>\n> ​\tcrontab\n\n\n\n> linux系统里的==执行计划任务的进程==--》==crond==\n>\n> crond会==每分钟==去检查下所有用户的计划任务\n>\n> \n>\n> \\# ps aux|grep crond\n>\n> root 887 0.0 0.1 36300 3508 ? Ss 9月24 0:00 /usr/sbin/==crond== -n\n>\n> root 16948 0.0 0.0 12320 984 pts/0 S+ 10:05 0:00 grep --color=auto ==crond==\n>\n> \\# cd ==/var/spool/cron/\t\t(注:统一存放计划任务的目录)==\n>\n> \\# ls\n>\n> \\#\n\n\n\n> 计划任务 原理 \n>\n> ![image-20220503205140202](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032051307.png)\n\n\n\n> 原理 时间的格式和语法(笔试)\n>\n> ![image-20220503205205407](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032052474.png)\n>\n> (注:每个用户都可以用的命令)\n>\n> \\# ==crontab -l\t(注:查看当前用户的计划任务)==(每个用户只能看自己的,root用户能看所有的)\n>\n> no crontab for root\n>\n> \\# \n>\n> \\# ==crontab -e\t(注:创建计划任务)==\n>\n> …… (注:vim编辑器 本质上是文本文件)\n>\n> \\# crontab -l\n>\n> ==30 4 * * *== bash /lianxi/9_25/backup_log.sh\n>\n> ==*/5 * * * *== bash /lianxi/9_25/backup_log.sh\n>\n> ==50 3 6-9 10 *== bash /lianxi/9_25/backup_log.sh\n>\n> \n>\n> ![image-20220503205331550](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032053580.png)\n>\n> ==\\*== 该范围内的任意时间\n>\n> ==,== 间隔的多个不连续时间点\n>\n> ==\\-== 一个连续的时间范围\n>\n> ==/n== 指定间隔的时间频率\n>\n> ​\t==(注:crond进程 最低的时间间隔是1分钟)==\n>\n> (注:时间不能冲突 日期和星期不能冲突)\n\n\n\n> \\# \n>\n> \\# cd ==/var/spool/cron/\t(注:统一存放计划任务的目录,一个用户对应一个文件名)==\n>\n> \\# ls\n>\n> cali liangluyao ==root==\n>\n> \\# ==cat root \t(注:文件里面 就是cronta -e编辑的)==\n>\n> 30 4 * * * bash /lianxi/9_25/backup_log.sh\n>\n> */5 * * * * bash /lianxi/9_25/backup_log.sh\n>\n> 50 3 6-9 10 * bash /lianxi/9_25/backup_log.sh\n>\n> \\#\n>\n> \\# ll\t\t==(注:每一个用户的计划任务都会放在/var/spool/cron/目录下)==\n>\n> 总用量 12\n>\n> -rw-------. 1 ==cali== cali 31 9月 25 10:27 cali\n>\n> -rw-------. 1 ==liangluyao== liangluyao 31 9月 25 10:28 liangluyao\n>\n> -rw-------. 1 ==root== root 139 9月 25 10:25 root\n>\n> \\# \n\n\n\n> ==问:如何知道计划任务是否执行?==\n>\n> ==答:看日志文件,/var/log/cron。==\n>\n> ​\t\t==或者直接去看效果。==\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> 日志文件==(注:记录crond执行的计划任务,存放在/var/log/cron,用来排错。)==\n>\n> \\# tail -f ==/var/log/cron== (注:tail -f 盯着文件末尾看)\n>\n> \n>\n> Sep 25 10:30:01 sanchuang-linux CROND[17143]: (root) CMD (bash /lianxi/9_25/backup_log.sh)\n>\n> Sep 25 10:30:01 sanchuang-linux CROND[17147]: (liangluyao) CMD (date >>~/liang.txt)\n>\n> Sep 25 10:30:02 sanchuang-linux CROND[17119]: (root) CMDOUT (tar: 从成员名中删除开头的“/”)\n>\n> Sep 25 10:30:02 sanchuang-linux CROND[17119]: (root) CMDOUT (tar: /var/log/audit/audit.log: 在我们读入文件时文件发生了变化)\n>\n> Sep 25 10:30:02 sanchuang-linux CROND[17155]: (cali) CMD (date >>~/cali.txt)\n\n\n\n> 示例1(root用户):\n>\n> 每天早上7:50自动开启sshd服务,22点50时关闭\n>\n> ==service sshd start (注:开启sshd服务)==\n>\n> ==service sshd stop (注:关闭sshd服务)==\n>\n> \n>\n> 50 7 * * * service sshd start\n>\n> 50 22 * * * service sshd stop\n>\n> \n>\n> 每隔5天的12点整==清空==一次FTP服务器公共目录/var/ftp/pub\n>\n> 0 12 */5 * * rm -rf /var/ftp/pub==/* (注:清空:删除里面所有东西)==\n>\n> \n>\n> \n>\n> 每周六的7:30时,==重新==启动httpd服务\n>\n> ==service httpd restart (注:重启httpd服务)==\n>\n> 30 7 * * 6 service httpd restart\n>\n> \n>\n> 每周一、三、五的17:30时,打包备份/etc/httpd目录\n>\n> 30 17 * * 1,3,5 tar czf /==backup==/httpd.tar.gz /etc/httpd ==(注:/backup/是备份目录)==\n>\n> \n>\n> 示例2(jerry用户):\t\t\t\t\t\t\t==(注:宿主目录:~/)==\n>\n> 每周日晚上23:55时将“/etc/passwd”文件的内容复制到==宿主目录==中,保存为pwd.txt文件 \n>\n> 55 23 * * 0 ==/usr/bin/cp== /etc/passwd ~/pwd.txt\t==(注:命令的绝对路径)==\n\n\n\n> /etc/crontab 是cron的一个配置文件\n>\n> \\# vim /etc/crontab \n>\n> SHELL=/bin/bash (注:计划任务执行命令时用/bin/bash执行)\n>\n> ==PATH===/sbin:/bin:/usr/sbin:/usr/bin ==(注:它有自己的PATH变量,和shell的PATH变量不同)==\n>\n> MAILTO=root\t\t==(注:所有 计划任务里的命令,建议使用命令的绝对路径,因为PATH变量的问题)==\n>\n> ​\t\t==(注↑:默认情况,计划任务出了问题,crontab会给root发邮件)==\n>\n> \\# For details see man 4 crontabs\n>\n> \n>\n> \\# Example of job definition:\t(注:对命令的解释)\n>\n> \\# .---------------- minute (0 - 59)\n>\n> \\# | .------------- hour (0 - 23)\n>\n> \\# | | .---------- day of month (1 - 31)\n>\n> \\# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...\n>\n> \\# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat\n>\n> \\# | | | | |\n>\n> \\# * * * * * user-name command to be executed\n\n\n\n> \\# crontab ==-u cali== -e\t ==(注:用root用户为cali创建计划任务)==\n>\n> \\# crontab -u cali -l (注:查看)\n\n\n\n> 1.电脑关机了计划任务是否执行?答:不执行\n>\n> ==2.用户没有登录,计划任务是否执行?答:会执行==\n\n\n\n> \\# ==w (注:查看哪个用户从哪里登录)==\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032102651.jpg) \n>\n> \\# ==tail -f /var/log/cron\t(注:日志文件)==\n\n\n\n> ==3.黑客也会去利用计划任务定时执行程序,你如何去检查?==\n>\n> ​\t\t\t去==/var/spool/cron==目录下查看每一个计划任务文件\n>\n> ​\t\t\t看日志 ==/var/log/cron==\n>\n> ​\t\t\tcrontd的顺风车目录\t(如下)\n>\n> \n>\n> \\# \n>\n> \\# ==cd /etc/cron\\*\\*\\*\\*\\*\\*\\*==\n>\n> cron.d/ ==cron.daily/== cron.deny ==cron.hourly/ cron.monthly/== crontab ==cron.weekly/==\n>\n> \\# cd /etc/cron\n>\n> (注:crontab的顺风车)\n>\n> \n>\n> ==黑客也可以把需要执行的程序放到这些文件夹里==\n>\n> ==cron.daily --》Linux系统里要求crond每天去执行的事情==\n>\n> ==cron.hourly --》Linux系统里要求crond每小时去执行的事情==\n>\n> ==cron.monthly --》Linux系统里要求crond每月去执行的事情==\n>\n> ==cron.weekly --》Linux系统里要求crond每周去执行的事情==\n>\n> (注:# ls cron.daily\n>\n> ​\t\t\t logrotate\t(每天都会执行,crond每天运行一次(脚本,用sh执行))\n>\n> ​\t\t\t\\# ls cron.hourly\n>\n> ​\t\t\t0==anacron\t(annacron 将电脑主机因为系统故障关机导致计划任务没有被执行,正常启动后,anacron会去检测没有执行的计划任何,重新执行一次)==\n\n\n\n### at\n\n> at 命令 一次性的计划任务\n>\n> yum install at -y\n>\n> \n>\n> \\# ==at 11:45==\n>\n> warning: commands will be executed using /bin/sh\n>\n> at> touch $(date +%F).txt \n>\n> at> <EOT>\t==(注:退出 Ctrl+D)==\n>\n> job 1 at Fri Sep 25 11:45:00 2020\n>\n> Can't open /var/run/atd.pid to signal atd. No atd running?\n>\n> \\# ==at -l\t\t(注:查看)==\n>\n> 1\tFri Sep 25 11:45:00 2020 a root\n>\n> \\# \n\n\n\n---\n\n## 二. 计划任务练习-备份脚本\n\n> 主要内容:==chmod 777== /opt/fnum.txt (注:==设置任何用户都可以对文件/opt/fnum.txt读写执行==)\n>\n> ==2>/dev/null==\n>\n> ==/dev/null 特殊的文件,相当于黑洞文件,任何的内容重定向到这个文件都会消失,不保存==\n>\n> ==正确的输出重定向==\n>\n> ==\\>==\n>\n> ==\\>>==\n>\n> ==错误的输出重定向==\n>\n> ==2>==\n>\n> ==2>> 追加==\n>\n> ==不管正确的还是错误的都往一个文件里重定向==\n>\n> ==&>==\n>\n> ==&>> 追加==\n>\n> ==\\>1.txt 清空1.txt文件里的内容==\n>\n> ==删除xull这个用户所有的计划任务== rm -rf /var/spool/cron/xull\n>\n> ​\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t==\\# crontab -u xull -r (注 *)==\n>\n> 取消计划任务\n\n\n\n> 脚本+计划任务=自动化\n>\n> 先编写脚本,再创建计划任务\n\n\n\n### 计划任务实验\n\n> 计划任务实验:\n>\n> \n>\n> 1.为root用户编写计划任务:每周2、4、6的10点到17点的每隔5分钟自动将/etc/passwd、/etc/shadow这2个重要系统文件到user.备份的日期和时间.tar.gz这种名称的文件里(例如:user.201202011615.tar.gz)备份文件放到/opt/目录下面。\n>\n> backup_shadow_pwd.sh\n>\n> \n>\n> \\# cat backup_shadow_pwd.sh \n>\n> \\#!/bin/bash\n>\n> mkdir -p /opt\t\t\t#注:date +%Y%m%d%H%M%S , ==date后面有空格==\n>\n> tar czf /opt/user.$(date +%Y%m%d%H%M%S).tar.gz /etc/passwd /etc/shadow\n>\n> \\#\t\t\t$(date +%Y-%m-%d-%H)\t注意空格 上面的\n>\n> ==crontab -e==\n>\n> */5 10-17 * * 2,4,6 bash /lianxi/9_25/backup_shadow_pwd.sh #==(注:路径要接对,绝对路径)==\n\n\n\n> 2.==root用户==在/opt==新建==了一个文件fnum.txt专门用来统计普通用户的文件个数。请==为普通用户hello编写计划任务==:要求每5分钟,将系统中属于hello用户的文件的个数自动保存到/opt/fnum.txt文件中。内容格式为:“日期时间 姓名 拥有的文件个数是:数目”。每行中间用“\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*”隔开\n>\n> file_num.sh\n>\n> \n>\n> \\# touch /opt/fnum.txt (注:==新建空文件,普通用户建不了,root用户去建==)\n>\n> \\# ==chmod 777== /opt/fnum.txt (注:==设置任何用户都可以对文件/opt/fnum.txt读写执行==)\n>\n> \n>\n> [cali@sanchuang-linux ~]$ crontab -l\n>\n> */5 * * * * date >>~/cali.txt\n>\n> 5 12-18 * * * date >>~/cali.txt\n>\n> */1 * * * * bash /home/cali/file_num.sh\n>\n> [cali@sanchuang-linux ~]$ pwd\n>\n> /home/cali\n>\n> $ cat file_num.sh ==(注:脚本放在普通用户家目录里)==\n>\n> \\#!/bin/bash\n>\n> fnum=$(find / -user cali -type f ==2>/dev/null== |wc -l) ==(注:普通用户 文件权限不够 是出错的)==\n>\n> (注↑:错误重对象)\n>\n> ctime=$(date +%F_%H%M%S)\n>\n> echo \"${ctime} cali the number of files : $fnum\" ==>>/opt/fnum.txt (注:追加重定向 写到文件里去)==\n>\n> echo \"\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\" ==>>/opt/fnum.txt (注:追加重定向 写到文件里去)==\n>\n> $ \n>\n> \n>\n> $ crontab -e\t\t==(注:是哪个用户就哪个用户创建计划任务,==cali创建)\n>\n> */1 * * * * bash /home/cali/file_num.sh\n>\n> \n>\n> $ pwd\n>\n> /home/cali\t==(注:脚本的路径)==\n\n\n\n> 每行中间用“\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*”隔开 解决方法\n>\n> \\# cat a.sh \n>\n> echo \"helllo\"\n>\n> echo \"\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\"\n>\n> echo \"cali\"\n>\n> echo \"\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\"\n>\n> \\# \n>\n> \n>\n> \\# num=$(find / -user liangluyao |wc -l)\n\n\n\n> $ find / -user cali -type f 2>/dev/null|wc -l\n>\n> \n>\n> ==/dev/null 特殊的文件,相当于黑洞文件,任何的内容重定向到这个文件都会消失,不保存==\n>\n> null 零,空,无效的\n\n\n\n### 重定向\n\n> ==正确的输出重定向==\n>\n> ==\\>==\n>\n> ==\\>>==\n>\n> \\=\\=\\=\\=\\=\\=\n>\n> ==错误的输出重定向==\n>\n> ==2>==\n>\n> ==2>> 追加==\n>\n> \\=\\=\\=\\=\\=\\=\n>\n> ==不管正确的还是错误的都往一个文件里重定向==\n>\n> ==&>==\n>\n> ==&>> 追加==\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032115780.jpg) \n>\n> ==ls 命令执行成功重定向到1.txt 执行失败重定向到2.txt==\n>\n> $ ==ls >1.txt 2>2.txt==\n>\n> \n>\n> $ ==>1.txt 清空1.txt文件里的内容==\n>\n> $ cat 1.txt \n>\n> $ \n>\n> \n>\n> $ ls &>1.txt ==不管正确的还是错误的都往一个文件里重定向==\n\n\n\n### 练习总结\n\n> 练习总结:\n>\n> 问题:\n>\n> 1. 2>/dev/null\n>\n> 2. 如何查看效果\n>\n> \\# cat fnum.txt\n>\n> \\# tail -f /var/log/cron (日志文件)\n>\n> 3. 取消计划任务\n>\n> ==删除xull这个用户所有的计划任务== rm -rf /var/spool/cron/xull\n>\n> ​\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t==\\# crontab -u xull -r (注 *)==\n>\n> 将文件里的计划任务注释或者删除 #*/1 * * * * bash /home/xull/file_num.sh\n>\n> \\# cd /var/spool/cron/ ——》# rm -rf xull ==# crontab -u xull -r==\n>\n> \\# cd /var/spool/cron/ ——》# vim xull ——》 加 # 注释掉\n>\n> 4. 某个用户的计划任务如何创建\n>\n> 5. 文件的路径问题和权限问题(root可以访问任务地方的文件,但是普通不行,只能访问有限的路径) \n>\n> \n>\n> 将root用户的所有计划任务追加到xull用户的计划任务里\n>\n> \\# cd /var/spool/cron\n>\n> \\# cat root >>xull\t(注:注意权限问题,能否访问)\n>\n> 每一个用户的计划任务都存放在一个文件里 /var/spool/cron/\n\n\n\n> 2.root用户在/opt2新建了一个文件fnum.txt专门用来统计普通用户的文件个数。请为普通用户xull编写计划任务:要求每5分钟,将==系统中属于xull用户的文件的个数==自动保存到/opt2/fnum.txt文件中。内容格式为:“日期时间 姓名 拥有的文件个数是:数目”。每行中间用“\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*”隔开\n>\n> \n>\n> 使用root用户新建/opt2目录\n>\n> mkdir /opt2\n>\n> cd /opt2/\n>\n> touch /opt2/fnum.txt 文件\n>\n> chmod 777 /opt2/fnum.txt\t授权\n>\n> \n>\n> \n>\n> ==xull用户需要去编写脚本,创建计划任务(普通用户)==\n>\n> ==脚本:建议放在用户的家目录下==\n>\n> \n>\n> \\# su - xull\n>\n> 上一次登录:五 9月 25 15:53:35 CST 2020pts/1 上\n>\n> $ pwd\n>\n> ==/home/xull==\n>\n> $ ls\n>\n> $ vim file_num.sh (注:脚本放到自己的家目录下,用户xull去创建)\n>\n> \n>\n> $ cat file_num.sh \n>\n> \\#!/bin/bash\n>\n> \n>\n> num=$(find / -user xull -type f 2>/dev/null |wc -l)\n>\n> \\#current time (注:当前的时间)\n>\n> ctime=$(date +%F%H%M%S)\n>\n> echo \"${ctime} xull 文件数量是$num\" >>/opt2/fnum.txt\t(注:>>追加)\n>\n> echo \"\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\" >>/opt2/fnum.txt\t\t(注:一行隔开)\n>\n> \n>\n> $ \n>\n> (注:vim交互式的。脚本是背后执行的,用echo)\n>\n> \n>\n> $ crontab -e\n>\n> */1 * * * * bash /home/xull/file_num.sh\n>\n> $ \n>\n> 切换到root用户\n>\n> $ exit\n>\n> \\# cd /var/spool/cron/ (注:该目录下文件存放计划任务)\n>\n> \\# ls\n>\n> cali liangluyao root ==xull==\n>\n> \\#cat xull\t(注:文件存放计划任务)\n>\n> ==*/1 * * * * bash /home/xull/file_num.sh==\n\n\n\n---\n\n## 三. 黑客-计划任务\n\n> 主要内容:假如你是黑客,想在别人的机器上,每10分钟让它的服务器重启一次或者每天重启一次\n>\n> 关机命令:init 6\n>\n> ​\t\t\t\t\treboot\n>\n> ==1.停止crond服务==\n>\n> \\# service crond stop\n>\n> 2.查找可能存放计划任务的目录\n>\n> /var/spool/cron\t(注:先挪走)\n>\n> /etc/cron.d (注:与cron.hourly 有关)\n>\n> /etc/cron.weekly\n>\n> /etc/cron.daily\n>\n> /etc/cron.monthly\n>\n> 3.检查发现没有问题了,再重新启动crond服务\n>\n> \\# service crond start\n>\n> Redirecting to /bin/systemctl start crond.service\n>\n> \\# ps aux|grep crond\n>\n> 实在有的话\n>\n> \\# tail -f /var/log/cron (日志文件)\n>\n> 开机启动流程\n>\n> \\# cd /root (注:root用户家目录下)\n>\n> \\# ls -a \t(注:隐藏文件)\n>\n> \\# vim .bashrc \n>\n> \\# vim .bash_profile\t\n>\n> \\# vim /etc/profile (注:可以快捷筛选查找 /reboot /init)\n>\n> \\# vim /etc/bashrc (注:可以快捷筛选查找 /reboot /init)\n>\n> \\# cat /etc/rc.local\n\n\n\n> 假如你是黑客,想在别人的机器上,每10分钟让它的服务器重启一次或者每天重启一次\n>\n> \\=\\=\\=\\=\n>\n> 192.168.0.45 root 123456\n>\n> \n>\n> 关机命令:init 6\n>\n> ​\t\t\t\t\treboot\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> 在各个路径下看 有没有可疑的 init6 和 reboot\n>\n> ==1.停止crond服务==\n>\n> \\# service crond stop\n>\n> 2.查找可能存放计划任务的目录\n>\n> /var/spool/cron\t(注:先挪走)\n>\n> /etc/cron.d (注:与cron.hourly 有关)\n>\n> /etc/cron.weekly\n>\n> /etc/cron.daily\n>\n> /etc/cron.monthly\n>\n> 3.检查发现没有问题了,再重新启动crond服务\n>\n> \\# service crond start\n>\n> Redirecting to /bin/systemctl start crond.service\n>\n> \\# ps aux|grep crond\n>\n> root 1506 3.6 0.1 36304 3656 ? Ss 16:54 0:00 /usr/sbin/crond -n\n>\n> root 1511 0.0 0.0 12320 1052 pts/0 S+ 16:54 0:00 grep --color=auto crond\n>\n> \\# \n>\n> 实在有的话\n>\n> \\# tail -f /var/log/cron (日志文件)\n>\n> (注:通过日志去排查)\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> 集中放计划任务的地方 /var/spool/cron/\n>\n> \\# cd /var/spool/cron/\n>\n> \\# ls \n>\n> cali liangluyao root xull\n>\n> \\# cat cali\n>\n> ……(查看有没有可疑的,vim全部注释掉)\n>\n> 或者把所有文件全部挪走,如下操作\n>\n> \\# ls \n>\n> cali liangluyao root xull\n>\n> \\# mkdir /backup (注:根下面建一个/backup 目录)/backup 备份目录\n>\n> mv * /backup/ (把文件cali liangluyao root xull 挪到 /backup 目录下)\n>\n> 计划任务停了,crond不会执行\n>\n> \\# cd /backup/\n>\n> \\# ls\n>\n> cali liangluyao root xull\n>\n> \\# cat cali\t\t(注:把计划任务文件挪走后,再再/backup目录下 一个个排查)\n>\n> ……\n>\n> \\# cat liangluyao\n>\n> ……\n>\n> \\# w\t\t\t\t(注:查看哪些用户登录)\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> 顺风车\n>\n> \\# cd /etc/cron.daily\n>\n> ​\t\t\\# ls\n>\n> ​\t\t\\# vim …\n>\n> \\# cd /etc/cron.hourly/\n>\n> \\# cd /etc/cron.monthly\n>\n> \\# cd /etc/cron.weekly\n>\n> \\# cd /etc/cron.d (注:每小时执行是每小时的第一分钟执行)\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032124429.jpg) \n>\n> (注:run-parts 是一个命令,运行这个文件夹里的所有文件)\n>\n> \\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\n>\n> 开机启动流程\n>\n> \\# cd /root (注:root用户家目录下)\n>\n> \\# ls -a \t(注:隐藏文件)\n>\n> \\# vim .bashrc \n>\n> \\# vim .bash_profile\t\n>\n> \\# vim /etc/profile (注:可以快捷筛选查找 /reboot /init)\n>\n> \\# vim /etc/bashrc (注:可以快捷筛选查找 /reboot /init)\n>\n> \\# cat /etc/rc.local\n>\n> \\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\=\\==\\=\\=\\=\\=\n\n\n\n---\n\n## 四. 变量定义和使用\n\n> 主要内容:\n>\n> ​\t\t变量的命名:1.下划线命名法 (shell里建议)2.驼峰命名法3.匈牙利命名法\n>\n> ​\t\t变量命名的注意事项\n>\n> ​\t\tshell里如果变量没有定义,输出的是空值\n>\n> ​\t\t==env== 查看shell里的==环境变量==\n>\n> ​\t\t==set== 查看当前shell里==所有的变量==\n>\n> ​\t\t==export 输出变量为全局变量==\n>\n> ​\t\t\\# ==echo $$ (注:显示当前bash的进程号)(注:$$代表当前bash的进程号)==\n>\n> ​\t\t\\# ==bash\t\t(注:起一个子进程,子bash)==\n>\n> ​\t\t\\# ==echo \"$mv $sg hello\"\t(注:输出一串内容的时候,用双引号引起来)==\n>\n> ​\t\t\\# ==echo '$mv $sg hello'\t\t(注:单引号:所见即所得 $接变量名不会引用变量的值)==\n\n\n\n```\nshell编程\n1.变量的定义\nvariable 变量的\n\nsg=tanglf\n\n变量的命名:\n1.下划线命名法 (shell里建议)\n\tsc_sg=tanglf\n2.驼峰命名法\n\tScSg=wangtc\n\t小驼峰\n\t\tscSg=wangtc\n\t大驼峰\n\t\tScSg=wangtc\n3.匈牙利命名法\n```\n\n\n\n```\n变量命名的注意事项:\n\t1.不是以数字开头\n\t2.不要全部是数字\n\t3.不要包含特殊符号 #!@^$<>等\n\t4.=左右不能有空格\n```\n\n\n\n> linux系统里的环境变量都是大写的\n>\n> 自定义变量尽量使用小写\n>\n> \n>\n> 变量尽量要先定义后使用\n>\n> shell里如果变量没有定义,输出的是空值\n>\n> \n>\n> \\# sc_sg=zhangxueyou\n>\n> \\# echo $sg_sg\n>\n> ​\t\t\t\t\t\t\t\t\t\t==(←注:变量sg_sg没有定义,输出的是空值)==\n>\n> \\# echo $sc_sg\n>\n> zhangxueyou\n>\n> \\# ==echo $sgsg/$mvmv==\n>\n> ==/\t\t\t\t\t(←注:变量{sgsg} {mvmv}没有定义,输出的是“/”根)==\n>\n> \\#\n>\n> \\# rm -rf ==$sgsg/$mvmv==\n>\n> rm: 在'/' 进行递归操作十分危险\n>\n> rm: 使用 --no-preserve-root 选项跳过安全模式\n>\n> \\# \n\n\n\n> ==env== 查看shell里的==环境变量==\n>\n> ==set== 查看当前shell里==所有的变量==\n>\n> \n>\n> 变量是有作用域\n>\n> 全局变量\n>\n> 局部变量\n>\n> ==export 输出变量为全局变量==\n>\n> ​\t\t==用法:先定义再输出==\n\n\n\n> ssh访问22号端口,sshd监听22号端口\n>\n> web服务是80端口\n\n\n\n> \\# ==echo $$ (注:显示当前bash的进程号)(注:$$代表当前bash的进程号)==\n>\n> 1425\n>\n> \\# \n>\n> \\# ==export sg \t(注:输出sg这个变量为全局变量)==\n\n\n\n> \\# echo $$\n>\n> ==1425==\n>\n> \\# mv=xull\n>\n> \\# ==bash\t\t(注:起一个子进程,子bash)==\n>\n> \\# echo $mv\n>\n> ​\t\t\t\t\t==(注:输出为空,变量不继承)==\n>\n> \\# echo $$\n>\n> ==1598==\n\n\n\n> \\# mv=xull\n>\n> \\# ==export mv\t(注:输出变量为全局变量)(注:export 输出)==\n>\n> \\# ==bash\t\t(注:起一个子进程,子bash)==\n>\n> \\# echo $mv\n>\n> Xull\t\t\t==(注:子进程继承了变量)==\n>\n> \\# \n\n\n\n> \\# vim /root/.bash_profile\n>\n> ![img](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202205032135309.jpg) \n\n\n\n> ==输出一串内容的时候,用双引号引起来==\n>\n> ==单引号:所见即所得 $接变量名不会引用变量的值==\n>\n> \n>\n> \\# echo ==\"$mv $sg hello\"\t(注:输出一串内容的时候,用双引号引起来)==\n>\n> xull wangtc hello\n>\n> \\# echo =='$mv $sg hello'\t\t(注:单引号:所见即所得 $接变量名不会引用变量的值)==\n>\n> $mv $sg hello\n>\n> \\# \n\n\n\n---\n\n","tags":["Linux","Crontab"],"categories":["Linux"]},{"title":"06_Linux基础-NGINX和浏览器、网页的关系-压缩命令-配置NGINX支持下载功能-备份脚本","url":"/posts/10149.html","content":"## 一. NGINX和浏览器、网页的关系\n\n```bash\nnginx是一个web服务器\nhtml语言编写网页\n\ncd /usr/local/nginx html\ncd html/ \t(注:存放网页路径)\n```\n\n\n\n```\n思考:\n\t1.网页和nginx的关系\n\t\tnginx将网页发送给浏览器\n\t2.浏览器和nginx的关系\n\t\t浏览器问nginx要网页\n\t\tnginx将网页发送给浏览器\n\t3.浏览器和网页的关系\n\t\t浏览器是能读懂网页的html,js,css代码,渲染出效果\n```\n\n![image-20220423200516418](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202204232005482.png)\n\n\n\n```\nweb:网站\n表单信息放到数据库里去,nginx只能访问静态页面,Python把信息传到数据库里。Python——》flask web后端——》user表\n```\n\n\n\n```bash\n如何判断nginx是否运行?\n1.看进程\n\tps aux|grep nginx\n2.看端口\n\tnetstat -anplut\n```\n\n\n\n```\n项目组:\n\t1.前端\n\t2.后端\n\t3.运维\n\t4.测试\n\t5.dba\n\t6.项目经理\n```\n\n\n\n```\ncd /usr/local/nginx/html/\t放网页\nrz 只能传文件,不能传文件夹\n```\n\n\n\n---\n\n## 二. 云服务器ssh登陆-安装NGINX-上传网页\n\n```\n自己的虚拟机的linux系统里呢?(如何上传自己的网页到linux系统呢)\n\tXshell连过去\n自己的云服务器,如何上传自己的网页到云服务器呢?\n\t1.xshell --》公网ip(云服务器的公网ip)106.54.83.86 (注:xshell连接)\n\t 用户名root --》密码是有个初始密码 (注:passwd 改密码)\n\t2.自己去编译安装nginx--》建议使用脚本安装-->启动nignx\n\t3.上传自己的网页到nginx的html目录下 (注:scp或上传Windows【中间环节】)\n\t4.去访问106.54.83.86\n```\n\n\n\n```bash\n(注)脚本:\n# cat onekey_install_nginx_v2.sh \n#!/bin/bash\n\n#1.下载nginx软件包\nmkdir -p /nginx2\ncd /nginx2\ncurl -O http://nginx.org/download/nginx-1.19.2.tar.gz\n\n#2.解压,进入文件夹\n\ntar xf nginx-1.19.2.tar.gz\ncd nginx-1.19.2\n\n#3.编译前的配置\n #新建用户sanchuang9\nuseradd sanchuang9\n #安装gcc和pcre-devel软件包,因为nginx需要这些软件,解决软件的依赖关系\nyum install gcc make pcre-devel zlib-devel -y\n #配置nginx,指定安装路径和启动nginx的用户名\n./configure --prefix=/usr/local/nginx2 --user=sanchuang9 \n\n#4.编译\nmake\n#5.编译安装\nmake install\n\n#6.关闭防火墙服务和设置开机不要启动\n\nservice firewalld stop\nsystemctl disable firewalld \n\n#7.修改PATH变量,方便可以直接使用nginx\necho \"PATH=$PATH:/usr/local/nginx2/sbin\" >>/root/.bashrc\n```\n\n\n\n```bash\nip add 看的是私网IP\nscp 远程copy\n/usr/local/nginx/sbin/nginx 启动nginx\nps aux|grep nginx 查看nginx进程\n```\n\n\n\n```\n搞一个自己的网站\n\t1.购买一个云服务器--》阿里云或者腾讯云,华为云,亚马逊免费试用 --》学生版 10元/月\n\t2.购买域名 5元/年\n\t\t在哪里购买的云服务器,就在哪里买域名,方便备案\n\t3.备案\t\n\t\t如果不备案,不能正常的使用域名去访问\n```\n\n\n\n```bash\ncat /etc/centos-release 查看centos版本\n```\n\n\n\n---\n\n## 三. 压缩命令-xz-gzip-bzip2-zip-tar-配置NGINX服务器支持下载功能\n\n> 主要内容:压缩命令-tar(重点)\t 对文件和文件夹进行压缩\n>\n> ​\t\t==tar -czf -->.tar.gz==\n>\n> ​\t\t==tar cjf -->.tar.bz2==\n>\n> ​\t\t==tar cJf -->.tar.xz==\n>\n> \t\t==tar tf \\*.tar.\\*==\t\n>\n> ​\t\t==tar xf \\*.tar.\\*==\n>\n> ​\t\t\\# tar xf boot_log_passwd.tar.gz ==-C== /zhanghuayou/\n>\n> ​\t\t\t\t\t压缩命令-xz-gzip-bzip2-zip:都只能对文件进行压缩\n>\n> ​\t\t\t\t\t\tzip -->.zip\n>\n> ​\t\t\t\t\t\tgzip -->.gz\n>\n> ​\t\t\t\t\t\txz --->.xz\n>\n> ​\t\t\t\t\t\tbzip2 -->.bz2\n>\n> ​\t\t\t\tzip yum install zip unzip -y\n>\n> ​\t\t\t\t==zip chenpeng.txt.zip chenpeng.txt==\n>\n> ​\t\t\t\t==unzip passwd.zip==\n>\n> ​\t\t\t\tgzip\n>\n> ​\t\t\t\t==gzip hosts==\n>\n> ​\t\t\t\t==gunzip hosts.gz==\n>\n> ​\t\t\t\t==zcat messages.gz==\n>\n> ​\t\t\t\txz\n>\n> ​\t\t\t\t==xz hosts==\n>\n> ​\t\t\t\t==unxz hosts.xz==\n>\n> ​\t\t\t\t==xzcat messages.xz==\n>\n> ​\t\t\t\tbzip2 yum install bzip2 -y\n>\n> ​\t\t\t\t==bzip2 passwd==\n>\n> ​\t\t\t\t==bunzip2 passwd.bz2==\n>\n> ​\t\t\t\t==bzcat passwd.bz2==\n>\n> ​\t\t\t\t\t\t\t配置nginx服务器支持下载功能\n\n\n\n### 压缩命令-xz-gzip-bzip2-zip-tar\n\n```\n为什么要打压缩包?\n\t备份的时候,能节约空间\n\t网络传送的时候,能节约时间\n```\n\n\n\n```\nwindows里有哪些解压缩软件?\n\twinrar\n\t7z\n\t好压\n\t快压\n\tZip\n```\n\n\n\n```\nwindows里的.rar压缩文件传递到linux里,是否能打开\n\tsc.rar (注:rar解压不了,linux里没这个软件,需要安装才有)\n\tsc.zip -->linux默认支持\nwindows能解压linux里的所有的压缩文件\n```\n\n\n\n```\nnginx-1.19.2.tar.gz linux里的压缩文件\n压缩文件红色的,可执行文件绿色的\n```\n\n\n\n### zip\n\n> zip\n>\n> zip只能对文件进行压缩,不能对文件夹进行压缩\n>\n> ​\t\tyum install zip unzip -y ==(注:zip需要安装)==\n>\n> zip 打压缩包\n>\n> unzip 解压的\n\n\n\n\n> \\# ==zip chenpeng.txt.zip chenpeng.txt== (注:==用法==)\n>\n> ​\t\t\t\t压缩后的文件 源文件\n>\n> [root@sanchuang-linux lianxi]# zip passwd.zip passwd \n>\n> adding: passwd (deflated 61%)\t(注:deflated压缩,泄气)\n>\n> \n>\n> ll -h 看大小\n>\n> passwd.zip\n>\n> \\# ==unzip passwd.zip 解压==\n>\n> Archive: passwd.zip\n>\n> inflating: passwd \n>\n> \\# ls\n>\n> passwd passwd.zip\n>\n> ==zip的缺点:有源文件和新文件==\n\n\n\n### gzip\n\n> gzip\n>\n> gzip可以直接在源文件上压缩,后缀名是.gz (注:与zip的区别,理解为zip的升级版)\n>\n> ​\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t==(注:gzip不需要安装)==\n>\n> hosts passwd passwd.zip\n\n\n\n> \\# ==gzip hosts (用法)== gzip + 源文件\n>\n> \\# ls\n>\n> hosts.gz passwd passwd.zip\n>\n> \n>\n> \\# ==gunzip hosts.gz (解压)==\n>\n> \n>\n> \\# ==zcat messages.gz (查看压缩文件)==\n\n\n\n### xz\n\n> xz\t\t\t==(注:xz不需要安装)==\n>\n> https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.8.11.tar.xz\n\n\n\n> \\# ==xz hosts (用法)==\n>\n> \\# ls\n>\n> hosts.xz passwd passwd.zip\n>\n> \n>\n> \\# ==unxz hosts.xz (解压)==\n>\n> \\# ls\n>\n> hosts passwd passwd.zip\n>\n> \n>\n> \\# ==xzcat messages.xz (查看压缩文件)==\n>\n> gz与xz 比较,xz效果好\n>\n> 推荐使用xz\n\n\n\n### bzip2\n\n> bzip2\t\t==(注:bzip2需要安装)==\n>\n> yum install bzip2 -y\n\n\n\n> \\# ==bzip2 passwd\t(用法)==\n>\n> passwd.bz2\n>\n> \n>\n> \\# ==bunzip2 passwd.bz2 (解压)==\n>\n> passwd\n>\n> \n>\n> \\# ==bzcat passwd.bz2 (查看压缩文件)==\n\n\n\n> zip -->.zip\n>\n> gzip -->.gz\n>\n> xz --->.xz\n>\n> bzip2 -->.bz2\n\n\n\n### tar\n\n```\ntar -->兼并了gzip,xz,bzip2\n\ntarball -->使用tar命令打的压缩包--》归档文件--》压缩文件--》一个压缩包里可以包含很多的文件\n\ntar是可以对文件和文件夹进行压缩的\n\nCompressed TAR Archive [compressed压缩的 archive归档]\n\nhttps://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.8.11.tar.xz\nhttp://nginx.org/download/nginx-1.19.2.tar.gz\nmysql-8.0.21-linux-glibc2.12-i686.tar.xz\nhttps://mirrors.tuna.tsinghua.edu.cn/apache/httpd/httpd-2.4.46.tar.bz2\n```\n\n\n\n### 配置NGINX服务器支持下载功能\n\n> (autoindex auto 自动 index索引)\n>\n> \\# cd /usr/local/nginx/conf/\t==(注:配置目录)==\n>\n> \\# \n>\n> \\# vim nginx.conf \t==(注2:修改配置文件)即加上autoindex on;这一行==\n>\n> ​ location / {\n>\n> ​ root html; (注4:指定nginx的存放网页的目录为html--》网页根目录)\n>\n> ​ index index.html index.htm; (注5:配置nginx服务器支持的首页为index.html 或者index.htm index.html的优先级要高,没有index.html的时候,就会去查找index.htm)\n>\n> ​ ==autoindex on; (注3:添加配置,让nginx支持显示文件夹里的内容)==\n>\n> ​ }\n>\n> \\# /usr/local/nginx/sbin/nginx -s reload 重新加载nginx\n\n![image-20220423202600884](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202204232026925.png)\n\n![image-20220423202613795](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202204232026825.png)\n\n压缩包上传\n\n\n\n---\n\n## 四. tar命令\n\n> tar命令\n>\n> 用途:制作归档文件、释放归档文件\n>\n> 格式:tar [选项]... 归档文件名 源文件或目录\n>\n> ​ \t\ttar [选项]... 归档文件名 [-C 目标目录]\n>\n> 常用命令选项\n>\n> -c:创建 .tar 格式的包文件 create\n>\n> -x:解开.tar格式的包文件 extract提取\n>\n> -v:输出详细信息 verbose冗余的\n>\n> -f:表示使用归档文件 file \n>\n> -t:列表查看包内的文件 list\n>\n> 常用命令选项\n>\n> -C:解包时进入指定的目标文件夹\n>\n> ==-z:调用gzip程序进行压缩或解压==\n>\n> ==-j:调用bzip2程序进行压缩或解==\n>\n> ==-J:调用xz程序进行压缩或解压==\n\n\n\n> \\=\\=\\= ==(经典组合)==\n>\n> ==创建压缩包==\n>\n> ​\t==tar -czf -->.tar.gz==\n>\n> ​\t==tar cjf -->.tar.bz2==\n>\n> ​\t==tar cJf -->.tar.xz==\n>\n> ==创建压缩包到指定的路径 使用绝对路径==\n>\n> \\# tar czf /zhanghuayou/passwd.tar.gz ==/etc/passwd==\n>\n> tar: 从成员名中删除开头的“/”\n\n![image-20220423202847149](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202204232028186.png)\n\n\n\n> ==查看压缩包里的内容==\n>\n> \t==tar tf \\*.tar.\\*==\t\n\n\n\n> ==解压--》默认解压到当前目录==\n>\n> ​\t==tar xf \\*.tar.\\*==\n>\n> ​\t==-C 解压到指定的路径==\n>\n> \\# tar xf boot_log_passwd.tar.gz ==-C== /zhanghuayou/\n\n\n\n> \\# mkdir tar\n>\n> \\# cd tar\n>\n> \\# ls\n>\n> \\# tar czf passwd.tar.gz ==/etc/passwd==\n>\n> ==tar: 从成员名中删除开头的“/”==\n>\n> \\# ls\n>\n> passwd.tar.gz\n>\n> \\# tar tf passwd.tar.gz \n>\n> ==etc/passwd\t\t\t\t\t(注:/ 没有了)==\n>\n> [root@sanchuang-linux tar]# ls\n>\n> passwd.tar.gz\n>\n> \\# tar xf passwd.tar.gz \n>\n> \\# ls\n>\n> ==etc== passwd.tar.gz\t\t\t\t==(注2:解压后是文件夹etc,没有“/”)==\n>\n> \\# cd etc/\n>\n> \\# ls\n>\n> passwd\n>\n> \\# \n\n\n\n> ==给文件夹打压缩包==\n>\n> \\# tar cJf boot.tar.xz /boot\n>\n> \\# tar czf boot.tar.gz /boot\n>\n> \\# tar cjf boot.tar.bz2 /boot\n>\n> \n>\n> \\# ==time tar czf boot.tar.gz /boot (注:压缩命令前接 time 可以看时间)==\n>\n> tar: 从成员名中删除开头的“/”\n>\n> \n>\n> real\t0m8.467s\n>\n> user\t0m6.851s\n>\n> sys\t0m2.226s\n>\n> \n>\n> \\# \n>\n> ==(注:↓接v可以看过程,信息输出。一般写脚本不接v)==\n>\n> \\# tar czvf boot_log_passwd.tar.gz /boot /var/log /etc/passwd ==(注:文件和目录)==\n>\n> \\# tar czf boot_log_passwd.tar.gz /boot /var/log /etc/passwd\n>\n> tar: 从成员名中删除开头的“/”\n>\n> tar: 从硬连接目标中删除开头的“/”\n>\n> \\# \n>\n> \n>\n> ==后面打包的文件如果压缩文件的名字一样,会覆盖==\n\n\n\n---\n\n## 五. 压缩练习-备份脚本\n\n> 主要内容:\n>\n> 排错多个文件 exclude 排除 ==(难点)==\n>\n> \\# tar ==--exclude==\\=/boot/{grub2,efi,loader} ==-czvf== no_grub_boot.tar.gz /boot\n>\n> \\# ==date +%Y%m%d%H%M%S==\n>\n> 20200924170954\n>\n> 当前的日期往后面推10天\n>\n> \\# ==date -d \"10 days\"==\n>\n> 如何得到命令的执行结果赋值给变量\n>\n> ==方法1:==\n>\n> ​\tctime=$(date +%F)\n>\n> ==方法2:反引号==\n>\n> ​\tctime=\\`date +%F\\`\n>\n> 命令的嵌套\n>\n> ==设置时间 -s==\n>\n> \\# ==date -s '2020-10-10'\t\t\t(注:调时间)==\n>\n> \\# date -s =='2020-10-10 9:53:00'\t\t(注:指定小时分钟秒)==\n>\n> \\# ==cal 看日历== calendar(日历)\n>\n> \\# ==cal 2020== 看2020年日历\n\n\n\n---\n\n```bash\n压缩练习:\n\t1.在windows里使用winrar软件压缩2个文件,一个是.rar格式的文件,一个是.zip的文件,具体压缩那个文件,你自己定义\n\t2.将文件传输到linux系统的/lianxi目录下,尝试解压.zip的文件\n# unzip\n\t3.复制/etc/passwd文件到/lianxi目录下,将/lianxi目录下的passwd文件压缩成passwd.xz\n# cp /etc/passwd . # xz passwd \n\t4.复制/etc/ssh/sshd_config 文件到/lianxi目录下,然后进行压缩为sshd_config.gz\n# cp /etc/ssh/sshd_config . # gzip sshd_config\n\t5.查看passwd.xz里的内容,查看sshd_config.gz里的内容\n# xzcat passwd.xz # zcat sshd_config.gz\n\t6.新建文件夹/backup_sc,然后复制/lianxi下的passwd.xz和sshd_config.gz到/backup_sc目录里\n\t7.到/backup_sc目录里解压passwd.xz和sshd_config.gz文件\n\t8.将/lianxi下的sshd_config.gz传到windows系统里看是否可以解压?\n```\n\n\n\n> 练习8:\n>\n> ​\t1.创建一个目录在/lianxi下叫tar\n>\n> \\# mkdir /lianxi/tar \n>\n> ​\t2.进入tar目录,复制/etc/hosts文件和/etc/passwd到tar目录下\n>\n> \\# cd /lianxi/tar # cp /etc/hosts . # cp /etc/passwd . \n>\n> ​\t3.复制/boot目录到tar目录下\n>\n> \\# cp /boot . -r \n>\n> ​\t4.将当前目录下的boot目录打包放在/lianxi/tar目录下叫boot.tar.gz\n>\n> \\# tar czf boot.tar.gz boot\n>\n> ​\t5.查看boot.tar.gz文件里的内容\n>\n> \\# tar tf boot.tar.gz\n>\n> ​\t6.将hosts文件和passwd文件打包放到host_passwd.tar.bz2文件\n>\n> \\# tar cjf host_passwd.tar.bz2 hosts passwd\n>\n> ​\t7.查看host_passwd.tar.bz2文件里的内容\n>\n> \\# tar tf host_passwd.tar.bz2\n>\n> ​\t8.将/boot/目录和/etc/passwd、/var/log目录备份到/lianxi目录下叫boot_pw_log.tar.xz\n>\n> \\# tar cJf /lianxi/boot_pw_log.tar.xz /boot /etc/passwd /var/log\n>\n> ​\t9.新建/bak目录,然后将/lianxi目录下的boot_pw_log.tar.xz解压到/bak目录下\n>\n> \\# mkdir -p /bak # tar xf boot_pw_log.tar.xz -C /bak\n>\n> ​\t10.将/boot目录下的除grub2目录以外的所有文件都备份到/bak目录下叫no-grub.tar.gz\n>\n> tar czvf --exclude ==(难点)==\n>\n> \\# tar ==--exclude=/boot/grub2 -czvf== no_grub_boot.tar.gz /boot \n>\n> centos8里的 (注:==--exclude=/boot/grub2 -czvf 前后不能错,grub2不能接/,-czvf -不能省略==)\n>\n> \\# tar ==--exclude=/boot/grub2 -czvf== no_grub_boot.tar.gz /boot \n>\n> centos7里的\n>\n> \\# tar czvf no_grub2_boot.tar.gz /boot ==--exclude=/boot/grub2==\n>\n> 排错多个文件 exclude 排除 ==(难点)==\n>\n> \\# tar ==--exclude==\\=/boot/{grub2,efi,loader} ==-czvf== no_grub_boot.tar.gz /boot\n>\n> (注:目录结构 {} 表示多个)\n\n\n\n```\n练习:\n\n编写一个脚本实现备份/var/log目录下的所有文件到/bak目录下,要求文件名是包含当天日期,精确到秒,文件名例如:2013-6-6-2_30_20-log.tar.gz。同时要求删除/bak目录下七天前的备份文件,只保留最近7天的文件。\n```\n\n> 需求分析:\n>\n> ==年月日小时分钟秒==\n>\n> ==时间戳:年月日小时分钟秒==\n>\n> ​\t获得当前的日期 date \n>\n> \t%Y year\t\t\t\t\t\t\t\t\t\t\t==(注:年)==\n>\t\t\t\t\t\t\t\t\t\n> \t%m month (01..12)\t\t\t\t\t\t==(注:月)==\n>\t\t\t\t\t\t\t\t\t\n> \t%M minute (00..59)\t\t\t\t\t\t==(注:分钟)==\n>\n> %d day of month (e.g., 01)\t\t\t\t\t==(注:日)==\n>\n> %H hour (00..23)\t\t\t\t\t\t\t\t\t==(注:小时)==\n>\n> %S second (00..60)\t\t\t\t\t\t\t\t==(注:秒)==\n>\n> %F full date; same as %Y-%m-%d\t\t==(注:年月日)==\n>\n> \n>\n> \\# ==date +%Y%m%d%H%M%S==\n>\n> 20200924170954\n>\n> \\# ==date +%Y-%m-%d%H%M%S==\n>\n> 2020-09-24171008\n>\n> \\# ==date +%Y-%m-%d_%H_%M_%S==\n>\n> 2020-09-24_17_10_31\n>\n> \\#\n>\n> \n>\n> 当前的日期往后面推10天\t==(推迟时间)==\n>\n> \\# ==date -d \"10 days\"==\n>\n> 2020年 10月 04日 星期日 17:21:27 CST\n>\n> \\# ==date -d 10days==\n>\n> 2020年 10月 04日 星期日 17:21:37 CST\n>\n> \\# \n>\n> \n>\n> \\# ==date -d 10hours==\n>\n> 2020年 09月 25日 星期五 03:22:13 CST\n>\n> \\# \n\n\n\n> 如何得到命令的执行结果赋值给变量\n>\n> ==方法1:$(\t)\t\t\t(更好,因为可以嵌套)==\n>\n> ​\t\tctime=$(date +%F)\n>\n> ==方法2:反引号\t\t\t(不能嵌套)==\n>\n> ​\t\tctime=\\`date +%F\\`\n>\n> \\# ==ctime=$(date +%F)==\n>\n> \\# echo $ctime\n>\n> 2020-09-24\n>\n> \\# ==sctime=\\`date +%F\\`==\n>\n> \\# echo $sctime\n>\n> 2020-09-24\n>\n> \\# \n>\n> \\# ==touch $(date +%F).txt==\n>\n> \\# sg=zhanghuayou\n>\n> \\# echo $sg\n>\n> zhanghuayou\n>\n> \\# echo $sg1\n>\n> ​\t\t\t\t\t\t(注:该行输出为空)\n>\n> \\# echo ==${sg}==1\n>\n> zhanghuayou==1==\n>\n> \\# \n>\n> \n>\n> 删除/bak目录下七天前的备份文件\n>\n> find /bak -type f -mtime +7 -name \"*.tar.gz\" -exec rm -rf {} \\;\n>\n> 脚本名字:\n>\n> ​\tbackup_log.sh\n\n\n\n> 命令的嵌套\n>\n> \\# which mkdir\n>\n> /usr/bin/mkdir\n>\n> \\# rpm -qf /usr/bin/mkdir \n>\n> coreutils-8.30-6.el8_1.1.x86_64\n>\n> \\# softname\\===$(rpm -qf $(which mkdir))\t\t\t\t(注:$(\t) 好,可以嵌套)==\n>\n> \\# echo $softname\n>\n> ==coreutils-8.30-6.el8_1.1.x86_64==\n>\n> \\# softname2\\===\\`rpm -qf \\`which mkdir\\`\\`==\n>\n> ==rpm:未给出要查询的参数==\n>\n> ==mkdir: 缺少操作数==\n>\n> 请尝试执行 \"mkdir --help\" 来获取更多信息。\n>\n> \\# \n\n\n\n---\n\n> 编写一个脚本实现==备份==/var/log目录下的所有文件到/bak目录下,要求文件名是包含当天日期,精确到秒,文件名例如:2013-6-6-2_30_20-log==.tar.gz==。同时要求删除/bak目录下七天前的备份文件,只保留最近7天的文件。\n>\n> ==通过文件名知道使用tar命令,而不是cp==\n\n> \\# mkdir /lianxi/9_25\n>\n> \\# cd /lianxi/9_25\n>\n> \\# vim backup_log.sh\n>\n> \\#!/bin/bash\n>\n> \n>\n> \\#获得当前的时间,精确到秒\n>\n> ctime=$(date +%Y%m%d%H%M%S)\n>\n> \n>\n> \\#备份\n>\n> mkdir -p /bak\n>\n> tar czf /bak/${ctime}-log.tar.gz /var/log\n>\n> \n>\n> \\#删除7天前的==备份文件==,只保留最近的7天内的文件\n>\n> find /bak -type f -mtime +7 ==-name “*log.tar.gz”== -exec rm -rf {} \\;\n\n\n\n> 怎么验证删除7天前的文件?\n>\n> 答:调时间\n>\n> ==设置时间 -s==\n>\n> \\# date\n>\n> 2020年 09月 25日 星期五 09:53:18 CST\n>\n> \\# ==date -s '2020-10-10'\t\t\t(注:调时间)==\n>\n> 2020年 10月 10日 星期六 00:00:00 CST\n>\n> \\# \n>\n> \\# date -s =='2020-10-10 9:53:00'\t\t(注:指定小时分钟秒)==\n>\n> 2020年 10月 10日 星期六 09:53:00 CST\n>\n> \\# \n>\n> \\# date -s '2020-9-25 9:55:00'\n>\n> 2020年 09月 25日 星期五 09:55:00 CST\n>\n> \\#\n\n\n\n> \\# ==cal 看日历== calendar(日历)\n>\n> \\# ==cal 2020== 看2020年日历\n>\n> ![image-20220423204712463](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202204232047523.png)\n>\n> ![image-20220423204723137](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202204232047209.png)\n>\n> \n\n\n\n---\n\n","tags":["Nginx","Linux"],"categories":["Linux"]},{"title":"05_Linux基础-NGINX编译安装^判断是否启动^修改端口^启动停止重启^相关路径^中文乱码","url":"/posts/43579.html","content":"## 一. 回顾\n\n```bash\n//\t\tservice sshd restart 刷新sshd服务\n 信息会写到/var/log/messages里,tail -f /var/log/messages动态监控\n /var/log/messages 记录日志\n//\t\troot用户有权限,可以更改普通用户密码,密码123也能成功\n\t\t一个安全的密码有:大小写、数字、特殊符号、足够的长度 Sanchuang123#\n//\t\t1.显示ps aux查看进程命令输出信息,从第2行到9行,并且显示行号。\n ps aux|cat -n|head -9|tail -8\n ps aux|cat -n|sed -n ‘2,9p’\n 2.使用find命令查找出/find目录下大小大于1M并且名字里包含vmlinuz的文件\n find /find -size +1M -iname “*vmlinuz*”\n find /find -size +1M -iname “*vmlinuz*” -exec ls -hl {} \\;\n (注1:ls -hl命令)\n\t\t查找出daydayup的文件然后删除它\n find / -name “daydayup” -exec rm -rf {} \\;\n (注2:字符串用””引号引起来)\n 3.将最近3小时内/lianxi目录下文件大小大于10K的文件 移动到/back目录下\n find /lianxi -mmin -180 -size +10k -type f -exec mv {} /back \\;\n 4.查找/home目录下用户是root,文件类型是f,这2个条件必须满足,然后再满足大小大于2k或者文件名包含cali的文件中的一个条件,查找出来后,复制到/lianxi目录下。\n\tfind /home -user root -type f \\( -size +2k -o -name \"*cali*\" \\) -exec cp {} /lianxi \\;\n\n```\n\n\n\n---\n\n## 二. NGINX\n\n```\n//\t\tnginx是一个web服务器软件,是使用c语言开发的软件,俄罗斯人开发\n http://nginx.org/\n nginx是开源免费的软件(增值的插件收费)\n 国内知名互联网公司都在使用nginx:\n\t\t\t淘宝,腾讯,百度,京东,小米,美团,字节跳动,金山云,37互娱等\n\t\thttp://nginx.org/en/download.html\n```\n\n![image-20220316092524896](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160925990.png)\n\n```\n\t\t前端 —— web服务器 —— 后端数据库\nHtml,css,js nginx,python mysql,redis\n```\n\n### 编译安装\n\n```bash\n//\t\t一键安装脚本\n [root@sanchuang-linux nginx]# cat onekey_install_nginx.sh \n #!/bin/bash\n #↑声明脚本用bash去执行\n #1.下载nginx软件包\n mkdir -p /nginx2\n cd /nginx2\n curl -O http://nginx.org/download/nginx-1.19.2.tar.gz\n\n #2.解压,进入文件夹\n tar xf nginx-1.19.2.tar.gz\n cd nginx-1.19.2\n\n #3.编译前的配置\n #新建用户sanchuang9\n useradd sanchuang9\n #安装gcc和pcre-devel软件包,因为nginx需要这些软件,解决软件的依赖关系\n yum install gcc make pcre-devel zlib-devel -y\n #配置nginx,指定安装路径和启动nginx的用户名\n ./configure --prefix=/usr/local/nginx2 --user=sanchuang9 \n\n #4.编译\n make\n #5.编译安装\n make install\n\n #6.关闭防火墙服务和设置开机不要启动\n service firewalld stop\n systemctl disable firewalld \n\n #7.修改PATH变量,方便可以直接使用nginx\n echo \"PATH=$PATH:/usr/local/nginx2/sbin\" >>/root/.bashrc\n```\n\n### 具体步骤\n\n```bash\n具体步骤\n//\tnginx的安装部署\n #1.下载nginx软件包\n mkdir -p /nginx\n cd /nginx(注2:进入指定路径)\n curl -O http://nginx.org/download/nginx-1.19.2.tar.gz(注1:curl是linux下面的字符界面浏览器)\n curl是字符界面的一个浏览器 (注3:-O就是下载到当前)\n\n #2.解压,进入文件夹(注3:#1完成后,nginx软件包下载完成,是一个红色的压缩包.tar.gz)\n tar xf nginx-1.19.2.tar.gz(注1:解压后得到一个文件夹,深蓝色。.tar.gz是linux的压缩格式)\n cd nginx-1.19.2(注2:进入这个得到的目录下)\n```\n\n```bash\n详细操作\n\t//cd nginx-1.19.2\n```\n\n![image-20220316092724052](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160927086.png)\n\n```bash\n configure配置\n # ./configure --help(注1:告诉我们可以配置什么东西)\n```\n\n![image-20220316092758056](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160927097.png)\n\n![image-20220316092811368](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160928420.png)\n\n> ​\t==--prefix=PATH\t\t\t指定安装路径==\n>\n> ​\t--sbin-path=PATH\t\t指定二进制程序路径\n>\n> ​\t--error-log-path=PATH\t指定错误日志路径\n>\n> ​\t--pid-path=PATH\t\t指定pid路径\n>\n> ​\t==--user=USER\t\t\t 指定启动nginx的用户==\n>\n> ​\t==--group=GROUP\t\t指定启动nginx的组==\n\n![image-20220316092838065](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160928130.png)\n\n> ​\t--with\t\t\t开启某样功能\n>\n> ​\t--without\t 禁用某样功能\n\n> 详细操作\n>\n> ​\t\t新建用户sanchuang(自动建一个同名的组)\n>\n> ![image-20220316093032655](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160930690.png)\n>\n> ​\t\t\\# ./configure --prefix=/usr/local/nginx --user=sanchuang \n>\n> ​\t\t(注1:配置nginx,指定安装路径和启动nginx的用户名)(下一步)\n\n> 详细操作\n>\n> ​\t\t解决依赖关系\n>\n> ![image-20220316093112870](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160931910.png)\n>\n> ```bash\n> //没有PCRE这个库\n> \tyum install gcc pcre-devel -y (devel开发包)\n> //装好后,继续配置\n> # ./configure --prefix=/usr/local/nginx --user=sanchuang\n> ```\n>\n> ![image-20220316093145472](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160931499.png)\n>\n> ```bash\n> //没有zlib这个库\n> yum install zlib-devel -y\n> (注1:开发库一般会提供很多的接口、很多的包、函数给我们)\n> //装好后继续\n> # ./configure --prefix=/usr/local/nginx --user=sanchuang\n> ```\n>\n> ![image-20220316093213881](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160932904.png)\n>\n> ​\t\t生成makefile文件(配置单)后面根据这个文件编译\n>\n> ​\t\t指定路径↓↓\n>\n> ![image-20220316093233539](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160932599.png)\n>\n> ​\t\t编译前的配置完成,如下\n\n> \n>\n> ```bash\n> # 3.编译前的配置\n> # 新建用户sanchuang\n> useradd sanchuang\n> # 安装gcc和pcre-devel软件包,因为nginx需要这些软件,解决软件的依赖关系\n> yum install gcc make pcre-devel zlib-devel -y\n> # 配置nginx,指定安装路径和启动nginx的用户名\n> ./configure --prefix=/usr/local/nginx --user=sanchuang \n> ```\n\n> ```bash\n> # 4.编译(注1:源码 编译成 二进制代码)\n> make\n> yum install make -y\n> # 5.编译安装(注2:本质上是cp,编译好的二进制程序是放在当前目录下)\n> make install(注2:make install 就是把当前下面的东西拷贝到/usr/local/niginx/下指定路径下去)\n> ```\n>\n> ![image-20220316093449432](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160934530.png)\n>\n> \n>\n> ```bash\n> // 进入/usr/local/nginx/目录(安装完成后)\n> # cd /usr/local/nginx/\n> # ls\n> conf html logs sbin\n> \n> conf是存放nginx的配置文件\n> html是存放网页的目录\n> logs 是存放日志文件的目录\n> sbin 是存放可执行程序,也就是nginx的启动程序\n> ```\n>\n> ```bash\n> //\t运行nginx程序\n> # cd sbin/\n> # ls\n> nginx\n> # ./nginx 运行nginx程序\n> ```\n>\n> ![image-20220316093531137](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160935178.png)\n>\n> ​\t//接下来判断nginx是否启动\n\n### 判断服务是否启动\n\n> ```bash\n> 判断一个服务是否启动的方法:\n> //\t1.看是否有相关的进程\n> \t# ps aux|grep nginx\n> ```\n>\n> ![image-20220316093633235](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160936274.png)\n>\n> ```bash\n> \t有两个进程,主进程和工作进程(注1:有这两个进程,说明nginx程序起来了)\n> 2.看是否有进程占用的端口号\n> # yum install lsof net-tools -y(注2:用来看端口号的软件”)\n> # lsof -i:80 只是看80端口被那个进程占用了(注3:两个命令都可以看端口号开没开)\n> ```\n>\n> ![image-20220316093704075](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160937120.png)\n>\n> ```bash\n> \t# netstat -anplut 查看本机上所有的开放的端口(注3:两个命令都可以看端口号开没开)\n> ```\n>\n> ![image-20220316093727014](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160937067.png)\n>\n> ```bash\n> (注4:0.0.0.0表示本机上所有的ip地址,:80表示所有ip地址上的80端口)\n> (注5:端口号在:80体现)\n> 开启了防火墙,所以Windows上的浏览器访问不过去\n> # service firewalld stop 关闭防火墙服务\n> # systemctl disable firewalld 设置防火墙服务开机不要启动\n> ```\n>\n> ![image-20220316093750934](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160937982.png)\n>\n> ```\n> 如下↓↓\n> ```\n\n> ```bash\n> #6.关闭防火墙服务和设置开机不要启动\n> service firewalld stop\n> systemctl disable firewalld \n> ```\n\n> ```bash\n> 详细操作\n> \t刚在启动nginx 是在/usr/local/nginx/sbin目录下启动的 ./nginx\n> \t怎么样让我们在任何地方敲nginx它都能找到\n> ```\n>\n> ![image-20220316093851369](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160938411.png)\n>\n> ```\n> \t做法:修改PATH变量\n> 如下\n> ```\n\n> ```bash\n> #7.修改PATH变量,方便可以直接使用nginx\n> echo \"PATH=$PATH:/usr/local/nginx/sbin\" >>/root/.bashrc\n> (注1:echo 在屏幕上输出,>>输出重对象,追加进去,把它写到/root/.bashrc里)\n> (注2:写脚本特别喜欢用重对象)\n> ```\n\n> ```bash\n> 编译安装的步骤:3部曲\n> 1. 编译前的配置 --》 生成配置单 (Makefile)\n> \t./configure --prefix=/usr/local/nginx --user=sanchuang\n> 2. 编译 --》根据配置单制作\n> \tmake\n> 3. 编译安装 --》将编译好的程序安装\n> \tmake install\n> ```\n\n> ```bash\n> 改首页\n> # cd /usr/local/nginx/html/\n> # ls\n> 50x.html index.html\n> # vim index.html 编辑下首页文件\n> (注1:index.html 首页:打开网站看到的第一个页面 --》首先看到的页面)\n> ```\n>\n> ![image-20220316094005835](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160940865.png)\n>\n> ```\n> \tvim 编辑器的复制和粘贴\n> \t\tyy 是复制当前行(注2:按下ESC后)\n> \t\tp 粘贴到下一行\n> ```\n>\n> ![image-20220316094037604](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160940638.png)\n>\n> ![image-20220316094046045](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160940080.png)\n>\n> ```bash\n> \t//\tvim chenpeng.html\n> \t\tls\n> ```\n>\n> ![image-20220316094112773](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160941813.png)\n>\n> ![image-20220316094121790](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160941822.png)\n>\n> ```\n> (注3:这里建的html叫什么名字,外面接的时候就要/接它)\n> (注4:默认情况下首页都叫index.html nginx里的规定)\n> ```\n\n\n\n### 回顾\n\n```\n web服务器:网站方面的应用 web server\n 提供网站服务\n\n server 服务器\n client 客户机\n broswer 浏览器\n http访问的端口是80\n https访问的端口是443\n nginx可以监听两个端口(80、443)(要记)\n https传输的内容经过加密,更加安全(注1:很多电商网站和银行网上支付都是https)\n```\n\n![image-20220316094226777](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160942822.png)\n\n```\n//\t安装两个nginx不冲突,路径不同就行。同时启动不能占用相同的端口\n nginx卸载,直接把这个目录删掉 rm -rf\n\n 脚本的意义:提前设置好的程序,按照程序去走\n \t\t 下到指定目录的路径\n```\n\n![image-20220316094252721](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160942770.png)\n\n```\n//\t80端口被占用,新建的nginx启动不了\n```\n\n![image-20220316094307770](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160943828.png)\n\n### 修改 8080 端口\n\n> //\t配置新的nginx使用8080端口 (注2:vim nginx.conf 80 /usr/local/nginx2/conf)\n>\n> ​\t(注3:改端口号,改了配置文件一定要重启reload)\n>\n> ```bash\n> # pwd\n> /usr/local/nginx2/conf\n> # ls\n> fastcgi.conf fastcgi_params.default mime.types nginx.conf.default uwsgi_params\n> fastcgi.conf.default koi-utf mime.types.default scgi_params uwsgi_params.default\n> fastcgi_params koi-win nginx.conf scgi_params.default win-utf\n> ```\n>\n> ```bash\n> \t# vim nginx.conf\n> listen 8080; 修改端口号80为8080(注1:找到这一行,修改8080)\n> ```\n>\n> ![image-20220316094529087](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160945122.png)\n>\n> //\t启动nginx的路径 /usr/local/nginx/sbin/nginx\n>\n> //\tnetstat -anplut 查看端口号\n>\n> ​\t\t有两个nginx,一个nginx监听8080端口,一个nginx监听80端口\n>\n> ![image-20220316094556682](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160945730.png)\n>\n> ​\t\t两个nginx不冲突,多个nginx可以共存\n>\n> //\t访问\n>\n> ​\t\t192.168.0.45\n>\n> ​\t\t192.168.0.45:8080\n>\n> ​\t\t可以 1个机器里面跑了2个网站\n\n### 启动/停止/重启 NGINX\n\n```bash\n//\t启动nginx\n # /usr/local/nginx/sbin/nginx\n # /usr/local/nginx2/sbin/nginx\n\t停止nginx\n # /usr/local/nginx/sbin/nginx -s stop\n # /usr/local/nginx2/sbin/nginx -s stop\n\t重启(重新加载)\t(注1:修改了配置文件一定要reload重启)\n \t# /usr/local/nginx2/sbin/nginx -s reload\n (注1:修改了配置文件一定要reload重启,不然不会生效)\n```\n\n### 相关路径\n\n![image-20220316094810280](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160948321.png)\n\n```bash\n //conf 放配置文件\n 修改nginx监听的端口号 \t\tconf/nginx.conf\n 修改nginx首页index.html内容 html/index.html\n 启动nginx\t/usr/local/nginx/sbin/nginx\n 重启nginx\t/usr/local/nginx/sbin/nginx -s reload(注1:前提条件nginx启动了)\n```\n\n### 编写自己的网页\n\n```bash\n//\t\t编写一个自己的网页 sc.html\n\t\t里面需要有文字,图片,链接\n\n /usr/local/nginx2/html (注1:存放网页的地方)\n # vim sc.html\n <html> (注4:html语言 有头有尾)\n <head> (注2:头部)\n <title>welcome to sanchuang</title> (注3:标题)\n </head>\n <body> (注5:body部分就是一段一段的话)\n <p>my name is chenpeng</p> (注6:p段落标记,表示一段)\n <p>my phone number is 18874991147</p>\n <p><h1>chenpeng linux</h1> (注7:h1字体加粗)\n <p><a href=\"https://www.qq.com\">qq.com</a></p>\n <p><a href=\"https://www.taobao.com\">taobao.com</a></p>\n <p><a href=\"https://www.jd.com\">jd.com</a></p> (注10:链接 a标签 href)\n <img src=\"linghuchong.jpg\">(注12:图片img src,图片放在sc.html同一文件夹下)\n <p><a href=\"index.html\">index.html</a>(注13:链接到首页)\n\n\n </body>\n </html>\n (注8:ESC :w 只保存,不退出)\n (注9:访问 192.168.0.45:8080/sc.html)\n (注11:首页(样例)/usr/local/nginx/html/index.html)\n 修改网页不需要重新启动nginx服务,只要刷新浏览器就可以了\n 只有修改了nginx的配置文件,才需要重新启动nginx服务 nginx -s reload\n//\t这是在8080端口,放到80端口操作↓↓\n```\n\n![image-20220316095132879](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160951912.png)\n\n### vim 基本使用\n\n```bash\n//\tvim的基本使用\n 1.按i 进入输入模式\n 2.按ESC返回到命令模式\n yy 复制当前行\n 2yy 复制两行 nyy复制多行\n p 粘贴(往下粘贴)\n u 撤销\n dd 删除当前行\n 2dd 删除两行 ndd删除多行\n```\n\n### 中文乱码\n\n```bash\n//\t解决访问时中文乱码问题\n <head>\n \t\t<meta charset=”utf8”>\n </head>\n (注1:可以在Windows sublime软件写*.html文件 上传到linux /usr/local/nginx/hml 里)\n```\n\n\n\n---\n\n## 三. Windows、Linux 文件传输\n\n```bash\n//\t\tWindows、linux文件传输\n 解决文件传输的问题\n 1.rz 和sz\n # yum install lrzsz -y\n # rz 从windows里上传文件到linux里 receive (注3:传到你当前路径 z是模式)\n # sz abcd.txt 从linux里发送文件abcd.txt到windows里 send (注4:z是模式)\n\t2.xftp传输\n\t\t需要安装xftp(注1:左右边直接拖过来)\n```\n\n![image-20220316095002232](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203160950271.png)\n\n```\n\t(yum provides rz 注2:查询rz命令是哪个软件包提供的)\n```\n\n\n\n---\n\n","tags":["Nginx","Linux"],"categories":["Linux"]},{"title":"04_Linux基础-.&..-cat-tac-重定向-EOF-基本命令","url":"/posts/62964.html","content":"## 一. 回顾\n\n```bash\n回顾\n//\t\t将/home/目录下的所有文件和文件夹复制到/jindafu目录下\n\t\tcp /home/* . -r\n#注:复制文件夹 接-r\t\t递归复制(因为提到了文件夹)\n#注:所有\t通配符*\n//\t\t复制/etc/hosts文件到jindafu,不给予覆盖提醒\n\t\t用cp的绝对路径\n\t\t\twhich cp\t得到cp的路径\n\t\t\t/usr/bin/cp /etc/hosts .\n#注:不给予提醒 输入cp命令的绝对路径\t因为cp命令是别名 所有会有提醒\n//\t\t将xiena目录改名为xienana\n\t\tmv xiena/ xienana\n//\t\t将singer目录下的所有文件复制到hejiong目录下\n\t\tcp haiquan/singer/* hejiong/\n#注:所有\t通配符*\n#注:复制文件不接-r\n//\t\t删除所有的xienana目录\n\t\tfind命令 或 tree查看xienana在哪 rm -rf 路径\n\t\tfind /hunantv/ -name “xienana” -exec rm -rf {} \\;\n//\t\t查看目录结构 tree 查看类型 file\n//\t\techo $PS1 $PS2 怎么看PS1 PS2\n//\t\thostname 查看主机名\n//\t\techo $SHELL 查看默认shell (是bash)\n//\t\tcat /ect/shells 查看机器里有哪些shell\n\t\tsh bash exit\n#/etc\t存放配置文件\n//\t\td 目录\n\t\t- 普通文件\n\t\tl 链接文件\n\t\tc 字符设备文件(显示)\n\t\tb 块设备文件 (磁盘)\n//\t\treboot 重启机器\n//\t\tclear 清屏\n//\t\t别名 alias , unalias , vim /root/.bashrc\n//\t\tenv 环境变量 set 所有变量\n\n```\n\n\n\n---\n\n## 二. . .. 删不掉\n\n```\n//\t\trm -rf 不会删除隐藏文件\n\t\trm -rf .lixh 删除隐藏文件\n\t\t.和..删不掉\n```\n\n\n\n---\n\n## 三. cat\n\n```bash\n//\t\tls 查看文件夹里的内容\n cat 1.查看文件里的内容\n \t2.可以将多个文件连接到一起输出\n -n, --number 给输出的行进行编号\n 用处2: cat tangliangfei.txt wangtc.txt (连接功能)\n 先将tangliangfei.txt内容输出,再将wangtc.txt内容输出\n```\n\n### tac 与 cat\n\n```\n//\t\ttac 逆序显示,从最后一行到第一行\n\t\t\t不能接-n\n\t\tcat 正序显示,从第一行到最后一行 (有-n选项)\n```\n\n\n\n---\n\n## 四. 重定向\n\n```bash\n//\t\t> 输出重定向,会覆盖原来的内容,如果文件不存在会自动新建\n\t\t\t重定向:就是将在屏幕上输出的内容,改变输出的方向,输出到文件里\n\t\t>> 追加输出重定向,不会覆盖原来的内容,只是在末尾追加,如果文件不存在会自动新建\n\t\t>会覆盖原来的内容,>>不覆盖,末尾追加\n\t\t# cat tangliangfei.txt wangtc.txt >tang_wang.txt\n\t\t# echo 123456789 >>tang_wang.txt \n\t\t(学会cat与>、>>的组合)\n```\n\n\n\n---\n\n## 五. here document\n\n```\n//\t\t生成指定内容的文件 --》here document --》主要用在写脚本生成指定的内容\n\t\t// <<EOF 定义的结束字符串\n\t\t\t当输入EOF的时候,结束 end of file \n```\n\n```bash\n# cat >chenpeng.txt <<EOF (注1:后面不一定非得EOF,但要起的有意义)\n> chen peng\t\t\t\t\t(注2:1个>符号,原来内容会被覆盖)\n> jiangsu\n> xinhua\n> nongda\n> linux\n> cali\n> EOF (注3:点回车)\n\n# cat >>cali.txt <<end(注1:2个>符号,内容追加,不覆盖)\n> sanchuang\n> nongda\n> changsha\n```\n\n\n\n---\n\n## 六. Shell 脚本\n\n```\n//\t\tshell脚本: 其实是一个文件,文件里面有很多的linux命令,这个文件可以执行,被执行的时候,会执行文件里的所有的命令\n```\n\n```bash\n# vim first_shell.sh\n#!/bin/bash(注1:声明这个脚本使用的解释器是bash)\n\nmkdir -p /test(注2:存在不报错,不存在就新建)\n\ncd /test\n\nmkdir sc{1..100}\n\ntouch pengyf{1..100}.txt\n\ncp /etc/hosts /test\n\ncat >sanchuang.txt <<EOF(注3:回车后直接打,文本文件里没有提示符>)\nsanchuang hunan changsha furongqu hunannongda\nfeng de yong\nlinux\nEOF(注4:结束)\n\necho \"####################################\"\ncat -n sanchuang.txt \necho \"####################################\"\n```\n\n```\n脚本写好了↑↑↑\n```\n\n```bash\n# bash first_shell.sh 执行脚本(注:内容如下)\n####################################\n 1\tsanchuang hunan changsha furongqu hunannongda\n 2\tfeng de yong\n 3\tlinux\n####################################\n//\t\t脚本在执行的时候,是从第1条命令,自上而下执行,如果中间有命令执行失败,后面的命令还是会执行的(Python中间出错,没有异常捕获的话,不再执行)\n```\n\n\n\n---\n\n## 七. more\n\n```\n// more命令 分页显示 (注1:没有-n选项,cat有-n选项)\n\t\t用途:全屏方式分页显示文件内容\n交互操作方法:\n 按Enter键向下逐行滚动\n 按空格键向下翻一屏、按b键向上翻一屏 back\n 按q键退出 (注2:显示完自动退出,与less的差别)\n```\n\n```bash\n# more messages \n```\n\n\n\n---\n\n## 八. ps aux\n\n```bash\n//\t\t# ps aux 查看linux当前运行的进程的信息--》任务管理器(ps -aux也可以)\n # ps -aux|more\n # cat messages |more 和 more messages 一样\n # cat -n messages |more 显示行号\n```\n\n\n\n---\n\n## 九. less\n\n```\n// less命令\n\t用途:与more命令相同,但扩展功能更多\n\t交互操作方法:\n \t与more命令基本类似,但个别操作会有些出入\n\t【page down】【page up】上翻下翻页(注1:more不支持)\n\t显示完不退出,按q退出 (注2:与more的差别)\n\t(注3:也支持空格、b、Enter,凡是more支持的less都支持)\n```\n\n```bash\n# less messages \n# cat messages |less\n```\n\n\n\n---\n\n## 十. head\n\n```\n// head命令(注1:默认取前10行,连续的几行)\n 用途:查看文件开头的一部分内容(默认为10行)\n 格式:head -n number 文件名\n 格式:head -数字 文件名\n```\n\n```bash\n cat -n passwd |head 显示前10行,有编号\n head passwd 显示前10行,没有编号\n head -5 passwd 显示前5行(没编号)\n head -n 5 passwd 显示前5行(没编号,与上一条命令效果一样)\n```\n\n\n\n---\n\n## 十一. tail\n\n```\n// tail命令\n 用途:查看文件结尾的少部分内容(默认为10行)\n 格式:tail -n number 文件名\n 格式:tail -数字 文件名\n tail -f 文件名 = tailf\t\t# 注:tailf不知道怎么用\n\t\t\t#注:tail -f 动态的监控文件末尾的变化\n```\n\n```bash\ntail passwd 取末尾10行(无编号)\ncat -n passwd |tail 取末尾10行(有编号)\ncat -n passwd |tail -5 取末尾5行(有编号)\ncat -n passwd |tail -1 最后1行(有编号)\ncat -n passwd |tail -n 3 取末尾3行(有编号)\n\ntail -n 2 passwd 显示最后2行\ntail -n -2 passwd 与上条效果一样\ntail -n +2 passwd 显示从第2行到末尾 (注1:用处:统计有多少行的时候,不想显示首行,统计磁盘挂载的时候不想看到标题这一行)\n (注2:df -Th 显示linux里的磁盘分区的使用情况)\n df -Th|tail -n +2 统计磁盘挂载不显示标题行\n df -Th|tail -n +2|wc -l 统计行数\n\n# tail -f feng.txt 动态的监控文件末尾的变化\n(注4:经常用来查看日志文件的变化,根据日志的记录去排错)\n(注2:重新打开窗口连过去,右边修改文件内容,左边动态监控文件末尾的变化,一有新的内容就显示)(注3:Ctrl+C 强行终止)\n```\n\n```\ntail -f 扩展 \n\t特别适合看某些日志文件\n /var 存放动态变化的文件 variable 变量,变化的,可变的\n log 日志:是程序记录它发生的事情\n```\n\n```bash\n# cd /var/log\t\t(注1:/var/log 存放大量日志文件)\n# tail -f secure 查看secure日志文件 (注2:secure 安全)\n(注3:别的窗口做操作,日志文件末尾动态更新)\n```\n\n\n\n---\n\n## 十二. sed\n\n```bash\n 1.取出passwd的第3行\n # cat -n /etc/passwd|head -3|tail -1 (注1:先取前3行,再取最后1行,用|管道)\n # cat /etc/passwd|head -3|tail -1 (注2:与上面命令比,没有编号3)\n\t2.取出passwd文件的第5行到10行\n\t#注:这种 先看末尾 用head 因为行数是从前到后计算的\n # cat -n /etc/passwd|head |tail -6 (注3:先head取默认前10行,再取后六行)\n\t\t\t\t\t\t\t\t\t (注4:从第5行到10行,tail -6,不是-5)\n\t# cat -n messages |head -200|tail -101 (100到200行)\n\t3.取出第3行,第5行,第10行\n\t# sed -n '1p;3p;5p' passwd (注5:-n是选项,符合要求的选项显示出来,不是显示行号的意思)\n\n\t练习3扩展\n\t// sed\n\t\t-n 作用:只是显示符合要求的行(注9:不符合要求的行不显示)\n 1p;3p;5p\n 1p 显示第1行 p 是print命令\n\t\t\t; 命令连接符号\n # cat -n passwd |sed -n ‘1p;3p;5p’ (注6:显示1、3、5行,有编号)\n # sed -n '1p;3p;5p' passwd (注7:没有编号)\n\t\t\t\t\t\t\t\t (注10:用双引号””也可以)\n # cat -n passwd |sed -n '3p;5p;10p' 显示不连续的3,5,10行的内容\t(这样写显示行号)\n # cat -n passwd |sed -n '3,10p' 显示第3行到第10行的内容,中间是连续的\n\n # cat -n passwd |sed '3,10p'(注8:sed后不接-n的话,会显示所有的行[包括不符合要求的行],只不过3到10行输出两遍,所有一定要接-n)\n\n总结:sed 1.显示连续的 2.显示不连续的\n```\n\n\n\n---\n\n## 十三. grep\n\n```bash\n//\t\tgrep 文本过滤 (过滤的是文件,不是文件夹目录)\n grep “root” /etc/passwd 包含root的行\n grep “^liang” /etc/passwd 以liang开头的行\n grep “bash$” /etc/passwd 以bash结尾的行\n Ctrl + c 终止\n//\t\t文本处理三剑客 sed grep awk\n```\n\n\n\n---\n\n## 十四. which\n\n```bash\nwhich 查找可执行文件并显示所在的位置\n\t\t搜索范围由PATH环境变量指定\n # which mkdir\n /usr/bin/mkdir\n # cd /usr/bin/\n # ll mkdir\n -rwxr-xr-x. 1 root root 195192 4月 10 02:53 mkdir\n\n rwxr-xr-x 权限\n r 读 read --》cat vim\n w 写 write --》 vim >>\n x 执行 execute ---》运行\n\n # ll first_shell.sh\n -rw-r--r--. 1 root root…… (注1:脚本无可执行权限)\n # bash first_shell.sh (注2:用bash去执行它)\n # chmod +x first_shell.sh (注3:给它可执行权限)\n -rwxr-xr-x. root root…… (注4:有可执行权限了)\n # ./first_shell.sh (注5:直接执行,直接在当前终端执行,当前bash执行)\n # /lianxi/first_shell.sh (注6:接绝对路径,接文件,直接执行)\n # chmod -x first_shell.sh (注7:取消可执行权限)\n # /lianxi/first_shell.sh \n -bash: /lianxi/first_shell.sh: 权限不够 (取消可执行权限后不能直接执行)\n```\n\n### whereis\n\n```bash\n//\t\twhereis 查找命令放到哪里(注1:跟which很像)(注2:没什么用,man手册在哪里不是很重要)\n\t\t# whereis mkdir\n\t\tmkdir: /usr/bin/mkdir /usr/share/man/man1/mkdir.1.gz\n\t\t\t\t\t\t\t\t(注2:压缩文件,是它的文档)\n 1.查看命令安放路径\n 2.该命令man手册的路径(man的时候看的内容的存放路径)\n\t//whereis和which的区别\n Which不显示man手册的路径,whereis显示man手册的路径\n # whereis mkdir\n mkdir: /usr/bin/mkdir /usr/share/man/man1/mkdir.1.gz\n # which mkidr\n /usr/bin/mkdir\n\t//whereis和which 都是到PATH变量里去找的 (共同点)\n```\n\n\n\n---\n\n## 十五. PATH\n\n```bash\n//PATH是路径\nwhich命令在查找命令的时候,会到PATH变量指定的路径下查找\n# which fengdeyong\n/usr/bin/which: no fengdeyong in (/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin)\n(备注1:红色为路径 备注2:多个文件夹用:冒号隔开)\n# echo $PATH (注3:$PATH 引用PATH变量)\n/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin\n查找的顺序是从左往右找,如果在第1个里面找到了,就不会往后面找,以此类推\n```\n\n### 深入理解 PATH 变量的作用\n\n> 1.编写一个schello.c的文件\n>\n> ```c\n> # vim schello.c (注1:编写脚本如下)\n> #include<stdio.h>\n> int main(){\n> \tprintf(\"hello,world\\n\"); (注2:\\n 换行)\n> \tprintf(\"i am cali\\n\");\n> \treturn 0;\n> }\n> # file schello.c \n> schello.c: C source, ASCII text (注3:C语言文件,文本文件,机器不能识别)\n> ```\n>\n> 2.编译成二进制程序文件\n>\n> gcc 是linux里的一个编译器,将c源码文件编译成二进制文件\n>\n> ![image-20220313140253260](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203131403345.png)\n>\n> gcc 是linux里的一个编译器,将c源码文件编译成二进制文件\n>\n> ```bash\n> # yum install gcc -y\n> # gcc -o schello schello.c (注1:-o 输出一个二进制文件)(注2:编译schello.c的命令)\n> # ls\t\t(↑↑注3:schello产生的文件,schello原来文件)\n> schello schello.c (注2:生成绿色可执行权限的文件 schello)\n> # ll\n> 总用量 20\n> -rwxr-xr-x. 1 root root 12744 9月 18 15:12 schello\n> -rw-r--r--. 1 root root 93 9月 18 15:08 schello.c\n> # ./schello (注4:./ 运行)\n> # /lianxi/sc/schello (注5:绝对路径运行,./相对路径或绝对路径都可以运行)\n> # schello 不能运行 (注6:linux不知道schello放在哪里,它只会到PATH变量里去找)\n> -bash: schello:未找到命令 (注7:PATH变量没有当前所在路径,没有/lianxi/sc)\n> (解决如下)\n> ```\n>\n> \n\n### 要让 Linux 系统知道我们的命令在哪里?\n\n```bash\n1.适应PATH变量,将我们的命令复制到PATH变量已有的路径下\n# echo $PATH\n/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin\n# cp schello /usr/local/bin/\n# schello (注1:成功运行)\nhello,world\ni am cali\n# which schello\n/usr/local/bin/schello (注2:复制到PATH变量的路径下后bash可以找到schello)\n2.修改PATH变量,添加我们自己的命令所在的路径\n①临时修改PATH变量\n# PATH=/lianxi/sc:$PATH 临时修改PATH变量\n(注3:先引用PATH变量的值,在和/lianxi/sc:字符串拼凑在一起再赋值给PATH变量)\n(注3:$PATH——》/lianxi/sc:+$PATH重新组合——》赋值PATH变量 从右到左)\n# echo $PATH\n/lianxi/sc:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin\n(注4:新的PATH变量,前面多了/lianxi/sc:)\n[root@sanchuang-linux sc]# which schello(注5:which 可以找到)\n/lianxi/sc/schello\n# schello (注6:bash可以运行)\nhello,world\ni am cali\n②永久有效\n修改文件,添加PATH变量,让它永久生效\n# vim /root/.bashrc \n\t.bashrc这个文件是linux系统开机启动或者用户登录都会运行这个文件里的命令,所以才会永久有效\nPATH=/lianxi/sc:$PATH (注1:打进去,放到最后一行)\n```\n\n```bash\n//\t\tmkdir 用C写的\n\n//\t\t# yum install python3 -y 安装python3软件\n # python3 (注1:进入Python3解释器)\n >>> a = 10 (注2:提示符>>>)\n >>> b = 20 (注4:Python不需要编译,Python代码直接运行,用Python解释器去解释)\n >>> sg = \"tangliangfei\"\n >>> c = a + b\n >>> c\n 30\n >>> print(sg) (注3:输出)\n tangliangfei\n >>> exit() (注5:exit()退出出 exit()是exit函数)\n```\n\n```bash\n//扩展\n.py结尾的文件,是python程序文件\n.sh结尾,shell脚本\n.c结尾,c语言\n# vim sc_py_hello.py\n#!/usr/bin/python3 (注1:which python3——》/usr/bin/python3)\n\t\t\t\t (注2:申明脚本是Python脚本,里面的命令用Python3解释器去解释)\nusername = input(\"please input your name:\")(注3:引号里面只是提示符,提示输什么)\n\t\t\t\t (注4:input()函数会接收你输入的东西,赋值给username)\nage = input(\"please input your age:\")\n\nprint(f\"your name is {username} ,your age is {age}\")(注5:print(f ) 语法)\n\t\t\t\t (注6:{username}{age} 引用变量的值)\n\n# ls\nschello schello.c sc_py_hello.py\n# python3 sc_py_hello.py (注7:直接执行Python3,类似于bash a.sh)\nplease input your name:cali\nplease input your age:18\nyour name is cali ,your age is 18\n[root@sanchuang-linux sc]# cat sc_py_hello.py \n \n# /lianxi/sc/sc_py_hello.py (注1:不能直接运行,如下 权限不够,pwd查看路径)\n-bash: /lianxi/sc/sc_py_hello.py: 权限不够\n# chmod +x sc_py_hello.py (注2:给它可执行权限)\n# /lianxi/sc/sc_py_hello.py (注3:可以直接执行了)\nplease input your name:wangtc\nplease input your age:18\nyour name is wangtc ,your age is 18\n\n//怎样让sc_py_hello.py 在PATH变量里运行\n # which sc_py_hello.py (注1:能运行,因为之前在PATH变量里已经添加这个路径了(/lianxi/sc))\n # sc_py_hello.py (注2:能运行,因为之前在PATH变量里已经添加这个路径了(/lianxi/sc))\n # echo $PATH\n /lianxi/sc:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin\n```\n\n```bash\n 总结:跟是用什么语言写的关系不大\n\t\t1.把它放到PATH变量所在的路径里面,并2.给它可执行权限 就能直接运行\n # chmod -x sc_py_hello.py (注3:取消可执行权限)\n # sc_py_hello.py (注4:不给它可执行权限,路径放在PATH变量所在的路径下,也不能直接执行)\n\t-bash: /lianxi/sc/sc_py_hello.py: 权限不够\n 总结:写的Python程序,一定要1.给它可执行权限,并2.把它放到PATH变量所在路径下面,不然不能执行\n //扩展 (注2:总结:文件名字很长,想敲个短一点的命令,考虑用别名 [快捷键])\n # alias sc_py_hello=sc_py_hello.py 定义别名,可以缩短命令的长度\n # sc_py_hello(注1:不想输这么长,可以使用别名,别名可以用来偷懒)\n please input your name:feng (运行成功,条件是在PATH变量路径下和可执行权限,如上面的操作)\n please input your age:19\n your name is feng ,your age is 19\n # which sc_py_hello\n alias sc_py_hello='sc_py_hello.py'\n\t\t/lianxi/sc/sc_py_hello.py\n```\n\n\n\n\n\n---\n\n## 十六. bash\n\n```\n\t//bash 是linux非常好的shell解析器 (注1:2件事要做)\n\t\t1.查找命令 --》PATH变量的路径下\n\t\t2.告诉内核去启动命令(运行这个命令)\n```\n\n\n\n---\n\n## 十七. /usr\n\n```\n// /usr 存放linux程序的目录 unix system resource \n /usr/bin 存放二进制程序,所有的用户都可以使用 binary\n /usr/sbin 存放二进制程序,有比较高的权限(root)的用户执行的程序 super user binary\n```\n\n```bash\n # which useradd(注1:查找useradd命令路径)\n /usr/sbin/useradd (注2:存放在sbin目录下)\n # su - xulilin (注3:切换为普通用户)\n $ which useradd\n $ /usr/sbin/useradd\n $ useradd xu123 (注4:普通用户不能执行sbin/下高级别命令)\n ……报错useradd:Permission denied (注5:权限被拒绝)\n```\n\n\n\n---\n\n## 十八. locate\n\n```bash\n//\t\tlocate 知识点(注4:需要安装)(注5经常需要更新# updatedb)\n# yum provides locate -y 查询locate是哪个软件包提供的(注1:新知识点)\nmlocate-0.26-20.el8.x86_64 : An utility for finding files by name\n(注3:yum provides …… -y 查询某命令是哪个软件包提供的)\n(注2:从结果知道 mlocate提供locate命令)\n# yum install mlocate -y 安装mlocate软件\n```\n\n```\nlocate命令\n格式:locate 文件名\n(注5:locate是到自己的数据库查找的,能具体到/下面,且必须更新自己的数据库)\n根据每天更新的数据库(/var/lib/mlocate)查找,速度块\n\t/var/lib/mlocate/mlocate.db\n\tdatabase 数据库(注6:db的解释)\n数据库里的内容还是根据/目录下的内容生成\n每天会自动更新数据库\t/var/lib/mlocate/mlocate.db\n手动更新数据库updatedb\n```\n\n```bash\n# updatedb 生成和更新数据库mlocate.db (注1:手动更新)\n# cd /var/lib/mlocate/\n# ls\nmlocate.db\n# locate mkdir(注2:将linux系统里面文件名里面包含了mkdir的文件全部找出来)\n/usr/bin/mkdir\n/usr/lib/python3.6/site-packages/pip/_vendor/lockfile/mkdirlockfile.py\n/usr/lib/python3.6/site-packages/pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-36.opt-1.pyc\n/usr/lib/python3.6/site-packages/pip/_vendor/lockfile/__pycache__/mkdirlockfile.cpython-36.pyc\n/usr/share/man/man1/mkdir.1.gz\n# which mkdir(注3:只是找到/usr下的mkdir,其他地方的mkdir没找出来)\n/usr/bin/mkdir\n```\n\n```\nlocate查找的范围:\n\t/--》mlocate.db里去查找(注2:在 根下面自己的数据库mlocate.db下面去查找)\n\t方式:模糊查找,文件名里包含就可以\n\t缺点:新的文件,有时候找不到,因为没有更新数据库 --》updatedb(注3:手动更新)\n\t可以查找任何文件(注4:新建的文件,# updatedb手动更新数据库,否则找不到)\nwhich 查找的范围:PATH变量\n\t方式:精确查找(注1:文件名必须一模一样)\n\t只能查找命令\n```\n\n### which、whereis、locate、find\n\n```\n//\t\twhich、whereis、locate、find 命令查找类\n Which、whereis 只能找命令\n loacte 也可以查找普通文件、可以查找任何文件\n```\n\n\n\n---\n\n## 十九. find\n\n> //*\t\tfind命令\n>\n> ​\t\t\t 格式:find [查找范围] [查找条件] [动作]\n> \n>\n> ​\t\tfind 可以找1.命令、2.文件 (即任何文件)\n>\n> ​\t (注1:融合了which、whereis、locate所有功能)\n>\n> ​\tfind命令\n>\n> ​\t用途:用于查找文件或目录\n>\n> ​\t格式:find [查找范围] [查找条件] [动作]\n>\n> ​\t常用查找条件\n>\n> ​\t==-name==:按文件名称查找\n>\n> ​\t==-iname==:按文件名称查找,不区分大小写\n>\n> ​\t==-size==: 按文件大小查找\n>\n> ​\t-user: 按文件属主查找\n>\n> ​\t==-type==: 按文件类型查找\n>\n> ​\t-perm :按文件权限查找\n>\n> ​\t==-mtime== :按文件更改时间查找\n>\n> ​\t-newer:按比某个文件更新的查找\n\n```bash\n-name和-iname\n # find /lianxi -name \"lixh.txt\"(注1:精确查找,-name根据文件名来)\n /lianxi/lixh.txt\n # find / -name \"schello\"(注2:精确查找,可以/下查找)\n /lianxi/sc/schello\n # find / -name \"schello*\"(注3:*模糊查找,可以/下查找)\n /lianxi/sc/schello.c\n /lianxi/sc/schello\n # find / -name \"li*.txt\"(注4:*模糊查找)\n # find / -iname \"lixh.txt\" (注5:-iname 查找的文件名不区分大小写)\n /lianxi/lixh.txt\n /lianxi/LIXH.TXT\n```\n\n```bash\n-size (大小)\n # ll -h 看文件夹下的每个文件的大小\n # du -a 查看文件夹下的每个文件的大小(单位KB)\n du -ah 查看文件夹下的每个文件的大小 (单位K、M、G)\n # find /boot -size +1M(注1:+1M 大于1M的 全部找出来)(注2:-1M、1M:小于1M,等于1M)\n /boot/grub2/fonts/unicode.pf2 (注3:查找的结果不是特别精准)\n /boot/initramfs-4.18.0-193.el8.x86_64kdump.img\n /boot/initramfs-4.18.0-193.el8.x86_64.img\n```\n\n```bash\n-type (类型)\n # find . -type d (注1:查找目录)\n # find . -type f (注2:查找普通文件)\n # find . -type l (注3:链接文件)\n # find . -type c (注4:字符设备文件)\n # find . -type b (注5:块设备文件)\n # find . -type p (注6:管道文件)\n # find . -type s (注7:socket文件)(进程与进程通信的文件)\n```\n\n```bash\n-mtime (以24小时为单位) 按文件更改时间查找\n-mmin (以分钟为单位)\n # find . -time +1 1天以前\n # find . -time -1 1天以内\n # find . -mmin -30 30分钟以内\n # find . -mmin +30 30分钟以前\n```\n\n```bash\n-user (属于哪个用户创建的文件)(用处不大)\n # find . -user root\n # find / -user cali\n```\n\n```bash\n-newer (比指定文件更新的文件,后建的文件)\n\t# find . -newer feng.txt\n```\n\n```bash\n//\t特殊查找条件\n-o :逻辑或,只要所给的条件中有一个满足,寻找条件就算满足 or\n-not :逻辑非,在命令中可用“!”表示。该运算符表示查找不满足所给条件的文件\n-a:逻辑与,系统默认是与,可不加,表示只有当所给的条件都满足时,寻找条件才算满and\n\n find /boot -size +1024k -a -name “vmlinuz*”(注1:逻辑与 -a可不加,系统默认逻辑与)\n find /boot -size +1024k -o -name “vmlinuz*”\n find . -user nie -type f -size +1k -o -name \"vmlinuz*\" \n find . -user nie -type f \\( -size +1k -o -name \"vmlinuz*\" \\) (注3:()改变了优先级,\\解释在下方)(注5:\\( \\)即() 改变了优先级)\n find /home !-user hello -exec ls -ld {} \\;\n\\ 转义字符 (注2:因为小括号()有特殊作用,接上/以后让它表示只是小括号)\n默认情况下-a的优先级高,先执行逻辑与(-a),再执行逻辑或(-o)\n# find / -iname \"*.conf\" -size +1k -type f -user root -o -size +10M\n(注4:前面先组合成一个条件,要么满足-o前面的,要么满足-o后面的条件)\n```\n\n```bash\n//\t扩展,接上面的命令 -exec 和 -ok\n\t # find /lianxi -name \"li*.txt\" -exec rm -rf {} \\;(注1:前面是查找,-exec表示要执行的动作)相关解释如下\n -exec 执行后面的命令\n rm -rf 具体删除命令\n {} 代表前面的find查找出来的内容,理解为一个容器存放前面find查找到的内容\n \\; 表示find命令结束符号\n # find /lianxi -name \"*.txt\" -size +1k -type f -exec cp {} /fengdeyong \\;\n (注2:文件名.txt结尾的,大小大于1k的,文件,拷贝到fengdeyong里面)\n (注3:find 找/lianxi 下的每一层)\n -ok\n -ok 让你确认一下,再执行\n # find . -name \"*wang*\" -ok rm -rf {} \\;\n < rm ... ./wangtc.txt > ? y\n < rm ... ./tang_wang.txt > ? y\n\n总结:-exec执行命令,不给与确认(写脚本常用,方便)\n\t -ok 执行命令,需要确认\n```\n\n```bash\n-maxdepth 查找文件时,目录的深度\n # find . -name bb\n ./aa/bb\n ./aa/bb/bb\n ./bb\n # find . -maxdepth 1 -name bb(注2:只挖1级)\n ./bb\n # find . -maxdepth 2 -name bb(注3:只挖2级)\n ./aa/bb\n ./bb\n # find . -maxdepth 3 -name bb(注4:只挖3级)\n ./aa/bb\n ./aa/bb/bb\n ./bb\n (注1:不接-maxdepth的话,有多少层挖多少层)\n # find /lianxi -name \"*.txt\"\n (注6:不接-maxdepth,东西太多了,挖的太深了)\n /lianxi/tangliangfei.txt\n /lianxi/chenpeng.txt\n /lianxi/cali.txt\n /lianxi/feng.txt\n /lianxi/aa/bb/feng.txt\n /lianxi/aa/feng.txt\n # find /lianxi -maxdepth 1 -name \"*.txt\"\n (注5:这种情况用的多,只想找1层的,只挖/lianxi下面的,子文件夹、子子文件夹下面都不要)\n /lianxi/tangliangfei.txt(注7:显示如下)\n /lianxi/chenpeng.txt\n /lianxi/cali.txt\n /lianxi/feng.txt\n```\n\n```bash\n//\t\t!取反 的使用,接上面的命令(注1:lianxi下面的不是*.txt的)\n # find /lianxi -maxdepth 1 ! -name \"*.txt\"(只对后面的条件取反)\n /lianxi\n /lianxi/passwd\n /lianxi/first_shell.sh\n /lianxi/messages\n /lianxi/sc\n /lianxi/LIXH.TXT\n /lianxi/aa\n /lianxi/bb\n```\n\n\n\n---\n\n","tags":["Linux"],"categories":["Linux"]},{"title":"03_Linux基础-文件类型-主辅提示符-第1提示符-3个时间-stat-其他基础命令","url":"/posts/43225.html","content":"## 一. stat 与 ll\n\n```\n//\t\tstat 与 ll \tstat 只能看自己。 ll能看文件夹下面的东西。\n//\t\t选项组合(不分先后顺序) 如 ls -Al (2个功能一起显示)\n//\t\tdu -sh\t统计文件和文件夹大小\n//\t\tmkdir -p\t如果父目录不存在,就新建\n\t\t\t\t\t如果文件夹存在,就不报错\n \t\t\t\t//\t写脚本经常用到\n\t \t\t -v\t\t给提醒(显示已经创建成功)(没什么用)\n```\n\n### stat 与 ll 与 ls -l -d\n\n```\n//\t\tstat 与 ll 与 ls -l -d\n\t\t\tstat 只能看本身的文件信息(文件夹本身)\n\t\t\tll\t能看文件夹下面的东西(文件夹里面的)\n\t\t\tls -l -d 只看它自己的详细信息 不看里面的(文件夹本身)\n```\n\n![image-20220310192151920](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101921976.png)\n\n![image-20220310192158823](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101921851.png)\n\n\n\n---\n\n## 二. 集合 {xx,xxx}\n\n### 1条命令建多个文件夹\n\n```\n#注:关键点{}\n//\t\tmkdir hunantv/{weishi,jingshi,dushi}\t\t一条命令建多个文件夹\n\t\t在 China_voice路径下建 hunantv文件夹下的 文件夹(hunantv在 China_voice下)\n```\n\n```\n\t\t{weishi,jingshi,dushi} 表示一个集合,有共同的上一级目录\n```\n\n![image-20220310191803814](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101918842.png)\n\n```\n\t\t只建一个文件夹的时候,不能用 { } 括起来,{ } 会成为文件名。\n//\t\t一条命令完成(日常用的不多)\t里面有好几级\n\t\t父目录不存在时候 接 -p 选项\n```\n\n![image-20220310191848767](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101918797.png)\n\n\n\n---\n\n## 三. \\{1\\.\\.100\\}\n\n```\n#注:mkdir sc{1..100}\n#注:rm -rf sc{1..100}\n//\t\tmkdir sc{1..100}\t产生1到100的文件\n\t\t{1..100} 代表 1 到 100的集合 和前面的sc 组合\n\t\tmkdir 可以一次性建立多个 的功能\n\t\t//\trm -rf sc{1..100}\n\t\t\trm -rf sc* \t2种都能删\n//\t\tmandatory 命令的\n\t\targuments 参数\n//\t\tmkdir -p\t如果父目录不存在,就新建\n\t\t\t\t\t如果文件夹存在,就不报错\n```\n\n![image-20220310192017460](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101920498.png)\n\n![image-20220310192023763](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101920800.png)\n\n```\n//\t\tmkdir -v\t给提醒\n```\n\n![image-20220310192037604](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101920641.png)\n\n\n\n---\n\n## 四. du -sh\n\n```\n//\t\tdu -sh 查看目录大小\n\t\t命令 选项 参数\n```\n\n\n\n---\n\n## 五. cd\n\n```\n//\t\tcd - 返回上一次所在的路径\n\t\tcd . 进入当前目录\n\t\tcd .. 返回到上一级目录\n\t\tcd ~ 返回到当前用户的家目录\n\t\tcd \t 返回到当前用户的家目录\ncd命令\n用途:切换工作目录(Change Directory)\t\n格式:cd [目录位置]\n#注:特殊目录 \n. 当前目录\n.. 上一级目录\n~ 用户主目录(家目录)\n- 上一次所在的工作目录(遥控器上的返回键)\n//\t\tuseradd xulilin 新建用户\n\t\tcd ~xulilin 进入xulilin这个用户的家目录\n\t\t[root@localhost xulilin]# pwd\n\t\t/home/xulilin\n//\t\tmkdir\t新建目录\n\t\ttouch qijian\t新建空文件\n\t\ttouch hengshan/yilin.txt\n```\n\n\n\n---\n\n## 六. cp -r\n\n```\n//\t\tcp /etc/hosts songshan/\t复制文件不接 -r\n\t\tcp hengshan/ songsahn/ -r 复制文件夹接 -r\n```\n\n\n\n---\n\n## 七. file\n\n```\n//\t\tfile taishan 查看文件类型\n```\n\n\n\n---\n\n## 八. 文件类型\n\n```\n//\t\t经典文件类型:目录\t\tdirectory\n\t\t\t\t\t空文件\t\tempty\n\t\t\t\t\t文本文件\ttext\n```\n\n![image-20220310192555585](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101925631.png)\n\n```\n//\t\tdu -sh taishan/ 查看文件大小\n//\t\trm -rf tianshan/\t 删除\n```\n\n\n\n---\n\n## 九. cp\n\n```\n//\t\tcp\t复制的时候:\n\t\t复制,粘贴,重命名一步到位(重命名要后面不存在)\n\t\tcp a.txt abc.txt (目录下有2个文件 a.txt abc.txt)\n\t\tcp a.txt songshan/feng.txt (复制到songshan下改名叫feng.txt)\n\t\tcp hengshan/ songshan/nanyue_hs -r(复制文件夹接-r)\n\t\t\t复制hengshan到songshan下 改名nanyue_hs\n```\n\n\n\n---\n\n## 十. mv\n\n```\n//\t\tmv\t剪切,粘贴,重命名一步到位(重命名要后面不存在)\n\t\tmv a.txt hengshan/aaa.txt (剪切粘贴,重命名为aaa.txt)\n\t\tmv songshan/ hengshan/shaolinshi (移动粘贴重命名为shaolinshi)\n\t\t\t移动重命名不需要接-r选项(与 cp 的不同点)\n```\n\n\n\n---\n\n## 十一. 主辅提示符\n\n```\n//\t\t主提示符\n\t\t[登录用户@主机名 工作目录]\n```\n\n```\n\t\t辅助提示符\n\t\t# $\n \t\t[root@localhost xuxia]#\n\t\t[root@localhost wuxia]# \n\t\t[xulilin@localhost ~]$ \n//\t\tlinux是一个多用户多任务的操作系统\n\t\troot用户家目录 /root\n\t\t普通用户家目录\t/home下面跟用户名同名\n```\n\n\n\n---\n\n## 十二. echo\n\n```\n//\t\techo 输出 相当于print\n\t\tPS1 是linux系统里内置的一个变量,不需要我们定义\n```\n\n\n\n---\n\n## 十三. 第1提示符\n\n```\n\t\t第1提示符变量 PS1 prompt symbol 提示 符号 variable 变量\n```\n\n### [\\u@\\h \\W]\\$解释\n\n```\n//\t\t# echo $PS1\t\t# 注:第一提示符\n\t\t[\\u@\\h \\W]\\$\n\t\t解释:\n\t\t\\u 引用当前的用户 user\n \t\t\\u the username of the current user\n\t\t\\h 引用当前的主机名 hostname\n\t\t\\W 引用当前工作的目录的名字 working\n\t\t\\$ 当用户为root的时候,就输出#,如果不是root就是$符号\n\t\t\\t 当前的时间\n```\n\n### 临时修改PS1变量\n\n```\n//\t\t# PS1='[\\h@\\u \\t@\\W]\\$' 临时修改PS1变量(没必要改知道就行)\t\\t 当前的时间\n```\n\n```bash\n[localhost@root 11:01:07@~]#\n[localhost@xulilin 11:03:08@boot]$PS1='[\\h#\\u \\t@\\W]\\$'\n[localhost#xulilin 11:03:32@boot]$ // # 也可以\n```\n\n### 第1、2提示符\n\n```\n//\t\t# echo $PS1\n\t\t[\\u@\\h \\W]\\$\n\t\t# echo $PS2 第2提示符\n\t\t>\n//\t\t一行没输完 会显示第2提示符>(只是提醒的作用)\n```\n\n\n\n---\n\n## 十四. $+变量名\n\n```\n\t\t$PS1 $+变量名 引用某个变量\n//\t\t# echo $PS1\n\t\t[\\u@\\h \\W]\\$\n//\t\tsg=\"tangliangfei\" 定义一个变量sg 赋值tangliangfei 右边赋值左边\n\t\techo $sg 输出sg这个变量的值\n\t\tshell编程里引用变量需要接$+变量名\n\t\tShell编程 linux里的命令编程\n//\t\tmv=\"liangly\"\n\t\techo $sg $mv\n\t\ttangliangfei liangly (都显示)\n```\n\n\n\n---\n\n## 十五. id\n\n```\n//\t\tid 命令\n\t\t[root@localhost china_voice]# id \n\t\tuid=0(root) gid=0(root) 组=0(root) 环境=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023\n\t\troot用户 uid 为0\n\t\tuser id 用户的编号 uid\n\t\tgroup id 组的编号 gid\n```\n\n\n\n---\n\n## 十六. Linux命令\n\n```\n//\t\tLinux命令\n\t\t\t用于实现某一类功能的指令或程序 \n\t\t\t命令的执行依赖于解释器程序(例如:/bin/bash)\n//\t\t人 <——> bash <——> 内核 <——> 硬件\n\t\tbash 就是解释器 相当于翻译 C语言写的 程序 工具\n\t\tLinux命令的分类\n\t\t\t内部命令:属于Shell解释器的一部分\n\t\t\t外部命令:独立于Shell解释器之外的程序文件\n//\t\tshell:是一类程序,用来解释用户输入的命令,然后告诉内核去执行这些命令\n\t\t\tbsh\n\t\t\tsh\n\t\t\tcsh\n\t\t\tbash\n\t\t\tksh\n\t\tbash是最流行的shell--》几乎所有的linux系统默认的shell都是bash\n```\n\n![image-20220310194610950](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101946989.png)\n\n```\n人——BASH——kernel\n```\n\n![image-20220310194628296](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101946345.png)\n\n```\n(大概了解)\n```\n\n\n\n---\n\n## 十七. cat /etc/shells\n\n```\n//\t\tcat /etc/shells 查看本机里有哪些shell\n\t\t/bin/sh 比较老的shell\n\t\t/bin/bash \n\t\t/usr/bin/sh\n\t\t/usr/bin/bash\n//\t\tsh 敲sh,使用sh,没有提示符,退出去 敲bash 或者 exit (父子进程)\n//\t\t切换shell sh 和 bash 命令 exit\n```\n\n\n\n---\n\n## 十八. ln -s\n\n```\n#注:链接文件 天蓝色\n//\t\tln -s\n\t\tln 创建链接文件(快捷方式)\n\t\t不要去删除原文件,不然会导致链接文件不可用 (一闪一闪 冒红)\n\t\tln -s 源文件 链接文件\t\tln -s xulilin xll\n\t\t-s symbol link 符号链接(软链接 soft)\n```\n\n```bash\n\t\t# mkdir changsha\n\t\t# ln -s changsha cs \n\t\t# ll\n\t\tlrwxrwxrwx. 1 root root 8 9月 17 11:19 cs -> changsha \n```\n\n\n\n---\n\n## 十九. echo $SHELL\n\n```\n//\t\t# echo $SHELL 查看linux系统里默认的shell\n\t\t/bin/bash\n```\n\n\n\n---\n\n## 二十. env\n\n```\n//\t\t# env 查看当前用户的环境变量(linux系统里预先定义的变量) environment\n\t\t当前用户的很多进程都可以使用的变量\n\t\t环境变量--》全局变量\n```\n\n\n\n---\n\n## 二一. set\n\n```\n\t\t# set 查看所有的变量(自定义变量和环境变量)\n```\n\n\n\n---\n\n## 二二. 内部外部命令\n\n```\n//\t\tbash - GNU Bourne-Again SHell\n\t\tBASH_BUILTINS builtin 内置(内部) built in\n\t\t额外安装的命令--》外部命令\n\t\t通过安装bash这个程序就可以得到的命令--》bash的内部命令\n\t\tyum install tree -y\ttree命令是外部命令,需要额外安装\n\t\tmkdir ip 外部命令 cd echo exit 内部命令\n```\n\n\n\n---\n\n## 二三. which\n\n```\n//\t\twhich bash \t\t\t查看bash命令存放在哪里\n\t\t/usr/bin/bash\n```\n\n\n\n---\n\n## 二四. rpm\n\n### rpm -qf\n\n```\n#注:rpm -qf\t查询命令通过那个软件包安装过来的\n#注:先用which 查看命令的绝对路径\n//\t\trpm -qf /usr/bin/bash 查询/usr/bin/bash是通过哪个软件包安装过来的\n\t\tbash-4.4.19-10.el8.x86_64\n```\n\n### rpm\n\n```\n//\t\trpm 是linux里的软件管理的命令,例如安装,卸载软件\n\t\t-qf \t查询文件是通过那个软件安装过来的\n//\t\t# which ip\n\t\t/usr/sbin/ip\n\t\t# rpm -qf /usr/sbin/ip\n\t\tiproute-5.3.0-1.el8.x86_64\n//\t\tbin 二进制 binary \n```\n\n\n\n---\n\n## 二五. /usr\n\n```\n#注:/usr\t存放安装软件的目录\tunix system resource\n//\t\t/usr 是linux里存放安装软件的目录 unix system resource unix 系统资源\n\t\t相当于windows里的Program Files\n//\t\t链接文件 浅蓝色\n\t\t正常文件 深蓝色\n//\t\t/ 根目录\n\t\t/root \t root用户的家目录\n\t\t/home/用户名同名的目录 普通用户的家目录\n```\n\n\n\n---\n\n## 二六. / 与 /root关系\n\n```\n//\t\t根目录和root用户的家目录的关系?\n\t\t/root 在/目录下,是包含关系\n//\t\t~ 代表家目录,当你所在的文件夹的路径是家目录,就会显示 ~\n\t\t普通用户只能进自己家目录,root用户能进任何家目录↓↓↓\n```\n\n### 进入其他用户家目录\n\n```bash\n[xulilin@localhost /]$ cd ~xulilin\t# 注:普通用户只能进自己家目录\n[xulilin@localhost ~]$ cd ~cali\n-bash: cd: /home/cali: 权限不够\n[xulilin@localhost ~]$ exit\n注销\n[root@localhost ~]# cd ~cali\n[root@localhost cali]# pwd\n/home/cali\n[root@localhost cali]# \n```\n\n\n\n---\n\n## 二七. hostname\n\n```\n//\t\t# hostname 查看主机名\n\t\tlocalhost.localdomain\n```\n\n### 临时、永久修改主机名\n\n### 临时修改\n\n```\n//\t\t# hostname sanchuang-linux 临时修改主机名(不能用下划线_)\n\t\t接着重新登录 su - root\t(当前终端登录)/ 或者重新建立一个连接(开一个终端登录) 重启后失效\n//\t\t为什么要修改主机名?\n\t\t\t方便识别,区别不同的服务器\n```\n\n### 永久修改\n\n```\n//*\t\t永久修改主机名\n\t\t# vim /etc/hostname 改这个文件,打个新名字。\n\t\t# cat /etc/hostname \n\t\tsanchuang-linux\n\t\t重启后生效\n//\t\treboot 重启\n//\t\t不一定非得 虚拟机 登录后 xshell才能登录\n//\t\t提示符\n\t\t\tPS1\t第一提示符\n\t\t\tPS2\t第二提示符\n```\n\n\n\n---\n\n## 二八. vim\n\n```\n//\t\tvim编辑器的使用\n\t\tvim 是linux里的字符界面的文本编辑器 ——》记事本 只能写文字\n\t\t安装vim\t\tyum install vim -y\n//\t\tvim sc.txt\n\t\t1.按字母键i进入输入模式 insert\n\t\t2.输入内容,可以是中文或者英文\n\t\t3.按ESC键,返回到命令模式 escape 离开,逃离\n\t\t4.输入:wq 退出并且保存 write quit\n\t\t\t :q! 退出不保存\n\t\t\t :q 退出(没有修改可以退出)\n```\n\n\n\n---\n\n## 二九. cat\n\n```\n//\t\t# cat sc.txt 查看文本文件里的内容\n```\n\n\n\n---\n\n## 三十. 快捷键\n\n```\n//\t\t快捷键\n\t\t//\tctrl + l\n\t\t//\tctrl + c\t强行终止命令 # ^ C\n\t\t\t\t比如 ping www.baidu.com ctrl + c\n\t\t//\ttab\t补齐命令 # mkd (之后按2下tab键)mkd开头的命令都列出来了\n\t\t\t\t补齐路径 # mkdir wang 唯一性就直接补齐 否则敲两下 列出wang…\n\t\t\t\t能识别唯一性的时候,按一次tab键\n\t\t\t\t不能识别唯一性的时候,需要按2次,然后自己输入\n\t\t// 上下方向键,可以调用以前使用过的命令\n```\n\n\n\n---\n\n## 三一. pwd\n\n```\n//\t\tpwd 查看工作目录\n\t\tcd 切换工作目录\n\t\tcd ~ (cd) 进入用户家目录\n\t\tcd -\t返回上一次目录\n\t\tcd ~ liangluyao 进入liangluyao家目录\n\t\tcd .. 返回上一级目录\n```\n\n\n\n---\n\n## 三二. 别名\n\n```\n//\t\tll 是 ls -l --color=auto的别名\n//\t\t# alias 查看linux里有哪些定义好的别名\n//\t\t# alias c=clear 临时定义c是clear的别名\n\t\tclear 是linux系统里的命令 命令有选项的 要同’ ’ (单引号)引起来 \n\t\t再开启一个终端 就没效了 临时定义\n\t\tc是自定义的名字,定义别名的时候,不要和系统里已经存在的命令冲突\n```\n\n### 取消别名\n\n```\n//\t\tunalias\t取消别名\n\t\t# alias mkdir=ls\n\t\t# unalias mkdir 取消别名\n```\n\n### 永久修改别名\n\n```\n//\t\t# vim /root/.bashrc 永久修改别名,需要重新登陆,或者su切换用户到root\n\t\t.bashrc 是一个隐藏文件 按i进去 进行别名定义——》ESC :wq\n```\n\n\n\n---\n\n## 三三. ls\n\n```\n//\t\tls命令\n\t\t用途:列表(List)显示目录内容 \n\t\t格式:ls [选项]... [目录或文件名]\n 常用命令选项\n -l :以长格式显示\n -d:显示目录本身的属性\n -t: 按文件修改时间进行排序\n -r :将目录的内容清单以英文字母顺序的逆序显示\n -a:显示所有子目录和文件的信息,包括隐藏文件\n -A:类似于“-a”,但不显示“.”和“..”目录的信息\n -h:以更易读的字节单位(K、M等)显示信息\n \t// 必须和 -l 一起用\n \t-h, --human-readable\n \t\t\twith -l and -s, print sizes like 1K 234M 2G etc.\n -R:递归显示内容\n \t一层一层显示,作用远远不及 tree好,很繁琐\n//\t\tls\t查看当前 目录\n ls /boot 查看/boot 下目录\n ls -l -d /boot 只显示本身的文件夹信息 ls -ld / ls -dl\n ls -t 时间 文件修改时间排序\n ls -r 英文字母 逆序显示\n ls -l -h /boot 显示/boot的各个文件的大小\n \t\t-h 必须和 -l 一起用 显示大小 K M G\n```\n\n### \\ls -l\n\n```\n//\t\t\\ls -l 不显示列出的文件类型颜色\n```\n\n### ls -l |grep \"^d\"\n\n```\n//\t\t# ls -l|grep \"^d\" \n\t\t解释如下\n//\t\t| 管道符号: 进程和进程之间通信的一种方式\n\t\t作用:将前面一个命令的输出送给后面一个命令作为输入\n\t\t\t中间商,借花献佛,提篮子\n//\t\tgrep :文本过滤的命令\n\t\t\t会根据匹配的字符串去过滤,显示出匹配内容的行\n\n//\t\t^d 表示以d开头的行\n//\t\t# ll|grep \"txt\"\n -rw-r--r--. 1 root root 0 9月 17 15:58 a.txt\n -rw-r--r--. 1 root root 0 9月 17 16:02 sc10.txt\n # ll|grep \"^d\"\n drwxr-xr-x. 5 root root 48 9月 17 09:51 hunantv\n drwxr-xr-x. 4 root root 42 9月 17 09:54 jiangsutv\n # ll|grep \"^-\"\n -rw-r--r--. 1 root root 0 9月 17 15:58 a.txt\n -rw-r--r--. 1 root root 0 9月 17 16:02 sc10.txt\n # ll|grep \"^-\"|wc -l\n 11\n```\n\n\n\n---\n\n## 三四. ASCII\n\n```\n//\t\tASCII 美国信息交换标准代码\n\t\t数字、大写字母、小写字母 ASCII码值 小——》大\n//\t\t一个字节=8位\n\t\t101010101\n//\t\tman ls ——》/-h 查找 -h\n//\t\t# man ls\n 回车:一行一行的往下走\n /-h 查找包含-h的行\n n 查找下一个 next\n N 查找上一个 next\n q 退出\t\n```\n\n\n\n---\n\n## 三五. 文件类型\n\n```\n//\t\t文件类型\t\t缩写\t\t应用\n 常规文件\t -\t\t 保存数据\n 目录 \t \t d\t\t 存放文件 directory\n 符号链接文件 \t l\t\t指向其它文件 link\n 字符设备文件\t c\t\tcharacter --》与字符显示相关的文件\n 块设备文件\t\tb\t\t block -->存放数据的块文件\n s \tsocket文件\n p \t管道文件 pipe\n```\n\n\n\n---\n\n## 三六. 「drwxr-xr-x. 5 root root 48 9月 17 09:51 hunantv」解释\n\n```\n//\t\t[root@sanchuang-linux china_voice]# ls -l\n\t\t总用量 0\n\t\tdrwxr-xr-x. 5 root root 48 9月 17 09:51 hunantv\n d 代表文件类型 directory 目录\n rwxr-xr-x 权限 r 读 read w写 write x 执行 execute\n . 和selinux权限相关\n 5 文件的链接数\n root 用户 \n root 组\n 48 文件大小\n 9月 17 09:51 文件的创建时间\n```\n\n\n\n## 三七. wc\n\n```\n//\t\twc 是一个统计命令,可以统计文件里有多少行,多少单词,多少字节\n\t\t\t-l 统计行数 lines\n\t\twc -l 统计行数\n```\n\n### 不显示文件名\n\n```\n//# wc -l a.txt (wc -l 也可以统计文件的行数) 直接统计会显示文件名\n\t3 a.txt\n//# cat a.txt |wc -l (cat管道传给wc 不会显示文件名)\n\t3\n\t\t//# cat /etc/passwd|wc -l\n\t\t\t27\n//# cat /etc/passwd|grep \"liang\"\n liangluyao:x:1001:1001::/home/liangluyao:/bin/bash\n liangluyao2:x:1002:1002::/home/liangluyao2:/bin/bash\n # cat /etc/passwd|grep \"root\"\n root:x:0:0:root:/root:/bin/bash\n operator:x:11:0:operator:/root:/sbin/nologin\n```\n\n### 练习\n\n```\n//\t\t1.统计出/dev目录下有多少字符设备文件\n\t\t ll /dev|grep “^c”|wc -l\n\t\t2.统计出/dev目录下有多少块设备文件\n\t\t ll /dev|grep “^b”|wc -l\n 3.统计/etc/目录下有多少文件夹和普通的文件\n ll /dev|grep “^-”|wc -l 文件\n ll /dev|grep “^d”|wc -l\t文件夹\n ll -R /etc|grep “^-”|wc -l\t统计/etc和子文件夹下的所有普通文件 更彻底(包含子目录下)\n ll -R /etc|grep “^d”|wc -l\t统计/etc和子文件夹下的所有文件夹 更彻底(包含子目录下)\n 4.统计/etc/ssh/sshd_config文件有多少行\n\t\t cat /etc/ssh/sshd_config |wc -l\n//\t\t统计文件夹里有多少文件\n \tll | grep wc \n//\t\t统计文件有多少行\n\t cat | wc\n```\n\n\n\n---\n\n## 三八. du\n\n```\n//\t\tdu 统计目录及文件的空间占用情况 disk usage(估算值,并不是很准确)\n *du -sh 统计汇总的大小(常用)黄金组合\n -s\n -s, --summarize 汇总的大小\n display only a total for each argument\n -h \n -h, --human-readable\n print sizes in human readable format (e.g., 1K 234M 2G)\n -a 统计文件和文件夹\n -a, --all\n write counts for all files, not just directories\n```\n\n### du -sh 与 ll -h 区别\n\n```\n du -sh /boot\n ll -h /boot\n//\t\t# ll -h /boot 只能统计文件的大小,文件夹里的所有的文件不会汇总\n 总用量 134M\n du -sh\t可以汇总\n ll -h 就是你文件里面有多少个单词 多少个字符\n # du -sh /boot\n 140M\t/boot\n # ll -h -d /boot\n dr-xr-xr-x. 6 root root 4.0K 9月 13 14:38 /boot\n//\t\t英文字母,数字 占1个字节\n 中文字母:utf8编码 3个字节\n ll -h 统计的是一个文件里有多少字符\n\t\t\t 统计文件里面文字的字节数\n\t\tdu 统计占用多少块\n\t\t\t统计文件存放在磁盘上消耗了多少个块\n//\t\t1个块的大小就是4096 (4K)\n```\n\n![image-20220311071612898](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203110716996.png)\n\n```\n//\t\ttouch\t新建空文件\n\t\t\t\t更新时间\n//\t\tstat host 查看三个时间\n 最近访问\n 最近更改\n 最近改动\n```\n\n\n\n---\n\n## 三九. 改为英文编码\n\n```\n//\t\t改为英文编码\n # LANG=en_US.UTF8\n # ll hosts \n -rw-r--r--. 1 root root 158 Sep 17 16:57 hosts\n```\n\n\n\n---\n\n## 四十. 3个时间\n\n```bash\n# stat hosts \n File: hosts\n Size: 158 \tBlocks: 8 IO Block: 4096 regular file\nDevice: fd00h/64768d\tInode: 17162314 Links: 1\nAccess: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)\nContext: unconfined_u:object_r:default_t:s0\nAccess: 2020-09-17 16:57:57.748799777 +0800\nModify: 2020-09-17 16:57:57.748799777 +0800\nChange: 2020-09-17 16:57:57.748799777 +0800\n Birth: -\n```\n\n```\n\t时间:\t\n\t\t访问时间 access time --》atime 打开这个文件 cat\n\t\t修改时间 modify time --》mtime 修改里面的内容,增加,删除内容等 vim\n\t\t更改时间 change time --》ctime 更改了文件的属性(名字,权限,大小,时间,用户,组)\n\t\t精确到纳秒\n\t\ttouch hosts\t三个时间都更新(都改了)\n```\n\n\n\n---\n\n## 四一. chmod\n\n```\n//\t\tchmod 修改权限 change mode \n\t\t\tchmod a+w hosts\n```\n\n![image-20220311072045096](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203110720169.png)\n\n```\n\t\tchown 修改属主和属组 change owner\n```\n\n![image-20220311072106068](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203110721123.png)\n\n```\n\t\tvim hosts 输入 :wq 修改数据\n//\t\t+0800 表示东八区 中国的上海,北京 \n\t\t乌鲁木齐 东六区\n//\t\t# cp /etc/passwd . 将/etc/passwd复制到当前目录\n\t\t现在我们敲的cp,都是 cp -i ,cp是别名\n```\n\n```bash\n # alias\n alias c='clear'\n alias cp='cp -i'\n \t\t -i, --interactive 交互式\n prompt before overwrite (overrides a previous -n option)\n```\n\n\n\n---\n\n## 四二. cp的时候覆盖文件,不给予提醒的方法\n\n```\n//\t\tcp的时候覆盖文件,不给与提醒的方法\n\t\t1.取消别名 --》不推荐\n\t\t\t# unalias cp\n\t\t2.使用cp命令的绝对路径 --》推荐\n```\n\n```bash\n\t\t # which cp\n\t\t\talias cp='cp -i'\n\t\t\t /usr/bin/cp\n\t\t\t# /usr/bin/cp feng changsha/ -r\n\t\t\t# /usr/bin/cp feng changsha/ -r 再次复制 覆盖不给提醒\n```\n\n\n\n---\n\n","tags":["Linux"],"categories":["Linux"]},{"title":"02_Linux基础-文件系统层次结构-提示符-进程-隐藏文件-通配符-绝对相对路径-其他基础命令","url":"/posts/34556.html","content":"## 一. 基本命令\n\n### ls\n\n```\nls --- 查看文件夹内容 ==> list\n```\n\n![image-20220306140133778](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061401811.png)\n\n#### ls -l\n\n```\n//\t\tls -l\t显示文件的详细信息\n```\n\n![image-20220306144158855](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061441930.png)\n\n```\n//\t\tls -l\t显示文件的详细信息 (大概能看到文件时间 ,不详细)\n\t\tll\t是 ls -l 的别名\n```\n\n![image-20220307114020028](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071140074.png)\n\n\n\n#### 其他参数\n\n```\n-l 显示文件的详细信息\n\t// use a long listing format ( 使用长格式显示 )\n-a 显示所有的文件和文件夹包括.和..\n-A 显示所有的文件和y文件夹,但是不包括.和..\n```\n\n```\n//\t\tls -a 显示所有的文件和文件夹 包括 . 和 ..\n```\n\n\n\n---\n\n### mkdir\n\n```\nmkdir --- 新建文件夹 ==> make directory(目录)\n\n\t--- mkdir可以一次性建多个文件夹 空格隔开\n\t--- 默认情况下 新建文件夹放在你所在的文件夹里\n```\n\n![image-20220306140213833](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061402859.png)\n\n```\n--- windows下\n\t\t--- dir ==> Windows里面显示文件夹下内容 (等同于Linux ls)\n\t\t--- mkdir ==> Windows里建目录\n```\n\n![image-20220306140244189](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061402223.png)\n\n![image-20220306140250947](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061402977.png)\n\n\n\n#### mkdir -p\n\n```\n//\t\tmkdir -p ( -P 的作用 )\n\t\t\t1 .如果文件存在就不报错\n\t\t\t2 .当父目录不存在就新建\n```\n\n![image-20220306142737547](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061427602.png)\n\n```\n\t\t//\t\t-p, --parents [ 选项 ]\n \t\t no error if existing, make parent directories as needed\n \t\t 1.如果文件存在就不报错\n \t\t 2.当父目录不存在就新建\n//\t\t参数: 参与进来的操作的对象\n\t\t\t 也可以没有\n\t\t\t\t如果没有参数,当前目录就是参数\n```\n\n\n\n---\n\n### cd\n\n```\ncd --- 进入目录 ==> change directory to other directory\n```\n\n![image-20220306140319474](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061403502.png)\n\n![image-20220306140335947](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061403973.png)\n\n\n\n---\n\n### pwd\n\n```\npwd --- 显示当前所在路径 \n\tprint working directory name\n\tPrint name of current/working directory\n```\n\n![image-20220306140421390](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061404419.png)\n\n\n\n---\n\n### man\n\n```\nman --- 查询命令的使用手册(指南)\n\t--- 按 q 退出 quit\n\t--- manual 手册,指南\n```\n\n![image-20220306140450247](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061404282.png)\n\n![image-20220306140456152](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061404178.png)\n\n\n\n---\n\n### . & ..\n\n```\n. --- 代表当前目录\n.. --- 代表上一级目录\n\t---cd .. 返回上一级目录\n```\n\n![image-20220306140528640](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061405670.png)\n\n\n\n---\n\n### useradd\n\n```\nuseradd cpen --- 新建一个普通用户\nsu - cpen --- 切换用户登录\n```\n\n```\nroot用户的家目录在/root\n普通用户的家目录在/home目录下和用户名同名的目录\n```\n\n![image-20220306140932423](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061409446.png)\n\n\n\n---\n\n### su & exit\n\n```\n--- su - cpen 切换用户登录\n--- - 是一个选项\n\n--- exit 注销\n\t--- 退出用户/注销 exit\n```\n\n![image-20220306141026442](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061410466.png)\n\n\n\n---\n\n### rm -rf\n\n```\n--- rm -rf 删除\n\trm --- 删除的命令 (remove)\n\t-rf --- 强制删除不给提醒\n\nrm -rf /china\t--- 删除/china目录\n\t--- /china --- 绝对路径\n```\n\n```bash\n[root@localhost china]# rm -rf jiangxi/ 删除数据一定要注意,非常不安全\n```\n\n\n\n#### rm -rf *\n\n```\nrm -rf *\n\trm -rf * 删除当前目录下所有的文件,但是隐藏文件不删除\n```\n\n![image-20220307111210242](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071112309.png)\n\n![image-20220307111425817](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071114881.png)\n\n![image-20220307111432706](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071114740.png)\n\n\n\n---\n\n### tree\n\n```\nyum install tree -y\n\t--- yum - linux里软件管理的命令\n\t--- install - 安装\n\t--- tree - 安装的具体软件名\n\t--- -y 自动安装,不需要输入yes确认\n\t\ntree --- 查看目录结构\n\tyum install tree -y\n```\n\n![image-20220306141156672](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061411723.png)\n\n\n\n---\n\n### tab\n\n```\n--- 文件路径补齐:tab键\n```\n\n\n\n---\n\n### passwd\n\n```\n//\t\t给用户设置密码\tpasswd username\n\t\t默认情况:root用户可以给任何一个用户设置密码\n\t\t\t\t普通用户只能给自己设置密码(root授权除外)\n```\n\n```\n回文\n\t\t回文\t123321(上海自来水来自海上)从左、右边念一样\n```\n\n![image-20220306142004534](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061420578.png)\n\n\n\n---\n\n### w\n\n```\n//\t\t查看有哪些用户登录在linux系统里 \tw\n\t\tWhat\n```\n\n![image-20220306142447353](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061424409.png)\n\n\n\n---\n\n### ssh\n\n```\n//\t\tssh ip地址\t\t连接到相同网段 的主机上\n```\n\n![image-20220306142517994](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061425076.png)\n\n\n\n---\n\n### Ctrl + L\n\n```\n//\t\t清屏 Ctrl + L\n```\n\n\n\n---\n\n### touch\n\n```\n//\t\ttouch\n\t\t\t1 .如果文件不存在,新建空文件\n\t\t\t2 .如果文件存在,就是更新时间\n\t\t//\ttouch a.txt 建立文本文件\n```\n\n![image-20220307113733818](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071137858.png)\n\n\n\n---\n\n### date\n\n![image-20220307113753598](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071137661.png)\n\n```\n//更新时间\n```\n\n![image-20220307113817224](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071138288.png)\n\n```\n//\t\tdate 查看当前时间\n```\n\n![image-20220310120605357](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101206464.png)\n\n\n\n---\n\n### stat\n\n```\n//\t\tstat\t\t查看文件的状态(详细信息)\n\t\t\t\t\tstat status 状态\n\t\t\t\t\t文件名、大小、用户、时间\n\t\t\t\t\t比 ls -l 更加详细的信息\n```\n\n![image-20220307114133662](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071141730.png)\n\n![image-20220307114146424](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071141483.png)\n\n\n\n---\n\n### cp\n\n```\n//\t\tcp 复制(复制的同时会粘贴) copy\n\t\t将文件复制到文件夹\n\t\tcp sc.txt hunan\n\t\t\t 源\t 目的地\n```\n\n![image-20220310121009737](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101210796.png)\n\n```\n//\t\tcp -r\n\t\t-r 复制文件夹的时候,需要接的选项 递归复制 ( 将子文件夹也复制过去 )\n\t\t#注:-r一般表示递归\n\t\tlinux里的操作哲学:\n\t\t\t1.没有消息就是好消息\n\t\t\t2. 一切皆文件\n```\n\n![image-20220310121118864](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101211902.png)\n\n![image-20220310121130633](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101211678.png)\n\n```\n//\t\t复制原来有的文件,提示:是否覆盖\n\t\t空文件夹,不会提醒 是否覆盖\n```\n\n![image-20220310121155097](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101211150.png)\n\n![image-20220310121200979](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101212054.png)\n\n\n\n---\n\n### mv\n\n```\n//\t\tmv\t\t\tmv - move (rename) files\n\t\t1 .移动--》当后面接的文件夹存在就是移动(剪切) move 后面必须是文件夹,不能是文件。\n\t\t2 .改名字(重命名)--》当后面接的文件夹不存在就是重命名\n```\n\n```\n1.移动 外面就没有这些文件了\n```\n\n![image-20220310121801689](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101218793.png)\n\n```\n2.重命名\n```\n\n![image-20220310121823828](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101218882.png)\n\n\n\n---\n\n### du -sh\n\n```\n#注:查看的是所有文件 汇总的大小,而不是分开的文件\n//\t\t查看文件夹大小 du -sh\t\n\t\t\t-sh 是选项\n```\n\n![image-20220310121922252](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101219312.png)\n\n\n\n---\n\n## 二. 目录结构\n\n```\nLinux目录结构\n\t--- / 根目录\n\t--- /root 家目录\n\t\t--- /是一个文件夹,/下的root 也是个文件夹\n\t\t--- Linux目录结构 ==> 文件夹的结构 ==> 倒立的树 ==> 树目录结构\n```\n\n![image-20220306140624588](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061406632.png)\n\n![image-20220306140632939](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061406966.png)\n\n\n\n### 家目录\n\n```\n/root 是root用户的家目录\n\t--- root用户是linux超级用户\n\t--- 家目录:用户登录进入Linux系统所在的目录 (home directory)\n\n普通用户的家目录在根下面的 home 下面\n```\n\n![image-20220306140708540](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061407565.png)\n\n```\n--- ~ 所在路径是用户的家目录\n```\n\n![image-20220306140724803](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061407832.png)\n\n\n\n### 文件系统层次结构\n\n```\n//\t\tlinux 文件系统层次结构 \n```\n\n![image-20220307112856570](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071128624.png)\n\n```\n//\t\t危险操作,不能做\n\t\trm -rf /\n\t\trm -rf /*\n\t\tcd / ——》 rm -rf *\n```\n\n![image-20220307112936742](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071129791.png)\n\n\n\n---\n\n## 三. 提示符\n\n```\n提示符\n\t--- # root使用的提示符\n\t--- $ 普通用户使用的提示符\n```\n\n\n\n---\n\n## 四. 进程\n\n```\n//\t\t进程 子进程、父进程\n\t\tbash\t 终端交互程序\n\t\tsshd进程\t远程登录\n\t\tsshd 监听 22号接口\n\t\tsshd 起的bash\n\t\tbash 接受人输入的东西(人机交互的程序)\n\t\t内核管操作系统,操作系统最核心的软件\n```\n\n![image-20220306141856984](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061418027.png)\n\n\n\n---\n\n## 五. 通用命令格式\n\n```\n//\t\tlinux命令的通用命令格式\n\t\t\t命令字符 [选项] [参数] // “[ ]” 里的 可接可不接\n\t\t\t如:ls\t -l\t /home\n\t\t\t[选项] 和 [参数] 有时候顺序可以颠倒\n//\t\toption 选项: 是可供选项的项目,可接可不接,有特殊作用\n```\n\n\n\n---\n\n## 六. 隐藏文件\n\n```\n//\t\t. 开头的文件在linux下是隐藏文件\n```\n\n\n\n---\n\n## 七. *\n\n```\n//\t\t* 是通配符:代表所有的文件\n//\t\tls -A 显示所有的文件和文件夹,但是不包括 . 和 ..\n```\n\n![image-20220307111626880](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071116926.png)\n\n```\n//\t\t选项可以组合,一般不分先后顺序\n\t\tls -al (常见)\t\tls -a -l\n```\n\n![image-20220307111652259](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071116336.png)\n\n![image-20220307111703548](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071117622.png)\n\n```\n//\t\t一般不分先后顺序\n\t\t[root@localhost ~]# ls -al\n\t\t[root@localhost ~]# ls -la\n\t\t[root@localhost ~]# ls -a -l\n\t\t[root@localhost ~]# ls -l -a\n```\n\n```\n//\t\t既没有参数,也没有选项,看当前 .\n\t\t\t可以没有参数和选项\n```\n\n![image-20220307112647502](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071126544.png)\n\n---\n\n## 八. * ? 通配符\n\n```\n//\t\trm -rf 删除\n\t \t\t -rf 强制删除\n\t\t\t\t* 代表任意字符 通配符\n\t\t\t\t? 代表一个字符 通配符\n\n-r\t递归\n-f\t强制删除,不给予提醒\t忽略不存在的文件\n-f, --force 强制删除。忽略不存在的文件,不提示确认\n```\n\n![image-20220310121434322](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101214413.png)\n\n![image-20220310121441584](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101214632.png)\n\n\n\n---\n\n## 九. 绝对路径、相对路径\n\n```\n//\t\t相对路径 和 绝对路径\n\t\t//绝对路径\n\t\t\t\t不考虑你当前的位置,从“/”到达目标文件需要经过的文件系统目录树的所有分支\t/home/hello/docs/share\n\t\t\t\t从/开始,一层一层往下走,不能跳跃,而且是绝对不会搞错的路径\n\t\t//相对路径\n\t\t\t\t参照你当前的位置,到达目标文件需要经过的文件系统目录树的所有分\n\t\t不以“/”开头\n\t\t\t\t不是以/开头的路径,可进可退\n\t\t\t\t以当前目录作为参照物\n```\n\n![image-20220307113450019](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071134064.png)\n\n![image-20220307113458512](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203071134553.png)\n\n```\n//\t\tcd ./hunan(不要这么写) 和 cd hunan 效果一样\n```\n\n\n\n---\n\n## 十. {1..100}\n\n```bash\n#注:这些操作也可以↓\n[root@cPen_centos8 lianxi]# rm -rf {1..50}.txt\n[root@cPen_centos8 ~]# echo {1..10}\n1 2 3 4 5 6 7 8 9 10\n//\t\ttouch sc{1..100}.txt\n\t\tmkdir hunan{1..100}\n```\n\n![image-20220310121548513](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101215608.png)\n\n![image-20220310121624213](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203101216340.png)\n\n```\n//\t\trm -rf hunan*\t删除上面建的文件\n\t\trm -rf sc*.txt\t删除上面建的.txt文件\n//\t\ttouch sc{1..100}.txt\t创建文件 sc1.txt、sc2.txt……sc100.txt\n\t\tcp *.txt beijing\t\t复制文件不需要接 -r 复制这些文件到beijing 文件夹下\n```\n\n\n\n---\n\n","tags":["Linux"],"categories":["Linux"]},{"title":"01_Linux基础-部署-VMware-Xshell-Xftp-内核-安迪比尔定理","url":"/posts/48860.html","content":"CentOS开源 免费 --- ==CentOS是Linux里的开源免费版本==\n\n## 一. 配置虚拟机\n\n### 1. 新建虚拟机\n\n![image-20220306132810763](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061328865.png)\n\n![image-20220306132843159](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061328202.png)\n\n![image-20220306132852047](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061328076.png)\n\n![image-20220306132944296](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061329324.png)\n\n![image-20220306132951879](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061329906.png)\n\n![image-20220306133209184](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061332226.png)\n\n![image-20220306133239524](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061332550.png)\n\n\n\n### 2. 放 镜像文件\n\n```\n镜像文件其实就是 系统盘\n\tiso结尾,iso其实就是压缩格式的文件 --- 里面很多文件\n\n从虚拟机里出来:按 Ctrl + Alt\n```\n\n![image-20220306133412744](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061334787.png)\n\n![image-20220306133424202](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061334233.png)\n\n![image-20220306133432057](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061334094.png)\n\n![image-20220306133440201](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061334231.png)\n\n![image-20220306133446130](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061334174.png)\n\n![image-20220306133452249](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061334283.png)\n\n\n\n### 总结\n\n```\n注①:root用户不需要创建,默认有,用户名就叫root\n\tLinux里的超级用户 root 123456\n\n注②:用虚拟机的意思其实和花钱买云服务器一模一样\n\n注③:1个CPU核心 对应 4G内存\n\n注④:企业服务器用xeon(至强)\n```\n\n![image-20220306133619051](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061336083.png)\n\n\n\n---\n\n## 二. 云厂商\n\n```\n阿里云\n--- 阿里云国际第四大云服务,主要业务在国内\n--- 国际上:亚马逊云、Google云、微软云、阿里云\n--- 带宽在云服务器里面是稀缺资源,越大价格越贵\n--- 学习时购买一个学生机(阿里云/腾讯云) \n```\n\n\n\n---\n\n## 三. CPU\n\n```\ncpu的概念 --- 大脑\n处理器:CPU\t\t中央处理器 (Central Processing Unit)\n\t--- 颗:物理的\n\t--- 核心:逻辑的\n\n1颗CPU里面有8个核 ==> 1个鸡蛋2个黄\n\t--- 核心越多CPU的处理能力越强,速度越快\n\n\t--- 个人电脑用酷睿,企业的服务器用至强(xeon)\n```\n\n```\n电脑cpu厂家:\n\t- Intel\t英特尔\t美国\n\t\tCore\t酷睿 i3 i5 i7 i9 ==> 个人电脑\n\t\tXeon\t至强 ==> 服务器使用的CPU\n\t- AMD\t美国\n```\n\n\n\n---\n\n## 四. 虚拟机 2G2核\n\n==虚拟机2G2C怎么回事?==\n\n```\n\t并不是分2个核2G给它,虚拟机跑起来后其实是进程,名字叫VMware .exe 不会消耗1个G,也就几百兆。虚拟机模拟出来的操作系统配置是两个核一个G,虚拟出的虚幻世界,进程并不会消耗一个G两个核,但确实会用电脑里面的cpu。都是模拟出来的,假的。\n```\n\n\n\n---\n\n## 五. 虚拟机软件\n\n```\n部署环境\n--- 软件:vmware workstation 15 pro\n--- xshell - windows里连接Linux系统的工具 ==> 远程连接工具\n--- xftp - windows里和Linux之间传输文件的工具\n```\n\n\n\n### Xshell\n\n```\n登录提示符 (vmware)\n--- Localhost 代表本机的主机名(默认主机名)\t==> local 本地;host 主机(电脑)\n--- login 登录\n--- root Linux里的超级用户,默认有 不需要新建\n```\n\n![image-20220306134312489](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061343511.png)\n\n```\n--- exit 退出系统 / 注销\n--- Ctrl + L\t 清除屏幕\n--- ip add\t 查看ip地址 ==> 每台计算机都需要一个ip地址 去上网\n--- inet ==> Internet\n```\n\n![image-20220306134332067](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061343105.png)\n\n\n\n#### 使用步骤\n\n```\n1. 双击 Xshell\n\n2. 未知主机秘钥,点“接受并保存”\n\n3. 用户名输入“root”密码输入“123456”,点确定(点记住用户名、密码)\n```\n\n![image-20220306134541298](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061345353.png)\n\n```\n--- 看到# 显示连接成功 ==> 在Windows里成功连到Linux\n```\n\n![image-20220306134559536](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061345565.png)\n\n![image-20220306134606498](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061346527.png)\n\n```\n--- 调背景的(ANSI Colors),可以调成白色背景\n--- 旁边的A logo 可以调字体\n```\n\n![image-20220306134622329](https://dlvr.cpen.top/gh/mycpen/image_bed/image/202203061346372.png)\n\n\n\n---\n\n## 六. CentOS\n\n```\nCentOS --- Community ENTerprise Operating System ==> 社区企业版操作系统\nRed Hat Enterprise Linux (RHEL) ==> 红帽企业版linux系统 ==> 开源 ==> centos\nCentOS 山寨的Redhat ==> CentOS被Redhat收购了\n```\n\n\n\n### 内核\n\n```\n内核\n\t--- 主要使用 C语言 编写 ==> 开源免费\n\t--- 安卓/centos/redhat/Ubuntu用的Linux内核\n\t--- Linus李纳斯 写出内核,还写了GIT 版本控制软件\n\t--- 内核相当于汽车的发动机\n```\n\n```\nkernel内核\n\t--- 内核:Linux系统内部最核心的软件\n\t--- http://www.kernel.org/ ==> organization 组织\n```\n\n\n\n#### 内核作用\n\n```\n内核的作用:\n\t- 1.对CPU进行调度管理\n\t- 2.对内存进行分配管理\n\t- 3.对磁盘进行管理\n\t- 4.对进程进行管理\n\t- 5.其他硬件 (网卡、声卡、显卡等)\n```\n\n\n\n---\n\n## 七. Linux 与 Windows 区别\n\n```\nLinux和windows的区别:\n\t--- Linux开源\n```\n\n\n\n```bash\n# root @ CentOS in ~ [13:51:11]\n$ uname -r\n4.18.0-193.14.2.el8_2.x86_64\n\n# 解释\n\t--- el8 ==> Enterprise Linux 8\n\t--- x86_64 ==> 系统64位\n\t\t- 64位 CPU一次性处理数据的大小\n\t\t- 1字节 = 8位\n\t\t- CPU带领操作系统的发展\n```\n\n\n\n---\n\n## 八. 安迪比尔定理\n\n```\n安迪比尔定理\n\t--- CPU带领操作系统的发展 ==> 硬件与软件,现在手机行业\n```\n\n```\n\t安迪-比尔定理 (Andy and Bill’s Law)是对IT产业中软件和硬件升级换代关系的一个概括。原话是 “Andy gives, Bill takes away.(安迪提供什么,比尔拿走什么。)” 安迪指英特尔前CEO安迪·格鲁夫,比尔指微软前任CEO比尔·盖茨,这句话的意思是,硬件提高的性能,很快被软件消耗掉了。\n```\n\n\n\n---\n\n","tags":["Linux"],"categories":["Linux"]}]