一桩删除用户引起的血案ReadyNAS目录结构笔记

原博_20180425 此前nas上整理用户和目录,删掉一个用户并合并目录之后,忽然发现Photos文件夹不见了,吐血三升。 后来在家里发现ftp突然连不上了,没找到proftpd设置哪里有问题,ReadyNAS这目录结构也不知怎么重启服务,只好ssh重启机器,依然无果。上web配置界面注意到应用程序界面都是空白,itunes服务和dlna服务都起不来了,报错:ReadyNAS – Cannot start service without volume – Error Code 15002040001真是屋漏偏逢连夜雨。 同时还在拖文件整理目录,忽然发现Photos竟然躺在整理拖下来视频的文件夹里,囧rz,除此之外,home文件夹竟然也在,大骇,根目录下home文件夹果然不见了-_-||| 一通搜索“home文件夹误删怎么办”,重建目录结构,把home文件夹放回原处;结果提示空间不足,见鬼。搜了几种可能性,甚至还有inode不足之类(df -i),一一排除,最后,工作文档移走,空间有了,呃,竟然攒了这么多数据,还好不是啥大问题。/home挂载在/md0,只有4G,要不要这么小气,好歹我四盘位呢,装系统前问一下我也好嘛-_-|||home搞好之后,ftp和dlna还是不行,于是web上操作了一下“卷清理”,也不知对应后台是什么命令,整理了三天服务没起来,但是/home挂载到数据盘下面去了,看不懂这波操作,倒是不用担心home空间问题了。 ReadyNAS的个人共享文件夹原来是 /home/用户名/ ,并不是一直以为的在/data下面,而web管理页面用户是admin,所以ftp共享目录无法设置个人文件夹共享,smb方式可以登录,然而这个又不知道哪里设置了。 继续解决服务起不来问题。用错误编号搜到这篇。 http://villasyslog.net/readyn... 症状相同,解释了症结在于/home和/app的挂载问题,区别在于我再次发现我的app文件夹是真不见了,人家解除屏蔽重启服务就行,我这哪儿去找/app文件夹啊。。。 cat /lib/systemd/system/home.mountcat /lib/systemd/system/apps.mount 继续在社区搜索,重装固件没有解决问题,然后终于找到网件工程师提供了一个小程序重建app目录。 https://community.netgear.com... 哦世界清净了,虽然已装app没出现,不过不妨碍再装嘛。 看最早移到数据盘的home/已经回复原位,上级目录data/已经空了,准备删除,还好在win下用smb连接删除,看到竟然在删除一堆文件我去,赶紧ssh到后台ls -la,赫然躺着.app/。。。把内容移到默认位置,已装app也恢复了。 又注意到/data/.app和/apps内容同步但是又不是硬连接,/etc/mtab查看了一下,好吧,/.apps和/data/apps,/和/data是同一个挂载点。。。终于找到事件源头,可能当时移动用户文件夹时,直接用mv -r,而由于/data 文件夹和/一个挂载点,所以把/home和隐藏的/.apps,/._share,/.vault也一起给移动了-_-|||/._share下面是各个文件夹的共享配置,所以ftp列表目录出问题了,应用程序也无法显示了。 终于大体上解决了,这么看网件自己的deb包都安装在/data/apps/,其实apt-get 安装也不是不可以了。不过检查了下/data下的子卷 btrfs subvolume list ./ ,好像混进了奇怪的文件夹,算了,还是再看看书研究一下子卷,不敢乱rm了。。。

June 26, 2019 · 1 min · jiezi

Vue $mount实战--实现消息弹窗组件

