yannstatic/static/2018/10/27/LVM-Logical-Volume-Manager.html

3060 lines
248 KiB
HTML
Raw Normal View History

2024-10-31 20:18:37 +01:00
<!DOCTYPE html><html lang="fr">
<head><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"><title>LVM (Logical Volume Manager) - YannStatic</title>
<meta name="description" content="LVM (Logical Volume Manager) permet de gérer des partitions logiques, et non pas physiques, ce qui a notamment comme avantage de pouvoir plus facilement modi...">
<link rel="canonical" href="https://static.rnmkcy.eu/2018/10/27/LVM-Logical-Volume-Manager.html"><link rel="alternate" type="application/rss+xml" title="YannStatic" href="/feed.xml">
<!-- - include head/favicon.html - -->
<link rel="shortcut icon" type="image/png" href="/assets/favicon/favicon.png"><link rel="stylesheet" href="/assets/css/main.css"><link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" ><!-- start custom head snippets --><link rel="stylesheet" href="/assets/css/expand.css">
<!-- end custom head snippets --><script>(function() {
window.isArray = function(val) {
return Object.prototype.toString.call(val) === '[object Array]';
};
window.isString = function(val) {
return typeof val === 'string';
};
window.hasEvent = function(event) {
return 'on'.concat(event) in window.document;
};
window.isOverallScroller = function(node) {
return node === document.documentElement || node === document.body || node === window;
};
window.isFormElement = function(node) {
var tagName = node.tagName;
return tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA';
};
window.pageLoad = (function () {
var loaded = false, cbs = [];
window.addEventListener('load', function () {
var i;
loaded = true;
if (cbs.length > 0) {
for (i = 0; i < cbs.length; i++) {
cbs[i]();
}
}
});
return {
then: function(cb) {
cb && (loaded ? cb() : (cbs.push(cb)));
}
};
})();
})();
(function() {
window.throttle = function(func, wait) {
var args, result, thisArg, timeoutId, lastCalled = 0;
function trailingCall() {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}
return function() {
var now = new Date,
remaining = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remaining <= 0) {
clearTimeout(timeoutId);
timeoutId = null;
lastCalled = now;
result = func.apply(thisArg, args);
} else if (!timeoutId) {
timeoutId = setTimeout(trailingCall, remaining);
}
return result;
};
};
})();
(function() {
var Set = (function() {
var add = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (data[i] === item) {
return;
}
}
this.size ++;
data.push(item);
return data;
};
var Set = function(data) {
this.size = 0;
this._data = [];
var i;
if (data.length > 0) {
for (i = 0; i < data.length; i++) {
add.call(this, data[i]);
}
}
};
Set.prototype.add = add;
Set.prototype.get = function(index) { return this._data[index]; };
Set.prototype.has = function(item) {
var i, data = this._data;
for (i = 0; i < data.length; i++) {
if (this.get(i) === item) {
return true;
}
}
return false;
};
Set.prototype.is = function(map) {
if (map._data.length !== this._data.length) { return false; }
var i, j, flag, tData = this._data, mData = map._data;
for (i = 0; i < tData.length; i++) {
for (flag = false, j = 0; j < mData.length; j++) {
if (tData[i] === mData[j]) {
flag = true;
break;
}
}
if (!flag) { return false; }
}
return true;
};
Set.prototype.values = function() {
return this._data;
};
return Set;
})();
window.Lazyload = (function(doc) {
var queue = {js: [], css: []}, sources = {js: {}, css: {}}, context = this;
var createNode = function(name, attrs) {
var node = doc.createElement(name), attr;
for (attr in attrs) {
if (attrs.hasOwnProperty(attr)) {
node.setAttribute(attr, attrs[attr]);
}
}
return node;
};
var end = function(type, url) {
var s, q, qi, cbs, i, j, cur, val, flag;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
s[url] = true;
for (i = 0; i < q.length; i++) {
cur = q[i];
if (cur.urls.has(url)) {
qi = cur, val = qi.urls.values();
qi && (cbs = qi.callbacks);
for (flag = true, j = 0; j < val.length; j++) {
cur = val[j];
if (!s[cur]) {
flag = false;
}
}
if (flag && cbs && cbs.length > 0) {
for (j = 0; j < cbs.length; j++) {
cbs[j].call(context);
}
qi.load = true;
}
}
}
}
};
var load = function(type, urls, callback) {
var s, q, qi, node, i, cur,
_urls = typeof urls === 'string' ? new Set([urls]) : new Set(urls), val, url;
if (type === 'js' || type ==='css') {
s = sources[type], q = queue[type];
for (i = 0; i < q.length; i++) {
cur = q[i];
if (_urls.is(cur.urls)) {
qi = cur;
break;
}
}
val = _urls.values();
if (qi) {
callback && (qi.load || qi.callbacks.push(callback));
callback && (qi.load && callback());
} else {
q.push({
urls: _urls,
callbacks: callback ? [callback] : [],
load: false
});
for (i = 0; i < val.length; i++) {
node = null, url = val[i];
if (s[url] === undefined) {
(type === 'js' ) && (node = createNode('script', { src: url }));
(type === 'css') && (node = createNode('link', { rel: 'stylesheet', href: url }));
if (node) {
node.onload = (function(type, url) {
return function() {
end(type, url);
};
})(type, url);
(doc.head || doc.body).appendChild(node);
s[url] = false;
}
}
}
}
}
};
return {
js: function(url, callback) {
load('js', url, callback);
},
css: function(url, callback) {
load('css', url, callback);
}
};
})(this.document);
})();
</script><script>
(function() {
var TEXT_VARIABLES = {
version: '2.2.6',
sources: {
font_awesome: 'https://use.fontawesome.com/releases/v5.0.13/css/all.css',
jquery: '/assets/js/jquery.min.js',
leancloud_js_sdk: '//cdn.jsdelivr.net/npm/leancloud-storage@3.13.2/dist/av-min.js',
chart: 'https://cdn.bootcss.com/Chart.js/2.7.2/Chart.bundle.min.js',
gitalk: {
js: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.js',
css: 'https://cdn.bootcss.com/gitalk/1.2.2/gitalk.min.css'
},
valine: 'https://unpkg.com/valine/dist/Valine.min.js'
},
site: {
toc: {
selectors: 'h1,h2,h3'
}
},
paths: {
search_js: '/assets/search.js'
}
};
window.TEXT_VARIABLES = TEXT_VARIABLES;
})();
</script>
</head>
<body>
<div class="root" data-is-touch="false">
<div class="layout--page js-page-root"><!----><div class="page__main js-page-main page__viewport hide-footer has-aside has-aside cell cell--auto">
<div class="page__main-inner"><div class="page__header d-print-none"><header class="header"><div class="main">
<div class="header__title">
<div class="header__brand"><svg id="svg" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="478.9473684210526" viewBox="0, 0, 400,478.9473684210526"><g id="svgg"><path id="path0" d="M308.400 56.805 C 306.970 56.966,303.280 57.385,300.200 57.738 C 290.906 58.803,278.299 59.676,269.200 59.887 L 260.600 60.085 259.400 61.171 C 258.010 62.428,256.198 63.600,255.645 63.600 C 255.070 63.600,252.887 65.897,252.598 66.806 C 252.460 67.243,252.206 67.600,252.034 67.600 C 251.397 67.600,247.206 71.509,247.202 72.107 C 247.201 72.275,246.390 73.190,245.400 74.138 C 243.961 75.517,243.598 76.137,243.592 77.231 C 243.579 79.293,241.785 83.966,240.470 85.364 C 239.176 86.740,238.522 88.365,237.991 91.521 C 237.631 93.665,236.114 97.200,235.554 97.200 C 234.938 97.200,232.737 102.354,232.450 104.472 C 232.158 106.625,230.879 109.226,229.535 110.400 C 228.933 110.926,228.171 113.162,226.434 119.500 C 226.178 120.435,225.795 121.200,225.584 121.200 C 225.373 121.200,225.200 121.476,225.200 121.813 C 225.200 122.149,224.885 122.541,224.500 122.683 C 223.606 123.013,223.214 123.593,223.204 124.600 C 223.183 126.555,220.763 132.911,219.410 134.562 C 218.443 135.742,217.876 136.956,217.599 138.440 C 217.041 141.424,215.177 146.434,214.532 146.681 C 214.240 146.794,214.000 147.055,214.000 147.261 C 214.000 147.467,213.550 148.086,213.000 148.636 C 212.450 149.186,212.000 149.893,212.000 150.208 C 212.000 151.386,208.441 154.450,207.597 153.998 C 206.319 153.315,204.913 150.379,204.633 147.811 C 204.365 145.357,202.848 142.147,201.759 141.729 C 200.967 141.425,199.200 137.451,199.200 135.974 C 199.200 134.629,198.435 133.224,196.660 131.311 C 195.363 129.913,194.572 128.123,193.870 125.000 C 193.623 123.900,193.236 122.793,193.010 122.540 C 190.863 120.133,190.147 118.880,188.978 115.481 C 188.100 112.928,187.151 111.003,186.254 109.955 C 185.358 108.908,184.518 107.204,183.847 105.073 C 183.280 103.273,182.497 101.329,182.108 100.753 C 181.719 100.177,180.904 98.997,180.298 98.131 C 179.693 97.265,178.939 95.576,178.624 94.378 C 178.041 92.159,177.125 90.326,175.023 87.168 C 174.375 86.196,173.619 84.539,173.342 83.486 C 172.800 81.429,171.529 79.567,170.131 78.785 C 169.654 78.517,168.697 77.511,168.006 76.549 C 167.316 75.587,166.594 74.800,166.402 74.800 C 166.210 74.800,164.869 73.633,163.421 72.206 C 160.103 68.936,161.107 69.109,146.550 69.301 C 133.437 69.474,128.581 70.162,126.618 72.124 C 126.248 72.495,125.462 72.904,124.872 73.033 C 124.282 73.163,123.088 73.536,122.219 73.863 C 121.349 74.191,119.028 74.638,117.061 74.858 C 113.514 75.254,109.970 76.350,108.782 77.419 C 107.652 78.436,100.146 80.400,97.388 80.400 C 95.775 80.400,93.167 81.360,91.200 82.679 C 90.430 83.195,89.113 83.804,88.274 84.031 C 85.875 84.681,78.799 90.910,74.400 96.243 L 73.400 97.456 73.455 106.028 C 73.526 117.055,74.527 121.238,77.820 124.263 C 78.919 125.273,80.400 127.902,80.400 128.842 C 80.400 129.202,81.075 130.256,81.900 131.186 C 83.563 133.059,85.497 136.346,86.039 138.216 C 86.233 138.886,87.203 140.207,88.196 141.153 C 89.188 142.098,90.000 143.104,90.000 143.388 C 90.000 144.337,92.129 148.594,92.869 149.123 C 93.271 149.410,93.600 149.831,93.600 150.059 C 93.600 150.286,93.932 150.771,94.337 151.136 C 94.743 151.501,95.598 153.004,96.237 154.475 C 96.877 155.947,97.760 157.351,98.200 157.596 C 98.640 157.841,99.900 159.943,101.000 162.267 C 102.207 164.817,103.327 166.644,103.825 166.876 C 104.278 167.087,105.065 168.101,105.573 169.130 C 107.658 173.348,108.097 174.093,110.006 176.647 C 111.103 178.114,112.000 179.725,112.000 180.227 C 112.000 181.048,113.425 183.163,114.678 184.200 C 115.295 184.711,117.396 188.733,117.720 190.022 C 117.855 190.562,118.603 191.633,119.381 192.402 C 120.160 193.171,121.496 195.258,122.351 197.039 C 123.206 198.820,124.167 200.378,124.487 200.501 C 124.807 200.624,125.953 202.496,127.034 204.662 C 128.114 206.828,129.676 209.299,130.505 210.153 C 131.333 211.007,132.124 212.177,132.262 212.753 C 132.618 214.239,134.291 217.048,136.288 219.5
" href="/">YannStatic</a></div><!--<button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button>--><!-- <li><button class="button button--secondary button--circle search-button js-search-toggle"><i class="fas fa-search"></i></button></li> -->
<!-- Champ de recherche -->
<div id="searchbox" class="search search--dark" style="visibility: visible">
<div class="main">
<div class="search__header"></div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<!-- <div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div> -->
</div>
</div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
json: '/search.json',
//searchResultTemplate: '<li><a href="https://static.rnmkcy.eu{url}">{date}&nbsp;{title}</a></li>'
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a></li>'
})
</script>
<!-- Fin déclaration champ de recherche --></div><nav class="navigation">
2024-11-28 11:42:23 +01:00
<ul><li class="navigation__item"><a href="/archive.html">Etiquettes</a></li><li class="navigation__item"><a href="/htmldoc.html">Documents</a></li><li class="navigation__item"><a href="/liens_ttrss.html">Liens</a></li><li class="navigation__item"><a href="/syntaxe-markdown.html">Aide</a></li></ul>
2024-10-31 20:18:37 +01:00
</nav></div>
</header>
</div><div class="page__content"><div class ="main"><div class="grid grid--reverse">
<div class="col-main cell cell--auto"><!-- start custom main top snippet --><div id="results-container" class="search-result js-search-result"></div><!-- end custom main top snippet -->
<article itemscope itemtype="http://schema.org/Article"><div class="article__header"><header><h1 style="color:Tomato;">LVM (Logical Volume Manager)</h1></header></div><meta itemprop="headline" content="LVM (Logical Volume Manager)"><div class="article__info clearfix"><ul class="left-col menu"><li>
2024-11-08 14:10:33 +01:00
<a class="button button--secondary button--pill button--sm" style="color:#00FFFF" href="/archive.html?tag=commande">commande</a>
2024-10-31 20:18:37 +01:00
</li></ul><ul class="right-col menu"><li>
<i class="far fa-calendar-alt"></i>&nbsp;<span title="Création" style="color:#FF00FF">27&nbsp;oct.&nbsp;&nbsp;2018</span>
<span title="Modification" style="color:#00FF7F">&nbsp;3&nbsp;déc.&nbsp;&nbsp;2022</span></li></ul></div><meta itemprop="datePublished" content="2022-12-03T00:00:00+01:00">
<meta itemprop="keywords" content="commande"><div class="js-article-content">
<div class="layout--article"><!-- start custom article top snippet -->
<style>
#myBtn {
display: none;
position: fixed;
bottom: 10px;
right: 10px;
z-index: 99;
font-size: 12px;
font-weight: bold;
border: none;
outline: none;
background-color: white;
color: black;
cursor: pointer;
padding: 5px;
border-radius: 4px;
}
#myBtn:hover {
background-color: #555;
}
</style>
<button onclick="topFunction()" id="myBtn" title="Haut de page">&#8679;</button>
<script>
//Get the button
var mybutton = document.getElementById("myBtn");
// When the user scrolls down 20px from the top of the document, show the button
window.onscroll = function() {scrollFunction()};
function scrollFunction() {
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
mybutton.style.display = "block";
} else {
mybutton.style.display = "none";
}
}
// When the user clicks on the button, scroll to the top of the document
function topFunction() {
document.body.scrollTop = 0;
document.documentElement.scrollTop = 0;
}
</script>
<!-- end custom article top snippet -->
<div class="article__content" itemprop="articleBody"><details>
<summary><b>Afficher/cacher Sommaire</b></summary>
<!-- affichage sommaire -->
<div class="toc-aside js-toc-root"></div>
</details><p><em>LVM (Logical Volume Manager) permet de gérer des partitions logiques, et non pas physiques, ce qui a notamment comme avantage de pouvoir plus facilement modifier leur taille.</em></p>
<ul>
<li><a href="#lvm">LVM</a>
<ul>
<li><a href="#pré-requis">Pré-requis</a></li>
<li><a href="#installation-du-package-lvm">Installation du package LVM</a></li>
<li><a href="#création-du-volume-physique-pv">Création du volume physique PV</a></li>
<li><a href="#création-dun-volume-logique-lv">Création dun volume logique LV</a></li>
<li><a href="#quelques-commandes-utiles">Quelques commandes utiles</a></li>
<li><a href="#supprimer-un-volume-logique-lv">Supprimer un volume logique LV</a></li>
<li><a href="#formatage-du-volume-logique-lv">Formatage du volume logique LV</a></li>
<li><a href="#augmenter-la-taille-dune-partition-lvm">Augmenter la taille dune partition LVM</a></li>
<li><a href="#réduire-la-taille-dune-partition-lvm">Réduire la taille dune partition LVM</a></li>
</ul>
</li>
<li><a href="#lvm-une-autre-manière-de-partitionner">LVM, une autre manière de partitionner</a>
<ul>
<li><a href="#introduction">Introduction</a>
<ul>
<li><a href="#avantages-de-lvm">Avantages de LVM</a></li>
<li><a href="#inconvénients-de-lvm">Inconvénients de LVM</a></li>
</ul>
</li>
<li><a href="#pré-requis">Pré-requis</a></li>
<li><a href="#installation">Installation</a></li>
<li><a href="#notions-et-vocabulaire">Notions et vocabulaire</a>
<ul>
<li><a href="#volume-physique">Volume physique</a></li>
<li><a href="#groupe-de-volumes">Groupe de volumes</a></li>
<li><a href="#volume-logique">Volume logique</a></li>
<li><a href="#synthèse-graphique">Synthèse graphique</a></li>
</ul>
</li>
<li><a href="#création">Création</a>
<ul>
<li><a href="#groupe-de-volumes">Groupe de volumes</a></li>
<li><a href="#volume-logique">Volume logique</a></li>
<li><a href="#système-de-fichiers">Système de fichiers</a></li>
</ul>
</li>
<li><a href="#suppression">Suppression</a></li>
<li><a href="#redimensionnement">Redimensionnement</a>
<ul>
<li><a href="#volume-physique">Volume physique</a>
<ul>
<li><a href="#agrandissement">Agrandissement</a></li>
<li><a href="#rétrécissement">Rétrécissement</a></li>
</ul>
</li>
<li><a href="#volume-logique">Volume logique</a>
<ul>
<li><a href="#agrandissement">Agrandissement</a></li>
<li><a href="#rétrécissement">Rétrécissement</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#snapshot">Snapshot</a>
<ul>
<li><a href="#création-dun-snapshot-lvm">Création dun snapshot LVM</a></li>
<li><a href="#redimensionnement-du-snapshot">Redimensionnement du snapshot</a></li>
<li><a href="#fusionner-un-snapshot">Fusionner un snapshot</a></li>
</ul>
</li>
<li><a href="#changement-dun-disque-défectueux">Changement dun disque défectueux</a>
<ul>
<li><a href="#principe">Principe</a></li>
<li><a href="#avec-gparted">Avec GParted</a></li>
<li><a href="#en-ligne-de-commande">En ligne de commande</a></li>
<li><a href="#finalisation">Finalisation</a></li>
</ul>
</li>
<li><a href="#mieux-comprendre-ou-aller-plus-loin">Mieux comprendre ou aller plus loin</a>
<ul>
<li><a href="#notion-extent">Notion “extent”</a></li>
<li><a href="#glossaire">Glossaire</a></li>
<li><a href="#lvm-et-raid">LVM et RAID</a></li>
<li><a href="#lvm-miroir">LVM miroir</a></li>
<li><a href="#monter-une-partition">Monter une partition</a>
<ul>
<li><a href="#obtenir-la-liste-des-groupes-logiques">Obtenir la liste des groupes logiques</a></li>
<li><a href="#obtenir-la-liste-des-partitions">Obtenir la liste des partitions</a></li>
<li><a href="#rendre-la-partition-disponible">Rendre la partition disponible</a></li>
<li><a href="#monter-la-partition">Monter la partition</a></li>
<li><a href="#-exemple"> Exemple</a></li>
</ul>
</li>
<li><a href="#vérifier-une-partition">Vérifier une partition</a>
<ul>
<li><a href="#rendre-la-partition-disponible">Rendre la partition disponible</a></li>
<li><a href="#lancer-fsck">Lancer fsck</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li><a href="#synthèse">Synthèse</a></li>
<li><a href="#sauvegarder-son-système-à-chaud-avec-lvm">Sauvegarder son système à chaud avec LVM</a>
<ul>
<li><a href="#pré-requis">Pré-requis</a></li>
<li><a href="#vérifications-préalables">Vérifications préalables</a></li>
<li><a href="#création-du-volume-de-sauvegarde">Création du volume de sauvegarde</a></li>
<li><a href="#snapshot-et-copie">Snapshot et copie</a></li>
<li><a href="#finitions">Finitions</a></li>
</ul>
</li>
</ul>
<h2 id="lvm">LVM</h2>
<h3 id="pré-requis">Pré-requis</h3>
<p>Partition non formatée</p>
<p>Il faut disposer dune partition non formatée. Dans notre cas, il sagit de /dev/sda9, qui dispose dun peu plus de 300 Go de libres. Cette partition sera utilisée principalement pour gérer des images de machines virtuelles créées avec KVM.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># fdisk -l /dev/sda
Disk /dev/sda: 750.2 GB, 750156374016 bytes
255 têtes, 63 secteurs/piste, 91201 cylindres, total 1465149168 secteurs
Unités = secteurs de 1 * 512 = 512 octets
Taille de secteur (logique / physique) : 512 octets / 4096 octets
taille d'E/S (minimale / optimale) : 4096 octets / 4096 octets
Identifiant de disque : 0x73a05bd4
Périphérique Amorce Début Fin Blocs Id Système
/dev/sda1 * 2048 102402047 51200000 7 HPFS/NTFS/exFAT
/dev/sda2 102402048 204802047 51200000 7 HPFS/NTFS/exFAT
/dev/sda3 204804094 1465147391 630171649 5 Étendue
La partition 3 ne débute pas sur une frontière de cylindre physique.
/dev/sda5 204804096 284803071 39999488 83 Linux
/dev/sda6 284805120 294567935 4881408 82 partition d'échange Linux / Solaris
/dev/sda7 294569984 392224767 48827392 83 Linux
/dev/sda8 392226816 802082815 204928000 83 Linux
/dev/sda9 802084864 1465147391 331531264 83 Linux
</code></pre></div></div>
<h3 id="installation-du-package-lvm">Installation du package LVM</h3>
<p>Sur une distribution de type Debian/Ubuntu</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo apt install lvm2
</code></pre></div></div>
<h3 id="création-du-volume-physique-pv">Création du volume physique PV</h3>
<p>La mise en place de volumes logiques est un modèle à trois couches :</p>
<ul>
<li>Volume physique</li>
<li>Volume groupe</li>
<li>Volume logique</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># pvcreate /dev/sda9
Writing physical volume data to disk "/dev/sda9"
Physical volume "/dev/sda9" successfully created
</code></pre></div></div>
<p>On peut lister les volumes physiques avec la commande pvdisplay. Exemple :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># pvdisplay
"/dev/sda9" is a new physical volume of "316,17 GiB"
--- NEW Physical volume ---
PV Name /dev/sda9
VG Name
PV Size 316,17 GiB
Allocatable NO
PE Size 0
Total PE 0
Free PE 0
Allocated PE 0
PV UUID ReKoL9-gneB-DXfg-5MpV-pKyP-n5Rl-TRdnXh
</code></pre></div></div>
<p>Création du Volume Groupe VG</p>
<p>Avant de pouvoir créer des volumes logiques, il faut avoir créé un Volume Group. Ceci seffectue via la commande vgcreate. La syntaxe est la suivante :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgcreate NOM-du-VG NOM-Du-PV
</code></pre></div></div>
<p>Exemple :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># vgcreate vmvg /dev/sda9
Volume group "vmvg" successfully created
</code></pre></div></div>
<p>On peut vérifier que cela est répercuté au niveau du volume physique. Le paramètre VG Name est maintenant renseigné :</p>
<p>Informations via la commande vgdisplay. Par exemple :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># vgdisplay vmvg
--- Volume group ---
VG Name vmvg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 1
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 0
Open LV 0
Max PV 0
Cur PV 1
Act PV 1
VG Size 316,17 GiB
PE Size 4,00 MiB
Total PE 80940
Alloc PE / Size 0 / 0
Free PE / Size 80940 / 316,17 GiB
VG UUID kd3LKL-tMjA-eIq4-EhMs-LdWV-LFVl-2rBhk1
</code></pre></div></div>
<h3 id="création-dun-volume-logique-lv">Création dun volume logique LV</h3>
<p>A ce niveau, il est possible de créer des volumes logiques sur notre VG, via la commande lvcreate, avec la syntaxe :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -L[taille] -n[nom-du-lv] [nom-du-vg]
</code></pre></div></div>
<p>Dans notre exemple, ce serait :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -L8000 -n vm_debian6 vmvg
Logical volume "vm_wheezy" created
</code></pre></div></div>
<p>Cette commande créera un volume logique de 8 Go sur le volume groupe vmvg, et nommé vm_debian6.</p>
<p>On peut avoir la liste des LV créés avec la commande lvscan :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># lvscan
ACTIVE '/dev/vmvg/vm_wheezy' [7,81 GiB] inherit
</code></pre></div></div>
<p>La commande lvdisplay pour les détails dun volume logique :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># lvdisplay
--- Logical volume ---
LV Path /dev/vmvg/vm_wheezy
LV Name vm_wheezy
VG Name vmvg
LV UUID bOAd1B-Xg0e-Unj3-onj2-IZUY-k654-tqdvtd
LV Write Access read/write
LV Creation host, time portable-vli, 2012-11-22 16:53:41 +0100
LV Status available
# open 0
LV Size 7,81 GiB
Current LE 2000
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:0
</code></pre></div></div>
<p>Les volumes logiques sont prêts à être utilisés par virt-manager…</p>
<h3 id="quelques-commandes-utiles">Quelques commandes utiles</h3>
<p>pvscan : liste les différents volumes physiques disponibles</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># pvscan
PV /dev/sda9 VG vmvg lvm2 [316,17 GiB / 300,55 GiB free]
Total: 1 [316,17 GiB] / in use: 1 [316,17 GiB] / in no VG: 0 [0 ]
</code></pre></div></div>
<p>vgscan : liste les différents volume groups</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># vgscan
Reading all physical volumes. This may take a while...
Found volume group "vmvg" using metadata type lvm2
</code></pre></div></div>
<p>lvscan : liste les différents volumes logiques</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># lvscan
ACTIVE '/dev/vmvg/vm_wheezy' [7,81 GiB] inherit
ACTIVE '/dev/vmvg/vm_debian6' [7,81 GiB] inherit
</code></pre></div></div>
<h3 id="supprimer-un-volume-logique-lv">Supprimer un volume logique LV</h3>
<p>Pour supprimer un volume logique, il suffit dutiliser la commande lvremove, une fois que le volume logique est démonté. Exemple :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code># lvscan
ACTIVE '/dev/vmvg/vm_wheezy' [7,81 GiB] inherit
ACTIVE '/dev/vmvg/vm_debian6' [7,81 GiB] inherit
ACTIVE '/dev/vmvg/vm_seven' [15,62 GiB] inherit
# lvremove /dev/vmvg/vm_wheezy
Do you really want to remove active logical volume vm_wheezy? [y/n]:
Logical volume "vm_wheezy" successfully removed
# lvscan
ACTIVE '/dev/vmvg/vm_debian6' [7,81 GiB] inherit
ACTIVE '/dev/vmvg/vm_seven' [15,62 GiB] inherit
</code></pre></div></div>
<h3 id="formatage-du-volume-logique-lv">Formatage du volume logique LV</h3>
<p>Afin de pouvoir monter le volume logique, il est nécessaire de le formater auparavant, via les commandes mkfs. Par exemple, pour formater en ext4, on utilisera la commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkfs -t ext4 /dev/vmvg/Vol1
</code></pre></div></div>
<p>On peut ensuite monter le volume comme une partition “normale” :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /Essai1
mount /dev/mvg/Vol1 /Essai1
df -h
</code></pre></div></div>
<h3 id="augmenter-la-taille-dune-partition-lvm">Augmenter la taille dune partition LVM</h3>
<p>Lun des avantages principaux des volumes logiques est de permettre de redimensionner la partition “à la volée” ou presque, beaucoup plus facilement et sans perte de données par rapport à une partition physique.</p>
<p>Pour ce faire, il est possible dutiliser la commande lvextend. Par exemple :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvextend -L 12G /dev/vmvg/Vol1
</code></pre></div></div>
<p>va étendre la taille du volume logique à 12 GB.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvextend -L +1G /dev/vmvg/Vol1
</code></pre></div></div>
<p>va ajouter 1 GB au volume logique. Il faut ensuite retailler le file system qui repose sur ce volume logique :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvextend -l +1125 /dev/vmvg/Vol1
</code></pre></div></div>
<p>va ajouter le reste disponible du “volume groupe” (Free PE/Size) au volume logique.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvextend -l 100%FREE /dev/vmvg/Vol1
</code></pre></div></div>
<p>va ajouter lespace restant disponible du “volume groupe”</p>
<p>Il faut ensuite retailler le file system qui repose sur ce volume logique :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /dev/vmvg/Vol1
e2fsck -f /dev/vmvg/Vol1
resize2fs /dev/vmvg/Vol1
mount /dev/vmvg/Vol1
</code></pre></div></div>
<h3 id="réduire-la-taille-dune-partition-lvm">Réduire la taille dune partition LVM</h3>
<p>Nous vous montrons ici comment réduire un volume ou une partition LVM sous Linux en redimensionnant dabord le système de fichiers, puis le volume logique.<br />
Dans cet exemple, nous allons travailler sur la réduction du volume logique /var/centos/var de 10 Go à 5 Go.</p>
<p>Vue densemble de Logical Volume Manager (LVM)</p>
<p>Avant de travailler à travers le processus de redimensionnement, il est important que vous compreniez dabord quelques concepts de base autour des volumes physiques, des groupes de volumes, des volumes logiques et du système de fichiers.</p>
<ul>
<li>Volume physique (PV) : Ceci peut être créé sur un disque physique entier (pensez à /dev/sda) ou sur une partition Linux.</li>
<li>Groupe de volume (VG) : Il est composé dau moins un ou plusieurs volumes physiques.</li>
<li>Volume logique (LV) : Cest ce quon appelle parfois la partition, elle se trouve à lintérieur dun groupe de volume et a un système de fichiers écrit sur elle.</li>
<li>Système de fichiers : Un système de fichiers tel que ext4 sera sur le volume logique.</li>
</ul>
<p>Comment diminuer ou rétrécir le volume logique</p>
<p>Pour diminuer la taille dune partition LVM, vous devez dabord diminuer le système de fichiers afin déviter une éventuelle corruption des données. Comme il est possible que cela se produise si vous entrez la commande incorrectement, il est fortement recommandé que vous ayez une sauvegarde complète de vos données avant de continuer. Réduire un volume logique vous donnera plus despace dans le groupe de volume, ce qui signifie que vous pourriez plutôt étendre un autre volume logique avec ce nouvel espace trouvé.</p>
<p>La première étape dépendra si vous cherchez à réduire le volume dune racine LVM ou dun volume non racine.<br />
<strong>Réduire le volume dune racine</strong><br />
Le volume de la racine serait typiquement le volume logique qui est monté sur /. Vous ne pouvez pas le démonter pour le rétrécir car il est utilisé par le système dexploitation en cours dexécution, ce qui signifie que vous devrez dabord démarrer à partir dun Live CD pour le faire.</p>
<p><strong>Réduire un volume non racinaire</strong><br />
Alternativement, si le volume que vous réduisez est un volume non racine, cest-à-dire tout autre volume non monté à la racine du système de fichiers, vous pouvez démonter le volume comme indiqué ci-dessous pour continuer. Veuillez noter que lorsque vous démontez le volume, les données ne seront pas disponibles, vous devrez peut-être planifier un temps darrêt et arrêter dexécuter les applications qui utilisent les données avant de les démonter. Démonter en spécifiant soit le volume logique, soit lemplacement où il est actuellement monté, dans lexemple ci-dessous nous spécifions le volume logique qui peut être trouvé dans /dev/(vg-name)/(lv-name).</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /dev/centos/var
</code></pre></div></div>
<p>Toutes les étapes suivantes sappliquent maintenant à un volume racinaire ou non racinaire.<br />
Avant de pouvoir tenter de réduire la taille dun volume LVM, vous devez dabord exécuter une vérification du système de fichiers. Si vous ne le faites pas, vous obtiendrez un message derreur et vous ne pourrez pas continuer. Cest une étape nécessaire car le redimensionnement dun système de fichiers en mauvais état peut entraîner une corruption des données. Loption -f permet dexécuter la vérification même si le système de fichiers semble propre, tandis que loption -y suppose que toutes les questions sont répondues par laffirmative et répondra si on lui demande de résoudre un problème.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>e2fsck -fy /dev/centos/var
</code></pre></div></div>
<p>Ensuite, vous devez rétrécir le système de fichiers, pour être sûr, nous allons rétrécir le système de fichiers plus bas que ce à quoi le volume logique va rétrécir. Cest parce que nous ne voulons pas réduire accidentellement le volume logique à une taille inférieure à celle du système de fichiers à létape suivante, car cela peut entraîner la corruption et la perte de données. Ne tinquiète pas, on récupérera lespace à la fin. <br />
La commande ci-dessous réduira la taille totale du système de fichiers de sorte quil ne soit que de 4G, notez que quelle que soit la taille que vous spécifiez de réduire à vous doit avoir en espace libre dans le système de fichiers sinon vous devez dabord supprimer les données.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>resize2fs /dev/centos/var 4G
</code></pre></div></div>
<p>Une fois le système de fichiers réduit, on peut réduire la taille du volume logique avec la commande lvreduce. Réduisez-le à la taille que vous voulez que le volume soit, comme spécifié par lindicateur -L. Au lieu de cela, si vous voulez réduire dune taille spécifiée, mettez simplement un - devant la taille. Les deux sont indiqués ci-dessous pour être complets, mais vous navez besoin den exécuter quun seul.</p>
<p>Pour réduire à 5G</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvreduce -L 5G /dev/vg/nom-disque
</code></pre></div></div>
<p>Réduire de 5G</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvreduce -L -5G /dev/vg/nom-disque
</code></pre></div></div>
<p>Une fois que vous exécutez la commande lvreduce, vous recevrez un avertissement vous indiquant la taille que vous avez choisi de réduire pour ainsi utiliser ceci comme une chance de confirmer que vous réduisez le volume logique à une taille qui nest PAS plus petite que la taille à laquelle vous avez précédemment réduit le système de fichiers. Une fois que vous avez confirmé, il vous suffit dentrery et dappuyer surenter.</p>
<p>Une fois que le volume logique a été réduit à la taille requise, exécutez resize2fs sur le volume car cela permettra détendre le système de fichiers pour utiliser tout lespace disponible dans le volume logique. Cela permet dutiliser tout lespace libre restant afin quaucun espace ne soit gaspillé à partir du moment où nous avons précédemment réduit le système de fichiers à une taille inférieure à celle du volume logique.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>resize2fs /dev/centos/var
</code></pre></div></div>
<p>Il ne reste plus quà monter le volume. Sil sagit dun volume racine et que vous travaillez dans un Live CD, redémarrez simplement dans votre système dexploitation Linux principal.<br />
Sil sagissait dun volume non racine et que vous lavez démonté pour compléter la réduction, il suffit de le remonter. Vous pouvez le faire avecmount -a en supposant que vous avez la configuration déjà définie dans /etc/fstab, sinon spécifiez le volume logique et où il doit être monté. Ici, nous montons manuellement sur /mnt juste pour tester.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount /dev/centos/centos/var /mnt
</code></pre></div></div>
<p>Après avoir redémarré le système dexploitation principal ou terminé le montage, vérifiez lespace affiché avec la commandedf pour confirmer quil a été réduit comme prévu.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[root@CentOS7 /]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/centos-root 9.8G 1.4G 8.5G 14% /
devtmpfs 908M 0 908M 0% /dev
tmpfs 914M 0 914M 0% /dev/shm
tmpfs 914M 8.6M 905M 1% /run
tmpfs 914M 0 914M 0% /sys/fs/cgroup
/dev/sda1 497M 96M 402M 20% /boot
/dev/mapper/centos-var 4.8G 20M 4.6G 1% /mnt
</code></pre></div></div>
<h2 id="lvm-une-autre-manière-de-partitionner">LVM, une autre manière de partitionner</h2>
<h3 id="introduction">Introduction</h3>
<p><strong>LVM</strong> (Logical Volume Manager, ou gestionnaire de volumes logiques en français) permet la création et la gestion de volumes logiques sous Linux. Lutilisation de volumes logiques remplace en quelque sorte le partitionnement des disques. Cest un système beaucoup plus souple, qui permet par exemple de diminuer la taille dun système de fichier pour pouvoir en agrandir un autre, sans se préoccuper de leur emplacement sur le disque.</p>
<p>Il permet notamment de redimensionner les partitions de disques sans reformatage.
Il permet également de rajouter des disques à la volée.</p>
<h4 id="avantages-de-lvm">Avantages de LVM</h4>
<ul>
<li>Il ny a pas de limitations « étranges » comme avec les partitions (primaire, étendue, etc.).</li>
<li>On ne se préoccupe plus de lemplacement exact des données.</li>
<li>On peut conserver quelques giga-octets de libres pour pouvoir les ajouter nimporte où et nimporte quand.</li>
<li>Les opérations de redimensionnement deviennent quasiment sans risques, contrairement au redimensionnement des partitions.</li>
<li>On peut créer des snapshots de volume sans perturber le fonctionnement de la machine et sans interruption de services.</li>
</ul>
<h4 id="inconvénients-de-lvm">Inconvénients de LVM</h4>
<ul>
<li>Si un des volumes physiques devient HS, alors cest lensemble des volumes logiques qui utilisent ce volume physique qui sont perdus. Pour éviter ce désastre, il faudra utiliser LVM sur des disques raid par exemple.</li>
</ul>
<h3 id="pré-requis-1">Pré-requis</h3>
<ul>
<li>Un disque ou une partition libre.</li>
<li>Ne pas avoir peur de la ligne de commande.</li>
</ul>
<h3 id="installation">Installation</h3>
<p>Installez le paquet lvm2</p>
<h3 id="notions-et-vocabulaire">Notions et vocabulaire</h3>
<h4 id="volume-physique">Volume physique</h4>
<p>Un volume physique ou « PV » pour « physical volume » est tout simplement un disque ou une partition. Bref, cest un espace de stockage bien réel (autrement dit un périphérique de la forme <code class="language-plaintext highlighter-rouge">/dev/sda2</code> par exemple), que lon va confier à LVM. Bien évidemment, tout ce qui était présent sur la partition sera effacé.</p>
<p class="warning">Avant de pouvoir définir le volume physique, il est nécessaire quune partition existe. Pour cela vous pouvez avoir recours à gparted sur un PC desktop et à parted sur serveur</p>
<h4 id="groupe-de-volumes">Groupe de volumes</h4>
<p>Un groupe de volumes ou « VG » pour « volume group » est, comme son nom lindique, un ensemble de volumes physiques. On a donc un ou plusieurs volumes physiques dans un groupe de volumes, et pour utiliser LVM, il faut obligatoirement au moins un groupe de volumes. Habituellement, sur les gros serveurs, on essaye de regrouper les disques en fonction de leur caractéristiques (capacités, performances, etc.). Pour un particulier, le fait de mettre plusieurs disques dans un même groupe de volume peut permettre « détaler » un système de fichiers sur plusieurs disques, et davoir donc <code class="language-plaintext highlighter-rouge">/home</code> par exemple qui utiliserait 2 disques. Une telle configuration est tout de même assez dangereuse en cas de perte dun disque… De plus, cela napporterait aucun gain de performance contrairement à du RAID-0 par exemple.</p>
<h4 id="volume-logique">Volume logique</h4>
<p>Un volume logique ou « LV » pour « logical volume » est ce que nous allons utiliser au final. Un volume logique est un espace « quelque part dans un groupe de volume » où lon peut mettre un système de fichiers. Cest donc ce qui remplace les partitions. On peut donc utiliser un volume logique pour mettre la mémoire virtuelle, un pour <code class="language-plaintext highlighter-rouge">/home</code>, “/”, etc.</p>
<p class="warning">Évitez de mettre “/boot/grub” dans un volume logique car cela peut poser des problèmes pour le démarrage du système. En effet, grub ne sait pas encore (novembre 2015) écrire dans un fichier localisé dans un tel volume. Or grub mémorise le résultat du démarrage courant dans le fichier /boot/grub/grubenv de manière à modifier le démarrage qui suit un démarrage défaillant.<br />
On peut y mettre à peu près tout … mais il vaut mieux éviter dy mettre “/boot”. Techniquement, ça doit fonctionner à peu près correctement depuis Grub 2, mais cela est encore sensible suivant la configuration, pour le moment il est vivement conseillé davoir au moins une partition de lancien temps avec “/boot” (ou “/” si le dossier “/boot” nest pas séparé) pour éviter les ennuis.</p>
<h4 id="synthèse-graphique">Synthèse graphique</h4>
<p>On peut voir les choses ainsi :</p>
<p><img src="/images/lvm01.png" alt="" /></p>
<h3 id="création">Création</h3>
<p>Puisque nous allons entrer toutes les commandes à venir en tant que root</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo -s
</code></pre></div></div>
<p>Voilà : le prompt est maintenant en mode root « # », cela nous évitera davoir à préfixer chaque commande par sudo.</p>
<p>Bonne nouvelle, les commandes LVM sont extrêmement simples à utiliser, et elles intègrent toutes une aide en ligne très bien conçue, claire, courte, mais suffisante. De plus, leurs noms se « devinent » assez facilement :</p>
<ul>
<li>toutes les commandes agissant sur les volumes physiques commencent par pv (pour physical volume);</li>
<li>toutes les commandes agissant sur les groupes de volumes commencent par vg (pour volumes group);</li>
<li>toutes les commandes agissant sur les volumes logiques commencent par lv (pour logical volume).</li>
</ul>
<p>La première chose à faire est de créer <strong>un volume physique</strong>, en attribuant une partition à LVM.</p>
<p>Essayez la commande suivante pour connaître la liste des commandes disponibles pour les volumes physiques :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>man -k pv
</code></pre></div></div>
<p>Parmi toutes les commandes renvoyées, on remarque une « pvcreate », ça doit être celle-là… ;-) Cette astuce fonctionne avec toutes les commandes LVM et permet de les retrouver facilement.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvchange (8) - change attributes of a physical volume
pvck (8) - check physical volume metadata
pvcreate (8) - initialize a disk or partition for use by LVM
pvdisplay (8) - display attributes of a physical volume
pvmove (8) - move physical extents
pvremove (8) - remove a physical volume
pvresize (8) - resize a disk or partition in use by LVM2
pvs (8) - report information about physical volumes
pvscan (8) - scan all disks for physical volumes
</code></pre></div></div>
<p>Il faudra donc créer (plutôt initier) notre volume physique par la commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvcreate /dev/sdc1
</code></pre></div></div>
<p>Cela nous permettra de lutiliser dans notre groupe de volume</p>
<p>Noter que la création dun volume physique avec un disque complet comme <code class="language-plaintext highlighter-rouge">/dev/sdc</code> nest pas recommandé : <a href="https:tldp.org/HOWTO/LVM-HOWTO/initdisks.html">https:tldp.org/HOWTO/LVM-HOWTO/initdisks.html</a></p>
<h4 id="groupe-de-volumes-1">Groupe de volumes</h4>
<p>Il existe de nombreuses options lors de la création dun groupe de volumes… Mais continuons de faire au plus simple. Le seul paramètre indispensable sera de lui donner un nom, nous utiliserons les valeurs par défaut pour tout le reste. Pour une raison que jexpliquerai par la suite, donnons-lui un nom très court (2 ou 3 caractères). Par exemple : « mvg » pour « mon vg ».</p>
<p>Pour connaitre la syntaxe de la commande vgcreate (comme pour toutes les autres commandes LVM), tapez simplement son nom :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgcreate
</code></pre></div></div>
<p>La syntaxe est donc :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgcreate VolumeGroupName PhysicalVolume [optionnellement d'autres PhysicalVolume]
</code></pre></div></div>
<p>Allons-y :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgcreate mvg /dev/sdc1
</code></pre></div></div>
<p>Si tout se passe bien, vous avez maintenant un groupe de volumes, contenant un disque physique. Vous pouvez obtenir dautres informations sur ce groupe de volumes en tapant vgdisplay:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> vgdisplay
--- Volume group ---
VG Name mvg
System ID
Format lvm2
Metadata Areas 1
Metadata Sequence No 3
VG Access read/write
VG Status resizable
MAX LV 0
Cur LV 2
Open LV 0
Max PV 0
Cur PV 1
Act PV 1
VG Size 186,31 GiB
PE Size 4,00 MiB
Total PE 47695
Alloc PE / Size 15360 / 60,00 GiB
Free PE / Size 32335 / 126,31 GiB
VG UUID BaTuai-1I8o-3rkY-Ut1r-ybta-mJnl-9X0oNZ
</code></pre></div></div>
<h4 id="volume-logique-1">Volume logique</h4>
<p>Nous y voilà… Cette fois-ci, nous allons vraiment créer deux espaces que lon pourra ensuite « formater » en ext4 par exemple.</p>
<p>Comme précédemment, le plus simple est de commencer par jeter un œil sur la syntaxe de la commande :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate
</code></pre></div></div>
<p>Les deux options vraiment importantes sont « -n » pour son nom, et « -L » pour sa taille. Le paramètre principal est « OriginalLogicalVolume ». Il sagit peut-être dune erreur dans le manuel (man). En fait, ce quil faut indiquer, cest bien le groupe de volumes dans lequel nous allons créer le volume logique. Pour lexemple présent, je fais ici deux volumes, 10 Gio et 50 Gio :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -n Vol1 -L 10g mvg
lvcreate -n Vol2 -L 50g mvg
</code></pre></div></div>
<p>Idem, on peut vérifier avec la commande lvdisplay:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> ~# lvdisplay
--- Logical volume ---
LV Name /dev/mvg/Vol1
VG Name mvg
LV UUID q0D6cQ-mcMP-q8sf-XTlI-DdxX-QHd1-qkaB5J
LV Write Access read/write
LV Status available
# open 0
LV Size 10,00 GiB
Current LE 2560
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:0
--- Logical volume ---
LV Name /dev/mvg/Vol2
VG Name mvg
LV UUID JZjMxI-cTAw-cbs6-02BM-4Mev-P2E7-b8JX0x
LV Write Access read/write
LV Status available
# open 0
LV Size 50,00 GiB
Current LE 12800
Segments 1
Allocation inherit
Read ahead sectors auto
- currently set to 256
Block device 252:1
</code></pre></div></div>
<h4 id="système-de-fichiers">Système de fichiers</h4>
<p>Avec les partitions, on avait des noms ressemblant à <code class="language-plaintext highlighter-rouge">/dev/sda3</code>, etc. Avec LVM, on utilise aussi des périphériques dans <code class="language-plaintext highlighter-rouge">/dev</code>, mais le chemin est de la forme <code class="language-plaintext highlighter-rouge">/dev/nom_du_vg/nom_du_lv</code>.
Autrement dit, puisquon a décidé dappeler nos volumes logiques “Vol1” et “Vol2”, les noms de ces périphériques de ce volume logique sont “/dev/mvg/Vol1” et “/dev/mvg/Vol2”.
À partir de maintenant, <code class="language-plaintext highlighter-rouge">/dev/mvg/Volx</code> peut être utilisé dans toutes les situations et avec toutes les commandes qui attendent quelque chose de la forme <code class="language-plaintext highlighter-rouge">/dev/…</code> Par exemple :</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code> mkfs <span class="nt">-t</span> ext4 /dev/mvg/Vol1
mkfs <span class="nt">-t</span> ext4 /dev/mvg/Vol2
<span class="nb">mkdir</span> /Essai1
mount /dev/mvg/Vol1 /Essai1
<span class="nb">df</span> <span class="nt">-h</span>
</code></pre></div></div>
<p>Et normalement, <code class="language-plaintext highlighter-rouge">/dev/mvg/Vol1</code> devrait être monté sur <code class="language-plaintext highlighter-rouge">/Essai</code>. Regardez bien la ligne correspondante. Si on avait choisi un nom de VG ou de LV plus long, la sortie de df aurait été modifiée, car le nom aurait « touché » les valeurs… On aurait été obligé de passer des lignes et laffichage aurait été plus difficile à lire. Techniquement, choisir des noms « longs » pour les VG et les LV ne pose aucun problème, mais cest laffichage qui sera parfois délicat. Pour cette raison uniquement, je préconise de se limiter à 7 caractères au total (donc par exemple 3 pour le VG et 4 pour le LV, ou 2 et 5, comme vous voulez).</p>
<blockquote>
<p>Pourquoi est-il écrit <code class="language-plaintext highlighter-rouge">/dev/mapper/mvg-Vol1</code> et non <code class="language-plaintext highlighter-rouge">/dev/mvg/Vol1</code> ?</p>
</blockquote>
<p class="info">Avec LVM en version 1, cest bien <code class="language-plaintext highlighter-rouge">/dev/mvg/Vol1</code> qui aurait été affiché. Depuis la version 2, LVM utilise le périphérique mapper, ce qui permet pas mal de choses (comme chiffrer les volumes logiques, etc.). Pour simplifier, disons que ces deux notations « /dev/mvg/Vol1 » et « /dev/mapper/mvg-Vol1 » sont synonymes. Dans la pratique, il est conseillé quand même dutiliser plutôt la forme « /dev/mvg/Vol1 », certaines commandes ne passeront pas autrement.</p>
<h3 id="suppression">Suppression</h3>
<p>Rien de plus simple :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /Essai1 # si le volume Vol1 est monté en /Essai1
lvremove /dev/mvg/Vol1
</code></pre></div></div>
<p><code class="language-plaintext warning highlighter-rouge">Attention, une fois un volume logique effacé, il est totalement impossible de récupérer les données qu'il contenait.</code></p>
<h3 id="redimensionnement">Redimensionnement</h3>
<h4 id="volume-physique-1">Volume physique</h4>
<h5 id="agrandissement">Agrandissement</h5>
<p>Imaginons maintenant que notre groupe de volume (mvg) nait plus suffisamment despace libre. On souhaite donc lui rajouter un volume physique afin de rajouter de lespace libre. Ça tombe bien, on dispose dun volume physique sdc2 que lon va pouvoir ajouter à mvg :</p>
<p>On initialise le volume en vue de son utilisation dans LVM :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvcreate /dev/sdc2
</code></pre></div></div>
<p>On rajoute le volume sdc2 au groupe de volume mvg :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgextend mvg /dev/sdc2
</code></pre></div></div>
<h5 id="rétrécissement">Rétrécissement</h5>
<p>Imaginons maintenant que la partition Boot soit devenue trop petite et que tout le reste du disque qui contient cette partition soit défini comme une partition utilisée en LVM (/dev/sda2 dans lexemple). Il sera alors nécessaire de diminuer lespace physique de ce groupe de volume (mvg).</p>
<p>En premier, il est nécessaire de rétrécir le ou les LV qui sont définis dans ce volume-groupe. Voir ci-après.</p>
<p>Puis il faut rétrécir lenveloppe physique. Normalement cest sans risque: Les commandes sont refusées si la demande est trop agressive.</p>
<p>Commençons par vérifier limplantation physique des données dans la partition. Le but est de vérifier que la fin de la partition nest pas utilisée. <code bash="">sudo pvs -v --segments /dev/sda2``` La dernière ligne de la réponse indique si la fin de la partition est libre ou non.
Si la fin de la partition n'a pas suffisamment d'espace libre, il est possible de procéder a une réorganisation physique.`sudo pvmove --alloc anywhere /dev/sda2:88888888-9999999999 /dev/sda2:0-88888887` (les valeurs 88888887 et 88888888 sont à adapter en fonction de la réponse précédente notamment la quantité d'espace libre en début de partition.
Lancer alors l'éditeur de partitions. Indiquer alors la nouvelle taille de la partition. Le minima possible est exprimé en MiO et obtenu par la formule 88888888*4</code></p>
<h4 id="volume-logique-2">Volume logique</h4>
<p>Il est très facile daugmenter ou de diminuer la taille dun volume logique. Mais attention, la taille dun LV na pas de lien direct avec la taille de ce quil contient (swap ou système de fichier). Le LV est une boîte, le système de fichier est le contenu de la boîte. Augmenter la taille de la boîte sans augmenter la taille du contenu ne pose pas de problème, mais linverse…</p>
<h5 id="agrandissement-1">Agrandissement</h5>
<p>Bien quil soit évidemment moins risqué dagrandir ou de diminuer la taille dun système de fichiers après lavoir démonté, la plupart des formats (ext3, reisersfs, ext4…) supportent désormais cette modification “à chaud” (avec des données qui restent donc accessibles en lecture/écriture durant toute lopération).</p>
<p>Pour agrandir un volume il est nécessaire de démonter le système de fichier, ici, prenons celui du volume logique Vol2 :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /Essai2
</code></pre></div></div>
<p>Maintenant nous allons ajouter 5Gio au volume et agrandir son système de fichier :
lvresize resizefs size +5G /dev/mvg/Vol2</p>
<p class="warning">Le paramètre <code class="language-plaintext highlighter-rouge">%%--%%resizefs</code> ne fonctionne pas avec tous les systèmes de fichiers (voir <a href="https:linux.die.net/man/8/fsadm">https:linux.die.net/man/8/fsadm</a>).</p>
<p>Une fois lopération terminée, le volume une fois monté a gagné 5Gio.</p>
<p>Il est également possible daugmenter la taille du volume logique à lensemble de lespace libre disponible sur le support en utilisant <strong>lvextend -l +100%FREE</strong>.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvextend <span class="nt">-l</span> +100%FREE /dev/mvg/Vol2
</code></pre></div></div>
<h5 id="rétrécissement-1">Rétrécissement</h5>
<p>Diminuer la taille dun système de fichier est un peu plus délicat. En effet, il faut dans un premier temps sassurer de pouvoir réduire dautant quon le souhaite.</p>
<p class="warning">Tous les systèmes de fichiers ne supportent pas dêtre redimensionnés (voir <a href="https:linux.die.net/man/8/fsadm">https:linux.die.net/man/8/fsadm</a>)</p>
<p>Voyons dabord lespace du système de fichier :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h -BM | grep ca
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">/dev/mapper/svg-ca 512M 230M 283M 45% /home/ca</code></p>
<p>Les valeurs qui nous intéressent sont la deuxième et la quatrième, à savoir :</p>
<ul>
<li>512Mio despace total</li>
<li>283Mio despace libre</li>
</ul>
<p>Lespace disque étant de 283Mio, nous pouvons réduire lespace de 256Mio et cest ce que nous allons faire.</p>
<p>Commençons par démonter le volume :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>umount /dev/mapper/svg-ca
</code></pre></div></div>
<p>Maintenant, nous allons retirer 256Mio :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvresize --resizefs --size -256M /dev/mapper/svg-ca
</code></pre></div></div>
<p>Si la partition nest pas démontée, la commande propose de la démonter et soccupera de la remonter une fois le redimensionnement terminé.</p>
<p>Le volume peut maintenant être monté :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount /dev/mapper/svg-ca /home/ca
</code></pre></div></div>
<p>Et on peut alors afficher sa nouvelle taille :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h -BM| grep ca
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">/dev/mapper/svg-ca 256M 230M 27M 90% /home/ca</code></p>
<p><code class="language-plaintext warning highlighter-rouge">Attention, il est possible que le rétrécissement soit refusé suite à une désorganisation qui se fait pendant la vie du LVM car la demande est trop importante</code><br />
Dans cas, voici la démarche à effectuer:</p>
<ul>
<li>Démonter le volume <code class="language-plaintext highlighter-rouge">sudo umount /dev/mapper/svg-ca</code></li>
<li>Contrôler la qualité du volume <code class="language-plaintext highlighter-rouge">sudo e2fsck -f /dev/mapper/svg-ca</code></li>
<li>Demander lespace réel minima nécessaire <code class="language-plaintext highlighter-rouge">sudo resize2fs -PM /dev/mapper/svg-ca</code></li>
<li>Rétrécir à la taille minima indiquée. Mettre la valeur retournée par la commande précédente (ou une valeur plus importante) à la place de la valeur 123456789 de cette commande <code class="language-plaintext highlighter-rouge">sudo lvresize --resizefs --size $((123456789/256+1))M /dev/mapper/svg-ca</code></li>
<li>Remonter le volume <code class="language-plaintext highlighter-rouge">mount /dev/mapper/svg-ca /home/ca</code></li>
</ul>
<h3 id="snapshot">Snapshot</h3>
<p><strong>Comprendre la magie du Snapshot LVM :</strong></p>
<p>Pourquoi donner une taille au snapshot ? Tout simplement parce que celui-ci est intelligent, donc il ne va pas copier lintégralité du LV original. Au contraire, il ne va stocker que les différences. Cest pourquoi il est instantané et commence avec une occupation taille nulle. La commande <code class="language-plaintext highlighter-rouge">lvdisplay</code> permet de voir lévolution de la taille.<br />
<strong>Avec LVM 2</strong>, les instantanés sont par défaut en lecture/écriture. Le fonctionnement est similaire aux instantanés en lecture seule avec la possibilité supplémentaire décrire sur linstantané : le bloc est alors marqué comme utilisé dans la table dexceptions et ne sera plus récupéré du volume source. Par exemple, on peut faire linstantané dun volume, le monter et tester un programme expérimental qui modifie les fichiers dessus. Si le résultat nest pas satisfaisant, on peut le démonter, le supprimer et remonter le système de fichiers originel à la place. Cest aussi utile pour créer des volumes utilisés avec Xen. Vous pouvez créer une image disque et en faire un instantané que vous pourrez modifier avec une instance spécifique de domU. Vous pourrez ensuite créer un autre instantané de limage originale et le modifier avec une autre instance de domU. Les instantanés ne stockent que les blocs modifiés. Pour <a href="#sauvegarder-son-système-à-chaud-avec-lvm">sauvegarder son système à chaud avec LVM</a></p>
<h4 id="création-dun-snapshot-lvm">Création dun snapshot LVM</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -L 10g -s -n lv_test_20110617 /dev/vg_data/lv_test
</code></pre></div></div>
<p>Va créer un snapshot du LV “<strong>lv_test</strong>” à la taille de <strong>10Go</strong> qui va avoir comme nom “<strong>lv_test_20110617</strong>”.</p>
<p class="warning">Attention, la taille dutilisation du snapshot évolue avec lutilisation. Si ce snapshot se retrouve rempli à 100%, il devient alors inutilisable (état “INACTIVE”) mais pas dinquiétude car il ny a pas dimpact pour le LV dorigine.</p>
<h4 id="redimensionnement-du-snapshot">Redimensionnement du snapshot</h4>
<p>La taille du snapshot est trop petite et elle arrive bientôt à 100%, pourtant vous avez encore besoin dutiliser ce snap ? Il faut donc redimensionner !
Vérifier avec vgdisplay que le VG dispose encore dassez despace libre (Free PE / Size) puis effectuer :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvresize -L +3GB /dev/vg_data/lv_test_20110617
</code></pre></div></div>
<p>Va ajouter <strong>3Go</strong> au snap <strong>lv_test_20110617</strong> qui est présent dans le VG <strong>vg_data</strong>.</p>
<h4 id="fusionner-un-snapshot">Fusionner un snapshot</h4>
<p>Le but ici est de fusionner un snapshot modifié vers le LV dorigine. Pour ainsi dire, “faire que les modifications apportées sur le snapshot se retrouvent sur le LV dorigine”.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvconvert --merge /path/to/dev/snap
</code></pre></div></div>
<p class="warning">Attention : vous avez besoin dun kernel (&gt;=2.6.33)</p>
<h3 id="changement-dun-disque-défectueux">Changement dun disque défectueux</h3>
<p>Votre disque /dev/sda présente des signes de faiblesse (signalés par SMART, par la présence de nombreux fichiers dans les dossiers “lost + found” de vos partitions). Vous désirez le remplacer par un disque neuf, de taille plus importante (surtout pas plus petite !), que vous avez installé dans la machine (ou sur un port USB) et qui est reconnu par le système comme étant /dev/sdb.</p>
<h4 id="principe">Principe</h4>
<p>Supposons que votre disque initial (/dev/sda) ait été formaté ainsi :<br />
/dev/sda1 est une partition primaire, de type bootable, montée sur /boot.<br />
/dev/sda2 est une partition étendue, contenant la partition logique /dev/sda5 de type lvm2.</p>
<p>Vous avez besoin de copier /dev/sda1 sur une partition /dev/sdb1, et /dev/sda5 sur une partition /dev/sdb5.</p>
<p>Vous allez utiliser loutil GParted pour préparer le disque /dev/sdb et copier la partition de boot. Gparted ne gérant pas lvm2, nous utiliserons la ligne de commande pour la copie de /dev/sda5.</p>
<h4 id="avec-gparted">Avec GParted</h4>
<p>Lancez Gparted (Système -&gt; Administration -&gt; Editeur de partitions GParted).
Les partitions de votre disque /dev/sda saffichent. Notez la taille de /dev/sda1, ainsi que son filesystem (ext2/ext3/ext4).</p>
<p>Passez au disque /dev/sdb. Créez-y une nouvelle partition primaire /dev/sdb1, de taille légèrement supérieure à celle de /dev/sda1. “Appliquez” pour que la création soit effective, puis modifiez (par clic droit) les drapeaux de /dev/sdb1 pour rendre cette partition bootable. Créez une partition étendue /dev/sdb2, occupant le reste du disque. Sur cette partition, créez une partition logique /dev/sdb5 non formatée. “Appliquez” pour que vos créations soient effectives.</p>
<p>Repassez au disque /dev/sda. Cliquez-droit sur /dev/sda1 et choisissez “Démonter” puis “Copier”. Repassez au disque /dev/sdb. Cliquez-droit sur /dev/sdb1 et choisissez “Coller” (ou “Paste”). “Appliquez” à nouveau. Fermez GParted.</p>
<h4 id="en-ligne-de-commande">En ligne de commande</h4>
<p>Remontez votre partition de boot :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mount /boot
</code></pre></div></div>
<p>Faites un scan des volumes physiques de LVM :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvscan
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PV /dev/sda5 VG delphy lvm2 [148,81 GiB / 4,87 GiB free]
Total: 1 [148,81 GiB] / in use: 1 [148,81 GiB] / in no VG: 0 [0 ]
</code></pre></div></div>
<p>Cela signifie que le volume physique (PV) /dev/sda5 est inclus dans le groupe de volumes (VG) nommé ici delphy (bien sûr le vôtre porte un autre nom).</p>
<p>Déclarez /dev/sdb5 comme volume physique :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvcreate /dev/sdb5
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Physical volume "/dev/sdb5" successfully created
</code></pre></div></div>
<p>Vérifiez quil existe bien, mais nest pas encore attribué à un groupe de volumes :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvscan
PV /dev/sda5 VG delphy lvm2 [148,81 GiB / 4,87 GiB free]
PV /dev/sdb5 lvm2 [465,47 GiB]
Total: 2 [614,28 GiB] / in use: 1 [148,81 GiB] / in no VG: 1 [465,47 GiB]
</code></pre></div></div>
<p>Attribuez /dev/sdb5 à votre groupe de volumes (ici delphy). Ce groupe de volumes est “étendu” à /dev/sdb5 :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo vgextend delphy /dev/sdb5
Volume group "delphy" successfully extended
</code></pre></div></div>
<p>Vérification :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvscan
PV /dev/sda5 VG delphy lvm2 [148,81 GiB / 4,87 GiB free]
PV /dev/sdb5 VG delphy lvm2 [465,46 GiB / 465,46 GiB free]
Total: 2 [614,27 GiB] / in use: 2 [614,27 GiB] / in no VG: 0 [0 ]
</code></pre></div></div>
<p>Lancez enfin le déplacement des données, du volume physique /dev/sda5 vers le volume physique /dev/sdb5 :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvmove /dev/sda5 /dev/sdb5
/dev/sda5: Moved: 0,3%
/dev/sda5: Moved: 0,7%
/dev/sda5: Moved: 1,0%
/dev/sda5: Moved: 1,3%
...
/dev/sda5: Moved: 99,8%
/dev/sda5: Moved: 100,0%
</code></pre></div></div>
<p class="warning">Attention, lopération peut prendre du temps (plusieurs heures pour les grosses partitions), suivant la taille des données à transférer, la rapidité des disques, etc.</p>
<p>Vérifiez que le contenu de /dev/sda5 a bien été transféré sur /dev/sdb5 :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvscan
PV /dev/sda5 VG delphy lvm2 [148,81 GiB / 148,81 GiB free]
PV /dev/sdb5 VG delphy lvm2 [465,46 GiB / 321,53 GiB free]
</code></pre></div></div>
<p>En effet, la totalité de /dev/sda5 est libre, et /dev/sdb5 est occupée par les données transférées.</p>
<p>Supprimez /dev/sda5 du groupe de volumes delphy :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo vgreduce delphy /dev/sda5
Removed "/dev/sda5" from volume group "delphy"
</code></pre></div></div>
<p>Vérifiez :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvscan
PV /dev/sdb5 VG delphy lvm2 [465,46 GiB / 321,53 GiB free]
PV /dev/sda5 lvm2 [148,81 GiB]
Total: 2 [614,28 GiB] / in use: 1 [465,46 GiB] / in no VG: 1 [148,81 GiB]
</code></pre></div></div>
<p>Enlevez le disque des volumes physiques :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo pvremove /dev/sda5
Labels on physical volume "/dev/sda5" successfully wiped
</code></pre></div></div>
<p><strong>Vous pouvez désormais enlever le disque.</strong></p>
<h4 id="finalisation">Finalisation</h4>
<p>Réinstallez GRUB sur le MBR de votre disque dur :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo grub-install /dev/sdb
</code></pre></div></div>
<p>Éteignez votre ordinateur, enlevez lancien disque et remplacez-le par le nouveau, au niveau des branchements.</p>
<h3 id="mieux-comprendre-ou-aller-plus-loin">Mieux comprendre ou aller plus loin</h3>
<h4 id="notion-extent">Notion “extent”</h4>
<p>Un extent, ou « physical extent » aussi appelé « PE », est un tout petit morceau dun groupe de volumes. En fait, au moment de la création dun groupe de volumes, le ou les disques sont découpés en morceaux de quelques Mio (4 Mio par défaut). Lorsquon crée un volume logique, LVM va utiliser autant de PE que nécessaires. La taille dun volume logique sera donc toujours un multiple de la taille dun PE.</p>
<h4 id="glossaire">Glossaire</h4>
<table>
<thead>
<tr>
<th>abrégé</th>
<th>anglais</th>
<th>français</th>
<th>description</th>
</tr>
</thead>
<tbody>
<tr>
<td>VG</td>
<td><strong>V</strong>olume <strong>G</strong>roup</td>
<td><strong>G</strong>roupe de <strong>V</strong>olumes</td>
<td> </td>
</tr>
<tr>
<td>LV</td>
<td><strong>L</strong>ogical <strong>V</strong>olume</td>
<td><strong>V</strong>olume <strong>L</strong>ogique</td>
<td>une “partition” dans un groupe de volumes</td>
</tr>
<tr>
<td>PV</td>
<td><strong>P</strong>hysical <strong>V</strong>olume</td>
<td><strong>V</strong>olume <strong>P</strong>hysique</td>
<td> </td>
</tr>
<tr>
<td>PE</td>
<td><strong>P</strong>hysical <strong>E</strong>xtent</td>
<td><strong>E</strong>tendue <strong>P</strong>hysique</td>
<td>un tout petit morceau dun groupe de volumes</td>
</tr>
</tbody>
</table>
<h4 id="lvm-et-raid">LVM et RAID</h4>
<p>Il est tout à fait possible dutiliser LVM sur un volume en RAID logiciel. Une fois que le RAID a été créé (<code class="language-plaintext highlighter-rouge">/dev/md0</code> par exemple), il suffit de le donner à LVM, avec la commande habituelle :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvcreate /dev/md0
</code></pre></div></div>
<p>Bien quil soit possible de partitionner le raid <code class="language-plaintext highlighter-rouge">/dev/md0</code> comme nimporte quel disque ordinaire (ce qui permet dobtenir des devices de la forme /dev/md0p1, /dev/md0p2 etc), je vous le déconseille vivement. En effet le but est bien dutiliser LVM pour découper lespace, et plus lancienne notion de partition physique. De plus, lutilisation de ces partitions nécessiterait des changements dans la configuration de LVM (filter dans /etc/lvm/lvm.conf). Bref, Cest se donner du mal pour pas grand chose.</p>
<p>Donc comme le montre la commande plus haut, le mieux est de donner lintégralité du RAID.</p>
<h4 id="lvm-miroir">LVM miroir</h4>
<p>Convertir un LVM en miroir</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvconvert -m 1 Volume_Group/Logical_Volume /dev/sdx1 /dev/sdy1
</code></pre></div></div>
<p>ou /dev/sdx1 est la partition LVM miroir à ajouter et /dev/sdy1 est la partition LVM de journalisation du miroir</p>
<p>Voir létat du miroir</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvs -a -o +devices
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> LV VG Attr LSize Origin Snap% Move Log Copy% Convert Devices
Logical_Volume Volume_Group mwi-a- 465.00g Logical_Volume_mlog 1.56 Home_mimage_0(0),Home_mimage_1(0)
[Logical_Volume_mimage_0] Volume_Group Iwi-ao 465.00g /dev/sdw1(0)
[Logical_Volume_mimage_1] Volume_Group Iwi-ao 465.00g /dev/sdx1(0)
[Logical_Volume_mlog] Volume_Group lwi-ao 4.00m /dev/sdy1(0)
</code></pre></div></div>
<h4 id="monter-une-partition">Monter une partition</h4>
<h5 id="obtenir-la-liste-des-groupes-logiques">Obtenir la liste des groupes logiques</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvm vgscan
</code></pre></div></div>
<h5 id="obtenir-la-liste-des-partitions">Obtenir la liste des partitions</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvm lvs
</code></pre></div></div>
<h5 id="rendre-la-partition-disponible">Rendre la partition disponible</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvm lvchange -ay /dev/VolGroup01/LogVol00
</code></pre></div></div>
<h5 id="monter-la-partition">Monter la partition</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mount /dev/VolGroup01/LogVol00 /media/user/point_de_montage
</code></pre></div></div>
<h5 id="exemple">Exemple</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>user@ubuntu:~$ sudo lvm vgscan
Reading all physical volumes. This may take a while...
Found volume group "Groupe_lvm" using metadata type lvm2
user@ubuntu:~$ sudo lvm lvs
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
home Groupe_lvm -wi-ao--- 500.00g
root Groupe_lvm -wi-a---- 20.00g
swap Groupe_lvm -wi-a---- 4.00g
user@ubuntu:~$ sudo lvm lvchange -ay /dev/Groupe_lvm/home
user@ubuntu:~$ sudo mkdir /media/user/montage
user@ubuntu:~$ sudo mount /dev/Groupe_lvm /home /media/user/montage
</code></pre></div></div>
<h4 id="vérifier-une-partition">Vérifier une partition</h4>
<h5 id="rendre-la-partition-disponible-1">Rendre la partition disponible</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvm lvchange -ay /dev/VolGroup01/LogVol00
</code></pre></div></div>
<h5 id="lancer-fsck">Lancer fsck</h5>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo fsck -f -y /dev/VolGroup01/LogVol00
</code></pre></div></div>
<h2 id="synthèse">Synthèse</h2>
<p><img src="/images/lvm_1.jpg" alt="" width="600" /></p>
<p>Les commandes (exécution en mode su)</p>
<p>Pour lister tous les périphériques visibles :</p>
<p>lvmdiskscan</p>
<p>Pour afficher les PVs créés :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvdisplay
pvs
</code></pre></div></div>
<p>Pour créer un disque physique :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvcreate /dev/sdb
</code></pre></div></div>
<p>Pour agrandir le PV à la totalité du disque physique (/dev/sdb</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvresize /dev/sdb
</code></pre></div></div>
<p>Pour savoir quels PVs sont utilisés et par qui :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvs -o+pv_used
</code></pre></div></div>
<p>Pour déplacer les données dun PV vers un autre du même VG :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvmove /dev/sdb /dev/sdc
</code></pre></div></div>
<p>Pour supprimer un PV non utilisé dun VG :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgreduce vg01 /dev/sdb
</code></pre></div></div>
<p>Pour supprimer un PV de LVM :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pvremove /dev/sdb
</code></pre></div></div>
<p>Pour créer un VG (vg01) dans le PV /dev/sdb :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgcreate vg01 /dev/sdb
</code></pre></div></div>
<p>Pour afficher les VGs créés :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgdisplay
vgs
</code></pre></div></div>
<p>Pour renommer un VG :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgrename vg01 Newvg01
</code></pre></div></div>
<p>Pour ajouter un PV à un VG :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vgextend vg01 /dev/sdc
</code></pre></div></div>
<p>Pour créer un LV de 5GB (lv01) dans le VG vg01 :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -L 5G -n lv01 vg01
</code></pre></div></div>
<p>Pour créer un LV en prenant la totalité de lespace disponible :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -l 100%FREE -n lv01 vg01
</code></pre></div></div>
<p>Pour créer un LV en prenant seulement 5% du VG :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvcreate -l 5%VG -n lv01 vg01
</code></pre></div></div>
<p>Pour afficher les LV créés :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvdisplay
lvs
</code></pre></div></div>
<p>Pour étendre un LV de 50GB :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvresize -L +50G /dev/vg01/lv01
</code></pre></div></div>
<p>Pour réduire un LV de 5% de sa taille :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvresize -l -5%LV /dev/vg01/lv01
</code></pre></div></div>
<blockquote>
<p>Attention : Lorsque vous souhaitez agrandir un LV, un VG ou un PV, il faut bien évidement vérifier la couche au dessus de lélément. Par exemple si vous voulez agrandir de 10GB le LV, il faut vérifier que le VG possède un espace non attribué de 10GB.</p>
</blockquote>
<p>Pour renommer un LV :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>lvrename lv01 Newlv01
</code></pre></div></div>
<p>Pour créer un FS dans le LV :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkfs.ext4 /dev/vg01/lv01
</code></pre></div></div>
<p>Pour redimensionner le FS dû au redimensionnement du LV :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>resize2fs /dev/vg01/lv01
</code></pre></div></div>
<p>Pour monter un répertoire dans le LV :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mkdir /data01
mount /dev/vg01/lv01 /data01
</code></pre></div></div>
<h2 id="sauvegarder-son-système-à-chaud-avec-lvm">Sauvegarder son système à chaud avec LVM</h2>
<h3 id="pré-requis-2">Pré-requis</h3>
<ul>
<li>Disposer des droits dadministration</li>
<li>Avoir son fichier racine / à sauvegarder dans un volume logique (lvm)</li>
<li>Avoir un peu despace disque disponible</li>
</ul>
<h3 id="vérifications-préalables">Vérifications préalables</h3>
<p>Vérifier que nous disposons despace libre pour la sauvegarde et le snapshot dans notre volume group.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo vgs
VG #PV #LV #SN Attr VSize VFree
corsair 1 4 0 wz--n- 29,81g 18,32g
</code></pre></div></div>
<p>Ici notre groupe de volumes appelé “corsair” possède 18Go despace disponible</p>
<h3 id="création-du-volume-de-sauvegarde">Création du volume de sauvegarde</h3>
<p>On cherche a savoir quelle taille de données on va sauvegarder</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h /
Sys. de fichiers Taille Uti. Disp. Uti% Monté sur
/dev/mapper/corsair-maracine 4,0G 1,8G 2,0G 47% /
</code></pre></div></div>
<p>Nous devons sauvegarder un peu moins de 2Go</p>
<p>Création dun volume de sauvegarde</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo lvcreate -n monbackup -L 2G corsair
Logical volume "monbackup" created
</code></pre></div></div>
<p>Un nouveau volume appelé monbackup dune taille de 2Go est créé dans le groupe de volume “corsair”</p>
<p>Création dun systeme de fichiers</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkfs.ext4 /dev/corsair/monbackup
</code></pre></div></div>
<p>Nous avons choisi ext4, mais il pourrait en être autrement.</p>
<p>Montage du FileSystem de backup</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir /ma_sauvegarde
sudo mount /dev/corsair/monbackup /ma_sauvegarde
</code></pre></div></div>
<p>Voila, nous avons notre File System /ma_sauvegarde qui pourra accueillir la sauvegarde.</p>
<h3 id="snapshot-et-copie">Snapshot et copie</h3>
<p>Faire un snapshot du système de fichiers racine / afin de pouvoir copier les données tranquillement.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo sync &amp;&amp; sudo lvcreate -s -n monsnapshot -L 2G corsair/maracine
</code></pre></div></div>
<p>Le volume de snapshot (temporaire) sappelle “monsnapshot”. En général, 2Go suffisent pour un snapshot de quelques heures de vie. Si le filesystem racine est beaucoup accédé/modifié, il faudra ajuster cette taille à la hausse.</p>
<p>Montage du snapshot</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo mkdir /mon_snapshot
sudo mount /dev/corsair/monsnapshot /mon_snapshot
</code></pre></div></div>
<p>Ici nous avons donc une image fixe de / qui se trouve dans /mon_snapshot, nous pouvons la copier.</p>
<ul>
<li>Copie des données</li>
</ul>
<p>sudo cp -ax /mon_snapshot/* /ma_sauvegarde/</p>
<p>Nous avons donc copié notre snapshot dans notre volume de sauvegarde !</p>
<p>Suppression du snapshot</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo umount /mon_snapshot
sudo lvremove corsair/monsnapshot
Do you really want to remove active logical volume monsnapshot? [y/n]: y
Logical volume "monsnapshot" successfully removed
</code></pre></div></div>
<h3 id="finitions">Finitions</h3>
<p>Les étapes précédentes nous permettent davoir un volume “monbackup” qui est une copie de la racine /</p>
<p>Pour pouvoir rendre cette copie bootable, il faut rendre la fstab cohérente :</p>
<p>Modifier la fstab et changer le nom du volume de / par celui de la sauvegarde.<br />
Dans notre exemple, il faudra remplacer “maracine” par “monbackup”</p>
<p>Editer le fichier /ma_sauvegarde/etc/fstab :</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/dev/mapper/corsair-monbackup / ext4 errors=remount-ro 0 1
</code></pre></div></div>
<p>Enfin, ajouter notre sauvegarde au menu boot de grub.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo update-grub
</code></pre></div></div>
</div>
<div class="d-print-none"><footer class="article__footer"><meta itemprop="dateModified" content="2018-10-27T00:00:00+02:00"><!-- start custom article footer snippet -->
<!-- end custom article footer snippet -->
<!--
<div align="right"><a type="application/rss+xml" href="/feed.xml" title="S'abonner"><i class="fa fa-rss fa-2x"></i></a>
&emsp;</div>
-->
</footer>
<div class="article__section-navigator clearfix"><div class="previous"><span>PRÉCÉDENT</span><a href="/2018/10/25/RECOLL-outil-de-recherche-textuelle-Linux.html">RECOLL outil de recherche textuelle pour Unix et Linux</a></div><div class="next"><span>SUIVANT</span><a href="/2018/10/27/logrotate.html">Logrotate, outil de gestion des fichiers "log"</a></div></div></div>
</div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
$(function() {
var $this ,$scroll;
var $articleContent = $('.js-article-content');
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var scroll = hasSidebar ? '.js-page-main' : 'html, body';
$scroll = $(scroll);
$articleContent.find('.highlight').each(function() {
$this = $(this);
$this.attr('data-lang', $this.find('code').attr('data-lang'));
});
$articleContent.find('h1[id], h2[id], h3[id], h4[id], h5[id], h6[id]').each(function() {
$this = $(this);
$this.append($('<a class="anchor d-print-none" aria-hidden="true"></a>').html('<i class="fas fa-anchor"></i>'));
});
$articleContent.on('click', '.anchor', function() {
$scroll.scrollToAnchor('#' + $(this).parent().attr('id'), 400);
});
});
});
})();
</script>
</div><section class="page__comments d-print-none"></section></article><!-- start custom main bottom snippet -->
<!-- end custom main bottom snippet -->
</div>
</div></div></div></div>
</div><script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $body = $('body'), $window = $(window);
var $pageRoot = $('.js-page-root'), $pageMain = $('.js-page-main');
var activeCount = 0;
function modal(options) {
var $root = this, visible, onChange, hideWhenWindowScroll = false;
var scrollTop;
function setOptions(options) {
var _options = options || {};
visible = _options.initialVisible === undefined ? false : show;
onChange = _options.onChange;
hideWhenWindowScroll = _options.hideWhenWindowScroll;
}
function init() {
setState(visible);
}
function setState(isShow) {
if (isShow === visible) {
return;
}
visible = isShow;
if (visible) {
activeCount++;
scrollTop = $(window).scrollTop() || $pageMain.scrollTop();
$root.addClass('modal--show');
$pageMain.scrollTop(scrollTop);
activeCount === 1 && ($pageRoot.addClass('show-modal'), $body.addClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.on('scroll', hide);
$window.on('keyup', handleKeyup);
} else {
activeCount > 0 && activeCount--;
$root.removeClass('modal--show');
$window.scrollTop(scrollTop);
activeCount === 0 && ($pageRoot.removeClass('show-modal'), $body.removeClass('of-hidden'));
hideWhenWindowScroll && window.hasEvent('touchstart') && $window.off('scroll', hide);
$window.off('keyup', handleKeyup);
}
onChange && onChange(visible);
}
function show() {
setState(true);
}
function hide() {
setState(false);
}
function handleKeyup(e) {
// Char Code: 27 ESC
if (e.which === 27) {
hide();
}
}
setOptions(options);
init();
return {
show: show,
hide: hide,
$el: $root
};
}
$.fn.modal = modal;
});
})();
</script><div class="modal modal--overflow page__search-modal d-print-none js-page-search-modal"><script>
(function () {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
// search panel
var search = (window.search || (window.search = {}));
var useDefaultSearchBox = window.useDefaultSearchBox === undefined ?
true : window.useDefaultSearchBox ;
var $searchModal = $('.js-page-search-modal');
var $searchToggle = $('.js-search-toggle');
var searchModal = $searchModal.modal({ onChange: handleModalChange, hideWhenWindowScroll: true });
var modalVisible = false;
search.searchModal = searchModal;
var $searchBox = null;
var $searchInput = null;
var $searchClear = null;
function getModalVisible() {
return modalVisible;
}
search.getModalVisible = getModalVisible;
function handleModalChange(visible) {
modalVisible = visible;
if (visible) {
search.onShow && search.onShow();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].focus();
} else {
search.onShow && search.onHide();
useDefaultSearchBox && $searchInput[0] && $searchInput[0].blur();
setTimeout(function() {
useDefaultSearchBox && ($searchInput.val(''), $searchBox.removeClass('not-empty'));
search.clear && search.clear();
window.pageAsideAffix && window.pageAsideAffix.refresh();
}, 400);
}
}
$searchToggle.on('click', function() {
modalVisible ? searchModal.hide() : searchModal.show();
});
// Char Code: 83 S, 191 /
$(window).on('keyup', function(e) {
if (!modalVisible && !window.isFormElement(e.target || e.srcElement) && (e.which === 83 || e.which === 191)) {
modalVisible || searchModal.show();
}
});
if (useDefaultSearchBox) {
$searchBox = $('.js-search-box');
$searchInput = $searchBox.children('input');
$searchClear = $searchBox.children('.js-icon-clear');
search.getSearchInput = function() {
return $searchInput.get(0);
};
search.getVal = function() {
return $searchInput.val();
};
search.setVal = function(val) {
$searchInput.val(val);
};
$searchInput.on('focus', function() {
$(this).addClass('focus');
});
$searchInput.on('blur', function() {
$(this).removeClass('focus');
});
$searchInput.on('input', window.throttle(function() {
var val = $(this).val();
if (val === '' || typeof val !== 'string') {
search.clear && search.clear();
} else {
$searchBox.addClass('not-empty');
search.onInputNotEmpty && search.onInputNotEmpty(val);
}
}, 400));
$searchClear.on('click', function() {
$searchInput.val(''); $searchBox.removeClass('not-empty');
search.clear && search.clear();
});
}
});
})();
</script><div class="search search--dark">
<div class="main">
<div class="search__header">Recherche</div>
<div class="search-bar">
<div class="search-box js-search-box">
<div class="search-box__icon-search"><i class="fas fa-search"></i></div>
<input id="search-input" type="text" />
<div class="search-box__icon-clear js-icon-clear">
<a><i class="fas fa-times"></i></a>
</div>
</div>
<button class="button button--theme-dark button--pill search__cancel js-search-toggle">
Annuler</button>
</div>
<div id="results-container" class="search-result js-search-result"></div>
</div>
</div>
<!-- Script pointing to search-script.js -->
<script>/*!
* Simple-Jekyll-Search
* Copyright 2015-2020, Christian Fei
* Licensed under the MIT License.
*/
(function(){
'use strict'
var _$Templater_7 = {
compile: compile,
setOptions: setOptions
}
const options = {}
options.pattern = /\{(.*?)\}/g
options.template = ''
options.middleware = function () {}
function setOptions (_options) {
options.pattern = _options.pattern || options.pattern
options.template = _options.template || options.template
if (typeof _options.middleware === 'function') {
options.middleware = _options.middleware
}
}
function compile (data) {
return options.template.replace(options.pattern, function (match, prop) {
const value = options.middleware(prop, data[prop], options.template)
if (typeof value !== 'undefined') {
return value
}
return data[prop] || match
})
}
'use strict';
function fuzzysearch (needle, haystack) {
var tlen = haystack.length;
var qlen = needle.length;
if (qlen > tlen) {
return false;
}
if (qlen === tlen) {
return needle === haystack;
}
outer: for (var i = 0, j = 0; i < qlen; i++) {
var nch = needle.charCodeAt(i);
while (j < tlen) {
if (haystack.charCodeAt(j++) === nch) {
continue outer;
}
}
return false;
}
return true;
}
var _$fuzzysearch_1 = fuzzysearch;
'use strict'
/* removed: const _$fuzzysearch_1 = require('fuzzysearch') */;
var _$FuzzySearchStrategy_5 = new FuzzySearchStrategy()
function FuzzySearchStrategy () {
this.matches = function (string, crit) {
return _$fuzzysearch_1(crit.toLowerCase(), string.toLowerCase())
}
}
'use strict'
var _$LiteralSearchStrategy_6 = new LiteralSearchStrategy()
function LiteralSearchStrategy () {
this.matches = function (str, crit) {
if (!str) return false
str = str.trim().toLowerCase()
crit = crit.trim().toLowerCase()
return crit.split(' ').filter(function (word) {
return str.indexOf(word) >= 0
}).length === crit.split(' ').length
}
}
'use strict'
var _$Repository_4 = {
put: put,
clear: clear,
search: search,
setOptions: __setOptions_4
}
/* removed: const _$FuzzySearchStrategy_5 = require('./SearchStrategies/FuzzySearchStrategy') */;
/* removed: const _$LiteralSearchStrategy_6 = require('./SearchStrategies/LiteralSearchStrategy') */;
function NoSort () {
return 0
}
const data = []
let opt = {}
opt.fuzzy = false
opt.limit = 10
opt.searchStrategy = opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = NoSort
opt.exclude = []
function put (data) {
if (isObject(data)) {
return addObject(data)
}
if (isArray(data)) {
return addArray(data)
}
return undefined
}
function clear () {
data.length = 0
return data
}
function isObject (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray (obj) {
return Boolean(obj) && Object.prototype.toString.call(obj) === '[object Array]'
}
function addObject (_data) {
data.push(_data)
return data
}
function addArray (_data) {
const added = []
clear()
for (let i = 0, len = _data.length; i < len; i++) {
if (isObject(_data[i])) {
added.push(addObject(_data[i]))
}
}
return added
}
function search (crit) {
if (!crit) {
return []
}
return findMatches(data, crit, opt.searchStrategy, opt).sort(opt.sort)
}
function __setOptions_4 (_opt) {
opt = _opt || {}
opt.fuzzy = _opt.fuzzy || false
opt.limit = _opt.limit || 10
opt.searchStrategy = _opt.fuzzy ? _$FuzzySearchStrategy_5 : _$LiteralSearchStrategy_6
opt.sort = _opt.sort || NoSort
opt.exclude = _opt.exclude || []
}
function findMatches (data, crit, strategy, opt) {
const matches = []
for (let i = 0; i < data.length && matches.length < opt.limit; i++) {
const match = findMatchesInObject(data[i], crit, strategy, opt)
if (match) {
matches.push(match)
}
}
return matches
}
function findMatchesInObject (obj, crit, strategy, opt) {
for (const key in obj) {
if (!isExcluded(obj[key], opt.exclude) && strategy.matches(obj[key], crit)) {
return obj
}
}
}
function isExcluded (term, excludedTerms) {
for (let i = 0, len = excludedTerms.length; i < len; i++) {
const excludedTerm = excludedTerms[i]
if (new RegExp(excludedTerm).test(term)) {
return true
}
}
return false
}
/* globals ActiveXObject:false */
'use strict'
var _$JSONLoader_2 = {
load: load
}
function load (location, callback) {
const xhr = getXHR()
xhr.open('GET', location, true)
xhr.onreadystatechange = createStateChangeListener(xhr, callback)
xhr.send()
}
function createStateChangeListener (xhr, callback) {
return function () {
if (xhr.readyState === 4 && xhr.status === 200) {
try {
callback(null, JSON.parse(xhr.responseText))
} catch (err) {
callback(err, null)
}
}
}
}
function getXHR () {
return window.XMLHttpRequest ? new window.XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
}
'use strict'
var _$OptionsValidator_3 = function OptionsValidator (params) {
if (!validateParams(params)) {
throw new Error('-- OptionsValidator: required options missing')
}
if (!(this instanceof OptionsValidator)) {
return new OptionsValidator(params)
}
const requiredOptions = params.required
this.getRequiredOptions = function () {
return requiredOptions
}
this.validate = function (parameters) {
const errors = []
requiredOptions.forEach(function (requiredOptionName) {
if (typeof parameters[requiredOptionName] === 'undefined') {
errors.push(requiredOptionName)
}
})
return errors
}
function validateParams (params) {
if (!params) {
return false
}
return typeof params.required !== 'undefined' && params.required instanceof Array
}
}
'use strict'
var _$utils_9 = {
merge: merge,
isJSON: isJSON
}
function merge (defaultParams, mergeParams) {
const mergedOptions = {}
for (const option in defaultParams) {
mergedOptions[option] = defaultParams[option]
if (typeof mergeParams[option] !== 'undefined') {
mergedOptions[option] = mergeParams[option]
}
}
return mergedOptions
}
function isJSON (json) {
try {
if (json instanceof Object && JSON.parse(JSON.stringify(json))) {
return true
}
return false
} catch (err) {
return false
}
}
var _$src_8 = {};
(function (window) {
'use strict'
let options = {
searchInput: null,
resultsContainer: null,
json: [],
success: Function.prototype,
searchResultTemplate: '<li><a href="{url}" title="{desc}">{title}</a></li>',
templateMiddleware: Function.prototype,
sortMiddleware: function () {
return 0
},
noResultsText: 'No results found',
limit: 10,
fuzzy: false,
debounceTime: null,
exclude: []
}
let debounceTimerHandle
const debounce = function (func, delayMillis) {
if (delayMillis) {
clearTimeout(debounceTimerHandle)
debounceTimerHandle = setTimeout(func, delayMillis)
} else {
func.call()
}
}
const requiredOptions = ['searchInput', 'resultsContainer', 'json']
/* removed: const _$Templater_7 = require('./Templater') */;
/* removed: const _$Repository_4 = require('./Repository') */;
/* removed: const _$JSONLoader_2 = require('./JSONLoader') */;
const optionsValidator = _$OptionsValidator_3({
required: requiredOptions
})
/* removed: const _$utils_9 = require('./utils') */;
window.SimpleJekyllSearch = function (_options) {
const errors = optionsValidator.validate(_options)
if (errors.length > 0) {
throwError('You must specify the following required options: ' + requiredOptions)
}
options = _$utils_9.merge(options, _options)
_$Templater_7.setOptions({
template: options.searchResultTemplate,
middleware: options.templateMiddleware
})
_$Repository_4.setOptions({
fuzzy: options.fuzzy,
limit: options.limit,
sort: options.sortMiddleware,
exclude: options.exclude
})
if (_$utils_9.isJSON(options.json)) {
initWithJSON(options.json)
} else {
initWithURL(options.json)
}
const rv = {
search: search
}
typeof options.success === 'function' && options.success.call(rv)
return rv
}
function initWithJSON (json) {
_$Repository_4.put(json)
registerInput()
}
function initWithURL (url) {
_$JSONLoader_2.load(url, function (err, json) {
if (err) {
throwError('failed to get JSON (' + url + ')')
}
initWithJSON(json)
})
}
function emptyResultsContainer () {
options.resultsContainer.innerHTML = ''
}
function appendToResultsContainer (text) {
options.resultsContainer.innerHTML += text
}
function registerInput () {
options.searchInput.addEventListener('input', function (e) {
if (isWhitelistedKey(e.which)) {
emptyResultsContainer()
debounce(function () { search(e.target.value) }, options.debounceTime)
}
})
}
function search (query) {
if (isValidQuery(query)) {
emptyResultsContainer()
render(_$Repository_4.search(query), query)
}
}
function render (results, query) {
const len = results.length
if (len === 0) {
return appendToResultsContainer(options.noResultsText)
}
for (let i = 0; i < len; i++) {
results[i].query = query
appendToResultsContainer(_$Templater_7.compile(results[i]))
}
}
function isValidQuery (query) {
return query && query.length > 0
}
function isWhitelistedKey (key) {
return [13, 16, 20, 37, 38, 39, 40, 91].indexOf(key) === -1
}
function throwError (message) {
throw new Error('SimpleJekyllSearch --- ' + message)
}
})(window)
}());
</script>
<!-- Configuration -->
<script>
SimpleJekyllSearch({
searchInput: document.getElementById('search-input'),
resultsContainer: document.getElementById('results-container'),
noResultsText: '<p>Aucun résultat!</p>',
json: '/search.json',
searchResultTemplate: '<li><a href="{url}">{date}&nbsp;{title}</a>&nbsp;(Création {create})</li>'
})
</script>
</div></div>
<script>(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function scrollToAnchor(anchor, duration, callback) {
var $root = this;
$root.animate({ scrollTop: $(anchor).position().top }, duration, function() {
window.history.replaceState(null, '', window.location.href.split('#')[0] + anchor);
callback && callback();
});
}
$.fn.scrollToAnchor = scrollToAnchor;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function affix(options) {
var $root = this, $window = $(window), $scrollTarget, $scroll,
offsetBottom = 0, scrollTarget = window, scroll = window.document, disabled = false, isOverallScroller = true,
rootTop, rootLeft, rootHeight, scrollBottom, rootBottomTop,
hasInit = false, curState;
function setOptions(options) {
var _options = options || {};
_options.offsetBottom && (offsetBottom = _options.offsetBottom);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroll && (scroll = _options.scroll);
_options.disabled !== undefined && (disabled = _options.disabled);
$scrollTarget = $(scrollTarget);
isOverallScroller = window.isOverallScroller($scrollTarget[0]);
$scroll = $(scroll);
}
function preCalc() {
top();
rootHeight = $root.outerHeight();
rootTop = $root.offset().top + (isOverallScroller ? 0 : $scrollTarget.scrollTop());
rootLeft = $root.offset().left;
}
function calc(needPreCalc) {
needPreCalc && preCalc();
scrollBottom = $scroll.outerHeight() - offsetBottom - rootHeight;
rootBottomTop = scrollBottom - rootTop;
}
function top() {
if (curState !== 'top') {
$root.removeClass('fixed').css({
left: 0,
top: 0
});
curState = 'top';
}
}
function fixed() {
if (curState !== 'fixed') {
$root.addClass('fixed').css({
left: rootLeft + 'px',
top: 0
});
curState = 'fixed';
}
}
function bottom() {
if (curState !== 'bottom') {
$root.removeClass('fixed').css({
left: 0,
top: rootBottomTop + 'px'
});
curState = 'bottom';
}
}
function setState() {
var scrollTop = $scrollTarget.scrollTop();
if (scrollTop >= rootTop && scrollTop <= scrollBottom) {
fixed();
} else if (scrollTop < rootTop) {
top();
} else {
bottom();
}
}
function init() {
if(!hasInit) {
var interval, timeout;
calc(true); setState();
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState();
});
$window.on('resize', function() {
disabled || (calc(true), setState());
});
hasInit = true;
}
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions,
refresh: function() {
calc(true, { animation: false }); setState();
}
};
}
$.fn.affix = affix;
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
function toc(options) {
var $root = this, $window = $(window), $scrollTarget, $scroller, $tocUl = $('<ul class="toc toc--ellipsis"></ul>'), $tocLi, $headings, $activeLast, $activeCur,
selectors = 'h1,h2,h3', container = 'body', scrollTarget = window, scroller = 'html, body', disabled = false,
headingsPos, scrolling = false, hasRendered = false, hasInit = false;
function setOptions(options) {
var _options = options || {};
_options.selectors && (selectors = _options.selectors);
_options.container && (container = _options.container);
_options.scrollTarget && (scrollTarget = _options.scrollTarget);
_options.scroller && (scroller = _options.scroller);
_options.disabled !== undefined && (disabled = _options.disabled);
$headings = $(container).find(selectors).filter('[id]');
$scrollTarget = $(scrollTarget);
$scroller = $(scroller);
}
function calc() {
headingsPos = [];
$headings.each(function() {
headingsPos.push(Math.floor($(this).position().top));
});
}
function setState(element, disabled) {
var scrollTop = $scrollTarget.scrollTop(), i;
if (disabled || !headingsPos || headingsPos.length < 1) { return; }
if (element) {
$activeCur = element;
} else {
for (i = 0; i < headingsPos.length; i++) {
if (scrollTop >= headingsPos[i]) {
$activeCur = $tocLi.eq(i);
} else {
$activeCur || ($activeCur = $tocLi.eq(i));
break;
}
}
}
$activeLast && $activeLast.removeClass('active');
($activeLast = $activeCur).addClass('active');
}
function render() {
if(!hasRendered) {
$root.append($tocUl);
$headings.each(function() {
var $this = $(this);
$tocUl.append($('<li></li>').addClass('toc-' + $this.prop('tagName').toLowerCase())
.append($('<a></a>').text($this.text()).attr('href', '#' + $this.prop('id'))));
});
$tocLi = $tocUl.children('li');
$tocUl.on('click', 'a', function(e) {
e.preventDefault();
var $this = $(this);
scrolling = true;
setState($this.parent());
$scroller.scrollToAnchor($this.attr('href'), 400, function() {
scrolling = false;
});
});
}
hasRendered = true;
}
function init() {
var interval, timeout;
if(!hasInit) {
render(); calc(); setState(null, scrolling);
// run calc every 100 millisecond
interval = setInterval(function() {
calc();
}, 100);
timeout = setTimeout(function() {
clearInterval(interval);
}, 45000);
window.pageLoad.then(function() {
setTimeout(function() {
clearInterval(interval);
clearTimeout(timeout);
}, 3000);
});
$scrollTarget.on('scroll', function() {
disabled || setState(null, scrolling);
});
$window.on('resize', window.throttle(function() {
if (!disabled) {
render(); calc(); setState(null, scrolling);
}
}, 100));
}
hasInit = true;
}
setOptions(options);
if (!disabled) {
init();
}
$window.on('resize', window.throttle(function() {
init();
}, 200));
return {
setOptions: setOptions
};
}
$.fn.toc = toc;
});
})();
/*(function () {
})();*/
</script><script>
/* toc must before affix, since affix need to konw toc' height. */(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
var TOC_SELECTOR = window.TEXT_VARIABLES.site.toc.selectors;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window);
var $articleContent = $('.js-article-content');
var $tocRoot = $('.js-toc-root'), $col2 = $('.js-col-aside');
var toc;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
var hasToc = $articleContent.find(TOC_SELECTOR).length > 0;
function disabled() {
return $col2.css('display') === 'none' || !hasToc;
}
tocDisabled = disabled();
toc = $tocRoot.toc({
selectors: TOC_SELECTOR,
container: $articleContent,
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
tocDisabled = disabled();
toc && toc.setOptions({
disabled: tocDisabled
});
}, 100));
});
})();
(function() {
var SOURCES = window.TEXT_VARIABLES.sources;
window.Lazyload.js(SOURCES.jquery, function() {
var $window = $(window), $pageFooter = $('.js-page-footer');
var $pageAside = $('.js-page-aside');
var affix;
var tocDisabled = false;
var hasSidebar = $('.js-page-root').hasClass('layout--page--sidebar');
affix = $pageAside.affix({
offsetBottom: $pageFooter.outerHeight(),
scrollTarget: hasSidebar ? '.js-page-main' : null,
scroller: hasSidebar ? '.js-page-main' : null,
scroll: hasSidebar ? $('.js-page-main').children() : null,
disabled: tocDisabled
});
$window.on('resize', window.throttle(function() {
affix && affix.setOptions({
disabled: tocDisabled
});
}, 100));
window.pageAsideAffix = affix;
});
})();
</script><!---->
</div>
<script>(function () {
var $root = document.getElementsByClassName('root')[0];
if (window.hasEvent('touchstart')) {
$root.dataset.isTouch = true;
document.addEventListener('touchstart', function(){}, false);
}
})();
</script>
</body>
</html>