我对alias的重新认识:通过alias让rm更安全
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html
rm的悲剧总是发生在不经意之间,所以无论是在shell脚本中还是交互式bash环境下,执行rm命令时总应该三思三思再三思。也因此,很多人想尽办法防止文件误删除,方法也各种各样。
1.1 alias一般用法
1.默认rm是"rm -i"的别名,ll就是"ls -l"的别名。可以自定义别名来代替某些命令配合某些选项,也可以定义别名组合多个命令。例如:
[root@xuexi ~]# alias ls='ls -lA'
这样在列出目录时将同时列出隐藏文件。
2.使用不带参数的alias将列出当前shell环境下所有的已定义的别名。
3.另外需要说明的是,当别名和命令同名时,将优先执行别名(否则别名就没有意义了),这可以从which的结果中看出:
[root@xuexi ~]# which mv
alias mv='mv -i'
/bin/mv
如果定义的命名名称和原始命令同名(例如定义的别名 ls='ls -l' ),此时如果想要明确使用原始命令,可以删除别名或者使用绝对路径或者使用转义符来还原命令。
4.alias命令是临时定义别名,要定义长久生效的别名就将别名定义语句写入/etc/profile或~/.bash_profile或~/.bashrc,第一个对所有用户有效,后面两个对对应用户有效。修改后记得使用source来重新调取这些配置文件。
5.使用unalias可以临时取消别名。
1.2 alias的缺陷
别名这东西定义和使用起来有点模糊,以下面这个别名命令为例,在有的shell脚本的书籍上使用了这样的定义,但却是错误的,原因稍后说明。
alias rmm='cp $@ ~/backup;rm $@'
该别名的目的是删除文件时先备份到一个目录下,然后再删除。按照man bash里的说明,别名rmm只是第一个cp命令的别名,分号后的rm不是别名的一部分,而是紧跟在别名后的下一行命令。当执行别名rmm时,首先读取别名到分号位置处,然后进行别名扩展,执行完别名命令后,再执行分号后的rm命令。
之所以说上面的命令是错误的命令,问题出在cp的参数"$@",该变量本表示提供的所有参数,但由于cp命令后使用分号分隔并定义了另一个命令,这使得执行别名命令时,参数无法传递到cp命令上,而只能传递到最后一个命令rm上,也就是说cp后的"$@"是空值。所以该别名等价于:
alias rmm='cp ~/backup;rm $@'
是否真的如此,使用echo测试一番即可。
[root@xuexi ~]# alias rmm='echo cp $@ ~/backup;echo rm $@'
[root@xuexi ~]# rmm /etc/fstab /etc/hosts
cp /root/backup
rm /etc/fstab /etc/hosts
从上面的结果中看到cp后的"$@"根本就没有进行扩展,而是空值。
那如果别名定义语句中没有使用分号或其他方法定义额外的命令,而是只有一个命令呢?别名一定就能正确工作吗?非也。以下面的例子为例:
[root@xuexi ~]# alias rmm='echo mv -f $@ ~/backup' [root@xuexi ~]# rmm /etc/fstab /etc/hosts
mv -f /root/backup /etc/fstab /etc/hosts
发现问题了吗?"$@"是扩展在"~/backup"目录之后的,也就是说下面mv的别名想要替代rm,是无法正常工作的:
alias rm='mv -f $@ ~/backup'
之所以无法正常工作,是因为~/backup也是"$@"的一部分,且是"$@"中最前面的参数。执行下面的命令就知道了:
[root@xuexi ~]# echo mv -f "$@" ~/backup /etc/fstab /etc/hosts
mv -f /root/backup /etc/fstab /etc/hosts
从上面的分析可以知道,alias是有其缺陷的,它只适合进行简单的命令和参数替换、补全,想要实现复杂的命令替代有点难度。因此man bash中建议尽量使用函数来取代别名(For almost every purpose, aliases are superseded by shell functions)。
1.3 别名的最佳实现
毫无疑问,写个shell脚本比别名安全、完整多了,这是替代别名的一种方法。而我个人的建议是,在别名的定义语句中使用函数来克服别名的缺陷。
例如,为了让rm安全执行,使用以下两种方法定义别名:
alias rm='copy1(){ /bin/cp -a $@ ~/backup;rm $@; };copy1 $@'
alias rm='move1(){ /bin/mv -f $@ ~/backup; };move1 $@'
因为执行别名时的参数只能传递给最后一个命令即copy1或move1函数,但"$@"代表的参数可以传递给函数,让函数中的"$@"得到正确的扩展,于是整个别名都能合理且正确地执行。
或者直接定义一个shell function替代rm。例如向/etc/profile.d/rm.sh文件中写入:
function rm(){ [ -d ~/rmbackup ] || mkdir ~/rmbackup;/bin/mv -f $@ ~/rmbackup; }
chmod +x /etc/profile.d/rm.sh
source /etc/profile.d/rm.sh
如此,执行rm命令时,便会执行此处定义的rm函数,使得rm变得更安全。但注意,这样的函数默认无法直接在脚本中使用,除非使用 export -f function_name 导出函数,使其可以被子shell继承。所以,可在/etc/profile.d/rm.sh文件的尾部加上导出语句:
function rm(){ [ -d ~/rmbackup ] || mkdir ~/rmbackup;/bin/mv -f $@ ~/rmbackup; }
export -f rm
如果function名和命令名相同,则默认优先执行function,除非使用command明确指定。例如上面定义了rm函数,如果想执行rm命令,除了使用/bin/rm,还可以如下操作:
command rm a.txt
如果是在shell脚本里涉及到rm命令,那么更建议在每次rm之前先cd到那个目录下,然后再rm相对路径,这样至少能保证不出现符号"/"。当然,更重要的是脚本习惯一些编写脚本的规范,印在骨子里那种,就算想出问题也难。
我对alias的重新认识:通过alias让rm更安全的更多相关文章
- 重新认识alias:通过alias让rm更安全
rm的悲剧总是发生在不经意之间,所以无论是在shell脚本中还是交互式bash环境下,执行rm命令时总应该三思三思再三思.也因此,很多人想尽办法防止文件误删除,方法也各种各样. 1.1.1 alias ...
- alias导致virtualenv异常的分析和解法
title: alias导致virtualenv异常的分析和解法 toc: true comments: true date: 2016-06-27 23:40:56 tags: [OS X, ZSH ...
- 以空白符结尾的 alias
网上经常有人问这个问题:为什么我写的 alias 在 sudo 下就不管用了? $ alias 'll=ls -l' $ sudo ll a-private-dir sudo: ll: command ...
- alias实现命令别名
需要经常进入/srv/www/app/account这个目录,每次都得重复的输入这一长串路径进入该目录,显得麻烦而费时,因此可以将"cd /srv/www/app/account" ...
- Nginx虚拟目录alias和root目录
nginx是通过alias设置虚拟目录,在nginx的配置中,alias目录和root目录是有区别的:1)alias指定的目录是准确的,即location匹配访问的path目录下的文件直接是在alia ...
- nginx root&alias文件路径配置
转:https://www.ttlsa.com/nginx/nginx-root_alias-file-path-configuration/ 总结: alias 改变了访问路径.root对应loca ...
- 命令别名alias设置
<转:http://vbird.dic.ksu.edu.tw/linux_basic/0320bash_3.php> 命令别名配置: alias, unalias 命令别名是一个很有趣的东 ...
- nginx root && alias 文件路径配置
文章摘自:http://www.ttlsa.com/nginx/nginx-root_alias-file-path-configuration/ nginx指定文件路径有两种方式root和alias ...
- alias function varibales in Linux/GNU and Mac alias命令细说
细说,在古文言中是”奸细佞臣的话“,现如今成了”详细说明“的缩略. alias是MS-DOC中cmds中doskey的counterpart,是”别名“或者”化名“的意思 alias强大之处在于可以化 ...
随机推荐
- 【转】权限管理学习 一、ASP.NET Forms身份认证
[转]权限管理学习 一.ASP.NET Forms身份认证 说明:本文示例使用的VS2017和MVC5. 系统无论大小.牛逼或屌丝,一般都离不开注册.登录.那么接下来我们就来分析下用户身份认证. 简单 ...
- python函数(二)
python函数(二) 变量的作用域 1.局部变量与全局变量 在函数内创建的变量被称为局部变量,这类变量的生命周期与函数相同,当函数执行完毕时,变量也就随之消失. 此类变量只能在函数内部调用,函数外不 ...
- line number is important in Exceptions.
行号作为debug信息 在出现异常时可以迅速定位 package ztest; public class Test { public static void main(String[] args) { ...
- Cura - CuraEngine - 架构分析
参考: https://blog.csdn.net/justdoithai/article/details/52746094
- JavaScript ~~ECMAScript
一.JavaScript 简介 HTML:从语义的角度,描述页面结构 CSS:从审美的角度,描述样式(美化页面) JavaScript:从交互的角度,描述行为(提升用户体验) 2.JavaScript ...
- (转)web前端知识精简
Web前端技术由 html.css 和 javascript 三大部分构成,是一个庞大而复杂的技术体系,其复杂程度不低于任何一门后端语言.而我们在学习它的时候往往是先从某一个点切入,然后不断地接触和学 ...
- [Project] MiniSearch文本检索简介
1. 预处理过程 预处理主要用来事先生成程序在运行过程中可能用到的数据,以便加速处理时间. 预处理的过程主要生成程序所需的三个文件:网页库文件,网页位置信息文件和倒排索引文件. 网页库文件 其中网页库 ...
- 微服务日志之.NET Core使用NLog通过Kafka实现日志收集
一.前言 NET Core越来越受欢迎,因为它具有在多个平台上运行的原始.NET Framework的强大功能.Kafka正迅速成为软件行业的标准消息传递技术.这篇文章简单介绍了如何使用.NET(Co ...
- WCF绑定netTcpBinding寄宿到控制台应用程序
契约 新建一个WCF服务类库项目,在其中添加两个WCF服务:GameService,PlayerService 代码如下: [ServiceContract] public interface IGa ...
- [转]SQL SERVER整理索引碎片测试
SQL SERVER整理索引碎片测试 SQL SERVER整理索引的方法也就这么几种,而且老是自作聪明的加入智能判断很不爽,还是比DBMS_ADVISOR差远了: 1SQL SERVER 2000/2 ...