之前的项目一直在使用Element-UI框架,element中的Notification、Message组件使用时不需要在html写标签,而是使用js调用。那时就很疑惑,为什么element ui使用this.$notify、this.$message就可以实现这样的功能?1、实现消息弹窗组件的几个问题如何在任何组件中使用this.$message就可以显示消息?如何将消息的dom节点插入到body中?同时出现多个消息弹窗时,消息弹窗的z-index如何控制?2、效果预览3、代码实现PMessage.vue<template> <transition name=“message-fade”> <div class=“p-message” :class="[type, extraClass]" v-show=“show” @mouseenter=“clearTimer” @mouseleave=“startTimer”> <div class=“p-message-container”> <i class=“p-message-icon” :class="p-message-icon-${type}"></i> <div class=“p-message-content”> <slot class=“p-message-content”> <div v-html=“message”></div> </slot> </div> </div> </div> </transition></template><script> // 绑定事件 function _addEvent(el, eventName, fn){ if(document.addEventListener){ el.addEventListener(eventName, fn, false); }else if(window.attachEvent){ el.attactEvent(‘on’ + eventName, fn); } }; // 解绑事件 function _offEvent(el, eventName, fn){ if(document.removeEventListener){ el.removeEventListener(eventName, fn, false); }else if(window.detachEvent){ el.detachEvent(‘on’ + eventName, fn); } }; export default { name: “PMessage”, data(){ return { type: ‘success’, duration: 3000, extraClass: ‘’, message: ‘’, timer: null, closed: false, show: false } }, methods: { startTimer(){ if(this.duration > 0){ this.timer = setTimeout(() => { if(!this.closed){ this.close(); } }, this.duration); } }, clearTimer(){ clearTimeout(this.timer); }, close(){ this.closed = true; if(typeof this.onClose === ‘function’){ // 调用onClose方法,以从p-message.js中的instances数组中移除当前组件,不移除的话就占空间了 this.onClose(); } }, // 销毁组件 destroyElement(){ _offEvent(this.$el, ’transitionend’, this.destroyElement); // 手动销毁组件 this.$destroy(true); this.$el.parentNode.removeChild(this.$el); }, }, watch: { // 监听closed,如果它为true,则销毁message组件 closed(newVal){ if(newVal){ this.show = false; // message过渡完成后再去销毁message组件及移除元素 addEvent(this.$el, ’transitionend’, this.destroyElement); } } }, mounted() { this.startTimer(); } }</script><style lang=“stylus”>@import “p-message.styl”</style>p-message.jsimport Vue from ‘vue’;import PMessage from ‘./PMessage.vue’;import {popupManager} from “../../common/js/popup-manager”;let PMessageControl = Vue.extend(PMessage);let count = 0;// 存储message组件实例,如需有关闭所有message的功能就需要将每个message组件都存储起来let instances = [];const isVNode = function (node) { return node !== null && typeof node === ‘object’ && Object.prototype.hasOwnProperty.call(node, ‘componentOptions’);};const Message = function (options) { options = options || {}; if(typeof options === ‘string’){ options = { message: options }; } let id = ‘message’ + ++count; let userOnClose = options.onClose; // PMsesage.vue销毁时会调用传递进去的onClose,而onClose的处理就是将指定id的message组件从instances中移除 options.onClose = function (){ Message._close(id, userOnClose); }; /* 这里传递给PMessageControl的data不会覆盖PMessage.vue中原有的data,而是与PMessage.vue中原有的data进行合并,类似 * 与mixin,包括传递methods、生命周期函数也是一样 / let instance = new PMessageControl({ data: options }); // 传递vNode if(isVNode(instance.message)){ instance.$slots.default = [instance.message]; instance.message = null; } instance.id = id; // 渲染元素,随后使用原生appendChild将dom插入到页面中 instance.$mount(); let $el = instance.$el; // message弹窗的z-index由popupManager来提供 $el.style.zIndex = popupManager.getNextZIndex(); document.body.appendChild($el); // 将message显示出来 instance.show = true; console.log(instance) instances.push(instance); return instance;};// message简化操作[‘success’,’error’].forEach(function (item) { Message[item] = options => { if(typeof options === ‘string’){ options = { message: options } } options.type = item; return Message(options); }});/* * 从instances删除指定message,内部使用 * @param id * @param userOnClose * @private /Message._close = function (id, userOnClose) { for(var i = 0, len = instances.length; i < len; i++){ if(instances[i].id === id){ if(typeof userOnClose === ‘function’){ userOnClose(instances[i]); } instances.splice(i, 1); break; } }};// 关闭所有messageMessage.closeAll = function () { for(var i = instances.length - 1; i >= 0; i–){ instances.close(); }};export default Message;popup-manager.jslet zIndex = 1000;let hasZIndexInited = false;const popupManager = { // 获取索引 getNextZIndex(){ if(!hasZIndexInited){ hasZIndexInited = true; return zIndex; } return zIndex++; }};export {popupManager};p-index.jsimport pMessage from ‘./p-message.js’;export default pMessage;p-message.styl.p-message{ position: fixed; top: 20px; left: 50%; padding: 8px 15px; border-radius: 4px; background-color: #fff; color: #000; transform: translateX(-50%); transition: opacity .3s, transform .4s; &.message-fade-enter, &.message-fade-leave-to{ opacity: 0; transform: translateX(-50%) translateY(-30px); } &.message-fade-enter-to, &.message-fade-leave{ opacity: 1; transform: translateX(-50%) translateY(0); } &.error{ color: #ff3737; } .p-message-icon{ / 使图标与内容能够垂直居中 / display: table-cell; vertical-align: middle; width: 64px; height: 45px; &.p-message-icon-success{ background: url("../../assets/images/icons/message-icon/icon_success.png") no-repeat 0 0; } &.p-message-icon-error{ background: url("../../assets/images/icons/message-icon/icon_error.png") no-repeat 0 0; } } .p-message-content{ / 使图标与内容能够垂直居中 */ display: table-cell; vertical-align: middle; padding-left: 15px; }}main.js// 引入pMessage组件import pMessage from ‘./components/p-message/p-index.js’;// 将pMessage绑定到Vue.prototype中。这样在组件中就可以通过this.$pMessage()的形式来使用了Vue.prototype.$pMessage = pMessage;3、参考参考了 Element-UI 的message代码封装Vue组件的一些技巧 ...

April 19, 2019 · 3 min · jiezi

Linux磁盘挂载、分区、扩容操作

本文最早发布于 Rootrl’s blog注:以下操作系统环境为CentOS7基本概念在操作前,首先要了解一些基本概念磁盘在Linux系统中所有的设备都会以文件的形式存储。设备一般保存在/dev目录下面,以sda、sda1、sda2 …,sdb、sdb1…,hda,hdb。现在的设备一般都是sd命名,以前的很老的硬盘是以ha命名。sda:第一块硬盘,如果对磁盘进行了分区会有sda1(第一个分区),sda2等。sdb:第二个硬盘,同样对硬盘分区后有sdb1,sdb2等。分区分区的目的就是便于管理,比如在Windows系统我们一般会分C盘,D盘,E盘等。Linux只能创建4个主分区,如果需要创建更多的分区那么久必须创建逻辑分区,其中逻辑分区需要占用一个主分区。文件系统Linux中的文件系统也就是分区类型,在Windows中有NTEF,FAT32等,linux中常见的有Ext2、Ext3、Ext4、Linux swap、proc、sysfs、tmpfs等,可以通过mount命名查看当前已挂载的文件系统。格式化在前面创建完分区后有一步是要对分区进行格式化,其实在Windows系统中也是一样,在创建好一个分区后也需要将分区格式化,只有格式化成具体的文件类型才能使用。挂载在Windows中分区格式化后就可以使用,但是在Linux系统中必须将分区挂载到具体的路径下才可以。常用命令lsblk 查看当前磁盘情况df -lh 查看文件系统情况 -l 查看挂载点parted -l 会列出文件系统类型fdisk -l 查看当前未挂载硬盘挂载新硬盘挂载一个新硬盘基本思路是:创建分区、创建文件系统、挂载。一、查看新硬盘首先,查看硬盘状况:fdisk -l其中:如果磁盘下面有类似:Disk /dev/sdc doesn’t contain a valid partition table;或者说磁盘下面没有类似于:sdb1 sdb2 说明该磁盘未挂载这里假设看到硬盘名为 /dev/sdb二、创建分区dfisk /dev/sdb根据提示,依次输入"n",“p” “1”,两次回车,“wq"意思就是新建一个主分区(1),大小是整个sdb磁盘,然后写入。注:上述操作为了简便,只是创建一个主分区。其实一个磁盘最多有四个主分区(包括一个扩展分区),1-4都是主分区,我们也可以把一个分区作为扩展分区(通过df -lh 查看到的system为Extended)此时磁盘已经分区,但是还没有文件系统,磁盘依然不能用三、写入系统mkfs.ext4 /dev/sdb该命令会格式化磁盘并写入文件系统四、挂载比如挂载到/data下面mkdir /data # 如果存在此步省略mount /dev/sdb /data五、设置开机自动挂载以上只是临时挂载,还需设置为开机自动挂载vim /etc/fstab# 然后在内容结尾处增加一行(注意文件类型要对应):/dev/sdb /data ext4 defaults 0 0扩容关于挂载到已有目录如果你要用来挂载的目录里面并不是空的,那么挂载了文件系统之后,原目录下的东西就会暂时的消失。并不是被覆盖掉,而是暂时的隐藏了起来,等到新分割槽被卸除之后,则原目录原本的内容就会再次出来。如果要永久挂载已有目录,可以在新硬盘创建文件系统后,先挂载到一个临时目录,然后把要扩展的目录复制到这临时目录,然后删除要扩展的目录,再卸载临时挂载点,重新挂载到要扩展的目录上。举例:# 比如要扩充 /var# 在创建好文件系统后 新建临时挂载点 storagemkdir /storage# 将/dev/sdb1挂载到/storage下mount /dev/sdb1 /storage# 拷贝/var下的所有内容到新的硬盘cp -pdr /var /storage# 或在/var 目录下执行:find . -depth -print | cpio - pldvm /temp# 删除当前/var目录下的内容rm -rf /var/*# 重新挂载硬盘到/var目录umount /dev/sdb1mount /dev/sdb1 /var# 过程中若提示磁盘忙,使用fuser找出将正在使用磁盘的程序并结束掉;fuser -m -v /varfuser -m -v -i -k /var扩展如果扩容比较频繁,那推荐使用LVM管理(最后一个参考链接)参考http://www.cnblogs.com/chenmh…https://segmentfault.com/a/11...https://blog.csdn.net/wzb56_e...https://www.cnblogs.com/sourc...http://www.cnblogs.com/gaojun… ...

November 30, 2018 · 1 min · jiezi