<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>https://wiki.alex-master.com/index.php?feed=atom&amp;namespace=0&amp;title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F%3A%D0%9D%D0%BE%D0%B2%D1%8B%D0%B5_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B</id>
		<title>VAAL-WIKI - Новые страницы [ru]</title>
		<link rel="self" type="application/atom+xml" href="https://wiki.alex-master.com/index.php?feed=atom&amp;namespace=0&amp;title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F%3A%D0%9D%D0%BE%D0%B2%D1%8B%D0%B5_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B"/>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%9D%D0%BE%D0%B2%D1%8B%D0%B5_%D1%81%D1%82%D1%80%D0%B0%D0%BD%D0%B8%D1%86%D1%8B"/>
		<updated>2026-04-16T14:06:12Z</updated>
		<subtitle>Материал из VAAL-WIKI</subtitle>
		<generator>MediaWiki 1.24.2</generator>

	<entry>
		<id>https://wiki.alex-master.com/index.php/5_Bitcoin_Casino_List</id>
		<title>5 Bitcoin Casino List</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/5_Bitcoin_Casino_List"/>
				<updated>2021-10-22T16:58:20Z</updated>
		
		<summary type="html">&lt;p&gt;Eracornet70: Новая страница: «[https://www.instapaper.com/p/bodyease61 www.Goldbitcoincasino.com] &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;div id=&amp;quot;toc&amp;quot; style=&amp;quot;background: #f9f9f9;border: 1px solid #aaa;displa…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://www.instapaper.com/p/bodyease61 www.Goldbitcoincasino.com] &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;div id=&amp;quot;toc&amp;quot; style=&amp;quot;background: #f9f9f9;border: 1px solid #aaa;display: table;margin-bottom: 1em;padding: 1em;width: 350px;&amp;quot;&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;p class=&amp;quot;toctitle&amp;quot; style=&amp;quot;font-weight: 700;text-align: center;&amp;quot;&amp;gt;Content&amp;lt;/p&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;ul class=&amp;quot;toc_list&amp;quot;&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;li&amp;gt; [#toc-0 20+ Additional Bitcoin Casinos Reviewed] &amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;li&amp;gt; [#toc-1 Provably Fair] &amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;But since there are quite a lot of cryptocurrency portals, there is not always time to look for the most satisfactory option. It happens that because of this, some gamblers are content with the first gambling resource they come across, and this is sad. We will provide you with a list of the most respectable and developed bitcoin casinos according to our version. You will have to choose only the best of the best, which will allow you to gamble with cryptocurrency with the maximum return. Among those are FortuneJack, Satoshi Casino, CloudBet, mBit, BitCasino, Bovada Casino, and Primedice.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Considering that the network governs itself, the safety of the currency is second to none.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Unfortunately, residents of the United States, the United Kingdom and various other countries are restricted.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Only the most experienced online gambling venues have Bitcoin, Litecoin, Ethereum, or any other crypto at their disposal.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Being well established they’re available in the UK, Canada, France, Spain, Japan, Thailand and a dozen other countries are accepted.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Players can prove that a casino game is fair by entering ID and other information.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Each day, a handful of different slots games developed by Playson are included in the “Game of the Day” promotion.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;When selecting a casino, you need to be aware of the concept of wagering requirements. This is a minimum amount of wagering you need to do before you can cash out any winnings from your bonus. For example, if you havea $100 bonus with wagering requirements of ‘35 times’ then you will need to wager $3,500 before you can cash out your winnings. Before you choose a Bitcoin casino for its bonuses, check on the rollover requirements. There’s no point of claiming a humongous amount of reward that claims you roll it over 80 times or a one that won’t allow you to withdraw more than you have deposited. Some bonuses, may, well, too good to be true, and, yes, sometimes they are not valid.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Last but definitely not least, how well is the online support of the casino. Fortunately this can be tested very easily by opening a ticket before spending a dime at the casino. A well supported Bitcoin casino will have multiple support channels such as social media, email support and an online chat with a rep ready to answer your questions right away. There are 2000+ games on mBit Casino and online support is available as well in the form of a chatroom. There is a robust support system to the website in the form on online ticketing, online chat and several social channels as well.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h2 id=&amp;quot;toc-0&amp;quot;&amp;gt;20+ Additional Bitcoin Casinos Reviewed&amp;lt;/h2&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;We also assess how fast and reliable these systems are in practice. Withdrawal and deposit times, along with fees or limits, are all evaluated before each of the crypto casinos can be considered for a listing on this site. There are a lot of factors that go into making a good gambling site, but to be called one of the top Bitcoin casinos, none are more important than customer support.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;MBit is considered one of the most respected crypto casinos in the world as it guarantees payouts. The number of available games on this crypto casino is humongous. There are 5,000+ games from 34 well-known providers like Microgaming and NetEnt. Their game selection includes slots, roulette, baccarat, blackjack, poker, and video poker. Like all good crypto betting sites, FortuneJack asks for minimal information during registration.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;That said, the site’s help articles are so comprehensive that you’ll probably find the answer to your query without any support. While we’d like mBitcasino to include a phone line, the site’s customer service options are more than satisfactory. 7Bit offers numerous welcome bonuses along with a very popular loyalty program. The site was launched back in 2014 and is owned and ran by Direx N.V. Casinos.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Another reason why eToro is the best option is that it offers a regulated cryptocurrency wallet. So after you buy Bitcoin you can keep some funds safe on eToro’s wallet and transfer the rest to your chosen Bitcoin casino. Withdrawals can be intitiated within your account section on the website in a few mouse clicks.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h3 id=&amp;quot;toc-1&amp;quot;&amp;gt;Provably Fair&amp;lt;/h3&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;If you reach higher score than the dealer without exceeding 21, you are the winner. If you want to read more, check our special article on Bitcoin slots. Table games include card games like Blackjack, Poker, Baccarat and Red dog. Roulette is often categorized as a table game or a random number game.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;We also recommend you avoid buying coins from anyone over a forum. You wouldn’t know who you were dealing with, and you may find that they fail to deliver on their promise. Beware of other Bitcoin casinos not on this list, as they might now be trustworthy. Overall, playing on the best BTC casinos has lots of benefits. If you bet $10,000 worth of BTC and win $2,000, it won’t feel like much of a win if the price of Bitcoin sinks so much that your withdrawal is only worth $5,000. This is why choosing a licensed BTC casino becomes even more important.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;You will be able to play slots, jackpots, table games, live casino games and more. Loki Casino is licensed and regulated under Antillephone N.V. The casino features a variety of slot games, roulette, poker and table games. While gambling is done in BTC, Bitcoin Casino will accept deposits in a variety of cryptocurrencies, including LTC, DOGE and ETH.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h2 id=&amp;quot;toc-2&amp;quot;&amp;gt;Where Can I Buy Bitcoin To Play At A Casino?&amp;lt;/h2&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Although PlayAmo accepts Bitcoin, all bonuses are represented in fiat currencies . We like the fact that you can activate your welcome bonus immediately after registration, which reduces the chance of any problems when you’re claiming it. Like most sites, Cloudbet also offers customer service via email.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;It’s commonplace these days for almost everything on the web to offer a mobile version. While many casinos have developed apps you can download onto your mobile device, many others have taken the mobile-optimized approach to their website. Some online casinos only accept the coin because of this fact. Players can make deposits faster at an Ethereum casino than they can at a Bitcoin casino. The fees that come along with this crypto are generally noticably smaller than those for bitcoin as well.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Eracornet70</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/10_Crypto_Casino</id>
		<title>10 Crypto Casino</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/10_Crypto_Casino"/>
				<updated>2021-10-22T16:57:26Z</updated>
		
		<summary type="html">&lt;p&gt;Eracornet70: Новая страница: «[https://www.instapaper.com/p/homeease20 http://www.GoldBitcoinCasino.com/] &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;div id=&amp;quot;toc&amp;quot; style=&amp;quot;background: #f9f9f9;border: 1px solid #aa…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://www.instapaper.com/p/homeease20 http://www.GoldBitcoinCasino.com/] &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;div id=&amp;quot;toc&amp;quot; style=&amp;quot;background: #f9f9f9;border: 1px solid #aaa;display: table;margin-bottom: 1em;padding: 1em;width: 350px;&amp;quot;&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;p class=&amp;quot;toctitle&amp;quot; style=&amp;quot;font-weight: 700;text-align: center;&amp;quot;&amp;gt;Content&amp;lt;/p&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;ul class=&amp;quot;toc_list&amp;quot;&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;li&amp;gt; [#toc-0 Write My Essay: The Best Cheap And Free Online Services] &amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;li&amp;gt; [#toc-1 Red Dog Casino] &amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The site offers both casino and sports betting under the same platform and has great bonuses to go along with it. We try to keep it updated with current bonuses and promotions. It’s not uncommon to receive no deposit bonuses on your email, once you have registered your account. Bitcoin sportsbooks make it easier than ever to bet on different matches. It’s both easier and cheaper to bet with Bitcoin instead of fiat currencies on regular gambling sites. Bonuses and promotions can differ widely between various Bitcoin casinos and betting sites.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;As hard as they are to win, it’s the main goal of all players for a reason. A jackpot can either have a set value or be of the progressive kind. A progressive jackpot means that it will increase the more rounds are being played and lost. Most of the biggest jackpot games have all their machines connected around the world, meaning their jackpot value can reach astronomical numbers. All good Bitcoin casinos need to have a decent library of Bitcoin table games . At BitStarz we’ve got an incredible library of Bitcoin table games from some of the best providers around.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;100% best customer service I have experienced with any online casino.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;MBit is considered one of the most respected crypto casinos in the world as it guarantees payouts.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Simply put, this site covers all the bases of what goes into making a great crypto platform.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;No bonus codes are needed, just go to the site using the links on this page to get the bonuses.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Bonus policy allows you to get more cryptocurrency for the game.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The relatively recent registration of this service did not prevent it from developing and gaining the attention of players from all over the world. Bitstarz is fast becoming one of the best bitcoin casinos in the industry. This proven fair casino offers over 1000 fair games and accepts various cryptocurrencies for deposits. Users appreciate this service for accepting a great number of fiat currencies and cryptocurrencies. It offers a large list of funds for withdrawing winnings. Also, users note the speed of payments, namely instant deposits and withdrawals.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;There are many advantages of playing at a Bitcoin casino too, such as no banks can ban you from depositing at a Bitcoin casino. Bitcoin casino reviews are extremely helpful in discovering any shady dealings that a Bitcoin live casino might be involved in. Just as well, there are many review aggregate sites out there that are specifically dedicated to reviewing online casinos.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h2 id=&amp;quot;toc-0&amp;quot;&amp;gt;Write My Essay: The Best Cheap And Free Online Services&amp;lt;/h2&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The catalog includes a good selection of slots and card games. Online casino gambling is illegal in various countries despite significant regulation. However, if you’re looking for something even better, how about playing your favorite casino games online?&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h3 id=&amp;quot;toc-1&amp;quot;&amp;gt;Red Dog Casino&amp;lt;/h3&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Bitcoin casinos offer bigger winnings to players – As Bitcoin casinos have lower costs than regular online casinos, they can offer better payouts. In addition, there are Bitcoin casino no deposit bonuses! Bonuses and promotions are a way for casino sites to advertise themselves and get new players. Bitcoin is anonymous, has fast transactions, extremely low fees, and no tax issues. Bitcoin casino is the smart alternative to regular casino sites. Blackjack is probably the most recognized casino game in the world today.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Our BTC Casino offer a range of video Slots, Blackjack, Roulette, Video Poker, Live Casino as well as our Exclusive games for Bitcoin gambling. If you bet $10,000 worth of BTC and win $2,000, it won’t feel like much of a win if the price of Bitcoin sinks so much that your withdrawal is only worth $5,000. If you feel you’ve been scammed, you can always request your credit card provider to perform a chargeback, allowing you to recoup your funds. They then pass on some of these savings to you in the form of frequent bonuses and promotions. Cryptocurrency helps them save money on deposit and payout fees, chargeback fees, and more.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Here are some of the most commonly offered coins accepted at online casinos. A no-deposit bonus is a rare bonus offered by crypto and bitcoin casinos. Simply put, it’s a bonus that doesn’t require a deposit to be claimed. No deposit bonuses are usually much smaller than traditional welcome bonuses. This makes sense, as it doesn’t require any kind of financial commitment.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Since no authority controls the market, the gaming sites don’t have to pay licensing and other fees. At the same time, Bitcoin is almost entirely anonymous, which has both pros and cons. No third party has access to your personal and financial information.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Keep in mind that many online casinos, especially those that aren’t extremely crypto-friendly, will not provide this service. Many online casinos that promote their use of Bitcoin will charge a fee for selling Bitcoin for the purpose of depositing cash. To put it simply, the cryptology behind Bitcoin ensures that all Bitcoin users can enjoy anonymity on their terms. With that security in mind, you can enjoy even more security when you consider online casinos with hefty safety and privacy measures.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;This is exactly what you get when you play at Bitcoin.com Games. Depositing and playing at our Bitcoin casino is really easy and straightforward. Our bitcoin casino is operated by the most trusted brand in the industry.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Eracornet70</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/10_Btc_Betting_Sites</id>
		<title>10 Btc Betting Sites</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/10_Btc_Betting_Sites"/>
				<updated>2021-10-22T16:49:52Z</updated>
		
		<summary type="html">&lt;p&gt;Eracornet70: Новая страница: «[https://www.inventables.com/users/borupwoods1323 http://www.goldbitcoincasino.com/] &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;div id=&amp;quot;toc&amp;quot; style=&amp;quot;background: #f9f9f9;border: 1px…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[https://www.inventables.com/users/borupwoods1323 http://www.goldbitcoincasino.com/] &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;div id=&amp;quot;toc&amp;quot; style=&amp;quot;background: #f9f9f9;border: 1px solid #aaa;display: table;margin-bottom: 1em;padding: 1em;width: 350px;&amp;quot;&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;p class=&amp;quot;toctitle&amp;quot; style=&amp;quot;font-weight: 700;text-align: center;&amp;quot;&amp;gt;Content&amp;lt;/p&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;ul class=&amp;quot;toc_list&amp;quot;&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;li&amp;gt; [#toc-0 Reason #4btc Is Better For Line Shopping] &amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;li&amp;gt; [#toc-1 Selecting Best Btc Sports Betting Sites For You] &amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;   &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;/ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;We consider BlockChain to be the best Bitcoin wallet for online gambling. However, it is important to note that it is just one of many options available. When the transaction is completed and the currency is in your account, you are just a few short steps from using BTC for online gambling. Bitcoin payouts are processed quicker than any other method. Some sites offer automatic withdrawals and players are paid in a matter of seconds. Almost all withdrawals with cryptocurrencies are processed in 24 hours or less.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Crypto bonuses starting from 125% to 150% are available, along with a 150% casino bonus and a flat 50% bonus on reload.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;Bitcoin only sportsbooks, because they don’t have the long history and experience of established books, don’t offer bettors the same bets and odds that traditional books do.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;li&amp;gt;You will just have to transfer them to a different wallet or exchange.&amp;lt;/li&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;  &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt; &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;/ul&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Every sportsbook that we recommend above not only accepts Bitcoin, but also has a long, proven history of reliability, sound financial planning, and top-notch customer service. Given their upstanding reputations, we are confident that these sportsbooks are safe options for your money and your Bitcoin. GTbets subjects Bitcoin bets, deposits, and withdrawals to the same rules as their traditional financial methods to ensure their clients’ safety and security. FortuneJack is also the best choice if you’re looking for a crypto gambling site that is dedicated to only using cryptocurrencies. With support for 9 different cryptocurrencies, and no need to verify your identity to play, FortuneJack is the go-to exchange for crypto enthusiasts who want to protect their identity.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Games like Dota 2 and sports betting on sports on this website can be managed easily. This Cyprus-based company has been providing betting services for four years. It is one of the few sportsbooks to allow users a chance at preventing their losses by diversifying their bets. The operator not only offers a broad choice of sports and casino related games to wager on, but it also gives a generous deposit bonus and accepts a variety of payment methods. Its odds are likewise competitive, and participants may choose from a variety of markets. Payment methods offered by online betting with BTC are mostly digital.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h2 id=&amp;quot;toc-0&amp;quot;&amp;gt;Reason #4btc Is Better For Line Shopping&amp;lt;/h2&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Many casino sites will enable you to deposit your money with Bitcoin but later convert it to fiat currency. You can then gamble in fiat, and once you cash out the funds are then converted back to BTC. The problem with this is you do lose on exchange rates on both ends. This is why we only recommend casinos that offer pure BTC betting. Without having to deal with banks and card providers, sportsbooks save time and money on both deposits and withdrawals. Plus, if the price of Bitcoin appreciates — which it has more often than not during its history— the betting sites value goes up based on how much digital currency it owns.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Their “Welcome Package” goes as high as 7 BTC (when you register just use the promo code “1xb_13206”). So if you win big and are restricted to one withdrawal a week, by the time you withdraw everything, crypto may have made it worth less than it was at the time of you winning big. If that happens, and if the crypto sportsbook you chose is trustworthy, you can relax and withdraw the maximum amount allowed each week until all your winnings are withdrawn. Once you’ve selected a platform you trust to bet with cryptocurrency, make sure it has the payout speeds and terms you need when cashing out your winnings.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;The website also offers an excellent sign-up bonus to new bettors, along with rollover promotions. Nitrogen Sports provides reliable odds with the best betting options for almost every sport and premier league on the planet. The player gets better privacy and a highly responsive customer support service. The platform only offers hot, online cold storage of crypto assets, which is risky. The biggest advantage of betting with Bitcoin is the higher profit margins.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;h3 id=&amp;quot;toc-1&amp;quot;&amp;gt;Selecting Best Btc Sports Betting Sites For You&amp;lt;/h3&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Coinbase isn’t the ideal exchange for gamblers, and we encourage bettors to seek out other alternatives if they happen to get banned for gambling transactions. Bans often happen when users make the mistake of sending their newly purchased Bitcoins at Coinbase directly to an online betting site . Coinbase charges the same fees for selling bitcoins into US Dollars as they do for buying them from a US bank account. Converting Bitcoins back into fiat currency is done through exchanges like Coinbase, but cannot be done through wallets.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;However, Bitcoin is pretty close and doesn’t require bettors to reveal too much of their personal information. Once you make the deposit on the betting site, you will have to actually transfer the BTC from your wallet. The Bitcoin blockchain will process the request in a maximum of fifteen minutes, and the betting site will take it from there. Sportsbetting.ag offers the same initial welcome bonus for Bitcoin bettors. And then they continue to offer a whopping 35% on all qualifying BTC deposits thereafter.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;Our expert reviews the best Bitcoin gambling sites of 2021. Discover the leading trusted online Bitcoin &amp;amp;amp; crypto casinos here. BetCoin AG is a company that runs one of the best live betting services in the world. The website is designed for best Bitcoin sports bettors and supports almost every main market in the live betting domain. Games and sports from many smaller markets are also available here.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;It’s even come to rival that of traditional betting sites, such as Coral and Betfair. Just like regular betting, these bets can be placed on anything from a game outcome, to how many points are scored in the first half. Betmaster is precisely what Indian bettors want when they search for crypto sports betting sites.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;This allows some of them, like 1xBit and Betcoin, to operate anonymously and accept players worldwide. If they accept players from a restricted country -- one for which they haven’t received an authorization to operate as a bookmaker -- then they might receive heavy sanctions . Such financial privacy keeps your activities hidden from your banks, credit rating agencies, and let’s be honest, your spouse/husband too, so you can bet bitcoin in peace. We’re living in a digital age that’s taking betting to the digital world too.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;In this guide, you’ll find everything you need to know on how to place a bet with BTC safely. Mortal Kombat X is a multi-platform fighting game by NetherRealm Studios for Xbox One, PlayStation 4, Microsoft Windows, iOS, and Android gaming platforms. From recently, gamblers from the whole world can use bitcoins for betting in this game. It combines elements of the best real-time strategy and traditional role-playing video games. Two teams, each of which has unique abilities, fight in opposition to each other in different game modes and on various maps. Given the unlimited possibility of improving the player’s skills, League of Legends cannot be won as a regular video game.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Eracornet70</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Expr</id>
		<title>Expr</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Expr"/>
				<updated>2019-03-02T11:02:36Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Добавил страницу &amp;quot;expr&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''expr''' — команда для вычисления арифметических выражений.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
&amp;lt;code bash&amp;gt;expr ВЫРАЖЕНИЯ&amp;lt;/code&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;code bash&amp;gt;expr OPTION&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Выражения == &lt;br /&gt;
Выражения состоят из аргументов отделяемых пробелами и могут принимать следующий вид:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; &lt;br /&gt;
| '''''Выражение''''' || '''''Результат'''''&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;|&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;'''arg1''', если он не пустой и не ''0'', в противном случае '''arg2'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;&amp;amp;&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;'''arg1''', если ни один аргумент не равен нулю или ''0'', в противном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;&amp;lt;&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;''1'', если '''arg1''' меньше '''arg2''', в обратном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;&amp;lt;=&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;''1'', если '''arg1''' меньше или равен '''arg2''', в обратном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;=&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;''1'', если '''arg1''' равен '''arg2''',  в обратном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;!=&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;''1'', если '''arg1''' не равен '''arg2''', в обратном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;&amp;gt;=&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;''1'', если '''arg1''' больше или равен '''arg2''', в обратном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;&amp;gt;&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;''1'', если '''arg1''' больше '''arg2''', в обратном случае ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;+&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Арифметическая сумма '''arg1''' и '''arg2'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;-&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Арифметическая разность '''arg1''' и '''arg2'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;*&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Арифметическое произведение '''arg1''' и '''arg2'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;/&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Арифметическое частное от деления '''arg1''' на '''arg2'''&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''arg1''' &amp;lt;nowiki&amp;gt;&amp;quot;%&amp;quot;&amp;lt;/nowiki&amp;gt; '''arg2'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Арифметический остаток от деления '''arg1''' на '''arg2'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''STRING''' &amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt; '''REGEXP'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Верно, если найдена маска '''REGEXP''' в строке '''STRING'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;match '''STRING REGEXP'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Тоже что и '''STRING : REGEXP'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;substr '''STRING POS LENGTH'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Подстрока из '''STRING''', первая позиция нумеруется как ''1''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;index '''STRING CHARS'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Позиция вхождения символа '''CHARS''' в строке '''STRING''', если найден, иначе ''0''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;length '''STRING'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Длина строки '''STRING'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;+ '''TOKEN'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Интерпретировать '''TOKEN''' как строку, даже если это ключевое слово '''match''' или оператор '''/'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;'''( EXPRESSION )'''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Значение выражения '''EXPRESSION'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Следует помнить, что операторы должны быть '''экранированы''' или заключены в '''кавычки'''. ''Арифметическое сравнение'' допустимо только для '''чисел''', иначе сравнивается, как '''текст'''. '''Сопоставление''' с '''шаблоном''' возвращает строку между \( и \) или нуль; если \( и \) не используются, то возвращается число совпавших символов или 0.&lt;br /&gt;
&lt;br /&gt;
Статус вычисления выражения устанавливается в:&amp;lt;br/&amp;gt;&lt;br /&gt;
* 0, если выражение не пустое и не 0;&lt;br /&gt;
* 1, если выражение равно нулю или 0;&lt;br /&gt;
* 2, если выражение синтаксически неверно;&lt;br /&gt;
* 3, если произошла ошибка.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Iproute2</id>
		<title>Iproute2</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Iproute2"/>
				<updated>2018-02-28T07:13:58Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''iproute2''' — это набор '''утилит''' для управления параметрами сетевых устройств в ядре ''Linux'…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''iproute2''' — это набор '''утилит''' для управления параметрами сетевых устройств в ядре ''Linux''. Эти утилиты были разработаны в качестве унифицированного интерфейса к ядру ''Linux'', которое непосредственно управляет сетевым трафиком.&lt;br /&gt;
&lt;br /&gt;
== Основные сведения ==&lt;br /&gt;
&lt;br /&gt;
''iproute2'' заменил полный набор классических сетевых утилит UNIX, которые ранее использовались для настройки сетевых интерфейсов, таблиц маршрутизации и управления arp‐таблицами: [[ifconfig]], [[route]], [[ARP|arp]], [[netstat]] и других, предназначенных для создания IP‐туннелей. ''iproute2'' предлагает унифицированный синтаксис для управления самыми разными аспектами сетевых интерфейсов. Этот синтаксис во многом проще и логичнее, чем синтаксис наследованных *nix утилит, и подобен синтаксису операционной системы ''Cisco IOS'''.&lt;br /&gt;
&lt;br /&gt;
Набор утилит включает в себя три основные программы:&lt;br /&gt;
&lt;br /&gt;
* '''ip''' — утилита для просмотра параметров и конфигурирования сетевых интерфейсов, сетевых адресов, таблиц маршрутизации, правил маршрутизации, arp‐таблиц, IP‐туннелей, адресов multicast рассылки, маршрутизацией multicast пакетов.&lt;br /&gt;
&lt;br /&gt;
* '''tc''' — утилита для просмотра и конфигурирования параметров управления трафиком (tc — аббревиатура от traffic control). Позволяет управлять классификацией трафика, дисциплинами управления очередями для различных классов трафика либо целиком для сетевого интерфейса (корневые дисциплины), что, в свою очередь, позволяет реализовать [[QoS]] в нужном для системы объёме:&lt;br /&gt;
** разделение разных типов трафика по классам (не только по битам [[ToS]] в [[IP‐пакет]]е, но и по другим данным из заголовка IP‐пакета)&lt;br /&gt;
** назначение разных дисциплин обработки очередей трафика с разным приоритетом, механизмами прохождения очереди, ограничениями по скорости и т. п.&lt;br /&gt;
&lt;br /&gt;
* '''ss''' — утилита для просмотра текущих соединений и открытых портов. Аналог традиционной утилиты [[netstat]].&lt;br /&gt;
&lt;br /&gt;
Автором ''iproute2'' является Алексей Кузнецов (Alexey Kuznetsov). Он разработал этот пакет, когда занимался расширением сетевых возможностей ядра Linux.&lt;br /&gt;
&lt;br /&gt;
== Утилита ip ==&lt;br /&gt;
'''ip''' — утилита командной строки из пакета ''iproute2'' для систем ''Linux''. Она позволяет выполнять настройку сетевой подсистемы и является заменой таких утилит как: [[ifconfig]], [[route]], [[ARP|arp]]. В следующей таблице показаны предлагаемые замены.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+Соответствие утилит из устаревшего пакета net-tools утилитам пакета iproute2&lt;br /&gt;
!Устаревшая утилита&lt;br /&gt;
!Заменена на&lt;br /&gt;
!Описание&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ifconfig&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ip addr&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ip link&amp;lt;/code&amp;gt;&lt;br /&gt;
|Настройка сетевого адреса, включение и выключение интерфейса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;route&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ip route&amp;lt;/code&amp;gt;&lt;br /&gt;
|Управление таблицами маршрутизации&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;arp&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ip neigh&amp;lt;/code&amp;gt;&lt;br /&gt;
|Управление [[ARP]]-кэшем&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;iptunnel&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ip tunnel&amp;lt;/code&amp;gt;&lt;br /&gt;
|Настройка тоннелей&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;nameif&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ifrename&amp;lt;/code&amp;gt;&lt;br /&gt;
|Переименование сетевого интерфейса&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;ipmaddr&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ip maddr&amp;lt;/code&amp;gt;&lt;br /&gt;
|Настройка [[мультикаст]]-групп рассылки&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;code&amp;gt;netstat&amp;lt;/code&amp;gt;&lt;br /&gt;
|&amp;lt;code&amp;gt;ip -s&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ss&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ip route&amp;lt;/code&amp;gt;&lt;br /&gt;
|Отображение различной сетевой статистики&lt;br /&gt;
|}&lt;br /&gt;
Для выполнения какой-либо операции после основной команды ip, указывается «объект» и команда (возможно с аргументами), которая должна быть выполнена для этого объекта.&lt;br /&gt;
&lt;br /&gt;
В качестве «объектов» можно указывать следующие значения: link, addr (адреса сетевых интерфейсов), route (маршруты), rule (правила), neigh, ntable, tunnel (тоннели), maddr, mroute, monitor, xfrm. Вместо полного имени объекта можно указывать только первые буквы, если это не вызывает неоднозначность.&lt;br /&gt;
&lt;br /&gt;
Можно указать команду &amp;lt;tt&amp;gt;help&amp;lt;/tt&amp;gt;, для вывода подсказки. Если не указывать объект, но указать команду &amp;lt;tt&amp;gt;help&amp;lt;/tt&amp;gt;, то выводится справка о программе. Если указать объект без команды, то выполняется команда &amp;lt;tt&amp;gt;show&amp;lt;/tt&amp;gt; — распечатывается список объектов указанного типа.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Примеры использования утилит из пакета iproute2 &amp;quot;&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable collapsible&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Команда&lt;br /&gt;
! Комментарий&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip help&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
| Вывод общей справки&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip a h&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
&amp;lt;pre&amp;gt;Usage: ip addr {add|change|replace} IFADDR dev STRING [ LIFETIME ]&lt;br /&gt;
                                                      [ CONFFLAG-LIST]&lt;br /&gt;
       ip addr del IFADDR dev STRING&lt;br /&gt;
       ip addr {show|flush} [ dev STRING ] [ scope SCOPE-ID ]&lt;br /&gt;
                            [ to PREFIX ] [ FLAG-LIST ] [ label PATTERN ]&lt;br /&gt;
IFADDR := PREFIX | ADDR peer PREFIX&lt;br /&gt;
          [ broadcast ADDR ] [ anycast ADDR ]&lt;br /&gt;
          [ label STRING ] [ scope SCOPE-ID ]&lt;br /&gt;
SCOPE-ID := [ host | link | global | NUMBER ]&lt;br /&gt;
FLAG-LIST := [ FLAG-LIST ] FLAG&lt;br /&gt;
FLAG  := [ permanent | dynamic | secondary | primary |&lt;br /&gt;
           tentative | deprecated | CONFFLAG-LIST ]&lt;br /&gt;
CONFFLAG-LIST := [ CONFFLAG-LIST ] CONFFLAG&lt;br /&gt;
CONFFLAG  := [ home | nodad ]&lt;br /&gt;
LIFETIME := [ valid_lft LFT ] [ preferred_lft LFT ]&lt;br /&gt;
LFT := forever | SECONDS&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Распечатка подсказки — команд и их аргументов для объекта addr. &amp;lt;br /&amp;gt;'''Заметьте, что вместо слов addr и help указаны сокращения.'''&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip a&amp;lt;/tt&amp;gt;''' &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 16436 qdisc noqueue&lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo&lt;br /&gt;
    inet6 ::1/128 scope host&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
2: eth1: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast qlen 1000&lt;br /&gt;
    link/ether 00:16:17:eb:a9:da brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 172.22.2.1/16 brd 172.22.255.255 scope global eth1&lt;br /&gt;
    inet6 fe80::216:17ff:feeb:a9da/64 scope link&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
3: eth2: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast qlen 1000&lt;br /&gt;
    link/ether 00:16:17:eb:d3:20 brd ff:ff:ff:ff:ff:ff&lt;br /&gt;
    inet 10.19.121.211/22 brd 10.19.123.255 scope global eth2&lt;br /&gt;
    inet6 fe80::216:17ff:feeb:d320/64 scope link&lt;br /&gt;
       valid_lft forever preferred_lft forever&lt;br /&gt;
5: ppp0: &amp;lt;POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP&amp;gt; mtu 1492 qdisc pfifo_fast qlen 3&lt;br /&gt;
    link/ppp&lt;br /&gt;
    inet 89.37.48.117 peer 81.9.101.117/32 scope global ppp0&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Распечатка всех (физических и виртуальных интерфейсов). Для сравнения приводится информацией, выводимая командой &amp;lt;tt&amp;gt;ifconfig -a&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;eth1      Link encap:Ethernet  HWaddr 00:16:17:EB:A9:DA&lt;br /&gt;
          inet addr:172.22.2.1  Bcast:172.22.255.255  Mask:255.255.0.0&lt;br /&gt;
          inet6 addr: fe80::216:17ff:feeb:a9da/64 Scope:Link&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1&lt;br /&gt;
          RX packets:13444859 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:7073798 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000&lt;br /&gt;
          RX bytes:2540456241 (2422.7 Mb)  TX bytes:916670636 (874.2 Mb)&lt;br /&gt;
          Interrupt:16 Base address:0x2000&lt;br /&gt;
&lt;br /&gt;
eth2      Link encap:Ethernet  HWaddr 00:16:17:EB:D3:20&lt;br /&gt;
          inet addr:10.19.121.211  Bcast:10.19.123.255  Mask:255.255.252.0&lt;br /&gt;
          inet6 addr: fe80::216:17ff:feeb:d320/64 Scope:Link&lt;br /&gt;
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1&lt;br /&gt;
          RX packets:266115675 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:409606457 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:1000&lt;br /&gt;
          RX bytes:294857473 (281.1 Mb)  TX bytes:109522306 (104.4 Mb)&lt;br /&gt;
          Interrupt:17 Base address:0x4000&lt;br /&gt;
&lt;br /&gt;
lo        Link encap:Local Loopback&lt;br /&gt;
          inet addr:127.0.0.1  Mask:255.0.0.0&lt;br /&gt;
          inet6 addr: ::1/128 Scope:Host&lt;br /&gt;
          UP LOOPBACK RUNNING  MTU:16436  Metric:1&lt;br /&gt;
          RX packets:3480203 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:3480203 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:0&lt;br /&gt;
          RX bytes:1531400801 (1460.4 Mb)  TX bytes:1531400801 (1460.4 Mb)&lt;br /&gt;
&lt;br /&gt;
ppp0      Link encap:Point-to-Point Protocol&lt;br /&gt;
          inet addr:89.37.48.117  P-t-P:81.9.101.117  Mask:255.255.255.255&lt;br /&gt;
          UP POINTOPOINT RUNNING NOARP MULTICAST  MTU:1492  Metric:1&lt;br /&gt;
          RX packets:46940444 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
          TX packets:66480329 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
          collisions:0 txqueuelen:3&lt;br /&gt;
          RX bytes:3859205550 (3680.4 Mb)  TX bytes:1343026828 (1280.8 Mb)&amp;lt;/pre&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip link&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
&amp;lt;pre&amp;gt;1: lo: &amp;lt;LOOPBACK,UP,LOWER_UP&amp;gt; mtu 16436 qdisc noqueue state UNKNOWN &lt;br /&gt;
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00&lt;br /&gt;
2: eth0: &amp;lt;BROADCAST,MULTICAST,UP,LOWER_UP&amp;gt; mtu 1500 qdisc pfifo_fast state UP qlen 1000&lt;br /&gt;
    link/ether 00:16:d4:b3:68:de brd ff:ff:ff:ff:ff:ff&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Вывод информации об интерфейсах. Напоминает данные, выводимые об адресах, но намного короче, так как указываются только [[MAC-адрес|физические адреса]] интерфейсов и не выводятся логические [[IP]]/[[IPv6]].&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip rou&amp;lt;/tt&amp;gt;'''&amp;lt;pre&amp;gt;81.9.101.117 dev ppp0  proto kernel  scope link  src 89.37.48.117&lt;br /&gt;
10.19.120.0/22 dev eth2  proto kernel  scope link  src 10.19.121.211&lt;br /&gt;
172.22.0.0/16 dev eth1  proto kernel  scope link  src 172.22.2.1&lt;br /&gt;
127.0.0.0/8 dev lo  scope link&lt;br /&gt;
default via 81.9.101.117 dev ppp0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Список сетевых маршрутов.&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip ro flush cache&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
| Очистка кэша маршрутов.&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip ro add 81.9.100.12   via 89.37.48.117 dev ppp0&amp;lt;/tt&amp;gt;'''&lt;br /&gt;
| Добавление нового маршрута.&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip ru&amp;lt;/tt&amp;gt;'''&amp;lt;pre&amp;gt;0:      from all lookup local&lt;br /&gt;
32764:  from 192.168.72.115 lookup co-tbl&lt;br /&gt;
32765:  from 89.37.48.117 lookup zet-tbl&lt;br /&gt;
32766:  from all lookup main&lt;br /&gt;
32767:  from all lookup default&amp;lt;/pre&amp;gt;&lt;br /&gt;
| Распечатка правил маршрутизации. Заметьте что в данном случае используются несколько таблиц маршрутизации.&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;tt&amp;gt;ip t&amp;lt;/tt&amp;gt;''' &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;tunl0: ip/ip  remote any  local any  ttl inherit  nopmtudisc&lt;br /&gt;
&amp;lt;/tt&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;gre0: gre/ip  remote any  local any  ttl inherit  nopmtudisc&amp;lt;/tt&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;sit0: ipv6/ip  remote any  local any  ttl 64  nopmtudisc&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Распечатка списка тоннелей.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [https://web.archive.org/web/20140623231840/http://www.linuxfoundation.org/collaborate/workgroups/networking/iproute2 Текущий официальный сайт]&lt;br /&gt;
* [http://ubuntologia.ru/forum/viewtopic.php?f=109&amp;amp;t=2300 Продолжение по мотивам статьи для системных администраторов старой закалки, которая поможет перейти на ''iproute2'' с legacy-утилит]&lt;br /&gt;
* [https://habrahabr.ru/post/320278/ Тяжелое расставание с Net-Tools, Хабрахабр, Микаел temujin Григорян]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Ifconfig</id>
		<title>Ifconfig</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Ifconfig"/>
				<updated>2018-02-28T06:59:24Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''ifconfig''' (сокр. '''i'''nter'''f'''ace '''config'''uration) — команда UNIXи UNIX‐подобных операционных систем.  ==…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''ifconfig''' (сокр. '''i'''nter'''f'''ace '''config'''uration) — команда UNIXи UNIX‐подобных операционных систем.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
 ifconfig [interface]&lt;br /&gt;
 ifconfig interface [aftype] options | address ...&lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
Команда &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; - аналог '''ipconfig''' Windows, с другими ключевыми параметрами и ''более широким функционалом''. Используется для назначения сетевого адреса, изменения настроек параметров сетевого адаптера и ''IP'' протокола. Она используется в большинстве ''*nix'' систем на этапе загрузки операционной системы для настройки сетевых интерфейсов. После этого она обычно используется только при отладке, настройке или восстановлении системы.&lt;br /&gt;
&lt;br /&gt;
При вызове '''''man ifconfig''''' (для '''FreeBSD''') — выводится полное руководство о параметрах команды.&lt;br /&gt;
&lt;br /&gt;
Если аргументы не переданы, &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; выдаёт информацию о состоянии активных интерфейсов. Если указан один аргумент — '''интерфейс''', выдаётся информация только о состоянии этого '''интерфейса'''; если указан один аргумент &amp;lt;tt&amp;gt;-a&amp;lt;/tt&amp;gt;, выдаётся информация о состоянии всех '''интерфейсов''', даже отключенных. Иначе команда конфигурирует указанный '''интерфейс'''.&lt;br /&gt;
&lt;br /&gt;
В современных дистрибутивах ''Linux'' утилита &amp;lt;tt&amp;gt;ifconfig&amp;lt;/tt&amp;gt; считается устаревшей и заменена утилитой [[iproute2]], основные функции настроек сетевого '''интерфейса''' получила утилита ip из состава [[iproute2]]. Для ''Unix'' систем не потеряло актуальности.&lt;br /&gt;
&lt;br /&gt;
== Семейство протоколов ==&lt;br /&gt;
Если первым после имени интерфейса идёт имя поддерживаемого семейства адресов, это семейство адресов используется для декодирования и выдачи всех адресов протокола. В настоящее время поддерживаются семейства адресов inet (TCP/IP, используется по умолчанию), inet6 (IPv6), ax25 (AMPR Packet Radio), ddp (Appletalk Phase 2), ipx (Novell [[IPX]]) и netrom (AMPR Packet Radio).&lt;br /&gt;
&lt;br /&gt;
== Опции ==&lt;br /&gt;
&lt;br /&gt;
{| align=&amp;quot;center&amp;quot; class=&amp;quot;standard&amp;quot;&lt;br /&gt;
|+&lt;br /&gt;
|-----&lt;br /&gt;
! |Опция&lt;br /&gt;
! |Описание&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''interface'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Имя интерфейса. Обычно это имя драйвера, за которым идет номер устройства, например, eth0 для первого интерфейса Ethernet.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''up'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Помечает интерфейс как включенный. Это можно использовать для включения интерфейса после ifconfig down. Это происходит автоматически при установке первого адреса интерфейса. Если интерфейс был переустановлен при предыдущей пометке в качестве отключенного, аппаратное обеспечение будет переинициализировано.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''down'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Помечает интерфейс как отключенный. Когда интерфейс помечен как отключенный, система не пытается пересылать сообщения через этот интерфейс. При возможности, интерфейс будет переустановлен, чтобы отключить также прием. Это действие не отключает автоматически маршруты, использующие данный интерфейс.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''arp'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Включает использование протокола разрешения адреса ([[ARP|Address Resolution Protocol]]) при сопоставлении адресов на уровне сети и адресов на уровне связи (используется по умолчанию). В настоящее время это реализуется путём сопоставления адресов DARPA Internet и адресов Ethernet 10 Мбит/с.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''-arp'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Отключает использование протокола разрешения адреса ([[ARP|Address Resolution Protocol]]).''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''promisc'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Помещает интерфейс в состояние promiscuous. В широковещательной сети это заставляет интерфейс получать все пакеты независимо от того, были ли они предназначены для этой машины или нет. Это позволяет, используя фильтры пакетов, анализировать сетевой трафик. Обычно, это хорошая техника охоты на сетевые проблемы, которые иначе трудно отловить. Здесь весьма полезна утилита [[tcpdump]]. С другой стороны, это позволяет хакерам исследовать движение паролей по сети и делать другие черные дела. Одна защита против этого типа нападения: не позволять присоединяться к сети чужим компьютерам. Другой способ: использовать безопасные опознавательные протоколы, типа Kerberos, или SRA login. Эта опция соответствует флагу PROMISC.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''-promisc'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Запрещает режим promiscuous.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''allmulti'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Включает или отключает режим all-multicast. В этом режиме все многоадресные (multicast) пакеты в сети будут приниматься этим интерфейсом.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''-allmulti'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Отключает режим all-multicast.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''metric N'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает стоимость маршрутизации для интерфейса равной n, вместо стандартного значения 0. Стоимость маршрутизации (routing metric) используется протоколом маршрутизации (см. [[routed]]). Большие стоимости делают маршрут менее предпочтительным; стоимости учитываются как дополнительные пересылки на пути к целей сети или хосту.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''mtu N'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Этот параметр устанавливает максимальный размер пакета ([[maximum transmission unit]] — MTU) для интерфейса. Обычно нет необходимости менять значение этого параметра, но, в некоторых случаях, уменьшение значения MTU позволяет добиться устойчивой работы абонентов с очень низким уровнем сигнала. Кроме того, он может использоваться для изменения параметров туннельных интерфейсов.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''dstaddr addr'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает удаленный IP-адрес для двухточечной связи (например, по протоколу [[PPP (сетевой протокол)|PPP]]). Это ключевое слово сейчас считается устаревшим; используйте вместо него ключевое слово pointopoint.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''netmask addr'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает маску сети IP для этого интерфейса. По умолчанию используется обычная маска сети класса A, B или C (что определяется по IP-адресу интерфейса), но можно установить любое значение.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''add addr/prefixlen'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Добавляет адрес IPv6 для интерфейса.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''del addr/prefixlen'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Удаляет адрес IPv6 для интерфейса.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''tunnel aa.bb.cc.dd'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Создаёт новое устройство SIT (IPv6-в-IPv4) — тоннель к указанной цели.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''irq'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает аппаратное прерывание, используемое данным устройством. Не для всех устройств можно динамически менять значение IRQ.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''io_addr addr'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает адрес начала области ввода-вывода для данного устройства.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''mem_start addr'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает адрес начала области разделяемой памяти, используемой этим устройством. Это нужно лишь для немногих устройств.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''media type'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает физический порт или тип носителя, используемый устройством. Не для всех устройств можно менять этот параметр, и для разных устройств могут поддерживаться различные значения. Типичные значения типа — [[10base2]] (коаксиальный кабель Ethernet), [[10baseT]] (витая пара Ethernet 10 Мбит/сек), [[AUI]] (внешний передатчик) и т. д. Специальный тип носителя auto можно использовать, чтобы потребовать от драйвера автоматически определять тип носителя. Не все драйверы могут это делать.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''bootproto [[static][dhcp]]'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает способ получения IP адреса.&lt;br /&gt;
(статический, которые описывается Вами, либо динамический получаемый от DHCP-сервера)''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''broadcast [addr]'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает широковещательный адрес. Широковещательный адрес обычно создается из сетевого адреса установкой всех бит части машины. Некоторые реализации IP используют другую схему, эта опция помогает приспособиться к этим странным средам. Если широковещательный (broadcast) адрес был установлен, ifconfig показывает флаг BROADCAST .''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''pointopoint [addr]'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Это ключевое слово включает двухточечный (point-to-point) режим интерфейса, означающий, что он обеспечивает непосредственную связь между двумя машинами, которую никто не прослушивает. Если указан также аргумент адрес, устанавливает соответствующий протоколу адрес другой стороны связи, как и устаревшее ключевое слово dstaddr. В противном случае, устанавливает или сбрасывает флаг IFF_POINTOPOINT для интерфейса.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''-pointopoint [addr]'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Это ключевое слово отключает двухточечный (point-to-point) режим интерфейса.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''hw class address'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает аппаратный адрес соответствующего интерфейса, если драйвер устройства поддерживает такую возможность. После ключевого слова hw необходимо указать имя класса оборудования, а также аппаратный адрес в текстовом виде. В настоящее время поддерживается оборудование классов ether (Ethernet), ax25 (AMPR AX.25), ARCnet и netrom (AMPR NET/ROM).''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''multicast'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает у интерфейса флаг поддержки групповой передачи данных. Обычно в этом нет нужды, поскольку драйвер сам выставляет этот флаг.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''address'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''IP-адрес, присваиваемый интерфейсу.''&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''txqueuelen length'''&amp;lt;/span&amp;gt;&lt;br /&gt;
| ''Устанавливает длину очереди передачи для устройства. Это позволяет установить меньшие значения для более медленных устройств с продолжительными задержками (модемные линии, ISDN), чтобы быстрая передача больших объёмов данных не слишком мешала передаче данных интерактивных сеансов, например, telnet.''&lt;br /&gt;
|+&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
&lt;br /&gt;
 # ifconfig eth0 inet 192.168.10.15 netmask 255.255.255.0&lt;br /&gt;
 # ifconfig eth0 up&lt;br /&gt;
 # ifconfig&lt;br /&gt;
 eth0      Link encap:Ethernet  HWaddr 00:18:F3:BE:18:1E&lt;br /&gt;
           inet addr:192.168.10.15  Bcast:192.168.10.255  Mask:255.255.255.0&lt;br /&gt;
           inet6 addr: fe80::218:f3ff:febe:181e/64 Scope:Link&lt;br /&gt;
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1&lt;br /&gt;
           RX packets:39456 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
           TX packets:45730 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
           collisions:0 txqueuelen:1000&lt;br /&gt;
           RX bytes:25457904 (24.2 Mb)  TX bytes:6540945 (6.2 Mb)&lt;br /&gt;
           Interrupt:20&lt;br /&gt;
 &lt;br /&gt;
 lo        Link encap:Local Loopback&lt;br /&gt;
           inet addr:127.0.0.1  Mask:255.0.0.0&lt;br /&gt;
           inet6 addr: ::1/128 Scope:Host&lt;br /&gt;
           UP LOOPBACK RUNNING  MTU:16436  Metric:1&lt;br /&gt;
           RX packets:182 errors:0 dropped:0 overruns:0 frame:0&lt;br /&gt;
           TX packets:182 errors:0 dropped:0 overruns:0 carrier:0&lt;br /&gt;
           collisions:0 txqueuelen:0&lt;br /&gt;
           RX bytes:12812 (12.5 Kb)  TX bytes:12812 (12.5 Kb)&lt;br /&gt;
 &lt;br /&gt;
 #&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[netstat]]&lt;br /&gt;
* [[iptables]]&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
[http://semenushkin.ru/2010/09/28/ifconfig-alias/ Дополнительный ip для интерфейса (ifconfig alias)]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Bash-task</id>
		<title>Bash-task</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Bash-task"/>
				<updated>2018-02-19T17:45:34Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;На данной странице представлены задачи  и примерные решения на bash(актуально для RHEL 7.x/CentOS 7.x. В других случаях требуется проверка).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Задача №1'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
'''Используя цикл и оператор выбора написать скрипт, реализующий следующее''':&lt;br /&gt;
* Выводит на экран(в терминал) '''меню с выбором''', состоящим из двух пунктов &amp;quot;''1)''&amp;quot; &amp;quot;''2)''&amp;quot;&lt;br /&gt;
* При выборе &amp;quot;''1)''&amp;quot; выводит текст на экран(в терминал), содержащий только цифру '''1'''&lt;br /&gt;
* При выборе &amp;quot;''2)''&amp;quot; выводит текст на экран(в терминал), содержащий только цифру '''2'''&lt;br /&gt;
* При вводе любого другого символа, выводит на экран сообщение о неправильном вводе  и  просит повторить ввод.&lt;br /&gt;
При неправильном вводе цикл бесконечен, т.е. продолжается пока не будет введён нужный символ, а затем снова выводится меню выбора.&lt;br /&gt;
'''Модернизировать'''(№1) скрипт так, чтобы при ''неправильном вводе'' он выводил сообщение о выходе из скрипта через ''три секунды'', после трёх секунд ожидания осуществляется выход из скрипта. '''Модернизировать'''(№2) скрипт добавив в него возможность прекращения работы в меню.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Вариант решения Задачи №1&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/env bash&lt;br /&gt;
#trap 'echo -e &amp;quot;\e[31mВот фиг тебе, а не прерывание\e[0m!&amp;quot;' 1 2 3 5 9 15&lt;br /&gt;
PS3='Введите значение: ' &amp;amp;&amp;amp; echo&lt;br /&gt;
                                                                                              &lt;br /&gt;
while :&lt;br /&gt;
do&lt;br /&gt;
         #clear&lt;br /&gt;
         options=(&amp;quot;1&amp;quot; &amp;quot;2&amp;quot;)&lt;br /&gt;
         #options=(&amp;quot;1&amp;quot; &amp;quot;2&amp;quot; &amp;quot;Завершение работы скрипта&amp;quot;) — для модернизации №2&lt;br /&gt;
         select opt in &amp;quot;${options[@]}&amp;quot;; do&lt;br /&gt;
         case &amp;quot;$opt&amp;quot; in&lt;br /&gt;
                 1) echo 'Ввели ' &amp;quot;$opt&amp;quot;&lt;br /&gt;
                    break 1&lt;br /&gt;
                 ;;&lt;br /&gt;
                 2) echo  'Ввели ' &amp;quot;$opt&amp;quot;&lt;br /&gt;
                    break 1&lt;br /&gt;
                 ;;  &lt;br /&gt;
                 # Для модернизации №2:&lt;br /&gt;
                 #'Завершение работы скрипта')&lt;br /&gt;
                 #  echo &amp;quot;Завершили работу скрипта&amp;quot;&lt;br /&gt;
                 #  exit&lt;br /&gt;
                 ;;                                                                         &lt;br /&gt;
                 *) echo 'Ввели неверный символ'&lt;br /&gt;
                    echo 'Повторите ввод'&lt;br /&gt;
                    break 1&lt;br /&gt;
                    #echo &amp;quot;Прекращаем работу скрипта через 3 секунды и осуществляем выход&amp;quot; — для модернизации №1&lt;br /&gt;
                    #sleep 3; exit 0 — для модернизации №1&lt;br /&gt;
                 ;;&lt;br /&gt;
           esac&lt;br /&gt;
           #break&lt;br /&gt;
           done&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Задача №2'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
'''Написать скрипт реализующий следующее''':&lt;br /&gt;
* Создать '''функцию''', которая реализует ''вывод списка директорий'' в файл '''/tmp/dir_list.log'''. При этом в качестве ''входного аргумента'' для функции служит переданный скрипту параметр, представляющий из себя ''абсолютный путь''.&lt;br /&gt;
* Создать '''функцию''', которая будет ''считывать содержимое'' '''/tmp/dir_list.log''' и выводить на экран, а также копировать это содержимое в '''/tmp/dir_list.0'''.&lt;br /&gt;
* Вызов функций происходит с ''задержкой в 5 секунд''.&lt;br /&gt;
* После успешной отработки скрипта и выхода из него файлы '''/tmp/dir_list.log''' и '''/tmp/dir_list.0''' должны быть автоматически удалены. Для этого пункта '''запрещается''' прямой вызов ''`rm -rf`'' или ''$(rm -rf)'' перед завершением скрипта.&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Подсказки для задачи №2&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
find .  -maxdepth 1  -type d -printf '%f\n' — выводит все директории&lt;br /&gt;
find .  -maxdepth 1  -type d| sed 's|./*||' | sed '/^$/d' — выводит все директории&lt;br /&gt;
find .  -maxdepth 1  -type d -printf '%f\n'|sed '1d' — выводит все директории, кроме первой(в ней размещается &amp;quot;.&amp;quot;)&lt;br /&gt;
ls -l|grep 'drwx'| awk '{print $9}'&lt;br /&gt;
for i in *; do  [ -d &amp;quot;$i&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$i&amp;quot;;done&lt;br /&gt;
ls -d */ | sed 's|\/||g'&lt;br /&gt;
find * -maxdepth 0 -type d&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Вариант решения Задачи №2&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/env bash&lt;br /&gt;
_find_dir=$1&lt;br /&gt;
log=&amp;quot;/tmp/dir_list.log&amp;quot;&lt;br /&gt;
log_0=&amp;quot;/tmp/dir_list.0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
trap &amp;quot;rm -rf $log $log_0&amp;quot; EXIT&lt;br /&gt;
&lt;br /&gt;
find_dir (){&lt;br /&gt;
        find $_find_dir  -maxdepth 1  -type d -printf '%f\n'|sed '1d' &amp;gt;&amp;gt; $log&lt;br /&gt;
        #find $_find_dir -maxdepth 0 -type d &amp;gt;&amp;gt; $log&lt;br /&gt;
        #ls -l $_find_dir|grep 'drwx'| awk '{print $9}'&amp;gt;&amp;gt; $log&lt;br /&gt;
        #cd $_find_dir;for i in *; do  [ -d &amp;quot;$i&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$i&amp;quot;;done &amp;gt;&amp;gt; $log &lt;br /&gt;
}&lt;br /&gt;
                                                                             &lt;br /&gt;
cp_list (){                                                                  &lt;br /&gt;
        cat $log|tee -a $log_0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
find_dir&lt;br /&gt;
sleep 5&lt;br /&gt;
cp_list&lt;br /&gt;
exit 0                                                                 &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Задача №3'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
'''Написать скрипт, который передаёт всю полученную в ходе своей работы информацию в системный журнал''':&lt;br /&gt;
* ''Дату и время'' в формате ''ГГГГ-ММ-ДД_ЧЧ-ММ-СС''.&lt;br /&gt;
* ''Список'' зарегистрировавшихся в системе,на ''текущий момент'', пользователей.&lt;br /&gt;
* ''Время'' работы системы(вывод должен быть представлен ''кириллицей'').&lt;br /&gt;
В консоли продемонстрировать вывод верно работающего скрипта.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Вариант решения Задачи №3&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/env bash&lt;br /&gt;
reg_u=$(who |awk {'print $1'})&lt;br /&gt;
xdate=$(date +%Y-%m-%d_%H-%M-%S)&lt;br /&gt;
upt=$(uptime -p |sed -e 's|up||g' -e 's|day.|дня(-ей)|' -e 's|hour.|час(-а,-ов)|' -e 's|minute.|минут(-ы)|')&lt;br /&gt;
upt_w=$(uptime -p |sed -e 's|up||g' -e 's|week.|недель(-я,-и)|' -e 's|day.|дня(-ь,-ей)|' -e 's|hour.|час(-а,-ов)|' -e's|minute.|минут(-ы)|')&lt;br /&gt;
&lt;br /&gt;
log_sys(){&lt;br /&gt;
        logger -i -t &amp;quot;CSys&amp;quot; Дата\/время: $xdate \| Зарегистрированные в системе пользователи: $reg_u \| Время работы системы: $1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if [ $(uptime|awk {'print $3'}) -gt 7 ]; then log_sys &amp;quot;$upt_w&amp;quot;; else log_sys &amp;quot;$upt&amp;quot;; fi&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Задача №4'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
'''Написать bash скрипт, который будет принимать в себя аргумент и, если значение, которое он принял будет чётное, то скрипт будет печатать только чётные значения до этого числа, если значение аргумента нечётное число, то печатать только нечётные значения до этого числа. В конце работы скрипт должен вывести сколько чётных или нечётных значений до этого числа.'''&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Первый вариант решения Задачи №4&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/env bash&lt;br /&gt;
&lt;br /&gt;
export chislo=$1&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if [[ $chislo =~  [a-zA-Z] ]]; then&lt;br /&gt;
        echo -e &amp;quot;\e[31mВвели не число\e[0m!&amp;quot;&lt;br /&gt;
&lt;br /&gt;
elif [[ $chislo -eq 0 ]]; then&lt;br /&gt;
        echo -e &amp;quot;Ввели число \e[31m0\e[0m&amp;quot;&lt;br /&gt;
        echo -e &amp;quot;Количество \e[32mчётных\e[0m элементов в числе \e[31m0\e[0m равно \e[31m1\e[0m&amp;quot;&lt;br /&gt;
&lt;br /&gt;
elif [[ ($chislo -gt 0) &amp;amp;&amp;amp; ($(($chislo % 2)) -eq 0) ]]; then&lt;br /&gt;
        even_chislo=$(seq 2 2 $chislo)&lt;br /&gt;
        echo &amp;quot;Все чётные числа входящие в $chislo:&amp;quot;&lt;br /&gt;
        for i in $even_chislo&lt;br /&gt;
        do&lt;br /&gt;
            echo $i&lt;br /&gt;
            new_chislo=( &amp;quot;${new_chislo[@]}&amp;quot; &amp;quot;$i&amp;quot; )&lt;br /&gt;
        done&lt;br /&gt;
        echo -e &amp;quot;Количество \e[32mчётных\e[0m элементов в числе \e[32m$chislo\e[0m равно \e[31m${#new_chislo[@]}\e[0m&amp;quot;&lt;br /&gt;
elif [[ ($chislo -gt 0) &amp;amp;&amp;amp; ($(($chislo % 2)) -eq 1) ]]; then&lt;br /&gt;
        odd_chislo=$(seq 1 2 $chislo)&lt;br /&gt;
        echo &amp;quot;Все нечётные числа входящие в $chislo:&amp;quot;&lt;br /&gt;
        for i in $odd_chislo&lt;br /&gt;
        do&lt;br /&gt;
                echo $i&lt;br /&gt;
                new_chislo=( &amp;quot;${new_chislo[@]}&amp;quot; &amp;quot;$i&amp;quot; )&lt;br /&gt;
        done&lt;br /&gt;
        echo -e &amp;quot;Количество \e[31mнечётных\e[0m элементов в числе \e[31m$chislo\e[0m равно \e[32m${#new_chislo[@]}\e[0m&amp;quot;&lt;br /&gt;
&lt;br /&gt;
elif [[ ($chislo -lt 0) &amp;amp;&amp;amp; ($(($(echo $chislo | sed 's|^-||g') % 2)) -eq 0) ]]; then&lt;br /&gt;
        echo &amp;quot;Все чётные числа входящие в $chislo:&amp;quot;&lt;br /&gt;
        chislo=$(echo $chislo | sed 's|^-||g')&lt;br /&gt;
        even_chislo=$(seq 2 2 $chislo)&lt;br /&gt;
        for i in $even_chislo&lt;br /&gt;
        do&lt;br /&gt;
            echo &amp;quot;-$i&amp;quot;&lt;br /&gt;
            new_chislo=( &amp;quot;${new_chislo[@]}&amp;quot; &amp;quot;$i&amp;quot; )&lt;br /&gt;
        done&lt;br /&gt;
        echo -e &amp;quot;Количество отрицательных \e[32mчётных\e[0m элементов в числе \e[32m-$chislo\e[0m равно \e[31m${#new_chislo[@]}\e[0m&amp;quot;&lt;br /&gt;
&lt;br /&gt;
elif [[ ($chislo -lt 0) &amp;amp;&amp;amp; ($(($(echo $chislo | sed 's|^-||g') % 2)) -eq 1) ]]; then&lt;br /&gt;
        echo &amp;quot;Все нечётные числа входящие в $chislo:&amp;quot;&lt;br /&gt;
        chislo=$(echo $chislo | sed 's|^-||g')&lt;br /&gt;
        odd_chislo=$(seq 1 2 $chislo)&lt;br /&gt;
        #echo &amp;quot;Все нечётные числа входящие в $chislo:&amp;quot;&lt;br /&gt;
        for i in $odd_chislo&lt;br /&gt;
        do&lt;br /&gt;
                echo &amp;quot;-$i&amp;quot;&lt;br /&gt;
                new_chislo=( &amp;quot;${new_chislo[@]}&amp;quot; &amp;quot;$i&amp;quot; )&lt;br /&gt;
        done&lt;br /&gt;
        echo -e &amp;quot;Количество отрицательных \e[31mнечётных\e[0m элементов в числе \e[31m-$chislo\e[0m равно \e[32m${#new_chislo[@]}\e[0m&amp;quot;&lt;br /&gt;
&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Второй вариант решения Задачи №4&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/env bash&lt;br /&gt;
num=$1&lt;br /&gt;
if [[ $num =~ - ]]; then&lt;br /&gt;
  printf &amp;quot;Требуется передать в скрипт целое ПОЛОЖИТЕЛЬНОЕ число\n&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
elif [[ &amp;quot;`expr $num % 2`&amp;quot; == 0 ]]; then&lt;br /&gt;
  for ((i=1; i&amp;lt;=$num; i++)); do&lt;br /&gt;
    if [[ &amp;quot;`expr $i % 2`&amp;quot; == 0 ]]; then&lt;br /&gt;
      echo &amp;quot;$i&amp;quot;&lt;br /&gt;
      ((chet+=1))&lt;br /&gt;
    else&lt;br /&gt;
      ((nchet+=1))&lt;br /&gt;
    fi&lt;br /&gt;
  done&lt;br /&gt;
elif [[ &amp;quot;`expr $num % 2`&amp;quot; == 1 ]]; then&lt;br /&gt;
  for ((i=1; i&amp;lt;=$num; i++)); do&lt;br /&gt;
    if [[ &amp;quot;`expr $i % 2`&amp;quot; == 0 ]]; then&lt;br /&gt;
      ((chet+=1))&lt;br /&gt;
    else&lt;br /&gt;
      echo &amp;quot;$i&amp;quot;&lt;br /&gt;
      ((nchet+=1))&lt;br /&gt;
    fi&lt;br /&gt;
  done&lt;br /&gt;
else&lt;br /&gt;
  printf &amp;quot;Требуется передать в скрипт целое ПОЛОЖИТЕЛЬНОЕ число\n&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
printf &amp;quot;Количество четных чисел %d \nКоличество нечетных чисел %d \n&amp;quot; &amp;quot;$chet&amp;quot; &amp;quot;$nchet&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;spoiler text=&amp;quot;Третий вариант решения Задачи №4&amp;quot;&amp;gt;&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/env bash&lt;br /&gt;
num=$1&lt;br /&gt;
i=1&lt;br /&gt;
if [[ $num =~ - ]]; then&lt;br /&gt;
  printf &amp;quot;Требуется передать в скрипт целое ПОЛОЖИТЕЛЬНОЕ число\n&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
elif [[ &amp;quot;`expr $num % 2`&amp;quot; == 0 ]]; then&lt;br /&gt;
  while (($i&amp;lt;=$num)); do&lt;br /&gt;
    if [[ &amp;quot;`expr $i % 2`&amp;quot; == 0 ]]; then&lt;br /&gt;
      echo &amp;quot;$i&amp;quot;&lt;br /&gt;
      ((chet+=1))&lt;br /&gt;
    else&lt;br /&gt;
      ((nchet+=1))&lt;br /&gt;
    fi&lt;br /&gt;
    ((i+=1))&lt;br /&gt;
  done&lt;br /&gt;
elif [[ &amp;quot;`expr $num % 2`&amp;quot; == 1 ]]; then&lt;br /&gt;
  while (($i&amp;lt;=$num)); do&lt;br /&gt;
    if [[ &amp;quot;`expr $i % 2`&amp;quot; == 0 ]]; then&lt;br /&gt;
      ((chet+=1))&lt;br /&gt;
    else&lt;br /&gt;
      echo &amp;quot;$i&amp;quot;&lt;br /&gt;
      ((nchet+=1))&lt;br /&gt;
    fi&lt;br /&gt;
    ((i+=1))&lt;br /&gt;
  done&lt;br /&gt;
else&lt;br /&gt;
  printf &amp;quot;Требуется передать в скрипт целое ПОЛОЖИТЕЛЬНОЕ число\n&amp;quot;&lt;br /&gt;
  exit 1&lt;br /&gt;
fi&lt;br /&gt;
printf &amp;quot;Количество четных чисел %d \nКоличесвто нечетных чисел %d \n&amp;quot; &amp;quot;$chet&amp;quot; &amp;quot;$nchet&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;/spoiler&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Ps</id>
		<title>Ps</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Ps"/>
				<updated>2018-02-07T10:14:28Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''ps''' (от англ. '''p'''rocess '''s'''tatus) — программа в UNIX, Unix-подобных и других POSIX-совместимых опер…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''ps''' (от англ. '''p'''rocess '''s'''tatus) — программа в UNIX, Unix-подобных и других POSIX-совместимых операционных системах, выводящая отчёт о работающих процессах.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ps [опции]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Опции, отбирающие процессы для отчёта:&lt;br /&gt;
** -A :	все процессы;&lt;br /&gt;
** -a :	связанные с конкретным терминалом, кроме главных системных процессов сеанса, часто используемая опция;&lt;br /&gt;
** -N :	отрицание выбора;&lt;br /&gt;
** -d :	все процессы, кроме главных системных процессов сеанса;&lt;br /&gt;
** -e :	все процессы;&lt;br /&gt;
** -f : расширение информации&lt;br /&gt;
** T :	все процессы на конкретном терминале;&lt;br /&gt;
** a :	процессы, связанные с текущим терминалом, а также процессы других пользователей;&lt;br /&gt;
** r :	информация только о работающих процессах;&lt;br /&gt;
* x : процессы, отсоединённые от терминала.&lt;br /&gt;
&lt;br /&gt;
== Выводимая информация ==&lt;br /&gt;
Столбцы:&lt;br /&gt;
* UID : идентификатор пользователя;&lt;br /&gt;
* PID : идентификатор процесса;&lt;br /&gt;
* PPID : идентификатор родительского процесса;&lt;br /&gt;
* C : приоритет процесса, используемый планировщиком задач;&lt;br /&gt;
* STIME : время старта процесса;&lt;br /&gt;
* TTY : терминал, с которым связан данный процесс;&lt;br /&gt;
* TIME : процессорное время, занятое этим процессом;&lt;br /&gt;
* CMD : команда, запустившая данный процесс «с некоторыми опциями выводит и каталог откуда процесс был запущен»;&lt;br /&gt;
* STAT : состояние, в котором на данный момент находится процесс.&lt;br /&gt;
&lt;br /&gt;
Опция '''''o''''' позволяет указать набор столбцов в ответе:&lt;br /&gt;
 ps o pid,user,command&lt;br /&gt;
&lt;br /&gt;
== Параметры STAT ==&lt;br /&gt;
&lt;br /&gt;
* R : процесс выполняется в данный момент&lt;br /&gt;
* S : процесс ожидает (т.е. спит менее 20 секунд)&lt;br /&gt;
* I : процесс бездействует (т.е. спит больше 20 секунд)&lt;br /&gt;
* D : процесс ожидает ввода-вывода (или другого недолгого события), непрерываемый&lt;br /&gt;
* Z : zombie или defunct процесс, то есть завершившийся процесс, код возврата которого пока не считан родителем&lt;br /&gt;
* T : процесс остановлен&lt;br /&gt;
* W : процесс в свопе&lt;br /&gt;
* &amp;lt; : процесс в приоритетном режиме.&lt;br /&gt;
* N : процесс в режиме низкого приоритета&lt;br /&gt;
* L : real-time процесс, имеются страницы, заблокированные в памяти.&lt;br /&gt;
* s : лидер сессии&lt;br /&gt;
&lt;br /&gt;
== Примеры использования ==&lt;br /&gt;
 # ps&lt;br /&gt;
 PID  TTY      TIME     CMD&lt;br /&gt;
 2643 pts/0    00:00:00 su&lt;br /&gt;
 2644 pts/0    00:00:00 bash&lt;br /&gt;
 3092 pts/0    00:00:00 ps&lt;br /&gt;
&lt;br /&gt;
 # ps ax&lt;br /&gt;
 PID TTY      STAT   TIME COMMAND&lt;br /&gt;
 1   ?        S      0:01 init [3]&lt;br /&gt;
 2   ?        SN     0:00 [ksoftirqd/0]&lt;br /&gt;
 3   ?        S&amp;lt;     0:00 [events/0]&lt;br /&gt;
 4   ?        S&amp;lt;     0:00 [khelper]&lt;br /&gt;
 5   ?        S&amp;lt;     0:00 [kblockd/0]&lt;br /&gt;
 29  ?        S      0:00 [pdflush]&lt;br /&gt;
&lt;br /&gt;
 # ps af&lt;br /&gt;
 PID  TTY      STAT   TIME COMMAND&lt;br /&gt;
 2617 pts/0    Ss     0:00 -bash&lt;br /&gt;
 2643 pts/0    S      0:00  \_ su -&lt;br /&gt;
 2644 pts/0    S      0:00      \_ -bash&lt;br /&gt;
 3100 pts/0    R+     0:00          \_ ps af&lt;br /&gt;
 2176 tty6     Ss+    0:00 /sbin/mingetty tty6&lt;br /&gt;
 2175 tty5     Ss+    0:00 /sbin/mingetty tty5&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
* Альтернативой &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; является команда &amp;lt;tt&amp;gt;[[top]]&amp;lt;/tt&amp;gt;, удобно выводящая на экран постоянно обновляющуюся информацию, однако &amp;lt;tt&amp;gt;top&amp;lt;/tt&amp;gt; ограничена размерами окна, поэтому всё, что не может поместиться на экран, просто игнорируется.&lt;br /&gt;
* Для команды &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; удобно пользоваться конвейером и утилитой [[less]] для пролистывания выводимой информации с помощью кнопок вверх и вниз, например &amp;lt;code&amp;gt;ps ax | less&amp;lt;/code&amp;gt;&lt;br /&gt;
* С помощью утилиты [[grep]] удобно искать и выводить только нужные процессы, например &amp;lt;code&amp;gt;ps ax | grep smbd&amp;lt;/code&amp;gt;&lt;br /&gt;
* В связи с возможностью написания модуля, подгружаемого к ядру, и возвращающего на запрос от &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; ''модифицированный'' список процессов, администраторам не рекомендуется всецело полагаться на результаты &amp;lt;tt&amp;gt;ps&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;top&amp;lt;/tt&amp;gt; при подозрениях на возможность несанкционированного вмешательства.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.opengroup.org/onlinepubs/009695399/utilities/ps.html Спецификация ps в Единой спецификации UNIX на сайте The Open Group]&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Ps_(Unix) Ссылка на англ. страницу Wiki]&lt;br /&gt;
* [https://www.opennet.ru/man.shtml?topic=ps&amp;amp;category=1&amp;amp;russian=5 MAN на OpenNET]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Sort</id>
		<title>Sort</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Sort"/>
				<updated>2018-01-10T10:29:47Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Добавлено описание команды sort&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''sort''' — Команда сортировки и/или слияния файлов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
'''sort'''  ['''''-c'''''] ['''''-m'''''] ['''''-u'''''] ['''''-o выходной_файл'''''] ['''''-y'''''килобайт] ['''''-z'''''длина]&amp;lt;br /&amp;gt;&lt;br /&gt;
:['''''-d'''''] ['''''-f'''''] ['''''-i'''''] ['''''-M'''''] ['''''-n'''''] ['''''-r'''''] ['''''-b'''''] ['''''-t'''''разделитель]&amp;lt;br /&amp;gt;&lt;br /&gt;
:['''''+позиция_1''''' ['''''-позиция_2''''']] ['''''файл ...''''']&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
Команда [[sort]] сортирует строки, входящие во все исходные файлы, и выдаёт результат на стандартный вывод. Если имена файлов не указаны, или в качестве файла указан -, исходная информация поступает со стандартного ввода. При упорядочении используется один или несколько ключей сортировки, выделяемых из каждой вводимой строки. По умолчанию ключ сортировки один – вся строка, а порядок является лексикографическим, соответствующим принятой кодировке символов.&lt;br /&gt;
;Основные параметры&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Обязательные аргументы для длинных форм параметров являются также обязательными и для коротких форм''.&lt;br /&gt;
;-b, --ignore-leading-blanks&lt;br /&gt;
: игнорировать пробелы в начале сортируемых полей или начале ключей&lt;br /&gt;
;-d, --dictionary-order&lt;br /&gt;
: воспринимать в составе ключей лишь буквы (латинского алфавита), цифры и пробелы, игнорируя все прочие символы&lt;br /&gt;
;-f, --ignore-case&lt;br /&gt;
: во время сортировки преобразует строчные (маленькие) в соответствующие прописные (большие) буквы, т.е. выполняется сортировка нечувствительная к регистру символов&lt;br /&gt;
;-g, --general-numeric-sort&lt;br /&gt;
: выполнять сравнение в соответствии с общим числовым значением (используют совместно с параметром -b). Это численная сортировка, при которой дополнительно распознаётся экспоненциальное представление чисел (например, 9.1019e7)&lt;br /&gt;
;-i, --ignore-nonprinting&lt;br /&gt;
: в ключах рассматриваются только печатаемые (ASCII) символы, а остальные игнорируются&lt;br /&gt;
;-M, --month-sort&lt;br /&gt;
: выполнять сравнение по трёх-символьным сокращениям англоязычных названий месяцев, т.е. (незнакомое) &amp;lt; `JAN' &amp;lt; ... &amp;lt; `DEC'&lt;br /&gt;
;-n, --numeric-sort&lt;br /&gt;
: числовая сортировка, т.е. сравнение ведётся по числовому значению (используют совместно с параметром -b)&lt;br /&gt;
;-r, --reverse&lt;br /&gt;
: сортировка выполняется в обратном порядке (по убыванию)&lt;br /&gt;
;-y''килобайт''&lt;br /&gt;
: количество дополнительной памяти, используемой командой [[sort]], существенно влияет на скорость её работы. Если опция ''-y'' отсутствует, [[sort]] начинает работу, используя область памяти некоторого стандартного размера, а в случае необходимости запрашивает дополнительную память. Если опция ''-y'' задана с аргументом, команда [[sort]] начинает работу, используя указанное число килобайт памяти, если только не нарушены ограничения сверху или снизу; в этом случае используется соответствующее крайнее значение. Таким образом, указание ''-y0'' гарантирует использование минимального объема памяти. Опция ''-y'' без аргумента задаёт область памяти максимального размера.&lt;br /&gt;
;-zдлина&lt;br /&gt;
: во время сортировки запоминается размер самой длинной строки, так что для фазы слияния команда [[sort]] может отвести буфер нужного размера. Если, в силу действия опций ''-c'' или ''-m'', фаза сортировки пропускается, используется некоторый стандартный размер. Наличие строк, превышающих по длине буфер, приводит к аварийному завершению команды. Задание заведомо достаточной длины гарантирует нормальное выполнение слияния.&lt;br /&gt;
&lt;br /&gt;
;Другие параметры:&lt;br /&gt;
&lt;br /&gt;
;-c, --check&lt;br /&gt;
: проверяет сортировался ли указанный файл. Если да, то не выполняет сортировку, иначе выводит сообщение об ошибке&lt;br /&gt;
;-k, --key=ПОЗ1[,ПОЗ2]&lt;br /&gt;
:выбирает ключ сортировки, начиная с позиции ''ПОЗ1'' и заканчивая позицией ''ПОЗ2'' (включительно). Номера полей и смещения символов указываются, начиная с 1&lt;br /&gt;
;-m, --merge&lt;br /&gt;
: объединяет ранее отсортированные ФАЙЛЫ, которые не сортируются повторно&lt;br /&gt;
;-o, --output=ФАЙЛ&lt;br /&gt;
: выводит результат в указанный файл ФАЙЛ вместо стандартного вывода&lt;br /&gt;
;-s, --stable&lt;br /&gt;
: стабилизирует сортировку, не выполняя сравнения последней пересортировки&lt;br /&gt;
;-S, --buffer-size=РАЗМЕР&lt;br /&gt;
: под основной буфер в памяти использует область размером РАЗМЕР&lt;br /&gt;
;-t, --field-separator=СИМВОЛ&lt;br /&gt;
: использовать СИМВОЛ в качестве разделителя полей&lt;br /&gt;
;-T, --temporary-directory=КАТАЛОГ&lt;br /&gt;
: использует указанный КАТАЛОГ для временных файлов, игнорируя переменную окружения $TMPDIR или /tmp; составные параметры могут указывать на различные каталоги&lt;br /&gt;
;-u, --unique&lt;br /&gt;
: уникальная сортировка: игнорирует повторяющиеся строки. Обычно применяют с параметром ''-c'' для проверки сортированных файлов с целью прерывания выполнения, если встретится несколько одинаковых строк подряд; без -c выводится только первая строка из одинаковых&lt;br /&gt;
;-z, --zero-terminated&lt;br /&gt;
:вместо символа новой строки (newline), завершает строки двоичным 0&lt;br /&gt;
;--help&lt;br /&gt;
:вывести справку о программе, её параметрах и завершить работу&lt;br /&gt;
;--version&lt;br /&gt;
: вывести информацию о версии программы и завершить работу&lt;br /&gt;
Синтаксис параметра ''-k'', ''--key=ПОЗ1[,ПОЗ2]'' означает следующее:&amp;lt;br /&amp;gt;&lt;br /&gt;
''ПОЗ'' указывается в формате ''F[.C][OPTS]'', где ''F'' является порядковым номером поля, а ''C'' позицией символа в этом поле. ''OPTS'' представляет собой одну или более одиночных букв, которые означают рассмотренные выше параметры и их действие перекрывает действие глобальных параметров для этого ключа. Если ни один ключ не задан, в качестве ключа используется вся строка. Ключ сортировки — это часть строки, которая рассматривается при сортировке, вместо того чтобы рассматривалась вся строка. Таким образом, команда:&lt;br /&gt;
;sort -k1.3&amp;lt;br /&amp;gt;&lt;br /&gt;
осуществляет сортировку по первому полю, начиная с его третьего символа. Команда:&lt;br /&gt;
;sort -k4.6,7n&lt;br /&gt;
означает сортировку с 6-го символа четвёртого поля до 1-го символа седьмого поля. Сортировка ведётся по числовому значению. Допускается задание нескольких параметров ''-k'' для того, чтобы определить несколько ключей, которые будут использованы последовательно в том порядке, в котором они указаны в командной строке. Величина размера ''SIZE'' памяти, отводимой для работы команды [[sort]] может быть задана со следующими суффиксами: ''%-1%'' от общей памяти; ''b'' — в байтах; ''K'' — 1024 байт (по умолчанию); и соответственно для ''M'', ''G'', ''T'', ''P'', ''E'', ''Z'', ''Y''. Если в командной строке не указан никакой файл или вместо имени стоит дефис, считывается стандартный ввод (с клавиатуры).&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
;Отсортировать файл ''f1'', используя в качестве ключа второе поле:&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''sort  +1 -2 f1''&amp;lt;/span&amp;gt;&lt;br /&gt;
;Отсортировать по убыванию содержимое файлов ''f2'' и ''f3'', поместив результат в файл ''f4''. Ключом сортировки служит первый символ второго поля&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''sort  -r -o f4 +1.0 -1.2 f2 f3''&amp;lt;/span&amp;gt;&lt;br /&gt;
;Отсортировать по убыванию содержимое файлов ''f5'' и ''f6''. Ключом сортировки служит первый не пробел второго поля&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''sort  -r +1.0b -1.1b f5 f6''&amp;lt;/span&amp;gt;&lt;br /&gt;
;Распечатать файл паролей, отсортировав его по числовым значениям идентификаторов пользователей (третье поле, поля разделяются символом &amp;lt;nowiki&amp;gt;:):&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''sort  -t: +2n -3 /etc/passwd''&amp;lt;/span&amp;gt;&lt;br /&gt;
;Распечатать строки уже отсортированного файла ''f7'', выводя лишь первую из строк с одинаковыми третьими полями&amp;lt;nowiki&amp;gt;:&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''sort  -um +2 -3 f7''&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Диагностика ==&lt;br /&gt;
Если в последней строке файла пропущен символ возврата каретки, то он добавляется автоматически, о чем выдаётся предупреждение.&lt;br /&gt;
&lt;br /&gt;
== Предостережения ==&lt;br /&gt;
Не гарантируется сохранение порядка следования строк с равными ключами. Не оговаривается приоритет различных способов сравнения (например, числового и словарного), поэтому задавать комбинацию флагов ''dMn'' не имеет смысла.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Usermod</id>
		<title>Usermod</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Usermod"/>
				<updated>2018-01-09T12:00:43Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''usermod'''(от англ. '''user''' '''mod'''ification)  - изменяет учётную запись пользователя.&amp;lt;br /&amp;gt; == Синтаксис…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''usermod'''(от англ. '''user''' '''mod'''ification)  - изменяет учётную запись пользователя.&amp;lt;br /&amp;gt;&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
'''usermod''' [''параметры''] ''LOGIN''&lt;br /&gt;
== Описание ==&lt;br /&gt;
Команда '''usermod''' изменяет системные файлы учётных записей согласно переданным в командной строке параметрам.&lt;br /&gt;
== Параметры ==&lt;br /&gt;
Параметры команды '''usermod''':&lt;br /&gt;
;-a, --append&lt;br /&gt;
: Добавить пользователя в дополнительную группу(ы). Использовать только вместе с параметром ''-G''.&lt;br /&gt;
;-c, --comment КОММЕНТАРИЙ&lt;br /&gt;
: Новое значение поля комментария в файле пользовательских паролей. Обычно его изменяют с помощью программы '''chfn'''.&lt;br /&gt;
;-d, --home ДОМАШНИЙ_КАТАЛОГ&lt;br /&gt;
: Новый домашний каталог пользователя. Если указан параметр ''-m'', то содержимое текущего домашнего каталога будет перемещено в новый домашний каталог, который будет создан, если он ещё не существует.&lt;br /&gt;
;-e, --expiredate ДАТА_УСТАРЕВАНИЯ&lt;br /&gt;
: Дата, когда учётная запись пользователя будет заблокирована. Дата задаётся в формате &amp;lt;ГГГГ&amp;gt;-&amp;lt;ММ&amp;gt;-&amp;lt;ДД&amp;gt;.&lt;br /&gt;
;-f, --inactive ДНЕЙ&lt;br /&gt;
: Число дней, которые должны пройти после устаревания пароля, чтобы учётная запись заблокировалась навсегда. Если указано значение 0, то учётная запись блокируется сразу после устаревания пароля, а при значении -1 данная возможность не используется. По умолчанию используется значение -1.&lt;br /&gt;
;-g, --gid ГРУППА&lt;br /&gt;
: Имя или числовой идентификатор новой начальной группы пользователя. Группа с таким именем должна существовать. Идентификатор группы должен указывать на уже существующую группу. По умолчанию идентификатор группы установлен в 1.&lt;br /&gt;
;-G, --groups ГРУППА1[,ГРУППА2,...[,ГРУППАN]]]&lt;br /&gt;
: Список дополнительных групп, членом которых также является пользователь. Каждая группа отделена от следующей запятой, &amp;lt;u&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;без промежуточных пробелов&amp;lt;/span&amp;gt;&amp;lt;/u&amp;gt;. Группы подвержены тем же ограничениям, что и группа, заданная с опцией ''-g''. Если пользователь в настоящее время является членом группы, которая не указана в списке, пользователь будет удален из группы. Такое поведение можно изменить с помощью опции ''-a'', которая добавляет пользователя в текущий список дополнительных групп.&lt;br /&gt;
;-l, --login НОВОЕ_ИМЯ&lt;br /&gt;
: Имя пользователя будет изменено с ''LOGIN'' на ''NEW_LOGIN''. Ничего другого не изменилось. В частности, имя домашнего каталога пользователя, вероятно, должно быть изменено вручную, чтобы отобразить новое имя входа.&lt;br /&gt;
;-L, --lock&lt;br /&gt;
: Заблокировать пароль пользователя. Это делается помещением символа '!' в начало шифрованного пароля, чтобы приводит к блокировке пароля. Не используйте этот параметр вместе с ''-p'' или ''-U''. '''Примечание''': Если вы хотите заблокировать учетную запись (не только доступ по паролю), вы также должны установить для ''EXPIRE_DATE'' значение 1.&lt;br /&gt;
;-o, --non-unique&lt;br /&gt;
: При использовании с параметром ''-u'', этот параметр позволяет указывать не уникальный числовой идентификатор пользователя.&lt;br /&gt;
;-p, --password ПАРОЛЬ&lt;br /&gt;
: Шифрованное значение пароля, которое возвращает функция '''crypt'''.&lt;br /&gt;
;-s, --shell ОБОЛОЧКА&lt;br /&gt;
: Имя новой регистрационной оболочки пользователя. Если задать пустое значение, то будет использована регистрационная оболочка по умолчанию.&lt;br /&gt;
;-u, --uid UID&lt;br /&gt;
: Числовое значение идентификатора пользователя (''ID''). Значение должно быть уникальным, если не задан параметр ''-o''. Значение должно быть неотрицательным. Значения от 0 до 999 обычно зарезервированы для системных учётных записей. Для всех файлов, которыми владеет пользователь и которые расположены в его домашнем каталоге идентификатор владельца файла будет изменён автоматически. Для файлов, расположенных вне домашнего каталога идентификатор нужно изменять вручную.&lt;br /&gt;
;-U, --unlock&lt;br /&gt;
: Разблокировать пароль пользователя. Это выполняется удалением символа '!' из начала шифрованного пароля. Не используйте этот параметр вместе с ''-p'' или ''-L''.&amp;lt;br /&amp;gt;'''Примечание''': Если вы хотите разблокировать учетную запись (не только доступ по паролю), вы также должны установить ''EXPIRE_DATE''(например, 99999 или значение EXPIRE из ''/etc/default/useradd'').&lt;br /&gt;
== Предостережения ==&lt;br /&gt;
Команда '''usermod''' не будет изменять имя пользователя, если этот пользователь в данный момент работает в системе. Если требуется изменить числовой идентификатор пользователя, нужно проверить, что от этого пользователя нет запущенных процессов. Владельца файлов '''crontab''' &amp;lt;u&amp;gt;нужно изменять вручную&amp;lt;/u&amp;gt;. Владельца заданий '''at''' &amp;lt;u&amp;gt;нужно изменять вручную&amp;lt;/u&amp;gt;. Также вручную нужно сделать все изменения связанные с ''NIS'' на сервере ''NIS''.&lt;br /&gt;
== Конфигурация ==&lt;br /&gt;
Следующие переменные конфигурации в файле ''/etc/login.defs'' изменяют поведение этого инструмента:&lt;br /&gt;
;MAIL_DIR (string)&lt;br /&gt;
: Почтовый каталог. Данный параметр нужен для управления почтовым ящиком при изменении или удалении учётной записи пользователя. Если параметр не задан, то используется значение указанное при сборке.&lt;br /&gt;
;MAIL_FILE (string)&lt;br /&gt;
: Определяет расположение файлов, содержащих почтовые сообщения пользователей, относительно их домашнего каталога. Переменные ''MAIL_DIR'' и ''MAIL_FILE'' используются [[useradd]], [[usermod]] и [[userdel]] для создания, перемещения или удаления файлов, содержащих почтовые сообщения пользователей. Если для ''MAIL_CHECK_ENAB'' установлено значение ''yes'', они также используются для определения переменной среды ''MAIL''.&lt;br /&gt;
;MAX_MEMBERS_PER_GROUP (number)&lt;br /&gt;
: Максимальное количество участников в группе. Когда достигнут максимум, в ''/etc/group'' запускается новая запись(строка) группы (с тем же именем, с тем же паролем и с тем же ''GID''). Значение по умолчанию равно 0, а это означает, что число членов в группе не ограничено. Эта функция(разделённая группа) позволяет ограничить длину строк в файле группы. Это полезно, чтобы убедиться, что строки для групп ''NIS'' не более 1024 символов. Если вам необходимо обеспечить соблюдение такого ограничения, вы можете использовать 25. '''Примечание''': Разделённые группы могут не поддерживаться всеми инструментами (даже в инструменте '''shadow'''. Вы не должны использовать эту переменную, если она вам не нужна).&lt;br /&gt;
== Файлы ==&lt;br /&gt;
;/etc/group&lt;br /&gt;
: Содержит информацию о группах&lt;br /&gt;
;/etc/passwd&lt;br /&gt;
: Содержит информацию о пользователях&lt;br /&gt;
;/etc/shadow&lt;br /&gt;
: Содержит защищаемую информацию о пользователях&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Userdel</id>
		<title>Userdel</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Userdel"/>
				<updated>2018-01-09T12:00:21Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''userdel'''(от англ. '''user''' '''del'''ete) - удаляет учётную запись и файлы пользователя.&amp;lt;br /&amp;gt; == Синтакс…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''userdel'''(от англ. '''user''' '''del'''ete) - удаляет учётную запись и файлы пользователя.&amp;lt;br /&amp;gt;&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
'''userdel''' [''параметры''] ''LOGIN''&lt;br /&gt;
== Описание ==&lt;br /&gt;
Команда [[userdel]] изменяет файлы системной учетной записи, удаляя все записи, относящиеся к имени пользователя ''LOGIN''. Именованный пользователь должен существовать.&lt;br /&gt;
== Параметры ==&lt;br /&gt;
Параметры команды '''userdel'':&lt;br /&gt;
;-f, --force&lt;br /&gt;
: Этот параметр заставляет удалять учётную запись пользователя, даже если пользователь всё ещё зарегистрирован. Он также заставляет [[userdel]] удалять домашний каталог пользователя и файлы, содержащие почтовые сообщения, даже если другой пользователь использует тот же домашний каталог, или, если файлы не принадлежит указанным пользователем. Если ''USERGROUPS_ENAB'' определено в ''yes'' в ''/etc/login.defs'', и если группа существует с тем же именем, что и удалённый пользователь, эта группа будет удалена, даже если она по-прежнему является основной группой другого пользователя. '''Примечание''': Этот параметр опасно использовать; он может привести систему в нерабочее состояние.&lt;br /&gt;
;-h, --help&lt;br /&gt;
: Показать краткую справку и закончить работу.&lt;br /&gt;
;-r, --remove&lt;br /&gt;
: Файлы в домашнем каталоге пользователя будут удалены вместе с самим домашним каталогом и почтовым ящиком. Пользовательские файлы, расположенные в других файловых системах, нужно искать и удалять вручную. Имя файла почтового ящика задаётся переменной ''MAIL_DIR'' в файле ''login.defs''.&lt;br /&gt;
== Замечания ==&lt;br /&gt;
== Предостережения ==&lt;br /&gt;
== Конфигурация ==&lt;br /&gt;
Следующие переменные конфигурации в файле ''/etc/login.defs'' изменяют поведение этого инструмента:&lt;br /&gt;
;MAIL_DIR (string)&lt;br /&gt;
: Почтовый каталог. Данный параметр нужен для управления почтовым ящиком при изменении или удалении учётной записи пользователя. Если параметр не задан, то используется значение указанное при сборке.&lt;br /&gt;
;MAIL_FILE (string)&lt;br /&gt;
: Определяет расположение файлов почтовых спутников пользователей относительно их домашнего каталога. Переменные ''MAIL_DIR'' и ''MAIL_FILE'' используются [[useradd]], [[usermod]] и [[userdel]] для создания, перемещения или удаления почтовой катушки пользователя. Если для ''MAIL_CHECK_ENAB'' установлено значение ''yes'', они также используются для определения переменной среды ''MAIL''.&lt;br /&gt;
;MAX_MEMBERS_PER_GROUP (number)&lt;br /&gt;
: Максимальное количество участников в группе. Когда достигнут максимум, в ''/etc/group'' запускается новая запись(строка) группы(с тем же именем, с тем же паролем и с тем же ''GID''). Значение по умолчанию равно 0, а это означает, что число членов в группе не ограничено. Эта функция(разделенная группа) позволяет ограничить длину строк в файле группы. Это полезно, чтобы убедиться, что строки для групп ''NIS'' не более 1024 символов. Если вам необходимо обеспечить соблюдение такого ограничения, вы можете использовать 25.&amp;lt;br /&amp;gt;'''Примечание''': Разделённые группы могут не поддерживаться всеми инструментами(даже в инструменте '''shadow'''. Вы не должны использовать эту переменную, если она вам не нужна).&lt;br /&gt;
;USERDEL_CMD (string)&lt;br /&gt;
: Определяет программу, которая будет запущена при удалении пользователя. Она должна удалять любые задания ''at/cron/печати'' удаляемого пользователя(передаётся в качестве первого аргумента).&lt;br /&gt;
;USERGROUPS_ENAB (boolean)&lt;br /&gt;
: Включить настройку битов группы ''umask'' как то же, что и биты владельца (примеры: 022 -&amp;gt; 002, 077 -&amp;gt; 007) для пользователей, не являющихся '''root''', если ''uid'' совпадает с именем ''gid'', а имя пользователя совпадает с именем основного названия группы. Если установлено ''yes'', [[userdel]] удалит группу пользователя, если в неё не будет больше членов, а [[useradd]] будет создавать по умолчанию группу с именем пользователя.&lt;br /&gt;
== Файлы ==&lt;br /&gt;
;/etc/group&lt;br /&gt;
: Содержит информацию о группах&lt;br /&gt;
;/etc/login.defs&lt;br /&gt;
: Содержит конфигурацию подсистемы теневых паролей&lt;br /&gt;
;/etc/passwd&lt;br /&gt;
: Содержит информацию о пользователях&lt;br /&gt;
;/etc/shadow&lt;br /&gt;
: Содержит защищаемую информацию о пользователях&lt;br /&gt;
== Возвращаемые значения ==&lt;br /&gt;
Команда [[userdel]] завершая работу, возвращает следующие значения:&lt;br /&gt;
;0&lt;br /&gt;
: успешное выполнение&lt;br /&gt;
;1&lt;br /&gt;
: не удалось изменить файл паролей&lt;br /&gt;
;2&lt;br /&gt;
: ошибка в параметрах команды&lt;br /&gt;
;6&lt;br /&gt;
: указанный пользователь не существует&lt;br /&gt;
;8&lt;br /&gt;
: пользователь сейчас работает в системе&lt;br /&gt;
;10&lt;br /&gt;
: не удалось изменить файл групп&lt;br /&gt;
;12&lt;br /&gt;
: не удалось удалить домашний каталог&lt;br /&gt;
== Предостережения ==&lt;br /&gt;
Команда [[userdel]] не будет удалять учётную запись, если пользователь в данный момент работает в системе. Вы должны завершить все запущенные процессы, принадлежащие учётной записи, которую нужно удалить. Нельзя удалить ''NIS'' атрибуты клиента ''NIS''. Это необходимо сделать на ''NIS'' сервере. Если значение переменной ''USERGROUPS_ENAB'' равно ''yes'' в файле ''/etc/login.defs'', то [[userdel]] удалит группу с именем как у пользователя. Чтобы избежать рассогласованности в базах данных групп и паролей, [[userdel]] проверит, что данная группа не используется в качестве первичной для другого пользователя, и выдаст предупреждение без удаления, если такое случится. Параметр ''-f'' поможет удалить группу в любом случае.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Useradd</id>
		<title>Useradd</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Useradd"/>
				<updated>2018-01-09T11:59:14Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''useradd'''(от англ. '''user''' '''add''') — регистрирует нового пользователя или изменяет информацию…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''useradd'''(от англ. '''user''' '''add''') — регистрирует нового пользователя или изменяет информацию по умолчанию о новых пользователях.&amp;lt;br /&amp;gt;&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
'''useradd''' [''параметры''] ''LOGIN''&amp;lt;br /&amp;gt;&lt;br /&gt;
'''useradd -D'''&amp;lt;br /&amp;gt;&lt;br /&gt;
'''useradd -D''' [''параметры'']&amp;lt;br /&amp;gt;&lt;br /&gt;
== Описание ==&lt;br /&gt;
При вызове без опции ''-D'' команда '''''useradd''''' создаёт новую учётную запись пользователя, используя значения, указанные в командной строке, а также значения по умолчанию из системы. В зависимости от параметров командной строки команда '''''useradd''''' будет обновлять системные файлы, а также может создавать домашний каталог нового пользователя и копировать исходные файлы.&amp;lt;br /&amp;gt;&lt;br /&gt;
Когда мы в терминале запускаем команду '''''useradd''''', происходит следующее:&lt;br /&gt;
#Она редактирует файлы ''/etc/passwd'', ''/etc/shadow'', ''/etc/group'' и ''/etc/gshadow'', внося в них нового пользователя.&lt;br /&gt;
#Создаётся и заполняется домашняя директория для нового пользователя.&lt;br /&gt;
#Устанавливаются права доступа и владелец домашней директории.&amp;lt;br /&amp;gt;&lt;br /&gt;
== Параметры ==&lt;br /&gt;
Параметры команды '''''useradd''''':&lt;br /&gt;
;-c, --comment КОММЕНТАРИЙ&lt;br /&gt;
: Любая текстовая строка. Обычно, здесь коротко описывается учётная запись, и в настоящее время используется как поле для имени и фамилии пользователя.&lt;br /&gt;
;-b, --base-dir БАЗОВЫЙ_КАТАЛОГ&lt;br /&gt;
: Базовый каталог по умолчанию для системы, если ''-d HOME_DIR'' не указан. ''BASE_DIR'' объединяется с именем учётной записи, чтобы определить домашний каталог. Если опция ''-m'' не используется, ''BASE_DIR'' должен существовать.&lt;br /&gt;
;-D, --defaults&lt;br /&gt;
: См. Ниже раздел «Изменение значений по умолчанию».&lt;br /&gt;
;-d, --home ДОМАШНИЙ_КАТАЛОГ&lt;br /&gt;
: Для создаваемого пользователя будет использован каталог ''БАЗОВЫЙ_КАТАЛОГ'' в качестве начального каталога. По умолчанию, это значение получается объединением ''ИМЕНИ'' пользователя с ''БАЗОВЫМ_КАТАЛОГОМ'' и используется как имя домашнего каталога. Каталог ''БАЗОВЫЙ_КАТАЛОГ'' необязательно должен существовать и не будет создан, если его нет.&lt;br /&gt;
;-e, --expiredate ДАТА_УСТАРЕВАНИЯ&lt;br /&gt;
: Дата, когда учётная запись пользователя будет заблокирована. Дата задаётся в формате &amp;lt;ГГГГ&amp;gt;-&amp;lt;ММ&amp;gt;-&amp;lt;ДД&amp;gt;.&lt;br /&gt;
;-f, --inactive ДНЕЙ&lt;br /&gt;
: Число дней, которые должны пройти после устаревания пароля, чтобы учётная запись заблокировалась навсегда. Если указано значение 0, то учётная запись блокируется сразу после устаревания пароля, а при значении -1 данная возможность не используется. По умолчанию используется значение -1.&lt;br /&gt;
;-g, --gid ГРУППА&lt;br /&gt;
: Имя или числовой идентификатор новой начальной группы пользователя. Группа с таким именем должна существовать. Идентификатор группы должен указывать на уже существующую группу. Идентификатор группы по умолчанию равен 1 или значению указанному в файле ''/etc/default/useradd''.&lt;br /&gt;
;-G, --groups ГРУППА 1 [,ГРУППА 2,...[,ГРУППА N]]]&lt;br /&gt;
: Список дополнительных групп, в которых числится пользователь. Перечисление групп осуществляется через запятую, без промежуточных пробелов. На указанные группы действуют те же ограничения, что и для группы указанной в параметре ''-g''. По умолчанию пользователь входит только в начальную группу.&lt;br /&gt;
;-h, --help&lt;br /&gt;
: Показать краткую справку и закончить работу.&lt;br /&gt;
;-m, --create-home&lt;br /&gt;
: Если домашнего каталога пользователя не существует, то он будет создан. Файлы из каталога ''КАТАЛОГ_ШАБЛОН'' будут скопированы в домашний каталог, если он указан параметр ''-k'', иначе будут использованы файлы из каталога ''/etc/skel''. Все подкаталоги каталога ''КАТАЛОГ_ШАБЛОН'' или ''/etc/skel'' будут также созданы в домашнем каталоге пользователя. Параметр ''-k'' можно использовать только вместе с параметром ''-m''. По умолчанию, домашний каталог не создаётся и файлы не копируются.&lt;br /&gt;
;-K, --key КЛЮЧ=ЗНАЧЕНИЕ&lt;br /&gt;
: Используется для изменения значений по умолчанию, хранимых в файле ''/etc/login.defs'' (''UID_MIN'', ''UID_MAX'', ''UMASK'', ''PASS_MAX_DAYS'' и других). Пример: ''-K PASS_MAX_DAYS=-1'' можно использовать при создании системной учётной записи, чтобы выключить устаревание пароля, даже если системная учётная запись вообще не имеет пароля. Можно указывать параметр ''-K'' несколько раз, например: ''-K UID_MIN=100 -K UID_MAX=499''. Замечание: запись вида ''-K UID_MIN=10,UID_MAX=499'' пока не работает.&lt;br /&gt;
;-l&lt;br /&gt;
: Не добавляйте пользователя в базы данных ''lastlog'' и ''faillog''. По умолчанию записи пользователя в базе данных ''lastlog'' и ''faillog'' сбрасываются, чтобы избежать повторного использования записи от ранее удаленного пользователя.&lt;br /&gt;
;-N, --no-user-group&lt;br /&gt;
: Не создавать группу с тем же именем, что и пользователь, но добавить пользователя в группу, указанную опцией ''-g'' или переменной ''GROUP'' в ''/etc/default/useradd''. Поведение по умолчанию (если параметры ''-g'', ''-N'' и ''-U'' не указаны) определяется переменной ''USERGROUPS_ENAB'' в ''login.defs''.&lt;br /&gt;
;-o, --non-unique&lt;br /&gt;
: Позволяет создать учётную запись с уже имеющимся (не уникальным) ''UID''.&lt;br /&gt;
;-p, --password ПАРОЛЬ&lt;br /&gt;
: Шифрованное значение пароля, которое возвращает функция '''''crypt'''''. По умолчанию учётная запись заблокирована.&lt;br /&gt;
;-s, --shell ОБОЛОЧКА&lt;br /&gt;
:Имя регистрационной оболочки пользователя. Если задать пустое значение, то будет использована регистрационная оболочка по умолчанию.&lt;br /&gt;
;-u, --uidUID&lt;br /&gt;
: Числовое значение идентификатора пользователя (''ID''). Оно должно быть уникальным, если не используется параметр ''-o''. Значение должно быть неотрицательным. По умолчанию используется наименьшее значение ''ID'' большее 999 и большее любого другого значения пользователя. Значения от 0 до 999 обычно зарезервированы для системных учётных записей.&lt;br /&gt;
;-U, --user-group&lt;br /&gt;
: Создайте группу с тем же именем, что и пользователь, и добавьте пользователя в эту группу. Поведение по умолчанию (если параметры ''-g'', ''-N'' и ''-U'' не указаны) определяется переменной ''USERGROUPS_ENAB'' в ''login.defs''.&lt;br /&gt;
&lt;br /&gt;
== Изменение значений по умолчанию ==&lt;br /&gt;
При вызове только с параметром ''-D'' '''''useradd''''' отображает текущие значения по умолчанию. При вызове с ''-D'' плюс другие параметры, '''''useradd''''' будет обновлять значения по умолчанию для указанных параметров. Допустимыми параметрами изменения по умолчанию являются:&lt;br /&gt;
;-b, --base-dir БАЗОВЫЙ_КАТАЛОГ&lt;br /&gt;
: Префикс пути для домашнего каталога нового пользователя. Имя пользователя будет прикреплено к концу ''BASE_DIR'', чтобы сформировать имя домашнего каталога нового пользователя, если параметр ''-d'' не используется при создании новой учётной записи.&lt;br /&gt;
;-e, --expiredate ДАТА_УСТАРЕВАНИЯ&lt;br /&gt;
: Дата, когда учётная запись пользователя заблокирована.&lt;br /&gt;
;-f, --inactive ДНЕЙ&lt;br /&gt;
: Число дней, которые должны пройти после устаревания пароля, перед тем как учётная запись будет заблокирована.&lt;br /&gt;
;-g, --gid ГРУППА&lt;br /&gt;
: Имя или числовой идентификатор новой начальной группы пользователя. Группа с таким именем должна существовать и для числового идентификатора должна быть запись.&lt;br /&gt;
;-s, --shell ОБОЛОЧКА&lt;br /&gt;
: Имя оболочки входа нового пользователя.&lt;br /&gt;
&lt;br /&gt;
== Замечания ==&lt;br /&gt;
Системный администратор сам решает, какие файлы нужно положить в каталог ''/etc/skel/''.&lt;br /&gt;
&lt;br /&gt;
== Предостережения ==&lt;br /&gt;
Вы не можете добавить пользователя в группу ''NIS'' или ''LDAP''. Это должно быть выполнено на соответствующем сервере. Аналогично, если имя пользователя уже существует во внешней пользовательской базе данных, такой как ''NIS'' или ''LDAP'', '''''useradd''''' будет отклонять запрос на создание учётной записи пользователя. Имена пользователей должны начинаться со строчной буквы или символа подчёркивания, и должны состоять только из строчных букв, подписи, тире и знака доллара. Это можно описать регулярным выражением: [a-z _] [a-z0-9 _-] * [$]&lt;br /&gt;
&lt;br /&gt;
== Конфигурация ==&lt;br /&gt;
Следующие переменные конфигурации в файле ''/etc/login.defs'' изменяют поведение этого инструмента:&lt;br /&gt;
;GID_MAX (number), GID_MIN (number)&lt;br /&gt;
: Диапазон идентификаторов групп, используемых для создания регулярных групп с помощью '''''useradd''''', '''''usermod''''' или '''''newusers'''''.&lt;br /&gt;
;MAIL_DIR (string)&lt;br /&gt;
: Почтовый каталог. Данный параметр нужен для управления почтовым ящиком при изменении или удалении учётной записи пользователя. Если параметр не задан, то используется значение указанное при сборке.&lt;br /&gt;
;MAIL_FILE (string)&lt;br /&gt;
: Определяет расположение файлов пользователей, в которых хранится почта, относительно их домашнего каталога. Переменные ''MAIL_DIR'' и ''MAIL_FILE'' используются '''''useradd''''', '''''usermod''''' и '''''userdel''''' для создания, перемещения или удаления файлов пользователя, в которых хранится почта. Если для ''MAIL_CHECK_ENAB'' установлено значение ''yes'', они также используются для определения переменной среды ''MAIL''.&lt;br /&gt;
;MAX_MEMBERS_PER_GROUP (number)&lt;br /&gt;
: Максимальное количество участников в группе. Когда достигнут максимум, в ''/etc/group'' запускается новая запись(строка) группы (с тем же именем, с тем же паролем и с тем же ''GID''). Значение по умолчанию равно 0, а это означает, что число членов в группе не ограничено. Эта функция (разделённая группа) позволяет ограничить длину строк в файле группы. Это полезно, чтобы убедиться, что строки для групп ''NIS'' не более 1024 символов. Если вам необходимо обеспечить соблюдение такого ограничения, вы можете использовать ''25''. '''Примечание'''. Разделённые группы могут не поддерживаться всеми инструментами (даже в инструменте ''shadow''. Вы не должны использовать эту переменную, если она вам не нужна).&lt;br /&gt;
;PASS_MAX_DAYS (number)&lt;br /&gt;
: Максимальное число дней использования пароля. Если пароль старее этого числа, то будет запущена процедура смены пароля. Если значение не задано, то предполагается значение -1 (то есть возможность ограничения не используется).&lt;br /&gt;
;PASS_MIN_DAYS (number)&lt;br /&gt;
: Максимальное число дней между изменениями пароля. Любая смена пароля ранее заданного срока выполнена не будет. Если значение не задано, то предполагается значение -1 (то есть возможность ограничения не используется).&lt;br /&gt;
;PASS_WARN_AGE (number)&lt;br /&gt;
: Число дней за которое начнёт выдаваться предупреждение об устаревании пароля. Нулевое значение означает, что предупреждение выдаётся в день устаревания, при отрицательном значении предупреждение выдаваться не будет. Если значение не задано, выдача предупреждения отключается.&lt;br /&gt;
;SYS_GID_MAX (number), SYS_GID_MIN (number)&lt;br /&gt;
: Диапазон идентификаторов групп, используемых для создания системных групп с помощью '''''useradd''''', '''''groupadd''''' или '''''newusers'''''.&lt;br /&gt;
;SYS_UID_MAX (number), SYS_UID_MIN (number)&lt;br /&gt;
: Диапазон идентификаторов пользователей, используемых для создания пользователей системы с помощью '''''useradd''''' или '''''newusers'''''.&lt;br /&gt;
;UID_MAX (number), UID_MIN (number)&lt;br /&gt;
: Диапазон идентификаторов пользователей, используемых для создания обычных пользователей с помощью '''''useradd''''' или '''''newusers'''''.&lt;br /&gt;
;UMASK (number)&lt;br /&gt;
: Задаёт начальное значение маски доступа. Если не указано, то маска доступа устанавливается в 022.&lt;br /&gt;
&lt;br /&gt;
== Файлы ==&lt;br /&gt;
;/etc/passwd&lt;br /&gt;
: содержит информацию о пользователях&lt;br /&gt;
;/etc/shadow&lt;br /&gt;
: содержит защищаемую информацию о пользователях&lt;br /&gt;
;/etc/group&lt;br /&gt;
: содержит информацию о группах&lt;br /&gt;
;/etc/default/useradd&lt;br /&gt;
: содержит защищаемую информацию о пользователях&lt;br /&gt;
;/etc/skel/&lt;br /&gt;
: каталог, содержащий пользовательские файлы по умолчанию&lt;br /&gt;
;/etc/login.defs&lt;br /&gt;
: содержит конфигурацию подсистемы теневых паролей&lt;br /&gt;
&lt;br /&gt;
== Возвращаемые значения ==&lt;br /&gt;
;0&lt;br /&gt;
: успешное выполнение&lt;br /&gt;
;1&lt;br /&gt;
: не удалось изменить файл паролей&lt;br /&gt;
;2&lt;br /&gt;
: ошибка в параметрах команды&lt;br /&gt;
;3&lt;br /&gt;
: недопустимое значение параметра&lt;br /&gt;
;4&lt;br /&gt;
: такой UID уже существует (и не задан параметр -o)&lt;br /&gt;
;6&lt;br /&gt;
: указанная группа не существует&lt;br /&gt;
;9&lt;br /&gt;
: имя пользователя уже существует&lt;br /&gt;
;10&lt;br /&gt;
: не удалось изменить файл групп&lt;br /&gt;
;12&lt;br /&gt;
: не удалось создать домашний каталог&lt;br /&gt;
;13&lt;br /&gt;
: не удалось создать почтовый ящик&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Mktemp</id>
		<title>Mktemp</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Mktemp"/>
				<updated>2017-12-07T10:00:16Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Описание ==&lt;br /&gt;
'''mktemp''' (от англ. '''m'''a'''k'''e '''temp'''late) - утилита для создания временного файла или каталога.&amp;lt;br /&amp;gt;&lt;br /&gt;
Создаёт временный файл или каталог, безопасно печатает его имя. ''TEMPLATE'' должен содержать как минимум 3 последовательных символа «''X''» в последнем компоненте. Если ''TEMPLATE'' не указан, используйте '''tmp'''.''XXXXXXXXXX'' и ''--tmpdir''. Файлы создаются с выставленными правами ''u+rw'', а каталоги — ''u+rwx'', минус ограничения [[umask]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Использование ==&lt;br /&gt;
* &amp;lt;tt&amp;gt;mktemp [OPTION] ... [TEMPLATE]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;-d, --directory&lt;br /&gt;
: создать каталог, а не файл.&lt;br /&gt;
&lt;br /&gt;
;-u, --dry-run&lt;br /&gt;
: ничего не создаёт; просто напечатает имя (небезопасно).&lt;br /&gt;
&lt;br /&gt;
;-q, --quiet&lt;br /&gt;
: подавить диагностику ошибки создания файла/каталога.&lt;br /&gt;
&lt;br /&gt;
;--suffix = SUFF&lt;br /&gt;
: добавляет SUFF в TEMPLATE; SUFF &amp;lt;u&amp;gt;не должен содержать косой черты&amp;lt;/u&amp;gt;. Этот параметр подразумевает, если TEMPLATE не заканчивается на X.&lt;br /&gt;
&lt;br /&gt;
;-p DIR, --tmpdir [= DIR]&lt;br /&gt;
: интерпретировать &amp;lt;u&amp;gt;TEMPLATE&amp;lt;/u&amp;gt; относительно &amp;lt;u&amp;gt;DIR&amp;lt;/u&amp;gt;; если &amp;lt;u&amp;gt;DIR&amp;lt;/u&amp;gt; не указан, используйте &amp;lt;u&amp;gt;$TMPDIR&amp;lt;/u&amp;gt;, если установлено, иначе &amp;lt;u&amp;gt;/tmp&amp;lt;/u&amp;gt;. С помощью этой опции, &amp;lt;u&amp;gt;TEMPLATE&amp;lt;/u&amp;gt; не может быть абсолютным именем; в отличие от &amp;lt;u&amp;gt;-t&amp;lt;/u&amp;gt;, &amp;lt;u&amp;gt;TEMPLATE&amp;lt;/u&amp;gt; может содержать косые черты, но [[mktemp]] создаёт только конечный компонент.&lt;br /&gt;
&lt;br /&gt;
;-t &lt;br /&gt;
: интерпретировать &amp;lt;u&amp;gt;TEMPLATE&amp;lt;/u&amp;gt; как единый компонент имени файла относительно каталога &amp;lt;u&amp;gt;$TMPDIR&amp;lt;/u&amp;gt;, если он установлен; иначе каталог указан через '''-p'''; иначе &amp;lt;u&amp;gt;/tmp&amp;lt;/u&amp;gt; [устарело]&lt;br /&gt;
&lt;br /&gt;
;--help&lt;br /&gt;
: отобразить эту справку и выйти&lt;br /&gt;
&lt;br /&gt;
;--version&lt;br /&gt;
: вывести информацию об утилите и выйти&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
[http://www.gnu.org/software/coreutils/ Справочная информация GNU coreutils]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://translationproject.org/team/ Сообщить об ошибках перевода mktemp]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Diskadd</id>
		<title>Diskadd</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Diskadd"/>
				<updated>2017-11-27T07:04:29Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;В данной статье рассматривается вопрос добавления диска и распределения дискового пространства в виртуальной машине '''VMWare''', с установленной ОС '''RHEL 6.x'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Распределение дискового пространства будет проходить на корневую директорию &amp;quot;/&amp;quot; средствами [[lvm]].&lt;br /&gt;
= Добавление HDD в виртуальную машину =&lt;br /&gt;
Для добавления диска в виртуальную машину '''VMWare''', требуется выполнить следующие шаги:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;1)&amp;lt;/span&amp;gt;  В случае, если ВМ, на которой требуется увеличить дисковое пространство, выключена необходимо произвести запуск ВМ.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;2)&amp;lt;/span&amp;gt;  В Библиотеке(&amp;quot;'''''Library'''''&amp;quot;) правой клавишей мыши открыть контекстное меню ВМ, выбрать элемент &amp;quot;'''''Settings'''''&amp;quot;, раскрывшегося контекстного меню.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_01.jpg|900px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;3)&amp;lt;/span&amp;gt;  В открывшемся окне &amp;quot;'''''Virtual Machine Settings'''''&amp;quot;, на вкладке &amp;quot;'''''Hardware'''''&amp;quot;, нажать кнопку &amp;quot;'''''Add'''''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_02.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;4)&amp;lt;/span&amp;gt;  В окне мастера &amp;quot;'''''Add Hardware Wizard'''''&amp;quot; выбрать элемент &amp;quot;'''''Hard Disk'''''&amp;quot; списка &amp;quot;'''''Hardware Types'''''&amp;quot; и нажать кнопку &amp;quot;'''''Next'''''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_03.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;5)&amp;lt;/span&amp;gt;  На вкладке &amp;quot;'''''Select a Disk Type'''''&amp;quot; выбираем рекомендуемые параметры, нажимаем кнопку &amp;quot;'''''Next'''''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_04.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;6)&amp;lt;/span&amp;gt;  На вкладке &amp;quot;'''''Select a Disk'''''&amp;quot;, выбираем значение &amp;quot;'''''Create a new virtual disk'''''&amp;quot;, нажимаем кнопку &amp;quot;'''''Next'''''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_05.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;7)&amp;lt;/span&amp;gt;  На вкладке &amp;quot;'''''Specify Disk Capacity'''''&amp;quot;, выставляем необходимые значения объёма диска(&amp;quot;'''''Maximum disk size'''''&amp;quot;), распределить весь выделенный объём сразу(&amp;quot;'''''Allocate all disk space now'''''&amp;quot;), хранить виртуальный диск в одном(&amp;quot;'''''single file'''''&amp;quot;) или в нескольких(&amp;quot;'''''multiple files'''''&amp;quot;) файлах, нажимаем кнопку &amp;quot;'''''Next'''''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_06.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;8)&amp;lt;/span&amp;gt;  На вкладке &amp;quot;'''''Specify Disk File'''''&amp;quot;, задаём имя файла(&amp;quot;'''''File name'''''&amp;quot;) виртуального диска, нажимаем кнопку &amp;quot;'''''Finish'''''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_07.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;9)&amp;lt;/span&amp;gt;  В окне &amp;quot;'''''Virtual Machine Settings'''''&amp;quot; нажимаем кнопку &amp;quot;'''''Ok'''''&amp;quot;.&lt;br /&gt;
[[File:Vm_add_disk-space_08.jpg|500px|center]]&lt;br /&gt;
&lt;br /&gt;
= Сканирование шины после добавления HDD =&lt;br /&gt;
Если добавить новый жёсткий диск в ВМ(виртуальную машину) VMware, он будет отображён только после перезагрузки виртуальной машины. Необходимо запустить сканирование шины '''''SCSI''''' в рабочей виртуальной машине для принудительного считывания подключенных дисков. Ниже приведены требуемые операции.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;1)&amp;lt;/span&amp;gt; Сначала, необходимо определить идентификатор шины:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; ls /sys/class/scsi_host&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host0&amp;lt;/span&amp;gt;&lt;br /&gt;
В примере идентификатор шины: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host0&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;2)&amp;lt;/span&amp;gt; Затем, принудительное сканирование, замена &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host0&amp;lt;/span&amp;gt; полученными данными:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;# &amp;lt;/nowiki&amp;gt;echo &amp;quot;- - -&amp;quot; &amp;gt; /sys/class/scsi_host/host0/scan&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Теперь можно запустить [[fdisk|fdisk -l]] и посмотреть изменения. Задача решена. В виртуальную машину Linux добавлен диск без необходимости перезагрузки.&amp;lt;br /&amp;gt;&lt;br /&gt;
Может быть случай, когда на первом шаге будет выдан результат, включающий в себя большое количество &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host*&amp;lt;/span&amp;gt;, т.е. будет выведен диапазон значений, например: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host0&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host1&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host2&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host3&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host4&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host5&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;host6&amp;lt;/span&amp;gt;...&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;hostN&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В таком случае, команду принудительного сканирования на шаге &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;2)&amp;lt;/span&amp;gt;, надо выполнять в следующем виде:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;# &amp;lt;/nowiki&amp;gt;cd /sys/class/scsi_host/; for i in /sys/class/scsi_host/host*; do echo &amp;quot;- - -&amp;quot; &amp;gt; $i/scan; done&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
::::::::::или&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;# &amp;lt;/nowiki&amp;gt;for i in {1..N}; do echo &amp;quot;- - -&amp;quot; &amp;gt; /sys/class/scsi_host/host$i/scan; done&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt; где ''N'', максимальное значение идентификатора шины, при выполнении команды &amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt; ls /sys/class/scsi_host&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Расширение корневой партиции средствами lvm =&lt;br /&gt;
В этой главе используется ОС RHEL 6.x (но также применимо к любому другому дистрибутиву Linux), который имеет раздел ''ext4'' '''''lv_root''''', установленный как &amp;quot;/&amp;quot; и '''''lv_swap''''', как своп из группы томов '''''vg_rhel69''''' (по умолчанию), имитируем, что у нас заканчивается пространство в '''''lv_root''''' (&amp;quot;/&amp;quot;) и группе томов ('''''vg_rhel69''''') нет свободного пространства. В предыдущих главах добавили новый диск с объёмом 20 ГБ. Теперь нужно назначить это пространство объёмом 20 ГБ группе томов, а затем расширить '''''lv_root'''''(&amp;quot;/&amp;quot;).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Внимание'''&amp;lt;/span&amp;gt;: '''сохраните все важные данные, хранящиеся на ВМ'''!&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;1)&amp;lt;/span&amp;gt; Сперва проверим использование дискового пространства файловой системы и информацию о логическом томе:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;# df -h&amp;lt;/nowiki&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;# lvs&amp;lt;/nowiki&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_09.jpg|600px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;2)&amp;lt;/span&amp;gt; Получаем информацию о новых добавленных дисках:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; fdisk -l&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_10.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;3)&amp;lt;/span&amp;gt; Создаём партицию на новом жёстком диске, используя LVM(8e)(на рисунке представлена последовательность выполнения операций):&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; fdisk /dev/sdс&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_11.jpg|500px|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;4)&amp;lt;/span&amp;gt; Идентифицируем тип файловой системы на смонтированных устройствах:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; df -T&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_12.JPG|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;5)&amp;lt;/span&amp;gt; Форматируем вновь созданную партицию следующей командой:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; mkfs.ext4 /dev/sdc1&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_13.jpg|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;6)&amp;lt;/span&amp;gt; Инициализируем созданную партицию как физический том:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; pvcreate /dev/sdc1&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_14.jpg|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;7)&amp;lt;/span&amp;gt; Сканируем группы томов используя следующую команду:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; vgs&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_15.jpg|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;8)&amp;lt;/span&amp;gt; Расширяем группу томов (&amp;quot;''''vg_rhel69'''&amp;quot;) новым физическим томом(&amp;quot;'''/dev/sdc1'''&amp;quot;):&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; vgextend vg_rhel69 /dev/sdc1&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_16.jpg|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;9)&amp;lt;/span&amp;gt; Расширим логический том (&amp;quot;'''lv_root'''&amp;quot;) всем свободным пространством группы томов(&amp;quot;'''vg_rhel69'''&amp;quot;):&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; lvextend -l +100%FREE /dev/vg_rhel69/lv_root&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_17.jpg|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;10)&amp;lt;/span&amp;gt; В конце изменяем размер файловой системы на логическом томе &amp;quot;'''lv_root'''&amp;quot;:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; resize2fs /dev/vg_rhel69/lv_root&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_18.jpg|center]]&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;11)&amp;lt;/span&amp;gt; Верифицируем, что корневой раздел на файловой системе увеличен, выполняя следующие команды:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; df -h&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; lvs&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; vgs&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Vm_add_disk-space_19.jpg|center]]&lt;br /&gt;
&lt;br /&gt;
= Ссылки =&lt;br /&gt;
[https://rbgeek.wordpress.com/2013/01/27/how-to-extend-the-root-partition-in-lvm/ Как расширить корневую партицию в LVM]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://melfis.ru/подключение-жестких-дисков-на-горячу/ Подключение HDD на горячую]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://notessysadmin.com/resize-lvm-on-centos7 Особенность расширения LVM тома на CentOS 7]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/ProFTPD_vsFTPD</id>
		<title>ProFTPD vsFTPD</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/ProFTPD_vsFTPD"/>
				<updated>2017-11-21T08:55:38Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
В данной статье кратко описан процесс развёртывание сервиса ftp на серверах с установленными ОС RHEL 6.x(CentOS 6.x) и RHEL 7.x(CetnOS 7.x).&amp;lt;br /&amp;gt;&lt;br /&gt;
Для ОС RHEL 6.x(CentOS 6.x) рассмотрена установка vsFTPD, в то время как для RHEL 7.x(CetnOS 7.x) — ProFTPD. Желательно наличие в системе подключенного репозитория [https://www.shellhacks.com/ru/epel-repo-centos-7-6-install/ EPEL].&lt;br /&gt;
&lt;br /&gt;
== Установка vsFTPD в RHEL 6.x(CentOS 6.x) ==&lt;br /&gt;
1) Создаём пользователя '''''ftpuser''''', назначаем ему домашнюю директорию '''/opt/ftp''':&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; useradd -d '/opt/ftp' -s /sbin/nologin ftpuser&amp;lt;/span&amp;gt;&lt;br /&gt;
2) Устанавливаем пароль для нового пользователя:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; passwd ftpuser&amp;lt;/span&amp;gt;&lt;br /&gt;
3) Создаём группу '''''ftpusers''''' для FTP пользователей, и добавляем в нее '''''ftpuser''''':&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; groupadd ftpusers&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; usermod -G ftpusers ftpuser&amp;lt;span&amp;gt;&lt;br /&gt;
4) Разрешаем пользователю чтение/запись в домашнюю директорию, изменяем права доступа и владельца:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; chown -R ftpuser:ftpusers '/opt/ftp'&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; chmod 775 '/opt/ftp'&amp;lt;/span&amp;gt;&lt;br /&gt;
5) Устанавливаем vsftpd:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; yum install vsftpd -y&amp;lt;/span&amp;gt;&lt;br /&gt;
6) Добавляем сервис в автозагрузку:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; chkconfig --levels 235 vsftpd on&amp;lt;/span&amp;gt;&lt;br /&gt;
7) Стартуем сервис:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; service vsftpd start&amp;lt;/span&amp;gt;&lt;br /&gt;
8) Создаём резервную копию конфигурационного файла vsftpd.conf:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.bkp&amp;lt;/span&amp;gt;&lt;br /&gt;
9) Создаём файл '''/etc/vsftpd/chroot_list''', внеся в него имя пользователя:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; echo 'ftpuser /opt/ftp'&amp;gt;/etc/vsftpd/chroot_list&amp;lt;/span&amp;gt;&lt;br /&gt;
10) Открываем в редакторе ([[vim]], [[vim|vi]], nano) файл '''/etc/vsftpd/vsftpd.conf''', и вносим изменения в следующие параметры (если параметр закомментирован его надо раскомментировать, если отсутствует — создать):&lt;br /&gt;
:::'''anonymous_enable=NO'''&lt;br /&gt;
:::'''local_enable=YES'''&lt;br /&gt;
:::'''write_enable=YES'''&lt;br /&gt;
:::'''local_umask=022'''&lt;br /&gt;
:::'''xferlog_enable=YES'''&lt;br /&gt;
:::'''dual_log_enable=YES'''&lt;br /&gt;
:::'''chown_uploads=YES'''&lt;br /&gt;
:::'''chown_username=ftpuser'''&lt;br /&gt;
:::'''chroot_local_user=YES'''&lt;br /&gt;
:::'''chroot_list_enable=YES'''&lt;br /&gt;
:::'''chroot_list_file=/etc/vsftpd/chroot_list'''&lt;br /&gt;
:::'''use_localtime=YES'''&lt;br /&gt;
11) Перезапускаем сервис, удаляем лишнее:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; service vsftpd restart&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Установка proFTPD в RHEL 7.x(CentOS 7.x) ==&lt;br /&gt;
1) Инсталлируем proftpd:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; yum install -y proftpd proftpd-utils&amp;lt;/span&amp;gt;&lt;br /&gt;
2) Добавляем группу и пользователя '''''vftp''''', задаём пароль:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; groupadd -g 510 vftp&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; useradd -g 510 -u 510 -c 'Virtual FTP User' -d /home/vftp -s /sbin/nologin vftp&amp;lt;span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; passwd vftp&amp;lt;/span&amp;gt;&lt;br /&gt;
3) Создаём '''виртуальных пользователей''' сервиса ''ftp'' и директории:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; /usr/bin/ftpasswd --passwd --file /etc/ftpd.passwd --name=ftpuser --shel=/sbin/nologin --home=/opt/ftp --uid=510 --gid=510&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; mkdir -p /opt/ftp&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; chown -R vftp:vftp /opt/ftp&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; /usr/bin/ftpasswd --group --name=vftp --file=/etc/ftpd.group --gid=510 --member ftpuser&amp;lt;/span&amp;gt;&lt;br /&gt;
4) Комментируем(символ комментария — '''#''') в конфиге '''''/etc/proftpd.conf''''' следующие строки:&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;AuthPAMConfig 		proftpd&amp;lt;/span&amp;gt;'''&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;AuthOrder 		mod_auth_pam.c* mod_auth_unix.c&amp;lt;/span&amp;gt;'''&lt;br /&gt;
5) Редактируем(''добавляем''/''изменяем'') в конфиге '''''/etc/proftpd.conf''''' следующие строки:&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;AuthUserFile /etc/ftpd.passwd&amp;lt;/span&amp;gt;'''&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;AuthGroupFile /etc/ftpd.group&amp;lt;/span&amp;gt;'''&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;AuthOrder mod_auth_file.c&amp;lt;/span&amp;gt;'''&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;RequireValidShell off&amp;lt;/span&amp;gt;'''&lt;br /&gt;
:::'''&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;AuthPAMConfig   proftpd&amp;lt;/span&amp;gt;'''&lt;br /&gt;
6) Проверяем синтаксис конфига:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; proftpd -t&amp;lt;/span&amp;gt;&lt;br /&gt;
7) Настраиваем автозапуск сервиса, стартуем сервис, проверяем статус:&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; systemctl enable proftpd.service&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; systemctl start proftpd.service&amp;lt;/span&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:darkgreen&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;#&amp;lt;/nowiki&amp;gt; systemctl status proftpd.service&amp;lt;/span&amp;gt;&lt;br /&gt;
8) Проверяем доступность ftp сервиса, подключившись под пользователем/паролем ftpuser/ftpuser&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
[http://www.andrewblog.ru/ustanovka-i-nastrojka-ftp-servera-na-freebsd-11-0-release-praktika-ispolzovaniya-proftpd/ Настройка proFTPD на FreeBSD 11]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://habrahabr.ru/sandbox/26850/ Настройка ProFTPd для хостинга]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://kamaok.org.ua/?p=97 Установка и настройка ProFTPD с авторизацией виртуальных пользователей на CentOS]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://www.howtoforge.com/proftpd-centos-7 proFTPD на CentOS 7]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://tnadm.blogspot.ru/2012/08/ftp-proftpd-ubuntu-1204-lts.html FTP-сервер (ProFTPd) на Ubuntu 12.04 LTS]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://thenest.ru/nastrojjka-proftpd-dlya-raboty-s-virtualnymi-polzovatelyami-i-proizvolnymi-direktoriyami/ Настройка proftpd для работы с виртуальными пользователями и произвольными директориями]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://10.160.22.182:9009/scripts/Var_Scripts/blob/master/AutoInstall_FTP.sh Скрипт автоматической инсталляции и настройки ftp]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Sed</id>
		<title>Sed</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Sed"/>
				<updated>2017-11-02T12:24:05Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Полностью отредактировал статью&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
&lt;br /&gt;
Команда [[sed]] - это редактор потока данных ('''S'''tream '''ED'''itor) для автоматического редактирования текстов. &amp;quot;''Редактор потока''&amp;quot; — в том смысле, что может редактировать входящий поток данных непрерывно, скажем, в составе программного канала (''pipe''). ''Автоматически'' — это значит, что, как только вы зададите правила редактирования, дальнейшее происходит без вашего утомительного участия. Другими словами, редактор [[sed]] не является ''интерактивным''.&lt;br /&gt;
&lt;br /&gt;
Программа [[sed]] сложнее, чем те команды, что мы уже успели рассмотреть в предыдущих статьях. В её составе арсенал собственных команд, поэтому, чтобы избежать тавтологии и путаницы, в этой статье команда [[sed]] впредь будет именоваться &amp;quot;''программой''&amp;quot; или &amp;quot;''редактором''&amp;quot;, а команды редактора [[sed]] — просто ''командами''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Программа [[sed]] способна выполнять сложные задания, и нужно потратить время, чтобы научиться эти задания формулировать. Но наряду со сложными действиями, у команды [[sed]] есть простые, но весьма полезные возможности, освоить которые не труднее, чем прочие команды UNIX. Не позволяйте себе из-за сложности освоения всей программы, отказываться от её простых аспектов. Мы начнем от простого к сложному, так что вы всегда сможете понять, где следует остановиться.&lt;br /&gt;
&lt;br /&gt;
=== Команда s — substitution (замена) ===&lt;br /&gt;
&lt;br /&gt;
Программа [[sed]] имеет множество собственных ''команд''. Большинство пользователей знают только команду '''s''', и этого вполне хватает, чтобы работать с редактором [[sed]].&amp;lt;br /&amp;gt; Команда '''s''' заменяет &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; на &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНУ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;sed s/ОБРАЗЕЦ/ЗАМЕНА/&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo день | sed s/день/ночь/&lt;br /&gt;
ночь&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проще не бывает. А вот пример с вводом из файла &amp;lt;u&amp;gt;zar.txt&amp;lt;/u&amp;gt;:&lt;br /&gt;
  По утрам он делал зарядку.&lt;br /&gt;
  Молния — электрический заряд.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed s/заряд/разряд/ zar.txt&lt;br /&gt;
По утрам он делал разрядку.&lt;br /&gt;
Молния — электрический разряд.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Я не брал выражение ''s/ОБРАЗЕЦ/ЗАМЕНА/'' в кавычки, так как данный пример не нуждается в кавычках, но если бы в нём ''присутствовали метасимволы'', то кавычки были бы '''обязательны'''. Чтобы не ломать себе каждый раз голову, и не ошибиться ненароком, всегда ставьте кавычки, лучше более &amp;quot;''сильные''&amp;quot; одинарные(' '), это хорошая привычка. Кашу маслом не испортишь. Я тоже во всех последующих примерах не буду манкировать кавычками.&lt;br /&gt;
&lt;br /&gt;
Как мы видим, заменяющая команда '''s''' имеет четыре составляющих:&lt;br /&gt;
&lt;br /&gt;
  '''''s'''''          —    сама команда&lt;br /&gt;
  '''''/.../.../'''''  —    разделитель&lt;br /&gt;
  '''''ОБРАЗЕЦ'''''    —    образец для поиска и последующей замены&lt;br /&gt;
  '''''ЗАМЕНА'''''     —    выражение, которое заменит собой ''ОБРАЗЕЦ'', если таковой будет найден!&lt;br /&gt;
&lt;br /&gt;
'''Прямой слэш''' ('''/''') используется в качестве разделителя по традиции, так как предок программы [[sed]] — редактор '''ed''' использует их (как и редактор [[Vim|vi]]). В некоторых случаях такой разделитель весьма неудобен, например, когда надо менять пути (''path'') к директориям, которые тоже содержат '''прямой слэш''' ('''/'''usr'''/'''local'''/'''bin). В этом случае приходится разделять прямые слэши обратными:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed 's/\/usr\/local\/bin/\/common\/bin/'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Это называется &amp;quot;'''частокол'''&amp;quot; и выглядит весьма уродливо, а главное, непонятно.&amp;lt;br /&amp;gt;&lt;br /&gt;
Уникальность программы [[sed]] в том, что она позволяет использовать любой разделитель, например знак &amp;lt;u&amp;gt;'''подчёркивания'''&amp;lt;/u&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo день | sed s_день_ночь_&lt;br /&gt;
ночь&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
или &amp;lt;u&amp;gt;'''двоеточие'''&amp;lt;/u&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo день | sed s:день:ночь:&lt;br /&gt;
ночь&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если в поисках разделителя, который вам нравится, вы получаете сообщение &amp;quot;'''''незавершённая команда `s' '''''&amp;quot;, значит этот ''символ'' &amp;lt;u&amp;gt;не годится в качестве разделителя&amp;lt;/u&amp;gt;, или вы просто &amp;lt;u&amp;gt;забыли поставить один-два разделителя&amp;lt;/u&amp;gt;.&lt;br /&gt;
В этой статье я вынужден использовать традиционный разделитель ('''/''') чтобы не сбивать читателя с толку, но в случае необходимости стану использовать в качестве разделителя '''тильду''' ('''~''').&lt;br /&gt;
&lt;br /&gt;
=== Регулярные выражения (РВ) ===&lt;br /&gt;
('''Regular expressions''', '''regexp''', '''RE''')&lt;br /&gt;
&lt;br /&gt;
Тема регулярных выражений настолько обширна, что ей посвящены целые книги (смотри ссылки в конце статьи). Тем не менее, говорить всерьёз о редакторе [[sed]], не применяя регулярных выражений, также непродуктивно, как разговаривать о тригонометрии при помощи счётных палочек. Поэтому необходимо рассказать хотя бы о тех регулярных выражениях, которые часто используются с программой [[sed]].&lt;br /&gt;
&lt;br /&gt;
'''с'''	— или любая другая буква. Большинство букв, цифр и прочих неспециальных символов считаются регулярными выражениями, представляющими сами себя.&lt;br /&gt;
&lt;br /&gt;
'''*'''	— Астериск, следующий за каким-либо символом или регулярным выражением, означает любое число (в том числе и нулевое) повторов этого символа или регулярного выражения.&lt;br /&gt;
&lt;br /&gt;
'''\+''' — Означает один или более повтор символа или регулярного выражения.&lt;br /&gt;
&lt;br /&gt;
'''\?''' — Означает ни одного или один повтор.&lt;br /&gt;
&lt;br /&gt;
'''\{i\}''' — Означает ровно '''i''' повторов.&lt;br /&gt;
&lt;br /&gt;
'''\{i,j\}''' — Число повторов находится в интервале от '''i''' до '''j''' включительно.&lt;br /&gt;
&lt;br /&gt;
'''\{i,\}''' — Число повторов больше или равно '''i'''.&lt;br /&gt;
&lt;br /&gt;
'''\{,j\'''} — Число повторов меньше или равно '''j'''.&lt;br /&gt;
&lt;br /&gt;
'''\(RE\''') — Запомнить регулярное выражение или его часть с целью дальнейшего использования как единое целое. Например, '''\(а-я\)*''' будет искать любое сочетание любого количества (в том числе и нулевого) строчных букв.&lt;br /&gt;
&lt;br /&gt;
'''.'''	— Означает любой символ, в том числе символ новой строки.&lt;br /&gt;
&lt;br /&gt;
'''^''' — Означает нулевое выражение в начале строки. Другими словами, то, перед чем стоит этот знак, должно появляться в начале строки. Например, '''^#include''' будет искать строки, начинающиеся с #include.&lt;br /&gt;
&lt;br /&gt;
'''$'''	— То же, что и предыдущее, только относится к концу строки.&lt;br /&gt;
&lt;br /&gt;
'''[СПИСОК]''' — Означает любой символ из ''СПИСКА''. Например, '''[aeiou]''' будет искать любую &amp;lt;u&amp;gt;английскую гласную букву&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''[^СПИСОК]''' — Означает любой символ, кроме тех, что в списке. Например, '''[^aeiou]''' будет искать &amp;lt;u&amp;gt;любую английскую согласную&amp;lt;/u&amp;gt;. Примечание: ''СПИСОК'' может быть &amp;lt;u&amp;gt;'''интервалом'''&amp;lt;/u&amp;gt;, например '''[а-я]''', что будет означать любую строчную букву. Если нужно включить в ''СПИСОК'' ''']''' (''квадратную скобку'') укажите её в списке &amp;lt;u&amp;gt;первой&amp;lt;/u&amp;gt;; если нужно включить в ''СПИСОК'' '''-''' (''дефис''), то укажите его в списке &amp;lt;u&amp;gt;первым&amp;lt;/u&amp;gt; или &amp;lt;u&amp;gt;последним&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''RE1\|RE2''' — Означает '''РВ1''' или '''РВ2'''.&lt;br /&gt;
&lt;br /&gt;
'''RE1RE2''' — Означает объединение регулярных выражений '''РВ1''' и '''РВ2'''.&lt;br /&gt;
&lt;br /&gt;
'''\n''' — Означает символ &amp;lt;u&amp;gt;новой строки&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''\$; \*; \.; \[; \\; \^''' — Означают соответственно: ''$; *; .; [; \; ^''&lt;br /&gt;
&lt;br /&gt;
'''''Внимание:''''' &amp;lt;u&amp;gt;Остальные условные обозначения на основе '''обратного слэша''' ('''\'''), принятые в языке '''С''', не поддерживаются программой [[sed]]&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''\1 \2 \3 \4 \5 \6 \7 \8 \9''' — Означает соответствующую по счёту часть регулярного выражения, запомненную при помощи знаков '''\(''' и '''\)'''.&lt;br /&gt;
&lt;br /&gt;
'''''Несколько примеров:'''''&lt;br /&gt;
&lt;br /&gt;
'''abcdef'''	—	Означает '''abcdef'''&lt;br /&gt;
&lt;br /&gt;
'''a*b'''	—	Означает ноль или любое количество букв ''''''а и одна буква '''b'''. Например, '''aaaaaab'''; '''ab'''; или '''b'''.&lt;br /&gt;
&lt;br /&gt;
'''a\?b'''	—	Означает '''b''' или '''ab'''&lt;br /&gt;
&lt;br /&gt;
'''a\+b\+'''	—	Означает одну или больше букв '''а''' и одну или больше букв '''b'''. Например: '''ab'''; '''aaaab'''; '''abbbbb'''; или '''aaaaaabbbbbbb'''.&lt;br /&gt;
&lt;br /&gt;
'''.*'''	—	Означает '''все символы на строке''', на '''всех строках''', ''включая пустые''.&lt;br /&gt;
&lt;br /&gt;
'''.\+'''       —	Означает '''все символы на строке''', но '''только на строках''', ''содержащих'' хотя бы ''один символ'''. '''Пустые строки''' ''не соответствуют'' данному регулярному выражению.&lt;br /&gt;
&lt;br /&gt;
'''^main.*(.*)''' —	Будет искать строки, начинающиеся со слова '''main''', а также имеющие в своём составе '''открывающую и закрывающие скобки''', причём ''перед и после открывающей скобки'' может находиться любое количество символов (&amp;lt;u&amp;gt;а может и не находиться&amp;lt;/u&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
'''^#'''	—	Будет искать строки, начинающиеся со знака '''#''' (например ''комментарии'').&lt;br /&gt;
&lt;br /&gt;
'''\\$'''	—	Будет искать строки, заканчивающиеся '''обратным слэшем''' ('''\''').&lt;br /&gt;
&lt;br /&gt;
'''[a-zA-Z_]''' —	Любые '''буквы''' или '''цифры'''&lt;br /&gt;
&lt;br /&gt;
'''[^	 ]\+''' —	Означает '''один''' или '''любое''' количество '''любых символов''', кроме '''пробела''' и '''табуляции'''. Обычно имеется в виду '''слово'''(В квадратной скобке, кроме символа '''^''', содержится ещё '''пробел''' и '''табуляция''').&lt;br /&gt;
&lt;br /&gt;
'''^.*A.*$'''	—	Означает заглавную букву '''А''' точно в ''середине строки''.&lt;br /&gt;
&lt;br /&gt;
'''A.\{9\}$'''  —	Означает заглавную букву '''А''', точно '''десятую по счёту от конца строки'''.&lt;br /&gt;
&lt;br /&gt;
'''^.\{,15\}A''' —	Означает заглавную букву '''А''', точно '''шестнадцатую по счёту от начала строки'''.&lt;br /&gt;
&lt;br /&gt;
Теперь, когда мы познакомились с некоторыми регулярными выражениями, вернемся к команде '''s''' редактора [[sed]].&lt;br /&gt;
&lt;br /&gt;
Использование символа '''&amp;amp;''', когда &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; неизвестен&lt;br /&gt;
&amp;quot;Как это неизвестен?&amp;quot;, — спросите вы — &amp;quot;Ты разве не знаешь, что хочешь заменить?&amp;quot; Отвечу: я хочу взять в скобки любые цифры, найденные в тексте. Как это сделать? Ответ: применить символ '''&amp;amp;'''.&lt;br /&gt;
&lt;br /&gt;
Символ '''&amp;amp;''' ('''амперсанд'''), будучи помещён в состав &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, означает '''любой найденный в тексте''' &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;. Например:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo 1234 | sed 's/[0-9]*/(&amp;amp;)/'&lt;br /&gt;
(1234)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Звёздочка ('''астериск''') после интервала '''[0-9]''' нужна чтобы заменены были все цифры, встретившиеся в &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;. Без неё получилось бы:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo 1234 | sed 's/[0-9]/(&amp;amp;)/'&lt;br /&gt;
(1)234&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
То есть в качестве &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦА''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; взята была первая же найденная цифра.&lt;br /&gt;
&lt;br /&gt;
Вот пример со вполне осмысленной нагрузкой: составим файл &amp;lt;u&amp;gt;formula.txt&amp;lt;/u&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
   a+432-10=n&lt;br /&gt;
&lt;br /&gt;
и применим к нему команду:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed 's/[0-9]*-[0-9]*/(&amp;amp;)/' formula.txt&lt;br /&gt;
a+(432-10)=n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Математическая формула приобрела однозначный смысл.&lt;br /&gt;
&lt;br /&gt;
Ещё символ '''амперсанда''' ('''&amp;amp;''') можно использовать для удвоения &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦА''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo 123 | sed &amp;quot;s/[0-9]*/&amp;amp; &amp;amp;/&amp;quot;&lt;br /&gt;
123 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;Тут есть одна тонкость&amp;lt;/u&amp;gt;. Если мы чуть усложним пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;123 abc&amp;quot; | sed &amp;quot;s/[0-9]*/&amp;amp; &amp;amp;/&amp;quot;&lt;br /&gt;
123 123 abc&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
как и следовало ожидать, удваиваются только цифры, так как в &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; нет букв. Но если мы поменяем части текста местами:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;abc 123&amp;quot; | sed &amp;quot;s/[0-9]*/&amp;amp; &amp;amp;/&amp;quot;&lt;br /&gt;
abc 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
то никакого удвоения цифр не получится. Это особенность регулярного выражения '''[0-9]*''' — оно ищет соответствия только в первом символе строки. Если мы хотим удвоения цифр, где бы они ни находились, нужно доработать регулярное выражение в &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo &amp;quot;abc defg 123&amp;quot; | sed &amp;quot;s/[0-9][0-9]*/&amp;amp; &amp;amp;/&amp;quot;&lt;br /&gt;
abc defg 123 123&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
тогда цифры будут удваиваться, независимо от количества предшествующих &amp;quot;слов&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Использование условных знаков '''\(''', '''\)''' и '''\1''' для обработки части &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦА''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
Условные знаки '''\(''' и '''\)''' (''escaped parentheses'') применяются для запоминания части регулярного выражения.&lt;br /&gt;
&lt;br /&gt;
Условный знак '''\1''' означает первую запомненную часть, '''\2''' — вторую, и так далее, вплоть до девяти запомненных частей (больше программа не поддерживает). Разберём пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo abcd123 | sed 's/\([a-z]*\).*/\1/'&lt;br /&gt;
abcd&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Здесь '''\([a-z]*\)''' означает, что программа должна запомнить все буквенные символы в любом количестве; '''.*''' означает любое количество символов после первой запомненной части; а '''\1''' означает , что мы хотим видеть только первую запомненную часть. Так и есть: в выводе программы мы видим только буквы и никаких цифр.&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы ''поменять'' &amp;lt;u&amp;gt;слова местами&amp;lt;/u&amp;gt;, нужно ''запомнить'' два суб-&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦА''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, а потом поменять их местами:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo глупый пингвин |sed 's/\([а-я]*\) \([а-я]*\)/\2 \1/'&lt;br /&gt;
пингвин глупый&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Здесь '''\2''' означает второй суб-&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, а '''\1''' — первый. Обратите внимание на интервал между первым выражением '''\([а-я]*\)''' и вторым выражением '''\([а-я]*\)'''. Он необходим, чтобы были найдены &amp;lt;u&amp;gt;два слова&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Знак '''\1''' вовсе не обязан быть только в &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, он может присутствовать также и в &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, например, когда мы хотим '''удалить''' ''дубликаты слов'':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo пингвин пингвин | sed 's/\([а-я]*\) \1/\1/'&lt;br /&gt;
пингвин&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Модификаторы замены команды s ===&lt;br /&gt;
&lt;br /&gt;
Модификаторы замены ставятся после последнего разделителя. Эти модификаторы определяют действия программы в случае, если в строке нашлось более одного совпадения с &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦОМ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, и каким образом производить замену.&lt;br /&gt;
&lt;br /&gt;
'''Модификатор /g'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Глобальная замена (Global replacement)&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Программа [[sed]], как и большинство утилит UNIX, при работе с файлами считывают по одной строке. Если мы приказываем заменить слово, программа заменит только первое совпавшее с &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦОМ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; слово на данной строке. Если мы хотим изменить каждое слово, совпавшее с &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦОМ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, то следует ввести модификатор '''/g'''.&lt;br /&gt;
&lt;br /&gt;
Без модификатора '''/g''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo кот этот, был самый обычный кот | sed 's/кот/котёнок/'&lt;br /&gt;
котёнок этот, был самый обычный кот&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Редактор заменил только первое совпавшее слово.&lt;br /&gt;
&lt;br /&gt;
А теперь с модификатором глобальной замены:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo кот этот, был самый обычный кот | sed 's/кот/котёнок/g'&lt;br /&gt;
котёнок этот, был самый обычный котёнок&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Все''' совпадения в данной строке были заменены.&lt;br /&gt;
&lt;br /&gt;
А если нужно изменить '''все слова''', скажем взять их в скобки? Тогда на помощь снова придут регулярные выражения. Чтобы выбрать все буквенные символы, как верхнего, так и нижнего регистра, можно воспользоваться конструкцией '''[А-Яа-я]''', но в неё не попадут такие слова как &amp;quot;что-то&amp;quot; или &amp;quot;с'езд&amp;quot;. Гораздо удобнее конструкция '''[^ ]*''', которая соответствует всем символам, кроме '''пробела'''. Итак:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo глупый пингвин робко прячет | sed 's/[^ ]*/(&amp;amp;)/g'&lt;br /&gt;
(глупый) (пингвин) (робко) (прячет)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Как выбрать нужное совпадение из нескольких'''&lt;br /&gt;
&lt;br /&gt;
Если не применять модификаторов, то программа [[sed]] заменит только первое совпавшее с &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦОМ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; слово. Если применить модификатор ''/g'', то программа заменит ''каждое совпавшее слово''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;u&amp;gt;А как можно выбрать одно из совпадений, если их несколько на строке?&amp;lt;/u&amp;gt; — При помощи уже знакомых нам условных знаков '''\(''' и '''\)''' запомнить суб-&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; и выбрать нужный при помощи знаков '''\1''' - '''\9'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo глупый пингвин | sed 's/\([а-я]*\) \([а-я]*\)/\2 /'&lt;br /&gt;
пингвин&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В этом примере мы запомнили оба слова, и, поставив второе (пингвин) на первое место, первое (глупый) удалили, поставив в секции &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; вместо него '''пробел'''. Если мы поставим вместо '''пробела''' какое-либо слово, то оно заменит первое (глупый):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo глупый пингвин | sed 's/\([а-я]*\) \([а-я]*\)/\2 умный /'&lt;br /&gt;
пингвин умный&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Числовой модификатор'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Это одно/двух/трёх-значное число, которое ставится после последнего разделителя и указывает, какое по счёту совпадение подлежит замене&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo очень глупый пингвин | sed 's/[а-я]*/хороший/2'&lt;br /&gt;
очень хороший пингвин&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В этом примере каждое слово является совпадением, и мы указали редактору, какое по счёту слово мы хотим заменить, поставив модификатор 2 после секции &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Можно комбинировать цифровой модификатор с модификатором '''/g'''. Если нужно оставить неизменным первое слово, а второе и последующие заменить на слово &amp;quot;(удалено)&amp;quot;, то команда будет такая:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo очень глупый пингвин | sed 's/[а-я]*/(удалено)/2g'&lt;br /&gt;
очень (удалено) (удалено)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если нужно действительно удалить все последующие совпадения, кроме первого, то в секции &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; следует поставить '''пробел''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo очень глупый пингвин | sed 's/[а-я]*/ /2g'&lt;br /&gt;
очень&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или вовсе ничего не ставить:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo очень глупый пингвин | sed 's/[^ ]*//2g'&lt;br /&gt;
очень&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Числовой модификатор может быть любым целым числом от '''1''' до '''512'''. Например, если нужно поставить '''двоеточие''' ''после'' '''80''' символа ''каждой строки'', то поможет команда:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  $ sed 's/./&amp;amp;:/80' имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Модификатор /p - выдавать на стандартный выход (печатать - print)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Программа [[sed]] и так по умолчанию выдаёт результат на стандартный выход (например экран монитора). Этот модификатор применяется только с опцией '''sed -n''', которая как раз блокирует вывод результата на экран&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Модификатор /w'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Позволяет записывать результаты обработки текста в указанный файл&amp;lt;/span&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed 's/ОБРАЗЕЦ/ЗАМЕНА/w имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Модификатор /e (расширение GNU)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Позволяет указать команду шелла (не программы sed) в качестве&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;. Если соответствие &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦУ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; будет найдено, то оно будет заменено на вывод указанной в секции &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; команды. Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo ночь | sed 's/ночь/echo день/e'&lt;br /&gt;
день&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Модификаторы /I и /i (расширение GNU)'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Делают процесс замены нечувствительным к регистру символов&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo Night | sed 's/night/day/i'&lt;br /&gt;
day&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Комбинации модификаторов'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkblue&amp;quot;&amp;gt;Модификаторы можно комбинировать, когда это имеет смысл. При этом следует ставить модификатор w последним&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
''Условные обозначения (расширение GNU'')&lt;br /&gt;
Их всего пять:&lt;br /&gt;
&lt;br /&gt;
'''\L''' — переводит символы &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; в нижний регистр&lt;br /&gt;
'''\l''' — переводит следующий символ &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; в нижний регистр&lt;br /&gt;
'''\U''' — переводит символы &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; в верхний регистр&lt;br /&gt;
'''\u''' — переводит следующий символ &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; в верхний регистр&lt;br /&gt;
'''\E''' — отменяет перевод, начатый '''\L''' или '''\U'''&lt;br /&gt;
По очевидным причинам эти условные обозначения применяются по одиночке. Например:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo глупый пингвин | sed 's/глупый/\u&amp;amp;/'&lt;br /&gt;
Глупый пингвин&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
или:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo маленький щенок | sed 's/[а-я]*/\u&amp;amp;/2'&lt;br /&gt;
маленький Щенок&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Мы рассмотрели почти все аспекты команды '''s''' редактора [[sed]]]. Теперь настала очередь рассмотреть опции этой программы.&lt;br /&gt;
&lt;br /&gt;
== Опции программы sed ==&lt;br /&gt;
&lt;br /&gt;
Программа имеет на удивление мало опций. (Что несколько компенсирует избыток команд, модификаторов и прочих функций). Кроме общеизвестных опций '''--help''' ('''-h''') и '''--version''' ('''-V'''), которые мы рассматривать не будем, их всего три:&lt;br /&gt;
&lt;br /&gt;
'''Опция -e'''&lt;br /&gt;
''--expression=набор_команд''&lt;br /&gt;
&lt;br /&gt;
Один из способов выполнения нескольких команд - применение опции ''-e''. Например:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed -e 's/a/A/' -e 's/b/B/' имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Все предыдущие примеры в этой статье не требовали применения опции '''-e''' только потому, что содержали одну команду. Мы могли поставить в примерах опцию '''-e''', это ничего бы не изменило.&lt;br /&gt;
&lt;br /&gt;
'''Опция -f'''&lt;br /&gt;
Если требуется выполнить большое количество команд, то удобнее записать их в файл и применить опцию '''-f''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed -f sedscript имя-файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Sedscript''' здесь — имя файла, содержащего команды. Этот файл называется скриптом программы [[sed]] (далее просто скрипт). Каждая команда скрипта должна занимать отдельную строку. Например:&lt;br /&gt;
&lt;br /&gt;
  # комментарий — Этот скрипт изменит все строчные гласные буквы на заглавные&lt;br /&gt;
  s/a/A/g&lt;br /&gt;
  s/e/E/g&lt;br /&gt;
  s/i/I/g&lt;br /&gt;
  s/o/O/g&lt;br /&gt;
  s/u/U/g&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Назвать скрипт можно как угодно, важно не путать файл скрипта с обрабатываемым файлом&amp;lt;/u&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''Опция -n'''&lt;br /&gt;
Программа '''sed -n''' не выводит ничего на стандартный выход. Чтобы получить вывод нужно специальное указание. Мы уже познакомились с модификатором '''/p''', при помощи которого можно дать такое указание. Вспомним файл zar.txt:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed 's/1-9/&amp;amp;/p' zar.txt&lt;br /&gt;
По утрам он делал зарядку.&lt;br /&gt;
Молния - электрический заряд.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так как совпадений с &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦОМ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; не найдено (в файле нет цифр), то команда '''s''' с модификатором '''/p''' и знаком '''&amp;amp;''' в качестве &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЫ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; (напомню, что '''амперсанд''' означает сам &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;), работает как команда [[cat]].&lt;br /&gt;
&lt;br /&gt;
Если &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; будет найден в файле, то строки, содержащие &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, будут удвоены:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed 's/зарядку/&amp;amp;/p' zar.txt&lt;br /&gt;
По утрам он делал зарядку.&lt;br /&gt;
По утрам он делал зарядку.&lt;br /&gt;
Молния - электрический заряд.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь добавим опцию '''-n''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -n 's/зарядк/&amp;amp;/p' zar.txt&lt;br /&gt;
По утрам он делал зарядку.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь наша программа работает, как команда [[grep]] — возвращает только строки, содержащие &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Выбор нужных элементов редактируемого текста ==&lt;br /&gt;
&lt;br /&gt;
Используя лишь одну команду '''s''', мы убедились в необыкновенно широких возможностях редактора [[sed]]. А ведь всё, что он делает, сводится к поиску и замене. Причём в процессе работы [[sed]] редактирует каждую строку поодиночке, не обращая внимания на другие. Было бы удобно ограничить круг строк, подлежащих изменению, например:&lt;br /&gt;
* Выбирать строки по номерам&lt;br /&gt;
* Выбирать строки в некотором диапазоне номеров&lt;br /&gt;
* Выбирать только строки, содержащие некое выражение&lt;br /&gt;
* Выбирать только строки между некоторыми выражениями&lt;br /&gt;
* Выбирать только строки от начала файла и до некоторого выражения&lt;br /&gt;
* Выбирать только строки от некоторого выражения и до конца файла&lt;br /&gt;
&lt;br /&gt;
Программа [[sed]] умеет всё это и даже больше. Любая команда редактора [[sed]] может применяться адресно, в некотором диапазоне адресов, или с вышеперечисленными ограничениями круга строк. Адрес или ограничение должны непосредственно предшествовать команде:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed 'адрес/ограничение команда'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Выбор строк по номерам'''&lt;br /&gt;
&lt;br /&gt;
Это самый простой случай. Просто указываем номер нужной строки перед командой:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '4 s/[а-я]*//i' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
В ранних сумерках утра,&lt;br /&gt;
В таянии вешнего снега,&lt;br /&gt;
всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '3 s/В/(В)/' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
В ранних сумерках утра,&lt;br /&gt;
(В) таянии вешнего снега,&lt;br /&gt;
Во всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Выбор строк в диапазоне номеров'''&lt;br /&gt;
&lt;br /&gt;
Диапазон указывается, как не удивительно, через запятую:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '2,3 s/В/(В)/' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
(В) ранних сумерках утра,&lt;br /&gt;
(В) таянии вешнего снега,&lt;br /&gt;
Во всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если нужно указать диапазон до последней строки файла, а вы не знаете, сколько в нём строк, то воспользуйтесь знаком '''$''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '2,$ s/в/(в)/i' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
(в) ранних сумерках утра,&lt;br /&gt;
(в) таянии вешнего снега,&lt;br /&gt;
(в)о всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Выбор строк, содержащих некое выражение'''&lt;br /&gt;
&lt;br /&gt;
Искомое выражение заключается в прямые слэши ('''/''') и ставится перед командой:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '/утра/ s/в/(в)/i' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
(в) ранних сумерках утра,&lt;br /&gt;
В таянии вешнего снега,&lt;br /&gt;
Во всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Выбор строк в диапазоне между двумя выражениями'''&lt;br /&gt;
&lt;br /&gt;
Также как и в случае с номерами строк, диапазон задается через запятую:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '/утра/,/мудро/ s/в/(в)/i' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
(в) ранних сумерках утра,&lt;br /&gt;
(в) таянии вешнего снега,&lt;br /&gt;
(в)о всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Выбор строк от начала файла и до некоего выражения'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '1,/снега/ s/в/(в)/i' gumilev.txt &lt;br /&gt;
Какая странная нега&lt;br /&gt;
(в) ранних сумерках утра,&lt;br /&gt;
(в) таянии вешнего снега,&lt;br /&gt;
Во всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Выбор строк от некоего выражения и до конца файла'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '/снега/,$ s/в/(в)/i' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
В ранних сумерках утра,&lt;br /&gt;
(в) таянии вешнего снега,&lt;br /&gt;
(в)о всем, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Другие команды редактора sed ==&lt;br /&gt;
&lt;br /&gt;
'''Команда d (delete)'''&lt;br /&gt;
&lt;br /&gt;
Удаляет из стандартного вывода указанные строки:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '2 d' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
В таянии вешнего снега,&lt;br /&gt;
Во всем, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Причём чаще пишут проще (без пробела):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed '2d' gumilev.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Все, что было сказано в предыдущем разделе о адресации строк, справедливо и для команды '''d''' (как и для почти всех команд редактора [[sed]]).&lt;br /&gt;
&lt;br /&gt;
При помощи команды '''d''' удобно выбросить ненужную &amp;quot;шапку&amp;quot; какого-нибудь почтового сообщения:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  $ sed '1,/^$/ d' имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(Удалить строки с первой и до первой пустой строки).&lt;br /&gt;
&lt;br /&gt;
Избавится от комментариев в конфигурационном файле:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
   $ sed '/^#/ d' /boot/grub/menu.lst&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
И мало ли, где нужно удалить лишние строчки!&lt;br /&gt;
&lt;br /&gt;
'''Команда p (print)'''&lt;br /&gt;
&lt;br /&gt;
Английское слово &amp;quot;print&amp;quot; переводится как &amp;quot;печатать&amp;quot;, что в русском языке ассоциируется с принтером, или, по крайней мере, с клавиатурой. На самом же деле, слово это в английском контексте зачастую означает просто вывод на экран монитора. Так что команда '''p''' ничего не печатает, а просто выводит на экран указанные строки.&lt;br /&gt;
&lt;br /&gt;
Будучи применённой сама по себе, команда '''p''' удваивает строки в выводе (ведь программа [[sed]] по умолчанию выводит строку на экран, а команда '''p''' выводит ту же строку вторично).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo у меня есть кот | sed 'p'&lt;br /&gt;
у меня есть кот&lt;br /&gt;
у меня есть кот&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Этому свойству находится применение, например удвоить пустые строки для улучшения вида текста:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '/^$/ p имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Но истинное своё лицо команда '''p''' раскрывает в сочетании с опцией '''-n''', которая, как вы помните, запрещает вывод строк на экран. Комбинируя опцию '''-n''' с командой '''p''', можно получить в выводе только нужные строки.&lt;br /&gt;
&lt;br /&gt;
Например, просмотреть строки с первой по десятую:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -n '1,10 p' имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или только комментарии:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -n '/^#/ p' /boot/grub/menu.lst&lt;br /&gt;
# GRUB configuration file '/boot/grub/menu.lst'.&lt;br /&gt;
# generated by 'grubconfig'.  Вск 23 Мар 2008 21:45:41&lt;br /&gt;
#&lt;br /&gt;
# Start GRUB global section&lt;br /&gt;
# End GRUB global section&lt;br /&gt;
# Linux bootable partition config begins&lt;br /&gt;
# Linux bootable partition config ends&lt;br /&gt;
# Linux bootable partition config begins&lt;br /&gt;
# Linux bootable partition config ends&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
Что весьма напоминает работу программы [[grep]], с чем мы уже сталкивались, когда говорили об опции '''-n''' с модификатором '''/p'''. Но, в отличие от команды [[grep]], редактор [[sed]] даёт возможность не только найти эти строки, но и изменить их, заменив, например, везде Linux на Unix:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -n '/^#/ p' /boot/grub/menu.lst | sed 's/Linux/Unix/'&lt;br /&gt;
# GRUB configuration file '/boot/grub/menu.lst'.&lt;br /&gt;
# generated by 'grubconfig'.  Вск 23 Мар 2008 21:45:41&lt;br /&gt;
#&lt;br /&gt;
# Start GRUB global section&lt;br /&gt;
# End GRUB global section&lt;br /&gt;
# Unix bootable partition config begins&lt;br /&gt;
# Unix bootable partition config ends&lt;br /&gt;
# Unix bootable partition config begins&lt;br /&gt;
# Unix bootable partition config ends&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Команда !'''&lt;br /&gt;
&lt;br /&gt;
Иногда нужно бывает редактировать все строки, кроме тех, что соответствуют &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦУ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, либо выбору. Символ восклицательного знака ('''!''') инвертирует выбор. Например удалим все строки, кроме второй из четверостишия Гумилева:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed '2 !d' gumilev.txt&lt;br /&gt;
В ранних сумерках утра,&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или выберем все строки, кроме комментариев, из файла /boot/grub/menu.lst:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$  sed -n '/^#/ !p' /boot/grub/menu.lst&lt;br /&gt;
default 1&lt;br /&gt;
timeout 20&lt;br /&gt;
gfxmenu (hd0,3)/boot/message&lt;br /&gt;
title SuSe on (/dev/hda3)&lt;br /&gt;
root (hd0,2)&lt;br /&gt;
kernel /boot/vmlinuz root=/dev/hda3 ro vga=773 acpi=off&lt;br /&gt;
title Linux on (/dev/hda4)&lt;br /&gt;
root (hd0,3)&lt;br /&gt;
kernel /boot/vmlinuz root=/dev/hda4 ro vga=0x317&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Команда q (quit)'''&lt;br /&gt;
&lt;br /&gt;
Команда '''q''' прекращает работу программы [[sed]] после указанной строки. Это удобно, если нужно прекратить редактирование после достижения определенного места в тексте:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$  sed '11 q' имя_файла&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Эта команда закончит работу по достижению 11-й строки.&lt;br /&gt;
&lt;br /&gt;
Команда '''q''' — одна из немногих команд [[sed]], не принимающих диапазонов строк. Не может же команда прекратить работу 10 раз подряд, если мы введём:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed '1,10 q'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Абсурд!&lt;br /&gt;
&lt;br /&gt;
'''Команда w (write)'''&lt;br /&gt;
&lt;br /&gt;
Подобно модификатору '''w''' команды '''s''', эта команда позволяет записать вывод программы в файл:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -n '3,$ w gum.txt' gumilev.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Мы получим файл gum.txt, содержащий две последние строки четверостишия Гумилёва из файла gumilev.txt. Причём, если такой файл уже существует, то будет перезаписан. Если не ввести опцию '''-n''', то программа, кроме создания файла gum.txt, еще и выведет на экран все содержание файла gumilev.txt.&lt;br /&gt;
&lt;br /&gt;
Для работы в командной строке, удобнее пользоваться обычным перенаправлением вывода ('''&amp;gt;''' или '''&amp;gt;&amp;gt;'''), но в [[sed]] скриптах, вероятно, команда '''w''' найдёт своё применение.&lt;br /&gt;
&lt;br /&gt;
'''Команда r (read)'''&lt;br /&gt;
&lt;br /&gt;
Эта команда не только прочтёт указанный файл, но и вставит его содержимое в нужное место редактируемого файла. Для выбора &amp;quot;нужного места&amp;quot; используется уже знакомая нам адресация (по номерам строк, по выражениям, и проч.). Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ echo Из стихотворения Гумилева: | sed 'r gumilev.txt'&lt;br /&gt;
Из стихотворения Гумилева:&lt;br /&gt;
Какая странная нега&lt;br /&gt;
В ранних сумерках утра,&lt;br /&gt;
В таянии вешнего снега,&lt;br /&gt;
Во всем, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Команда ='''&lt;br /&gt;
&lt;br /&gt;
Выдаст номер указанной строки:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed  '/снега/=' gumilev.txt&lt;br /&gt;
Какая странная нега&lt;br /&gt;
В ранних сумерках утра,&lt;br /&gt;
3&lt;br /&gt;
В таянии вешнего снега,&lt;br /&gt;
Во всём, что гибнет и мудро.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Или:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ sed -n  '/снега/=' gumilev.txt&lt;br /&gt;
3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Команда принимает только один адрес, не принимает интервалов.&lt;br /&gt;
&lt;br /&gt;
'''Команда y'''&lt;br /&gt;
&lt;br /&gt;
Эта команда заменяет символы из секции &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЕЦ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; символами секции &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНА''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;, работая как программа ''tr''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$  echo Автомобиль — наследие прошлого | sed 'y/Авто/Паро/'&lt;br /&gt;
Паромобиль — наследие прошлого&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''y''' работает, только если количество символов в &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ОБРАЗЦЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt; равно количеству символов в &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;u&amp;gt;''ЗАМЕНЕ''&amp;lt;/u&amp;gt;&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Скрипты программы sed ==&lt;br /&gt;
&lt;br /&gt;
Для того, чтобы пользоваться редактором [[sed]] как полноценным текстовым редактором, необходимо освоить составление скриптов [[sed]]. Программа [[sed]] имеет собственный несложный язык программирования, позволяющий составлять скрипты, способные творить чудеса.&lt;br /&gt;
&lt;br /&gt;
Эта статья не может вместить описания скриптов [[sed]], как и её автор не ставит себе задачу освоение языка программирования [[sed]]. В этой статье я делал акцент на использование редактора [[sed]] в командной строке, имея прицел на использование его в качестве фильтра в программных каналах (''pipes''). По этой причине я опустил многочисленные команды [[sed]], применяющиеся только в его скриптах.&lt;br /&gt;
&lt;br /&gt;
Существует множество любителей редактора [[sed]], и множество статей на тему скриптописания, в том числе и в Рунете. Так что для заинтересовавшихся этой замечательной программой не составит труда пополнить свои знания.&lt;br /&gt;
&lt;br /&gt;
=== Программа sed и символы кириллицы ===&lt;br /&gt;
&lt;br /&gt;
Как видно из примеров в этой статье, программа [[sed]] на правильно русифицированной системе свободно владеет &amp;quot;великим и могучим&amp;quot; языком.&lt;br /&gt;
&lt;br /&gt;
== Резюме программы sed ==&lt;br /&gt;
&lt;br /&gt;
Программа [[sed]] — это многофункциональный редактор потока данных, незаменимый для:&lt;br /&gt;
* Редактирования больших текстовых массивов&lt;br /&gt;
* Редактирования файлов любой величины, когда последовательность редактирующих действий слишком сложна&lt;br /&gt;
* Редактирования данных по мере их поступления, в том числе в режиме реального времени — то есть в случаях, когда затруднительно или вовсе невозможно использовать интерактивные текстовые редакторы.&lt;br /&gt;
&lt;br /&gt;
Для освоения программы [[sed]] в полном объёме потребуются недели или даже месяцы работы, так как для этого необходимо:&lt;br /&gt;
&lt;br /&gt;
* Изучить регулярные выражения&lt;br /&gt;
* Научиться писать скрипты [[sed]], освоив несложный язык программирования, применяющийся в этих скриптах&lt;br /&gt;
&lt;br /&gt;
С другой стороны, освоить несколько наиболее употребительных команд редактора [[sed]] не сложнее, чем любую команду UNIX; надеюсь, данная статья поможет вам в этом.&lt;br /&gt;
&lt;br /&gt;
== Таблица соответствия спецсимволов ==&lt;br /&gt;
Использование '''HEX-16''' позволяет вставлять спецсимволы&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Символ в ASCII'''&amp;lt;/span&amp;gt; !! &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''Соответствие в HEX-16'''&amp;lt;/span&amp;gt; !! &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Символ в ASCII'''&amp;lt;/span&amp;gt; !! &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''Соответствие в HEX-16'''&amp;lt;/span&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''!''' || style=&amp;quot;text-align:center;&amp;quot; | \x21 || style=&amp;quot;text-align:center;&amp;quot; | '''&amp;quot;''' || style=&amp;quot;text-align:center;&amp;quot; | \x22&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''#''' || style=&amp;quot;text-align:center;&amp;quot; | \x23 || style=&amp;quot;text-align:center;&amp;quot; | '''$''' || style=&amp;quot;text-align:center;&amp;quot; | \x24&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''%''' || style=&amp;quot;text-align:center;&amp;quot; | \x25 || style=&amp;quot;text-align:center;&amp;quot; | '''&amp;amp;''' || style=&amp;quot;text-align:center;&amp;quot; | \x26&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | ''' ' ''' || style=&amp;quot;text-align:center;&amp;quot; | \x27 || style=&amp;quot;text-align:center;&amp;quot; | '''(''' || style=&amp;quot;text-align:center;&amp;quot; | \x28&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | ''')''' || style=&amp;quot;text-align:center;&amp;quot; | \x29 || style=&amp;quot;text-align:center;&amp;quot; | '''*''' || style=&amp;quot;text-align:center;&amp;quot; |\x2A&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''+''' || style=&amp;quot;text-align:center;&amp;quot; | \x2B || style=&amp;quot;text-align:center;&amp;quot; | ''',''' || style=&amp;quot;text-align:center;&amp;quot; | \x2C&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-''' || style=&amp;quot;text-align:center;&amp;quot; | \x2D || style=&amp;quot;text-align:center;&amp;quot; | '''.''' || style=&amp;quot;text-align:center;&amp;quot; | \x2E&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''/''' || style=&amp;quot;text-align:center;&amp;quot; | \x2F || style=&amp;quot;text-align:center;&amp;quot; | '''0''' || style=&amp;quot;text-align:center;&amp;quot; | \x30&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''1''' || style=&amp;quot;text-align:center;&amp;quot; | \x31 || style=&amp;quot;text-align:center;&amp;quot; | '''2''' || style=&amp;quot;text-align:center;&amp;quot; | \x32&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''3''' || style=&amp;quot;text-align:center;&amp;quot; | \x33 || style=&amp;quot;text-align:center;&amp;quot; | '''4''' || style=&amp;quot;text-align:center;&amp;quot; | \x34&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''5''' || style=&amp;quot;text-align:center;&amp;quot; | \x35 || style=&amp;quot;text-align:center;&amp;quot; | '''6''' || style=&amp;quot;text-align:center;&amp;quot; | \x36&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''7''' || style=&amp;quot;text-align:center;&amp;quot; | \x37 || style=&amp;quot;text-align:center;&amp;quot; | '''8''' || style=&amp;quot;text-align:center;&amp;quot; | \x38&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''9''' || style=&amp;quot;text-align:center;&amp;quot; | \x39 || style=&amp;quot;text-align:center;&amp;quot; | ''':''' || style=&amp;quot;text-align:center;&amp;quot; | \x3A&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | ''';''' || style=&amp;quot;text-align:center;&amp;quot; | \x3B || style=&amp;quot;text-align:center;&amp;quot; | '''&amp;lt;''' || style=&amp;quot;text-align:center;&amp;quot; | \x3C&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''=''' || style=&amp;quot;text-align:center;&amp;quot; | \x3D || style=&amp;quot;text-align:center;&amp;quot; | '''&amp;gt;''' || style=&amp;quot;text-align:center;&amp;quot; | \x3E&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''?''' || style=&amp;quot;text-align:center;&amp;quot; | \x3F || style=&amp;quot;text-align:center;&amp;quot; | '''@''' || style=&amp;quot;text-align:center;&amp;quot; | \x40&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''A''' || style=&amp;quot;text-align:center;&amp;quot; | \x41 || style=&amp;quot;text-align:center;&amp;quot; | '''B''' || style=&amp;quot;text-align:center;&amp;quot; | \x42&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''C''' || style=&amp;quot;text-align:center;&amp;quot; | \x43 || style=&amp;quot;text-align:center;&amp;quot; | '''D''' || style=&amp;quot;text-align:center;&amp;quot; | \x44&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''E''' || style=&amp;quot;text-align:center;&amp;quot; | \x45 || style=&amp;quot;text-align:center;&amp;quot; | '''F''' || style=&amp;quot;text-align:center;&amp;quot; | \x46&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''G''' || style=&amp;quot;text-align:center;&amp;quot; | \x47 || style=&amp;quot;text-align:center;&amp;quot; | '''H''' || style=&amp;quot;text-align:center;&amp;quot; | \x48&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''I''' || style=&amp;quot;text-align:center;&amp;quot; | \x49 || style=&amp;quot;text-align:center;&amp;quot; | '''J''' || style=&amp;quot;text-align:center;&amp;quot; | \x4A&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''K''' || style=&amp;quot;text-align:center;&amp;quot; | \x4B || style=&amp;quot;text-align:center;&amp;quot; | '''L''' || style=&amp;quot;text-align:center;&amp;quot; | \x4C&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''M''' || style=&amp;quot;text-align:center;&amp;quot; | \x4D || style=&amp;quot;text-align:center;&amp;quot; | '''N''' || style=&amp;quot;text-align:center;&amp;quot; | \x4E&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''O''' || style=&amp;quot;text-align:center;&amp;quot; | \x4F || style=&amp;quot;text-align:center;&amp;quot; | '''P''' || style=&amp;quot;text-align:center;&amp;quot; | \x50&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''Q''' || style=&amp;quot;text-align:center;&amp;quot; | \x51 || style=&amp;quot;text-align:center;&amp;quot; | '''R''' || style=&amp;quot;text-align:center;&amp;quot; | \x52&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''S''' || style=&amp;quot;text-align:center;&amp;quot; | \x53 || style=&amp;quot;text-align:center;&amp;quot; | '''T''' || style=&amp;quot;text-align:center;&amp;quot; | \x54&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''U''' || style=&amp;quot;text-align:center;&amp;quot; | \x55 || style=&amp;quot;text-align:center;&amp;quot; | '''V''' || style=&amp;quot;text-align:center;&amp;quot; | \x56&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''W''' || style=&amp;quot;text-align:center;&amp;quot; | \x57 || style=&amp;quot;text-align:center;&amp;quot; | '''X''' || style=&amp;quot;text-align:center;&amp;quot; | \x58&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''Y''' || style=&amp;quot;text-align:center;&amp;quot; | \x59 || style=&amp;quot;text-align:center;&amp;quot; | '''Z''' || style=&amp;quot;text-align:center;&amp;quot; | \x5A&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[''' || style=&amp;quot;text-align:center;&amp;quot; | \x5B || style=&amp;quot;text-align:center;&amp;quot; | '''\''' || style=&amp;quot;text-align:center;&amp;quot; | \x5C&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | ''']''' || style=&amp;quot;text-align:center;&amp;quot; | \x5D || style=&amp;quot;text-align:center;&amp;quot; | '''^''' || style=&amp;quot;text-align:center;&amp;quot; | \x5E&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''_''' || style=&amp;quot;text-align:center;&amp;quot; | \x5F || style=&amp;quot;text-align:center;&amp;quot; | '''`''' || style=&amp;quot;text-align:center;&amp;quot; | \x60&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''a''' || style=&amp;quot;text-align:center;&amp;quot; | \x61 || style=&amp;quot;text-align:center;&amp;quot; | '''b''' || style=&amp;quot;text-align:center;&amp;quot; | \x62&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''c''' || style=&amp;quot;text-align:center;&amp;quot; | \x63 || style=&amp;quot;text-align:center;&amp;quot; | '''d''' || style=&amp;quot;text-align:center;&amp;quot; | \x64&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''e''' || style=&amp;quot;text-align:center;&amp;quot; | \x65 || style=&amp;quot;text-align:center;&amp;quot; | '''f''' || style=&amp;quot;text-align:center;&amp;quot; | \x66&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''g''' || style=&amp;quot;text-align:center;&amp;quot; | \x67 || style=&amp;quot;text-align:center;&amp;quot; | '''h''' || style=&amp;quot;text-align:center;&amp;quot; | \x68&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''i''' || style=&amp;quot;text-align:center;&amp;quot; | \x69 || style=&amp;quot;text-align:center;&amp;quot; | '''j''' || style=&amp;quot;text-align:center;&amp;quot; | \x6A&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''k''' || style=&amp;quot;text-align:center;&amp;quot; | \x6B || style=&amp;quot;text-align:center;&amp;quot; | '''l''' || style=&amp;quot;text-align:center;&amp;quot; | \x6C&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''m''' || style=&amp;quot;text-align:center;&amp;quot; | \x6D || style=&amp;quot;text-align:center;&amp;quot; | '''n''' || style=&amp;quot;text-align:center;&amp;quot; | \x6E&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''o''' || style=&amp;quot;text-align:center;&amp;quot; | \x6F || style=&amp;quot;text-align:center;&amp;quot; | '''p''' || style=&amp;quot;text-align:center;&amp;quot; | \x70&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''q''' || style=&amp;quot;text-align:center;&amp;quot; | \x71 || style=&amp;quot;text-align:center;&amp;quot; | '''r''' || style=&amp;quot;text-align:center;&amp;quot; | \x72&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s''' || style=&amp;quot;text-align:center;&amp;quot; | \x73 || style=&amp;quot;text-align:center;&amp;quot; | '''t''' || style=&amp;quot;text-align:center;&amp;quot; | \x74&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''u''' || style=&amp;quot;text-align:center;&amp;quot; | \x75 || style=&amp;quot;text-align:center;&amp;quot; | '''v''' || style=&amp;quot;text-align:center;&amp;quot; | \x76&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''w''' || style=&amp;quot;text-align:center;&amp;quot; | \x77 || style=&amp;quot;text-align:center;&amp;quot; | '''x''' || style=&amp;quot;text-align:center;&amp;quot; | \x78&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''y''' || style=&amp;quot;text-align:center;&amp;quot; | \x79 || style=&amp;quot;text-align:center;&amp;quot; | '''z''' || style=&amp;quot;text-align:center;&amp;quot; | \x7A&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''{''' || style=&amp;quot;text-align:center;&amp;quot; | \x7B || style=&amp;quot;text-align:center;&amp;quot; | '''&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;''' || style=&amp;quot;text-align:center;&amp;quot; | \x7C&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''}''' || style=&amp;quot;text-align:center;&amp;quot; | \x7D || style=&amp;quot;text-align:center;&amp;quot; | '''~''' || style=&amp;quot;text-align:center;&amp;quot; | \x7E&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''DEL''' || style=&amp;quot;text-align:center;&amp;quot; | \x7F || || &lt;br /&gt;
|}&lt;br /&gt;
Пример использования:&amp;lt;br /&amp;gt;&lt;br /&gt;
Требуется: заменить '''&amp;quot;hello&amp;quot;,''' на '''&amp;quot;hello world&amp;quot;,'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed 's/\x22hello\x22\x2C/\x22hello world\x22\x2C/g'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
За основу статьи взята информация с [http://open-club.ru/main/reading/HuMan_sed open-club.ru]&amp;lt;br /&amp;gt;&lt;br /&gt;
Таблица символов [http://defindit.com/ascii.html ASCII]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://habrahabr.ru/company/ruvds/blog/327530/ Bash-скрипты, часть 7: sed и обработка текстов]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://rus-linux.net/MyLDP/consol/sed.html Изучаем команды Linux: sed]&amp;lt;br /&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Max_Open_Files</id>
		<title>Max Open Files</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Max_Open_Files"/>
				<updated>2017-10-18T07:45:13Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Добавлена страница &amp;quot;Max Open Files&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:В процессе настройки ОС RHEL(5.x-7.x)/CentOS(5.x-7.x) необходимо осуществить обязательную настройку дескрипторов на каждой системе:&amp;lt;br /&amp;gt;&lt;br /&gt;
''Все действия'' необходимо производить под правами суперпользователя root(или используя утилиту '''''sudo'''''). Изменить файл ''limits.conf'' находящийся по пути ''/etc/security/'' с добавлением ниже описанных строк в ''начале файла'':&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''* soft stack 2048'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''* hard stack 2048'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''* soft nproc 65536'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''* hard nproc 65536'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''* soft nofile 1024000'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''* hard nofile 1024000'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При этом необходимо сохранить закомментированные строки. &lt;br /&gt;
* Изменить файл ''20-nproc.conf''(RHEL 7.x/CentOS 7.x) в директории ''/etc/security/limits.d'' закомментировав в нём строку таким образом:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''# * soft nproc 4096'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* Изменить файл ''90-nproc.conf''(RHEL 5.x-6.x/CentOS 5.x-6.x) в директории ''/etc/security/limits.d'' закомментировав в нём строку таким образом:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;'''''# * soft nproc 1024'''''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для вступления параметров в силу необходимо перезагрузить ОС. Проверка вступления параметров в силу осуществляется с помощью следующих команд:&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''# ulimit –n''''' — ''Максимальное количество открытых файлов''. &amp;lt;u&amp;gt;Значение 1024000&amp;lt;/u&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''# ulimit –s''''' — ''Размер стека''. &amp;lt;u&amp;gt;Значение 2048&amp;lt;/u&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''# ulimit –u''''' — ''Максимальное число процессов''. &amp;lt;u&amp;gt;Значение 65536&amp;lt;/u&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ссылки:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://linux-notes.org/uvelichit-max-open-file-limit-v-linux/ Увеличение Max Open Files Limit в Unix/Linux]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://www.tecmint.com/increase-set-open-file-limits-in-linux/ Increase Open Files Limit]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_ZooKeeper_%D0%BD%D0%B0_%D0%9E%D0%A1_CentOS_7.3</id>
		<title>Установка ZooKeeper на ОС CentOS 7.3</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/%D0%A3%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0_ZooKeeper_%D0%BD%D0%B0_%D0%9E%D0%A1_CentOS_7.3"/>
				<updated>2017-07-28T11:33:53Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
На данной странице приводится инструкция по установке прикладного ПО ''Zookeeper'' на ОС RHEL и CentOS веток 5.x-6.x, 7.x.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''ZooKeeper''''' — распределённый сервис конфигурирования и синхронизации, не знаю как вам, но мне данное определение мало что раскрывает. Оглядываясь на свой опыт, могу дать альтернативное определение '''''ZooKeeper''''', это распределенное ''&amp;lt;u&amp;gt;key&amp;lt;/u&amp;gt;''/''&amp;lt;u&amp;gt;value&amp;lt;/u&amp;gt;''(''&amp;lt;u&amp;gt;ключ&amp;lt;/u&amp;gt;''/''&amp;lt;u&amp;gt;значение&amp;lt;/u&amp;gt;'') хранилище со следующими свойствами:&lt;br /&gt;
* ''пространство ключей образует &amp;lt;u&amp;gt;дерево&amp;lt;/u&amp;gt; (иерархию подобную файловой системе)'';&lt;br /&gt;
* ''значения могут содержаться в любом &amp;lt;u&amp;gt;узле&amp;lt;/u&amp;gt; иерархии, а не только в &amp;lt;u&amp;gt;листьях&amp;lt;/u&amp;gt; (как если бы файлы одновременно были бы и каталогами), &amp;lt;u&amp;gt;узел&amp;lt;u/&amp;gt; иерархии называется &amp;lt;u&amp;gt;znode&amp;lt;/u&amp;gt;'';&lt;br /&gt;
* ''между клиентом и сервером двунаправленная связь, следовательно, клиент может подписываться как изменение конкретного значения или части иерархии'';&lt;br /&gt;
* ''возможно создать временную пару &amp;lt;u&amp;gt;ключ&amp;lt;/u&amp;gt;/&amp;lt;u&amp;gt;значение&amp;lt;/u&amp;gt;, которая существует, пока клиент, её создавший, подключен к кластеру'';&lt;br /&gt;
* ''все данные должны помещаться в память'';&lt;br /&gt;
* ''устойчивость к смерти некритического кол-ва узлов кластера(наличие &amp;lt;u&amp;gt;кворума&amp;lt;/u&amp;gt;)''.&lt;br /&gt;
&lt;br /&gt;
== Установка ПО Zookeeper на RHEL/CentOS 6.x ==&lt;br /&gt;
Для инсталляции будет использоваться [http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz zookeeper версии 3.4.6]. &lt;br /&gt;
В файл ''~/.bash_profile'', пользователя из-под которого планируется запуск сервисов, должны быть внесены переменные окружения ''JAVA''/''JRUBY'':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# .bash_profile&lt;br /&gt;
&lt;br /&gt;
# Get the aliases and functions&lt;br /&gt;
if [ -f ~/.bashrc ]; then&lt;br /&gt;
        . ~/.bashrc&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# User specific environment and startup programs&lt;br /&gt;
&lt;br /&gt;
PATH=/opt/java/bin:$PATH:$HOME/bin:/opt/jruby/bin&lt;br /&gt;
JRUBY_HOME=/opt/jruby&lt;br /&gt;
PATH=$PATH:$HOME/bin&lt;br /&gt;
&lt;br /&gt;
export PATH&lt;br /&gt;
export JRUBY_HOME&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В данном примере настройка ПО ''ZooKeeper'' выполняется под суперпользователем &amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;root&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
В данной главе рассматривается вариант установки ПО ''ZooKeeper'' на 6 хостах(&amp;lt;u&amp;gt;'''официальная документация рекомендует использовать нечётное кол-во хостов — 3, 5, 7 и т.д.'''&amp;lt;/u&amp;gt;). При этом, в данном случае, для работы ПО ''ZooKeeper'' необходимо обеспечить &amp;lt;u&amp;gt;постоянную&amp;lt;/u&amp;gt; работу любых четырёх узлов ПО ''ZooKeeper'' из шести. &amp;lt;br /&amp;gt;&lt;br /&gt;
Для установки ПО ''ZooKeeper'' на серверах,  необходимо выполнить следующие команды на сервере:&amp;lt;br /&amp;gt;&lt;br /&gt;
::::&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;1)&amp;lt;/span&amp;gt;'''# wget &amp;lt;nowiki&amp;gt;http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz&amp;lt;/nowiki&amp;gt; -O /opt/zookeeper.tar.gz'''&amp;lt;br /&amp;gt;&lt;br /&gt;
::::::::::::::::::::::или&lt;br /&gt;
::::&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# wget &amp;lt;nowiki&amp;gt;http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz&amp;lt;/nowiki&amp;gt; -O /opt/zookeeper.tar.gz'''&lt;br /&gt;
::::&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;2)&amp;lt;/span&amp;gt;'''# cd /opt; tar zxvf zookeeper.tar.gz &amp;amp;&amp;amp; mv zookeeper-3.4.6 zookeeper; chmod +x -R zookeeper/ &amp;amp;&amp;amp; mkdir -p /opt/zookeeper/{data,log}'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# sed -i &amp;quot;s|#!/usr/bin/env bash|#!/usr/bin/env bash \n . ~/.bash_profile|&amp;quot; /opt/zookeeper/bin/zkEnv.sh'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# sed -i &amp;quot;s|ZOO_LOG_DIR=\x22\x2E\x22|ZOO_LOG_DIR=\x22/opt/zookeeper/log\x22|&amp;quot; /opt/zookeeper/bin/zkEnv.sh'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# sed -i &amp;quot;s|ZOO_LOG4J_PROP=\x22INFO,CONSOLE\x22|ZOO_LOG4J_PROP=\x22INFO,ROLLINGFILE\x22|&amp;quot; /opt/zookeeper/bin/zkEnv.sh'''&lt;br /&gt;
::::&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;3)&amp;lt;/span&amp;gt;'''# cat &amp;gt;&amp;gt;/opt/zookeeper/conf/zoo.cfg&amp;lt;&amp;lt;EOF'''&lt;br /&gt;
::::'''# Конфигурационный файл ZooKeeper'''&lt;br /&gt;
::::'''# Порт для подключения клиентов'''&lt;br /&gt;
::::'''clientPort=3000'''&lt;br /&gt;
::::'''# Путь к директории с данными ZooKeeper'''&lt;br /&gt;
::::'''dataDir=/opt/zookeeper/data'''&lt;br /&gt;
::::'''# Длина такта (в миллисекундах)'''&lt;br /&gt;
::::'''tickTime=2000'''&lt;br /&gt;
::::'''# Количество тактов для подключения к лидеру и синхронизации с ним'''&lt;br /&gt;
::::'''initLimit=10'''&lt;br /&gt;
::::'''# Количество тактов для синхронизации с лидером'''&lt;br /&gt;
::::'''syncLimit=5'''&lt;br /&gt;
::::'''# Периодичность удаления старых данных ZooKeeper (в часах). 0 - не удалять.'''&lt;br /&gt;
::::'''autopurge.purgeInterval=1'''&lt;br /&gt;
::::'''# Количество файлов, оставляемое при удалении старых данных'''&lt;br /&gt;
::::'''autopurge.snapRetainCount=3'''&lt;br /&gt;
::::'''# Адреса всех серверов кластера ZooKeeper'''&lt;br /&gt;
::::'''# Формат: server.number=host:leader_port:election_port[:observer]'''&lt;br /&gt;
::::'''server.1=&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_1&amp;lt;/span&amp;gt;:3001:3002'''&lt;br /&gt;
::::'''server.2=&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_2&amp;lt;/span&amp;gt;:3001:3002'''&lt;br /&gt;
::::'''server.3=&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_3&amp;lt;/span&amp;gt;:3001:3002'''&lt;br /&gt;
::::'''server.4=&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_4&amp;lt;/span&amp;gt;:3001:3002'''&lt;br /&gt;
::::'''server.5=&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_5&amp;lt;/span&amp;gt;:3001:3002'''&lt;br /&gt;
::::'''server.6=&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_6&amp;lt;/span&amp;gt;:3001:3002'''&lt;br /&gt;
::::'''EOF'''&lt;br /&gt;
::::&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;4)&amp;lt;/span&amp;gt;'''# chown user_dev:user_dev -R /opt/zookeeper/ &amp;amp;&amp;amp; scp -Cqr  /opt/zookeeper/ root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_2&amp;lt;/span&amp;gt;:/opt/;'''&amp;lt;br /&amp;gt;&amp;amp;ensp;&amp;amp;nbsp;'''# scp -Cqr  /opt/zookeeper/ root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_3&amp;lt;/span&amp;gt;:/opt/'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# scp -Cqr  /opt/zookeeper/ root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_4&amp;lt;/span&amp;gt;:/opt/'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# scp -Cqr  /opt/zookeeper/ root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_5&amp;lt;/span&amp;gt;:/opt/'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# scp -Cqr  /opt/zookeeper/ root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_6&amp;lt;/span&amp;gt;:/opt/'''&lt;br /&gt;
::::&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;5)&amp;lt;/span&amp;gt;'''# echo '1' &amp;gt; /opt/zookeeper/data/myid;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_2&amp;lt;/span&amp;gt; &amp;quot;echo 2 &amp;gt; /opt/zookeeper/data/myid &amp;amp;&amp;amp; chown user_dev. /opt/zookeeper/data/myid;&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_3&amp;lt;/span&amp;gt; &amp;quot;echo 3 &amp;gt; /opt/zookeeper/data/myid &amp;amp;&amp;amp; chown user_dev. /opt/zookeeper/data/myid;&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_4&amp;lt;/span&amp;gt; &amp;quot;echo 4 &amp;gt; /opt/zookeeper/data/myid &amp;amp;&amp;amp; chown user_dev. /opt/zookeeper/data/myid;&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_5&amp;lt;/span&amp;gt; &amp;quot;echo 5 &amp;gt; /opt/zookeeper/data/myid &amp;amp;&amp;amp; chown user_dev. /opt/zookeeper/data/myid;&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_6&amp;lt;/span&amp;gt; &amp;quot;echo 6 &amp;gt; /opt/zookeeper/data/myid &amp;amp;&amp;amp; chown user_dev. /opt/zookeeper/data/myid;&amp;quot;'''&lt;br /&gt;
::::&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;6)&amp;lt;/span&amp;gt;'''# chmod +x /opt/zookeeper/check_zoo.sh; sleep 0.2; echo '*/1 * * * * /opt/zookeeper/check_zoo.sh' &amp;gt;&amp;gt; /var/spool/cron/root'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_2&amp;lt;/span&amp;gt; &amp;quot;chmod +x /opt/zookeeper/check_zoo.sh; sleep 0.2; echo '*/1 * * * * /opt/zookeeper/check_zoo.sh' &amp;gt;&amp;gt; /var/spool/cron/root&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_3&amp;lt;/span&amp;gt; &amp;quot;chmod +x /opt/zookeeper/check_zoo.sh; sleep 0.2; echo '*/1 * * * * /opt/zookeeper/check_zoo.sh' &amp;gt;&amp;gt; /var/spool/cron/root&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_4&amp;lt;/span&amp;gt; &amp;quot;chmod +x /opt/zookeeper/check_zoo.sh; sleep 0.2; echo '*/1 * * * * /opt/zookeeper/check_zoo.sh' &amp;gt;&amp;gt; /var/spool/cron/root&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_5&amp;lt;/span&amp;gt; &amp;quot;chmod +x /opt/zookeeper/check_zoo.sh; sleep 0.2; echo '*/1 * * * * /opt/zookeeper/check_zoo.sh' &amp;gt;&amp;gt; /var/spool/cron/root&amp;quot;'''&amp;lt;br /&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;'''# ssh root@&amp;lt;span style=&amp;quot;color:darkred&amp;quot;&amp;gt;ip_addr_6&amp;lt;/span&amp;gt; &amp;quot;chmod +x /opt/zookeeper/check_zoo.sh; sleep 0.2; echo '*/1 * * * * /opt/zookeeper/check_zoo.sh' &amp;gt;&amp;gt; /var/spool/cron/root&amp;quot;'''&lt;br /&gt;
&lt;br /&gt;
== Установка ПО Zookeeper на RHEL/CentOS 7.x ==&lt;br /&gt;
Для инсталляции будет использоваться [http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz zookeeper версии 3.4.10]. &lt;br /&gt;
В файл ~/.bash_profile, пользователя из-под которого планируется запуск сервисов, должны быть внесены переменные окружения JAVA/JRUBY:&lt;br /&gt;
 # .bash_profile&lt;br /&gt;
 # Get the aliases and functions&lt;br /&gt;
 if [ -f ~/.bashrc ]; then&lt;br /&gt;
       . ~/.bashrc&lt;br /&gt;
 fi&amp;lt;br /&amp;gt;&lt;br /&gt;
 # User specific environment and startup programs&lt;br /&gt;
 PATH=/opt/java/bin:$PATH:$HOME/bin:/opt/jruby/bin&lt;br /&gt;
 JRUBY_HOME=/opt/jruby&lt;br /&gt;
 PATH=$PATH:$HOME/bin&amp;lt;br /&amp;gt;&lt;br /&gt;
 export PATH&lt;br /&gt;
 export JRUBY_HOME&lt;br /&gt;
&lt;br /&gt;
Все действия выполняются под пользователем root(&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;сервер 10.160.20.186&amp;lt;/span&amp;gt;, владельцем директорий будет пользователь ''user_dev'', запуск сервиса будет осуществляться из-под пользователя ''user_dev''): &lt;br /&gt;
* '''Переходим в каталог /opt и скачиваем актуальную версию ПО Zookeeper(в нашем случае — 3.4.10) с официального сайта'''&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''# cd /opt &amp;amp;&amp;amp; wget &amp;lt;nowiki&amp;gt;http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz&amp;lt;/nowiki&amp;gt;'''&amp;lt;/span&amp;gt;&lt;br /&gt;
* '''Распаковываем скачанный архив, переименовываем директорию, назначаем владельцем пользователя ''user_dev'' '''&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''# tar xzvf zookeeper-3.4.10.tar.gz &amp;amp;&amp;amp; mv zookeeper-3.4.10 zookeeper &amp;amp;&amp;amp; chown user_dev. -R /opt/zookeeper'''&amp;lt;/span&amp;gt;&lt;br /&gt;
* '''Настраиваем инстанс ''zookeeper'' на сервере''': &lt;br /&gt;
 '''a)''' Добавляем в файл zkEnv.sh строку &amp;quot;. ~/.bash_profile&amp;quot; сразу после строки &amp;quot;#!/usr/bin/env bash&amp;quot; (для упрощения приводится команда [[sed]]):&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# sed -i &amp;quot;s|#!/usr/bin/env bash|#!/usr/bin/env bash \n . ~/.bash_profile|&amp;quot; /opt/zookeeper/bin/zkEnv.sh&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''b)''' Изменяем параметр ZOO_LOG_DIR в файле zkEnv.sh(для упрощения приводится команда sed):&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# sed -i &amp;quot;s|ZOO_LOG_DIR=\x22\x2E\x22|ZOO_LOG_DIR=\x22/opt/zookeeper/log\x22|&amp;quot; /opt/zookeeper/bin/zkEnv.sh&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''c)''' Изменяем параметр ZOO_LOG4J_PROP в файле zkEnv.sh(для упрощения приводится команда [[sed]]):&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# sed -i &amp;quot;s|ZOO_LOG4J_PROP=\x22INFO,CONSOLE\x22|ZOO_LOG4J_PROP=\x22INFO,ROLLINGFILE\x22|&amp;quot; /opt/zookeeper/bin/zkEnv.sh&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''d)''' Создаём директории data и log:&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#  mkdir -p /opt/zookeeper/{data,log}&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''e)''' Создаём файл myid в директории data и в него помещаем значение 1:&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# echo '1' &amp;gt; /opt/zookeeper/data/myid&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''f)''' Настраиваем файл /opt/zookeeper/conf/zoo.cfg, далее приведена настройка для сервера 10.160.22.186:&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# echo &amp;gt; /opt/zookeeper/conf/zoo.cfg&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# cat &amp;gt;&amp;gt;/opt/zookeeper/conf/zoo.cfg &amp;lt;&amp;lt;EOF&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#   ZooKeeper   node2 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#.... &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;clientPort=3010 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#      ZooKeeper &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;dataDir=/opt/zookeeper/data &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#   ( ) &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;tickTime=2000 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#.......... &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;initLimit=20 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#...... &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;syncLimit=10 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#     ZooKeeper ( ). 0 -  . &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;autopurge.purgeInterval=1 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#  ,..... &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;autopurge.snapRetainCount=3 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;#     ZooKeeper &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# : server.number=host:leader_port:election_port[:observer] &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;server.1=10.160.22.186:3001:3002 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;server.2=10.160.22.186:3003:3004 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;server.3=10.160.22.188:3005:3006 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;server.4=10.160.22.188:3007:3008 &amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;EOF &amp;lt;/span&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
 '''g)''' Создаём файл сервиса ZooKeeper:&lt;br /&gt;
  &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# touch /etc/systemd/system/ZooKeeper.service&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''h)''' Редактируем созданный на этапе '''g''') файл:&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;# cat &amp;gt;&amp;gt; /etc/systemd/system/ZooKeeper.service &amp;lt;&amp;lt;EOF&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;[Unit]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Description=Apache Zookeeper server.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;&amp;lt;nowiki&amp;gt;Documentation=http://zookeeper.apache.org&amp;lt;/nowiki&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Requires=network.target remote-fs.target.&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;After=network.target remote-fs.target&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;br /&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;[Service]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Type=forking&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;User=user_dev&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Group=user_dev&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;ExecStart=/opt/zookeeper/bin/zkServer.sh start&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;ExecStop=/opt/zookeeper/bin/zkServer.sh stop&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;ExecReload=/opt/zookeeper/bin/zkServer.sh restart&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Restart=always&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;br/&amp;gt;		&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;[Install]&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;WantedBy=multi-user.target&amp;lt;/span&amp;gt;&lt;br /&gt;
 &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;EOF&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;		&lt;br /&gt;
* '''Назначаем владельцем директорий /opt/zookeeper пользователя user_dev:'''&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''#chown user_dev. -R /opt/zookeeper'''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Добавляем сервис ZooKeeper.service в автозагрузку:'''&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''# systemctl enable ZooKeeper.service&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Запускаем сервисы:'''&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''#systemctl daemon-reload &amp;amp;&amp;amp; systemctl start ZooKeeper.service&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Проверяем статусы сервиса:'''&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''#systemctl status ZooKeeper.service&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
	&lt;br /&gt;
 * ZooKeeper.service - Apache Zookeeper server&lt;br /&gt;
    Loaded: loaded (/etc/systemd/system/ZooKeeper.service; enabled; vendor preset: disabled)&lt;br /&gt;
    Active: active (running) since Пт 2017-07-28 08:44:33 MSK; 1h 2min ago&lt;br /&gt;
     Docs: &amp;lt;nowiki&amp;gt;http://zookeeper.apache.org&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
   Process: 2275 ExecStart=/opt/zookeeper/bin/zkServer.sh start (code=exited, status=0/SUCCESS)&lt;br /&gt;
  Main PID: 2290 (java)&lt;br /&gt;
    CGroup: /system.slice/ZooKeeper.service&lt;br /&gt;
            L-2290 java -Dzookeeper.log.dir=/opt/zookeeper/log -Dzookeeper.root.logger=INFO,ROLLINGFILE -cp /o &lt;br /&gt;
  pt/zookeeper/bin/../build/classes:/opt/zookeeper/bin/../build/lib/*.jar:/op...&lt;br /&gt;
 июл 28 08:44:32 VM-V-App-03 systemd[1]: Starting Apache Zookeeper server...&lt;br /&gt;
 июл 28 08:44:32 VM-V-App-03 zkServer.sh[2275]: ZooKeeper JMX enabled by default&lt;br /&gt;
 июл 28 08:44:32 VM-V-App-03 zkServer.sh[2275]: Using config: /opt/zookeeper/bin/../conf/zoo.cfg&lt;br /&gt;
 июл 28 08:44:33 VM-V-App-03 systemd[1]: Started Apache Zookeeper server.&lt;br /&gt;
&lt;br /&gt;
* '''Перезагружаем сервер, после чего проверяем загрузились ли сервисы ZooKeeper'''&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;P.S.&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt; ==&lt;br /&gt;
'''''Для проверки получения ответа с сервера 10.160.22.186 выполним команды на сервере 10.160.22.188(должен быть инсталлирован netcat):'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''# echo &amp;quot;ruok&amp;quot; | nc 10.160.22.186 3010  ; echo '''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''# echo &amp;quot;ruok&amp;quot; | nc 10.160.22.186 3020  ; echo '''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
[http://zookeeper.apache.org Apache Zookeeper Home]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://apache-mirror.rbc.ru/pub/apache/zookeeper/zookeeper-3.4.10/zookeeper-3.4.10.tar.gz Пакет ПО Zookeeper версии 3.4.10]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://habrahabr.ru/post/144708/ ZooKeeper или пишем сервис распределенных блокировок ]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://10.160.22.182:9009/scripts/Var_Scripts/blob/master/zk_inst_kbsh_tk2.sh Скрипт первоначальной установки ZooKeeper]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://10.160.22.182:9009/scripts/Var_Scripts/tree/master Репозиторий со скриптами автоматизации установки ZooKeeper]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Advanced_Bash-Scripting_Guide</id>
		<title>Advanced Bash-Scripting Guide</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Advanced_Bash-Scripting_Guide"/>
				<updated>2017-06-22T09:28:17Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''bash''' (от англ. '''B'''ourne '''a'''gain '''sh'''ell, каламбур «Born again» shell — «возрождённый» shell) — усовершенствованная и модернизированная вариация командной оболочки Bourne shell. Одна из наиболее популярных современных разновидностей командной оболочки UNIX. Особенно популярна в среде Linux, где она часто используется в качестве предустановленной командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[File:Bash_highway_to_shell.jpg|center|250px]]&lt;br /&gt;
Bash — это командный процессор, работающий, как правило, в интерактивном режиме в текстовом окне. Bash также может читать команды из файла, который называется скриптом (или сценарием). Как и все Unix-оболочки, он поддерживает автодополнение имён файлов и директорий, подстановку вывода результата команд, переменные, контроль за порядком выполнения, операторы ветвления и цикла. Ключевые слова, синтаксис и другие основные особенности языка были заимствованы из sh. Другие функции, например, история, были скопированы из csh и ksh. Bash в основном удовлетворяет стандарту POSIX, но с рядом расширений.&lt;br /&gt;
&lt;br /&gt;
Название «bash» является акронимом от Bourne-again-shell («ещё-одна-командная-оболочка-Борна») и представляет собой игру слов: Bourne-shell — одна из популярных разновидностей командной оболочки для UNIX (sh), автором которой является Стивен Борн (1978), усовершенствована в 1987 году Брайаном Фоксом. Фамилия Bourne (Борн) перекликается с английским словом born, означающим «родившийся», отсюда: рождённая-вновь-командная оболочка.&lt;br /&gt;
&lt;br /&gt;
В сентябре 2014 года в bash была обнаружена широко эксплуатируемая уязвимость Bashdoor.&lt;br /&gt;
&lt;br /&gt;
Данный документ является копией электронной версии [[:File:Advanced-Bash-Scripting-Guide.pdf|Advanced-Bash-Scripting-Guide]] &lt;br /&gt;
= Часть первая. Введение =&lt;br /&gt;
'''Shell''' — это командная оболочка. Но это не просто промежуточное звено между пользователем и операционной системой, это ещё и мощный язык программирования. Программы на языке shell называют сценариями, или скриптами. Фактически, из скриптов доступен полный набор команд, утилит и программ Unix. Если этого недостаточно, то к вашим услугам внутренние команды shell — условные операторы, операторы циклов и пр., которые увеличивают мощь и гибкость сценариев. Shell-скрипты исключительно хороши при программировании задач администрирования системы и др., которые не требуют для своего создания полновесных языков программирования.&lt;br /&gt;
== Зачем необходимо знание языка Shell? ==&lt;br /&gt;
&amp;lt;br /&amp;gt;Знание языка командной оболочки является залогом успешного решения задач администрирования системы. Даже если вы не предполагаете заниматься написанием своих сценариев. Во время загрузки Linux выполняется целый ряд сценариев из /etc/rc.d, которые настраивают конфигурацию операционной системы и запускают различные сервисы, поэтому очень важно четко понимать эти скрипты и иметь достаточно знаний, чтобы вносить в них какие либо изменения. Язык сценариев легок в изучении, в нем не так много специфических операторов и конструкций.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Синтаксис языка достаточно прост и прямолинеен, он очень напоминает команды, которые приходится вводить в командной строке. Короткие скрипты практически не нуждаются в отладке, и даже отладка больших скриптов отнимает весьма незначительное время.&lt;br /&gt;
Shell-скрипты очень хорошо подходят для быстрого создания прототипов сложных приложений, даже не смотря на ограниченный набор языковых конструкций и определенную &amp;quot;медлительность&amp;quot;. Такой метод позволяет детально проработать структуру будущего приложения, обнаружить возможные&amp;quot;ловушки&amp;quot; и лишь затем приступить к кодированию на C, C++, Java, или Perl.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Скрипты возвращают нас к классической философии Unix — &amp;quot;разделяй и властвуй&amp;quot; т.е. разделение сложного проекта на ряд простых подзадач. Многие считают такой подход наилучшим или, по меньшей мере, наиболее эстетичным способом решения возникающих проблем, нежели использование нового поколения языков — &amp;quot;всё-в-одном&amp;quot;, таких как Perl.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Для каких задач неприменимы скрипты'''''&amp;lt;/span&amp;gt;:&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для ресурсоемких задач, особенно когда важна скорость исполнения (поиск, сортировка и т.п.)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для задач, связанных с выполнением математических вычислений, особенно это касается вычислений с плавающей запятой, вычислений с повышенной точностью, комплексных чисел(для таких задач лучше использовать C++ или FORTRAN)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для кросс-платформенного программирования (для этого лучше подходит язык C)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для сложных приложений, когда структурирование является жизненной необходимостью(контроль за типами переменных, прототипами функций и т.п.)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для целевых задач, от которых может зависеть успех предприятия&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;когда во главу угла поставлена безопасность системы, когда необходимо обеспечить целостность системы и защитить её от вторжения, взлома и вандализма&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для проектов, содержащих компоненты, очень тесно взаимодействующие между собой&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для задач, выполняющих огромный объем работ с файлами&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для задач, работающих с многомерными массивами&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;когда необходимо работать со структурами данных, такими как связанные списки или деревья&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;когда необходимо предоставить графический интерфейс с пользователем (GUI)&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;когда необходим прямой доступ к аппаратуре компьютера&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;когда необходимо выполнять обмен через порты ввода-вывода или сокеты&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;когда необходимо использовать внешние библиотеки&amp;lt;/span&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;для проприетарных, &amp;quot;закрытых&amp;quot; программ (скрипты представляют из себя исходные тексты программ, доступные для всеобщего обозрения)&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Если &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;выполняется хотя бы одно&amp;lt;/span&amp;gt; из вышеперечисленных условий, то вам лучше обратиться к более мощным скриптовым языкам программирования, например '''Perl''', '''Tcl''', '''Python''', '''Ruby''' или к высокоуровневым компилирующим языкам — '''C''', '''C++''' или '''Java'''. Но даже в этом случае, создание прототипа приложения на языке '''shell''' может существенно облегчить разработку.&lt;br /&gt;
Название BASH — это аббревиатура от &amp;quot;Bourne-Again Shell&amp;quot; и игра слов от, ставшего уже классикой,&amp;quot;Bourne Shell&amp;quot; Стефена Бурна (Stephen Bourne). В последние годы BASH достиг такой популярности,что стал стандартной командной оболочкой de facto для многих разновидностей Unix. Большинство принципов программирования на BASH одинаково хорошо применимы и в других командных оболочках, таких как Korn Shell (ksh), от которой Bash позаимствовал некоторые особенности,&lt;br /&gt;
и CShell и его производных(Примечательно, что C Shell не рекомендуется к использованию из-за отдельных проблем, отмеченных Томом Кристиансеном (Tom Christiansen) в октябре 1993 года на Usenet post). &lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Далее, в тексте документа вы найдете большое количество примеров скриптов, иллюстрирующихвозможности shell. Все примеры -- работающие. Они были протестированы, причем некоторые из них могут пригодиться в повседневной работе. Уважаемый читатель может &amp;quot;поиграть&amp;quot; с рабочим кодом скриптов, сохраняя их в файлы, с именами scriptname.sh.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Не забудьте выдать этим файлам право на исполнение (chmod u+rx scriptname.sh), после чего сценарии можно будет запустить на исполнение и проверить результат их работы. Вам следует помнить, что описание некоторых примеров следует после исходного кода этого примера, поэтому, прежде чем запустить сценарий у себя — ознакомьтесь с его описанием. Скрипты были написаны автором книги, если не оговаривается иное.&lt;br /&gt;
&lt;br /&gt;
== Для начала о Sha-Bang ==&lt;br /&gt;
&amp;lt;br /&amp;gt;В простейшем случае, скрипт — это ни что иное, как простой список команд системы, записанный в файл. Создание скриптов поможет сохранить ваше время и силы, которые тратятся на ввод последовательности команд всякий раз, когда необходимо их выполнить.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример. cleanup'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий очистки лог-файлов в /var/log'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 # cleanup&lt;br /&gt;
 # Для работы сценария требуются права root.&lt;br /&gt;
 cd /var/log&lt;br /&gt;
 cat /dev/null &amp;gt; messages&lt;br /&gt;
 cat /dev/null &amp;gt; wtmp&lt;br /&gt;
 echo &amp;quot;Лог-файлы очищены.&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример. cleanup'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Расширенная версия предыдущего сценария.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# cleanup, version 2&lt;br /&gt;
# Для работы сценария требуются права root.&lt;br /&gt;
LOG_DIR=/var/log&lt;br /&gt;
ROOT_UID=0 # Только пользователь с $UID 0 имеет привилегии root.&lt;br /&gt;
LINES=50 # Количество сохраняемых строк по-умолчанию.&lt;br /&gt;
E_XCD=66 # Невозможно сменить каталог?&lt;br /&gt;
E_NOTROOT=67 # Признак отсутствия root-привилегий.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]; then &lt;br /&gt;
 echo &amp;quot;Для работы сценария требуются права root.&amp;quot; &lt;br /&gt;
exit $E_NOTROOT&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ -n &amp;quot;$1&amp;quot; ]; then &lt;br /&gt;
# Проверка наличия аргумента командной строки&lt;br /&gt;
 lines=$1&lt;br /&gt;
else lines=$LINES # Значение по-умолчанию, если число не задано в командной строке&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Stephane Chazelas предложил следующее,&lt;br /&gt;
#+ для проверки корректности аргумента, переданного из командной строки,&lt;br /&gt;
#+ правда это достаточно сложно для данного руководства.&lt;br /&gt;
#&lt;br /&gt;
# E_WRONGARGS=65 # Не числовой аргумент&lt;br /&gt;
#&lt;br /&gt;
# case &amp;quot;$1&amp;quot; in&lt;br /&gt;
# &amp;quot;&amp;quot; ) lines=50;;&lt;br /&gt;
# *[!0-9]*) echo &amp;quot;Usage: `basename $0` file-to-cleanup&amp;quot;; exit $E_WRONGARGS;;&lt;br /&gt;
# * ) lines=$1;;&lt;br /&gt;
# esac&lt;br /&gt;
#&lt;br /&gt;
#* Конец проверки корректности аргумента&lt;br /&gt;
&lt;br /&gt;
cd $LOG_DIR&lt;br /&gt;
if [ `pwd` != &amp;quot;$LOG_DIR&amp;quot; ]; then &lt;br /&gt;
# или if [ &amp;quot;$PWD&amp;quot; != &amp;quot;$LOG_DIR&amp;quot; ]&lt;br /&gt;
# не в /var/log?&lt;br /&gt;
 echo &amp;quot;Невозможно перейти в каталог $LOG_DIR.&amp;quot; &lt;br /&gt;
exit $E_XCD&lt;br /&gt;
fi # Проверка каталога перед очисткой лог-файлов.&lt;br /&gt;
# более эффективный вариант:&lt;br /&gt;
#&lt;br /&gt;
# cd /var/log || {&lt;br /&gt;
# echo &amp;quot;Невозможно перейти в требуемый каталог.&amp;quot; &amp;gt;&amp;amp;2# exit $E_XCD;&lt;br /&gt;
# }&lt;br /&gt;
&lt;br /&gt;
tail -$lines messages &amp;gt; mesg.temp # Сохранить последние строки в лог-файле.&lt;br /&gt;
mv mesg.temp messages&lt;br /&gt;
# cat /dev/null &amp;gt; messages&lt;br /&gt;
#* Необходимость этой команды отпала, поскольку очистка выполняется выше.&lt;br /&gt;
cat /dev/null &amp;gt; wtmp # команды ': &amp;gt; wtmp' и '&amp;gt; wtmp' имеют тот же эффект.&lt;br /&gt;
echo &amp;quot;Лог-файлы очищены.&amp;quot;&lt;br /&gt;
exit 0 # Возвращаемое значение 0&lt;br /&gt;
#+ указывает на успешное завершение работы сценария.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Если вы не желаете полностью вычищать системные логи, то выше представлена улучшенная версия предыдущего сценария. Здесь сохраняются последние несколько строк (по-умолчанию — 50).&lt;br /&gt;
Если файл сценария начинается с последовательности #!, которая в мире Unix называется '''''sha-bang''''', то это указывает системе какой интерпретатор следует использовать для исполнения сценария. Это двухбайтовая последовательность, или — специальный маркер, определяющий тип сценария, в данном случае — сценарий командной оболочки (см. man magic). Более точно, '''''sha-bang''''' определяет интерпретатор, который вызывается для исполнения сценария, это может быть командная оболочка(shell), иной интерпретатор или утилита:&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 #!/usr/bin/perl&lt;br /&gt;
 #!/usr/bin/tcl&lt;br /&gt;
 #!/bin/sed -f&lt;br /&gt;
 #!/usr/awk -f&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Каждая, из приведенных выше сигнатур, приводит к вызову различных интерпретаторов, будь то /bin/sh — командный интерпретатор по-умолчанию (bash для Linux-систем), либо иной. При переносе сценариев с сигнатурой '''''#!/bin/sh''''' на другие Unix системы, где в качестве командного интерпретатора задан другой shell, вы можете лишиться некоторых особенностей, присущих bash. Поэтому такие сценарии должны быть POSIX совместимыми.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание на то, что сигнатура должна указывать правильный путь к интерпретатору, впротивном случае вы получите сообщение об ошибке -- как правило это &amp;quot;Command not found&amp;quot;.&lt;br /&gt;
Сигнатура '''''#!''''' может быть опущена, если вы не используете специфичных команд. Во втором примере(см. выше) использование сигнатуры #! обязательно, поскольку сценарий использует специфичную конструкцию присваивания значения переменной '''lines=50'''. Ещё раз замечу, что сигнатура '''''#!/bin/sh''''' вызывает командный интерпретатор по-умолчанию — /bin/bash в Linux-системах.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
В данном руководстве приветствуется модульный подход к построению сценариев. Записывайте, собирайте свою коллекцию участков кода, который может вам встретиться. В конечном итоге вы соберете свою &amp;quot;библиотеку&amp;quot; подпрограмм, которые затем сможете использовать при написании своих сценариев. Например, следующий отрывок сценария проверяет количество аргументов в командной строке:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ $# -ne Number_of_expected_args ]; then &lt;br /&gt;
 echo &amp;quot;Usage: `basename $0` whatever&amp;quot; &lt;br /&gt;
 exit $WRONG_ARGS&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Запуск сценария ===&lt;br /&gt;
Запустить сценарий можно командой '''''sh scriptname''''' или '''''bash scriptname'''''. (Не рекомендуется запуск сценария командой '''sh &amp;lt; scriptname''', поскольку это запрещает использование устройства стандартного ввода '''stdin''' в скрипте). Более удобный вариант — сделать файл скрипта исполняемым, командой [[chmod]].&lt;br /&gt;
&amp;lt;br /&amp;gt;Это:&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;chmod 555 scriptname (выдача прав на чтение/исполнение любому пользователю в системе)&amp;lt;/source&amp;gt;&lt;br /&gt;
или&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;chmod +rx scriptname (выдача прав на чтение/исполнение любому пользователю в системе)&amp;lt;/source&amp;gt;&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;chmod u+rx scriptname (выдача прав на чтение/исполнение только &amp;quot;владельцу&amp;quot; скрипта)&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
После того, как вы сделаете файл сценария исполняемым, вы можете запустить его примерно такой командой ./scriptname.&lt;br /&gt;
Если, при этом, текст сценария начинается с корректной сигнатуры ('''''&amp;quot;sha-bang&amp;quot;'''''), то для его исполнения будет вызван соответствующий интерпретатор.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
И наконец, завершив отладку сценария, вы можете поместить его в каталог '''''/usr/local/bin'''''(естественно, что для этого вы должны обладать правами root), чтобы сделать его доступным для себя и других пользователей системы. После этого сценарий можно вызвать, просто напечатав название файла в командной строке и нажав клавишу '''[ENTER]'''.&lt;br /&gt;
=== Упражнения ===&lt;br /&gt;
1) Системные администраторы часто создают скрипты для автоматизации своего труда. Подумайте, для выполнения каких задач могут быть написаны сценарии.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
2) Напишите сценарий, который выводит '''''дату''''', '''''время''''', '''''список зарегистрировавшихся пользователей''''', и '''''uptime системы''''' и сохраняет эту информацию в системном журнале.&lt;br /&gt;
&lt;br /&gt;
= Часть вторая. Основы =&lt;br /&gt;
== Служебные символы ==&lt;br /&gt;
Служебные символы, используемые в текстах сценариев:&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''#'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Комментарии&amp;lt;/span&amp;gt;. &lt;br /&gt;
&amp;lt;br /&amp;gt;Строки, начинающиеся с символа # (за исключением комбинации #!) являются комментариями.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Эта строка — комментарий.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Комментарии могут располагаться и в конце строки с исполняемым кодом.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;Далее следует комментарий.&amp;quot; # Это комментарий.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Комментариям могут предшествовать пробелы (пробел, табуляция).&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Перед комментарием стоит символ табуляции.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Исполняемые команды не могут следовать за комментарием в той же самой строке. Пока что еще не существует способа отделения комментария от &amp;quot;исполняемого кода&amp;quot;, следующего за комментарием в той же строке.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Само собой разумеется, экранированный символ '''''#''''' в операторе [[echo]] не воспринимается как начало комментария. Более того, он может использоваться в операциях подстановки параметров и в константных числовых выражениях.&lt;br /&gt;
 echo &amp;quot;Символ # &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;не означает начало комментария.&amp;lt;/span&amp;gt;&amp;quot;&lt;br /&gt;
 echo 'Символ # &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;не означает начало комментария.&amp;lt;/span&amp;gt;'&lt;br /&gt;
 echo Символ \# &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;не означает начало комментария.&amp;lt;/span&amp;gt;&lt;br /&gt;
 echo А здесь символ # &amp;lt;span style=&amp;quot;color:gray&amp;quot;&amp;gt;''означает начало комментария.''&amp;lt;/span&amp;gt;&lt;br /&gt;
 echo ${PATH#*:} # Подстановка — не комментарий.&lt;br /&gt;
 echo $(( 2#101011 )) # База системы счисления — не комментарий.&lt;br /&gt;
&lt;br /&gt;
Двойные кавычки('''''&amp;quot;'''''), одинарная кавычка(&amp;lt;nowiki&amp;gt;'&amp;lt;/nowiki&amp;gt;) и символ обратного &amp;quot;слеша&amp;quot;('''''\''''') экранируют действие символа '''''#'''''.&lt;br /&gt;
В операциях поиска по шаблону символ '''''#''''' так же не воспринимается как начало комментария.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;''''';'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Разделитель команд. '''''[Точка-с-запятой]'''''&amp;lt;/span&amp;gt; &lt;br /&gt;
Позволяет записывать две и более команд в одной строке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo hello; echo there &lt;br /&gt;
if [ -x &amp;quot;$filename&amp;quot; ]; then # Обратите внимание: &amp;quot;if&amp;quot; И &amp;quot;then&amp;quot; разделены точкой с запятой. &lt;br /&gt;
# Почему? &lt;br /&gt;
echo &amp;quot;Файл $filename найден.&amp;quot;; cp $filename $filename.bak&lt;br /&gt;
  else echo &amp;quot;Файл $filename не найден.&amp;quot;; touch $filename&lt;br /&gt;
fi; &lt;br /&gt;
echo &amp;quot;Конец.&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Следует отметить, что символ &amp;lt;big&amp;gt;''''';'''''&amp;lt;/big&amp;gt; иногда так же как и &amp;lt;big&amp;gt;'''''#'''''&amp;lt;/big&amp;gt; необходимо экранировать.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;''''';;'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Ограничитель в операторе выбора case. '''''[Двойная-точка-с-запятой]'''''&amp;lt;/span&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
case &amp;quot;$variable&amp;quot; &lt;br /&gt;
in &lt;br /&gt;
abc) echo &amp;quot;$variable = abc&amp;quot; ;;&lt;br /&gt;
xyz) echo &amp;quot;$variable = xyz&amp;quot; ;;&lt;br /&gt;
esac&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''.'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Команда &amp;quot;точка&amp;quot;('''''.''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Эквивалент команды '''''source'''''. Это встроенная команда '''''bash'''''. &amp;quot;точка&amp;quot; может являться частью имени файла. Если имя файла начинается с точки, то это &amp;quot;скрытый&amp;quot; файл, т.е. команда [[Ls_—_Команда_печати_содержимого_каталога|ls]] при обычных условиях его не отображает:&lt;br /&gt;
[[File:Ls hidden.PNG|center|650px]]&lt;br /&gt;
&amp;lt;br /&amp;gt;Если подразумевается имя каталога, то одна точка означает текущий каталог и две точки — каталог уровнем выше или родительский каталог:&lt;br /&gt;
[[File:Parent dir.PNG|center|400px]]&lt;br /&gt;
Символ &amp;lt;big&amp;gt;'''''.'''''&amp;lt;/big&amp;gt; (&amp;quot;точка&amp;quot;) довольно часто используется для обозначения каталога назначения в операциях копирования/перемещения файлов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cp /home/bozo/current_work/junk/* .&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Символ &amp;lt;big&amp;gt;'''''.'''''&amp;lt;/big&amp;gt; (&amp;quot;точка&amp;quot;) в операциях поиска. При выполнении поиска по шаблону, в регулярных выражениях, символ &amp;lt;big&amp;gt;'''''.'''''&amp;lt;/big&amp;gt; (&amp;quot;точка&amp;quot;) обозначает одиночный символ.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''&amp;quot;'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Двойные кавычки('''''&amp;quot;''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
В строке &amp;quot;STRING&amp;quot;, ограниченной двойными кавычками не выполняется интерпретация большинства служебных символов, которые могут находиться в строке.&lt;br /&gt;
* &amp;lt;big&amp;gt;'&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Одинарные кавычки(')&amp;lt;/span&amp;gt;&lt;br /&gt;
Одинарные кавычки  'STRING' экранируют все служебные символы в строке STRING. Это более строгая форма экранирования.&lt;br /&gt;
* &amp;lt;big&amp;gt;''''','''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Запятая(''''',''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Оператор запятая(&amp;lt;big&amp;gt;''''','''''&amp;lt;/big&amp;gt;) используется для вычисления серии арифметических выражений. Вычисляются все выражения, но возвращается результат последнего выражения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
let &amp;quot;t2 = ((a = 9, 15 / 3))&amp;quot; # Присваивает значение переменной &amp;quot;a&amp;quot; и вычисляет &amp;quot;t2&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''\'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Обратный слэш('''''\''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Комбинация \X &amp;quot;экранирует&amp;quot; символ X. Аналогичный эффект имеет комбинация с &amp;quot;одинарными кавычками&amp;quot;, т.е. 'X'. Символ \ может использоваться для экранирования кавычек &amp;quot; и '.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''/'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Слэш('''''/''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Разделитель, используемый в указании пути к каталогам и файлам. Слэш отделяет элементы пути к каталогам и файлам (например, /home/bozo/projects/Makefile).&lt;br /&gt;
В арифметических операциях — это оператор деления.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''`'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Обратная кавычка('''''`''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
С помощью символа обратной кавычки(&amp;lt;big&amp;gt;'''''`'''''&amp;lt;/big&amp;gt;) осуществляется подстановка команд. Обратные кавычки могут использоваться для записи в переменную команды '''''`command`'''''.&lt;br /&gt;
* &amp;lt;big&amp;gt;''''':'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Двоеточие(''''':''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Пустая команда. Это эквивалент операции &amp;quot;NOP&amp;quot; (no op, нет операции). Может рассматриваться как синоним встроенной команды true. Команда &amp;quot;:&amp;quot; так же является встроенной командой Bash, которая всегда возвращает &amp;quot;true&amp;quot; (0).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
echo $? # 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Бесконечный цикл:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
while :&lt;br /&gt;
do &lt;br /&gt;
operation-1 &lt;br /&gt;
operation-2 &lt;br /&gt;
... &lt;br /&gt;
operation-n&lt;br /&gt;
done&lt;br /&gt;
# То же самое:&lt;br /&gt;
# while true&lt;br /&gt;
# do&lt;br /&gt;
# ...&lt;br /&gt;
# done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Символ-заполнитель в условном операторе if/then:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if condition&lt;br /&gt;
then : # Никаких действий не производится и управление передаётся дальше&lt;br /&gt;
else &lt;br /&gt;
 take-some-action&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Как символ-заполнитель в операциях, которые предполагают наличие двух операндов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
: ${username=`whoami`}&lt;br /&gt;
# ${username=`whoami`} без символа : выдает сообщение об ошибке,&lt;br /&gt;
# если &amp;quot;username&amp;quot; не является командой...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Как символ-заполнитель для оператора вложенного документа.&lt;br /&gt;
В операциях с подстановкой параметров:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
: ${HOSTNAME?} ${USER?} ${MAIL?}&lt;br /&gt;
#Вывод сообщения об ошибке, если одна или более переменных не определены.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В операциях замены подстроки с подстановкой значений переменных.&lt;br /&gt;
В комбинации с оператором &amp;gt; (оператор перенаправления вывода), усекает длину файла до нуля. Если указан несуществующий файл — то он создаётся.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
: &amp;gt; data.xxx # Файл &amp;quot;data.xxx&amp;quot; — пуст&lt;br /&gt;
# Тот же эффект имеет команда cat /dev/null &amp;gt;data.xxx&lt;br /&gt;
# Однако в данном случае не производится создание нового процесса, поскольку &amp;quot;:&amp;quot; является встроенной командой.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В комбинации с оператором '''''&amp;gt;&amp;gt;''''' — если задано имя существующего файла, то эта комбинация на него никак не влияет (''''': &amp;gt;&amp;gt; target_file'''''). Если задано имя несуществующего файла, то он создаётся.&lt;br /&gt;
Вышеизложенное применимо только к обычным файлам и неприменимо к конвейерам, символическим ссылкам и другим специальным файлам. Символ &amp;lt;big&amp;gt;:&amp;lt;/big&amp;gt; может использоваться для создания комментариев, хотя и не рекомендуется. Если строка комментария начинается с символа &amp;lt;big&amp;gt;'''''#'''''&amp;lt;/big&amp;gt;, то такая строка не проверяется интерпретатором на наличие ошибок. Однако в случае оператора &amp;lt;big&amp;gt;''''':'''''&amp;lt;/big&amp;gt; это не так.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
: Это комментарий, который генерирует сообщение об ошибке, ( if [ $x -eq 3] ).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Символ &amp;lt;big&amp;gt;''''':'''''&amp;lt;/big&amp;gt; может использоваться как разделитель полей в /etc/passwd и переменной $PATH.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $PATH&lt;br /&gt;
/usr/local/bin:/bin:/usr/bin:/usr/X11R6/bin:/sbin:/usr/sbin:/usr/games&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''!'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Восклицательный знак('''''!''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Инверсия (или логическое отрицание) используемое в условных операторах.&lt;br /&gt;
Оператор &amp;lt;big&amp;gt;'''''!'''''&amp;lt;/big&amp;gt; инвертирует код завершения команды, к которой он применен. Также используется для логического отрицания в операциях сравнения, например, операция сравнения &amp;quot;равно&amp;quot;(=), при использовании оператора отрицания, преобразуется в операцию сравнения — &amp;quot;не равно&amp;quot; ( != ). Символ &amp;lt;big&amp;gt;'''''!'''''&amp;lt;/big&amp;gt; является зарезервированным ключевым словом BASH. В некоторых случаях символ &amp;lt;big&amp;gt;'''''!'''''&amp;lt;/big&amp;gt; используется для косвенного обращения к переменным.&lt;br /&gt;
Кроме того, из командной строки оператор &amp;lt;big&amp;gt;'''''!'''''&amp;lt;/big&amp;gt; запускает механизм историй Bash. Примечательно, что этот механизм недоступен из сценариев(т.е. исключительно из командной строки).&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''*'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Символ &amp;quot;звёздочка&amp;quot;('''''*''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Символ &amp;lt;big&amp;gt;'''''*'''''&amp;lt;/big&amp;gt; (&amp;quot;звёздочка&amp;quot;) служит &amp;quot;шаблоном&amp;quot; для подстановки в имена файлов. Одиночный символ &amp;lt;big&amp;gt;'''''*'''''&amp;lt;/big&amp;gt; означает любое имя файла в заданном каталоге.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo *&lt;br /&gt;
abs-book.sgml add-drive.sh agram.sh alias.sh&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В регулярных выражениях токен &amp;lt;big&amp;gt;'''''*'''''&amp;lt;/big&amp;gt; представляет любое количество (в том числе и 0) символов. В арифметических выражениях символ &amp;lt;big&amp;gt;'''''*'''''&amp;lt;/big&amp;gt; обозначает операцию умножения. Двойная звёздочка (два символа звёздочки, следующих подряд друг за другом — &amp;lt;big&amp;gt;'''''**'''''&amp;lt;/big&amp;gt;),обозначает операцию возведения в степень.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''?'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Вопросительный знак('''''?''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Оператор проверки условия. В некоторых выражениях символ &amp;lt;big&amp;gt;'''''?'''''&amp;lt;/big&amp;gt; служит для проверки выполнения условия. В конструкциях с двойными скобками, символ &amp;lt;big&amp;gt;'''''?'''''&amp;lt;/big&amp;gt; подобен трёхместному оператору языка C. В выражениях с подстановкой параметра, символ &amp;lt;big&amp;gt;'''''?'''''&amp;lt;/big&amp;gt; проверяет — установлена ли переменная.&lt;br /&gt;
Символ &amp;lt;big&amp;gt;'''''?'''''&amp;lt;/big&amp;gt; обозначает одиночный символ при подстановке в имена файлов. В регулярных выражениях служит для обозначения одиночного символа.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''$'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Символ доллара('''''$''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Символ &amp;lt;big&amp;gt;'''''$'''''&amp;lt;/big&amp;gt; предшествующий имени переменной, указывает на то, что будет получено значение переменной:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
var1=5&lt;br /&gt;
var2=23skidoo&lt;br /&gt;
echo $var1 # 5&lt;br /&gt;
echo $var2 # 23skidoo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В регулярных выражениях, символ  &amp;lt;big&amp;gt;'''''$'''''&amp;lt;/big&amp;gt; обозначает конец строки.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''${ }'''''&amp;lt;/big&amp;gt; — подстановка параметра.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''$*'''''&amp;lt;/big&amp;gt;,&amp;lt;big&amp;gt;'''''$@'''''&amp;lt;/big&amp;gt; — параметры командной строки.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''$?'''''&amp;lt;/big&amp;gt; — Переменная &amp;quot;$?&amp;quot; хранит код завершения последней выполненной команды, функции или сценария.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''$$'''''&amp;lt;/big&amp;gt; — Переменная &amp;quot;$$&amp;quot; хранит id процесса сценария.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''( )'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Круглые скобки('''''()''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Команды, заключённые в круглые скобки (&amp;lt;big&amp;gt;'''''( )'''''&amp;lt;/big&amp;gt;) исполняются в дочернем процессе — subshell.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(a=hello; echo $a)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Переменные, создаваемые в дочернем процессе не видны в &amp;quot;родительском&amp;quot; сценарии. Родительский процесс-сценарий, не может обращаться к переменным, создаваемым в дочернем процессе.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
a=123&lt;br /&gt;
( a=321; )&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = 123&lt;br /&gt;
#Переменная &amp;quot;a&amp;quot; в скобках подобна локальной переменной.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Круглые скобки (&amp;lt;big&amp;gt;'''''()'''''&amp;lt;/big&amp;gt;) также используются для инициализации массивов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Array=(element1 element2 element3)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''(( ))'''''&amp;lt;/big&amp;gt; — двойные круглые скобки.Вычисляется целочисленное выражение, заключенное между двойными круглыми скобками &amp;lt;big&amp;gt;'''''(( ))'''''&amp;lt;/big&amp;gt;.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''{}'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Фигурные скобки('''''{}''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Команда интерпретируется как список команд, разделённых точкой с запятой, с вариациями, представленными в фигурных скобках. При интерпретации имён файлов (подстановка) используются параметры, заключённые в фигурные скобки. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
grep Linux file*.{txt,htm*}# Поиск всех вхождений слова &amp;quot;Linux&amp;quot;&lt;br /&gt;
# в файлах &amp;quot;fileA.txt&amp;quot;, &amp;quot;file2.txt&amp;quot;, &amp;quot;fileR.html&amp;quot;, &amp;quot;file-87.htm&amp;quot;, и пр.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Использование ''неэкранированных'' или ''неокавыченных'' пробелов внутри фигурных скобок недопустимо!&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo {file1,file2}\ :{\ A,&amp;quot; B&amp;quot;,' C'}&lt;br /&gt;
file1 : A file1 : B file1 : C file2 : A file2 : B file2 : C&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''{}'''''&amp;lt;/big&amp;gt; — Известен так же как &amp;quot;вложенный блок&amp;quot;, эта конструкция, фактически, создаёт анонимную функцию. Однако, в отличии от обычных функций, переменные, создаваемые во вложенных блоках кода, доступны объемлющему сценарию.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ { local a; a=123; }&lt;br /&gt;
bash: local: can only be used in a function&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
a=123&lt;br /&gt;
{ a=321; }&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot;&lt;br /&gt;
# a = 321 (значение, присвоенное во вложенном блоке кода)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Код, заключенный в фигурные скобки, может выполнять перенаправление ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример.'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вложенные блоки и перенаправление ввода-вывода.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Чтение строк из файла /etc/fstab.&lt;br /&gt;
File=/etc/fstab&lt;br /&gt;
{read line1&lt;br /&gt;
read line2&lt;br /&gt;
} &amp;lt; $File&lt;br /&gt;
echo &amp;quot;Первая строка в $File :&amp;quot;&lt;br /&gt;
echo &amp;quot;$line1&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Вторая строка в $File :&amp;quot;&lt;br /&gt;
echo &amp;quot;$line2&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример.'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сохранение результата исполнения вложенного блока в файл'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# rpm-check.sh&lt;br /&gt;
# Запрашивает описание rpm-архива, список файлов, и проверяется возможность установки.&lt;br /&gt;
# Результат сохраняется в файле.&lt;br /&gt;
#&lt;br /&gt;
# Этот сценарий иллюстрирует порядок работы со вложенными блоками кода.&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
E_NOARGS=65&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]; then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` rpm-file&amp;quot; &lt;br /&gt;
 exit $E_NOARGS&lt;br /&gt;
fi&lt;br /&gt;
{&lt;br /&gt;
   echo &lt;br /&gt;
   echo &amp;quot;Описание архива:&amp;quot; &lt;br /&gt;
   rpm -qpi $1 # Запрос описания.&lt;br /&gt;
   echo&lt;br /&gt;
   echo &amp;quot;Список файлов:&amp;quot;&lt;br /&gt;
   rpm -qpl $1 # Запрос списка.&lt;br /&gt;
   echo&lt;br /&gt;
   rpm -i --test $1 # Проверка возможности установки.&lt;br /&gt;
   if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]; then&lt;br /&gt;
      echo &amp;quot;$1 может быть установлен.&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
      echo &amp;quot;$1 — установка невозможна!&amp;quot;&lt;br /&gt;
   fi&lt;br /&gt;
   echo&lt;br /&gt;
}&amp;gt; &amp;quot;$1.test&amp;quot; # Перенаправление вывода в файл.&lt;br /&gt;
echo &amp;quot;Результаты проверки rpm-архива находятся в файле $1.test&amp;quot;&lt;br /&gt;
# За дополнительной информацией по ключам команды rpm см. man rpm.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В отличие от групп команд в (круглых скобках), описаных выше, вложенные блоки кода, заключённые в {фигурные скобки} исполняются в пределах того же процесса, что и сам скрипт (т.е. не вызывают запуск дочернего процесса — subshell)!&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''{ } \;'''''&amp;lt;/big&amp;gt; — ''pathname'', полное имя файла (т.е. путь к файлу и его имя). Чаще всего используется совместно с командой [[find]].&lt;br /&gt;
Обратите внимание на то, что символ &amp;lt;big&amp;gt;''''';'''''&amp;lt;/big&amp;gt; , которым завершается ключ ''-exec'' команды [[find]], экранируется обратным слэшем. Это необходимо, чтобы предотвратить его интерпретацию.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''[ ]'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Квадратные скобки('''''[ ]''''')&amp;lt;/span&amp;gt;&lt;br /&gt;
Проверка истинности выражения, заключенного в квадратные скобки &amp;lt;big&amp;gt;'''''[ ]'''''&amp;lt;/big&amp;gt;. Примечательно, что &amp;lt;big&amp;gt;'''''['''''&amp;lt;/big&amp;gt; является частью встроенной команды ''test'' (и её синонимом), и не имеет никакого отношения к &amp;quot;внешней&amp;quot; утилите /usr/bin/test.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''[[ ]]'''''&amp;lt;/big&amp;gt; — Проверка истинности выражения, заключенного между '''[[ ]]''' (зарезервированное слово интерпретатора).&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''[ ]'''''&amp;lt;/big&amp;gt; — Элемент массива. При работе с массивами в квадратных скобках указывается порядковый номер того элемента массива, к которому производится обращение.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Array[1]=slot_1&lt;br /&gt;
echo ${Array[1]}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''[ ]'''''&amp;lt;/big&amp;gt; — диапазон символов. В регулярных выражениях, в квадратных скобках задаётся диапазон искомых символов.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''&amp;gt;'''''&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;'''''&amp;amp;&amp;gt;'''''&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;'''''&amp;gt;&amp;amp;'''''&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;'''''&amp;gt;&amp;gt;'''''&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;'''''&amp;lt;'''''&amp;lt;/big&amp;gt; — Перенаправление.&lt;br /&gt;
&amp;lt;br /&amp;gt;Конструкция &amp;lt;big&amp;gt;''scriptname''&amp;lt;/big&amp;gt; '''''&amp;gt;''''' &amp;lt;big&amp;gt;''filename''&amp;lt;/big&amp;gt; перенаправляет вывод '''scriptname''' в файл '''filename'''. Если файл '''filename''' уже существовал, то его прежнее содержимое будет утеряно.&lt;br /&gt;
&amp;lt;br /&amp;gt;Конструкция &amp;lt;big&amp;gt;''command''&amp;lt;/big&amp;gt; '''''&amp;amp;&amp;gt;''''' &amp;lt;big&amp;gt;''filename''&amp;lt;/big&amp;gt; перенаправляет вывод команды '''command''', как с ''stdout'', так и с ''stderr'', в файл '''filename'''.&lt;br /&gt;
&amp;lt;br /&amp;gt;Конструкция &amp;lt;big&amp;gt;''command''&amp;lt;/big&amp;gt; '''''&amp;gt;&amp;amp;2''''' перенаправляет вывод с ''stdout'' на ''stderr''.&lt;br /&gt;
&amp;lt;br /&amp;gt;Конструкция &amp;lt;big&amp;gt;''scriptname''&amp;lt;/big&amp;gt; '''''&amp;gt;&amp;gt;''''' &amp;lt;big&amp;gt;''filename''&amp;lt;/big&amp;gt; добавляет вывод '''scriptname''' к файлу '''filename'''. Если задано имя несуществующего файла, то он создаётся.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''&amp;lt;&amp;lt;'''''&amp;lt;/big&amp;gt; — Перенаправление ввода на встроенный документ.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''(command)&amp;gt;'''''&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;'''''&amp;lt;(command)'''''&amp;lt;/big&amp;gt; — Подстановка процесса.&lt;br /&gt;
В операциях сравнения, символы &amp;quot;&amp;lt;&amp;quot; и &amp;quot;&amp;gt;&amp;quot; обозначают операции сравнения строк. А так же операции сравнения целых чисел.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''&amp;lt;'''''&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;'''''&amp;gt;'''''&amp;lt;/big&amp;gt; — Посимвольное ASCII-сравнение.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
veg1=carrots&lt;br /&gt;
veg2=tomatoes&lt;br /&gt;
if [[ &amp;quot;$veg1&amp;quot; &amp;lt; &amp;quot;$veg2&amp;quot; ]]; then&lt;br /&gt;
 echo &amp;quot;Не смотря на то, что в словаре слово $veg1 предшествует слову $veg2,&amp;quot;&lt;br /&gt;
 echo &amp;quot;это никак не отражает мои кулинарные предпочтения.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Интересно. Каким словарем вы пользуетесь?&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''\&amp;lt;'''''&amp;lt;/big&amp;gt;,&amp;lt;big&amp;gt;'''''\&amp;gt;'''''&amp;lt;/big&amp;gt; — границы отдельных слов в регулярных выражениях.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep '\&amp;lt;the\&amp;gt;' textfile&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''|'''''&amp;lt;/big&amp;gt; — Конвейер(pipe).&lt;br /&gt;
Передает вывод предыдущей команды на ввод следующей или на вход командного интерпретатора shell. Этот метод часто используется для связывания последовательности команд в единую цепочку.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo ls -l | sh&lt;br /&gt;
# Передаёт вывод &amp;quot;echo ls -l&amp;quot; командному интерпретатору shell,&lt;br /&gt;
# тот же результат даёт простая команда &amp;quot;ls -l&amp;quot;.&lt;br /&gt;
cat *.lst | sort | uniq&lt;br /&gt;
# Объединяет все файлы &amp;quot;.lst&amp;quot;, сортирует содержимое и удаляет повторяющиеся строки.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Конвейеры (еще их называют каналами) — это классический способ взаимодействия процессов, с помощью которого ''stdout'' одного процесса перенаправляется на ''stdin'' другого. Обычно используется совместно с командами вывода, такими как [[cat]] или [[echo]], от которых поток данных поступает в &amp;quot;фильтр&amp;quot; (команда, которая на входе получает данные, преобразует их и обрабатывает).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;cat $filename | grep $search_word&amp;lt;/source&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
В конвейер могут объединяться и сценарии на языке командной оболочки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# uppercase.sh : Преобразование вводимых символов в верхний регистр.&lt;br /&gt;
tr 'a-z' 'A-Z'&lt;br /&gt;
# Диапазоны символов должны быть заключены в кавычки&lt;br /&gt;
# чтобы предотвратить порождение имен файлов от однобуквенных имен файлов.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
А теперь попробуем объединить в конвейер команду [[Ls_—_Команда_печати_содержимого_каталога|ls -l]] с этим сценарием:&lt;br /&gt;
[[File:Uppercase_0.PNG|center|600px]]&lt;br /&gt;
Выход ''stdout'' каждого процесса в конвейере должен читаться на входе ''stdin'' последующим, в конвейере, процессом. Если этого не делается, то поток данных блокируется, в результате конвейер будет работать не так как ожидается!&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat file1 file2 | ls -l | sort # Вывод команды &amp;quot;cat file1 file2&amp;quot; будет утерян.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Конвейер исполняется в дочернем процессе, а посему — не имеет доступа к переменным сценария.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable=&amp;quot;initial_value&amp;quot;&lt;br /&gt;
echo &amp;quot;new_value&amp;quot; | read variable &lt;br /&gt;
echo &amp;quot;variable = $variable&amp;quot; # variable = initial_value&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если одна из команд в конвейере завершается аварийно, то это приводит каварийному завершению работы всего конвейера!&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''&amp;gt;|'''''&amp;lt;/big&amp;gt; — принудительное перенаправление, даже если установлен ключ ''noclobber option''.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''||'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; логическая операция OR(логическое ИЛИ).&amp;lt;/span&amp;gt;&lt;br /&gt;
В опрециях проверки условий, оператор &amp;lt;big&amp;gt;'''''||'''''&amp;lt;/big&amp;gt; возвращает 0 ('''success'''), если один из операндов имеет значение ''true'' (ИСТИНА).&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''&amp;amp;'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Амперсанд&amp;lt;/span&amp;gt;&lt;br /&gt;
Выполнение задачи в фоне. Команда, за которой стоит &amp;lt;big&amp;gt;'''''&amp;amp;'''''&amp;lt;/big&amp;gt;, будет исполняться в фоновом режиме.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ sleep 10 &amp;amp;&lt;br /&gt;
[1] 850&lt;br /&gt;
[1]+ Done    sleep 10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В сценариях команды, и даже циклы могут запускаться в фоновом режиме.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример.'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Запуск цикла в фоновом режиме'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# background-loop.sh&lt;br /&gt;
for i in 1 2 3 4 5 6 7 8 9 10 # Первый цикл.&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$i &amp;quot;&lt;br /&gt;
done &amp;amp; # Запуск цикла в фоне.&lt;br /&gt;
       # Иногда возможны случаи выполнения этого цикла после второго цикла.&lt;br /&gt;
echo # Этот 'echo' иногда не отображается на экране.&lt;br /&gt;
for i in 11 12 13 14 15 16 17 18 19 20 # Второй цикл.&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$i &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo # Этот 'echo' иногда не отображается на экране.&lt;br /&gt;
# ======================================================&lt;br /&gt;
# Ожидается, что данный сценарий выведет следующую последовательность:&lt;br /&gt;
# 1 2 3 4 5 6 7 8 9 10&lt;br /&gt;
# 11 12 13 14 15 16 17 18 19 20&lt;br /&gt;
# Иногда возможен такой вариант:&lt;br /&gt;
# 11 12 13 14 15 16 17 18 19 20&lt;br /&gt;
# 1 2 3 4 5 6 7 8 9 10 bozo $&lt;br /&gt;
# (Второй 'echo' не был выполнен. Почему?)&lt;br /&gt;
# Изредка возможен такой вариант:&lt;br /&gt;
# 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20&lt;br /&gt;
# (Первый 'echo' не был выполнен. Почему?)&lt;br /&gt;
# Крайне редко встречается и такое:&lt;br /&gt;
# 11 12 13 1 2 3 4 5 6 7 8 9 10 14 15 16 17 18 19 20&lt;br /&gt;
# Второй цикл начал исполняться раньше первого.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда, исполняемая в пределах сценария в фоне, может подвесить сценарий, ожидая нажатия клавиши. К счастью, это легко &amp;quot;лечится&amp;quot;.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''&amp;amp;&amp;amp;'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; логическая операция ''AND'' (логическое И).&amp;lt;/span&amp;gt;&lt;br /&gt;
В операциях проверки условий, оператор &amp;lt;big&amp;gt;'''''&amp;amp;&amp;amp;'''''&amp;lt;/big&amp;gt; возвращает 0 ('''success''') тогда, и только тогда, когда оба операнда имеют значение ''true''(ИСТИНА).&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Знак дефиса (''-'')&amp;lt;/span&amp;gt;&lt;br /&gt;
Префикс ключа. С этого символа начинаются опциональные ключи команд:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
COMMAND -[Option1][Option2][...]&lt;br /&gt;
ls -al&lt;br /&gt;
sort -dfu $filename&lt;br /&gt;
set -- $variable&lt;br /&gt;
&lt;br /&gt;
if [ $file1 -ot $file2 ];then&lt;br /&gt;
 echo &amp;quot;Файл $file1 был создан раньше чем $file2.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq &amp;quot;$b&amp;quot; ]; then&lt;br /&gt;
 echo &amp;quot;$a равно $b.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if [ &amp;quot;$c&amp;quot; -eq 24 -a &amp;quot;$d&amp;quot; -eq 47 ]; then&lt;br /&gt;
 echo &amp;quot;$c равно 24, а $d равно 47.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; — перенаправление из/в ''stdin'' или ''stdout''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(cd /source/directory &amp;amp;&amp;amp; tar cf - . ) | (cd /dest/directory &amp;amp;&amp;amp; tar xpvf -)&lt;br /&gt;
# Перемещение полного дерева файлов и подкаталогов из одной директории в другую&lt;br /&gt;
# спасибо Алану Коксу (Alan Cox) &amp;lt;a.cox@swansea.ac.uk&amp;gt;, за небольшие поправки&lt;br /&gt;
# 1) cd /source/directory Переход в исходный каталог, содержимое которого будет перемещено&lt;br /&gt;
# 2) &amp;amp;&amp;amp; &amp;quot;И-список&amp;quot;: благодаря этому все последующие команды будут выполнены&lt;br /&gt;
# только тогда, когда 'cd' завершится успешно&lt;br /&gt;
# 3) tar cf - . ключом 'c' архиватор 'tar' создает новый архив,&lt;br /&gt;
# ключом 'f' (file) и последующим '-' задается файл архива -- stdout,&lt;br /&gt;
# в архив помещается текущий каталог ('.') с вложенными подкаталогами.&lt;br /&gt;
# 4) | конвейер с ...&lt;br /&gt;
# 5) ( ... ) subshell-ом (дочерним экземпляром командной оболочки)&lt;br /&gt;
# 6) cd /dest/directory Переход в каталог назначения.&lt;br /&gt;
# 7) &amp;amp;&amp;amp; &amp;quot;И-список&amp;quot;, см. выше&lt;br /&gt;
# 8) tar xpvf - Разархивирование ('x'), с сохранением атрибутов &amp;quot;владельца&amp;quot; и прав доступа ('p') к файлам,&lt;br /&gt;
# с выдачей более подробных сообщений на stdout ('v'),&lt;br /&gt;
# файл архива -- stdin ('f' с последующим '-').&lt;br /&gt;
#&lt;br /&gt;
# Примечательно, что 'x' -- это команда, а 'p', 'v' и 'f' -- ключи&lt;br /&gt;
# Во как!&lt;br /&gt;
# Более элегантный вариант:&lt;br /&gt;
# cd source-directory&lt;br /&gt;
# tar cf - . | (cd ../target-directory; tar xzf -)&lt;br /&gt;
#&lt;br /&gt;
#cp -a /source/directory /dest имеет тот же эффект.&lt;br /&gt;
&lt;br /&gt;
bunzip2 linux-2.4.3.tar.bz2 | tar xvf -&lt;br /&gt;
# --разархивирование tar-файла-- | --затем файл передается утилите &amp;quot;tar&amp;quot;--&lt;br /&gt;
# Если у вас утилита &amp;quot;tar&amp;quot; не поддерживает работу с &amp;quot;bunzip2&amp;quot;,&lt;br /&gt;
# тогда придется выполнять работу в два этапа, с использованием конвейера.&lt;br /&gt;
# Целью данного примера является разархивирование тарбола (tar.bz2) с исходными текстами ядра.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Обратите внимание, что в этом контексте &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; - не самостоятельный оператор Bash, а скорее опция, распознаваемая некоторыми утилитами Unix (такими как [[tar]], [[cat]] и т.п.), которые выводят результаты своей работы в ''stdout''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo &amp;quot;whatever&amp;quot; | cat -&lt;br /&gt;
whatever&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В случае, когда ожидается имя файла, тогда &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; перенаправляет вывод на ''stdout'' (вспомните пример с [[Tar|tar cf]]) или принимает ввод с ''stdin''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ file&lt;br /&gt;
Usage: file [-bciknvzL] [-f namefile] [-m magicfiles] file...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Сама по себе команда [[file]] без параметров завершается с сообщением об ошибке.&lt;br /&gt;
Добавим символ &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; и получим более полезный результат. Это заставит командный интерпретатор ожидать ввода от пользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ file -&lt;br /&gt;
abc&lt;br /&gt;
standard input:  ASCII text&lt;br /&gt;
bash$ file -&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
standard input:   Bourne-Again shell script text executable&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь команда принимает ввод пользователя со ''stdin'' и анализирует его.&lt;br /&gt;
Используя передачу ''stdout'' по конвейеру другим командам, можно выполнять довольно эффектные трюки, например вставка строк в начало файла.&lt;br /&gt;
С помощью команды [[diff]] — находить различия между одним файлом и частью другого:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt; grep Linux file1 | diff file2 -&amp;lt;/source&amp;gt;&lt;br /&gt;
И наконец пример использования служебного символа &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; с командой [[tar]].&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример.'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Резервное архивирование всех файлов, которые были изменены втечение последних суток'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Резервное архивирование (backup) всех файлов в текущем каталоге,&lt;br /&gt;
# которые были изменены в течение последних 24 часов&lt;br /&gt;
# в тарболл (tarball) (.tar.gz - файл).&lt;br /&gt;
BACKUPFILE=backup&lt;br /&gt;
archive=${1:-$BACKUPFILE}&lt;br /&gt;
# На случай, если имя архива в командной строке не задано,&lt;br /&gt;
# т.е. по-умолчанию имя архива -- &amp;quot;backup.tar.gz&amp;quot;&lt;br /&gt;
tar cvf - `find . -mtime -1 -type f -print` &amp;gt; $archive.tar&lt;br /&gt;
gzip $archive.tar&lt;br /&gt;
echo &amp;quot;Каталог $PWD заархивирован в файл \&amp;quot;$archive.tar.gz\&amp;quot;.&amp;quot;&lt;br /&gt;
# Stephane Chazelas заметил, что вышеприведенный код будет &amp;quot;падать&amp;quot;&lt;br /&gt;
# если будет найдено слишком много файлов&lt;br /&gt;
# или если имена файлов будут содержать символы пробела.&lt;br /&gt;
# Им предложен альтернативный код:&lt;br /&gt;
# -------------------------------------------------------------------&lt;br /&gt;
# find . -mtime -1 -type f -print0 | xargs -0 tar rvf &amp;quot;$archive.tar&amp;quot;&lt;br /&gt;
# используется версия GNU утилиты &amp;quot;find&amp;quot;.&lt;br /&gt;
# find . -mtime -1 -type f -exec tar rvf &amp;quot;$archive.tar&amp;quot; '{}' \;&lt;br /&gt;
# более универсальный вариант, хотя и более медленный,&lt;br /&gt;
# зато может использоваться в других версиях UNIX.&lt;br /&gt;
# -------------------------------------------------------------------&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Могут возникнуть конфликтные ситуации между опреатором перенаправления &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt;  и именами файлов, начинающимися с символа &amp;quot;-&amp;quot;. Поэтому сценарий должен проверять имена файлов и предварять их префиксом пути, например, ''./-FILENAME'', ''$PWD/-FILENAME'' или ''$PATHNAME/-FILENAME''.&lt;br /&gt;
Если значение переменной начинается с символа &amp;quot;-&amp;quot;, то это тоже может быть причиной появления ошибок.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
var=&amp;quot;-n&amp;quot;&lt;br /&gt;
echo $var&lt;br /&gt;
# В данном случае команда приобретет вид &amp;quot;echo -n&amp;quot; и ничего не выведет.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; — предыдущий рабочий каталог. Команда cd - выполнит переход в предыдущий рабочий каталог, путь к которому хранится в переменной окружения $OLDPWD.&lt;br /&gt;
Не путайте оператор &amp;quot;-&amp;quot; (предыдущего рабочего каталога) с оператором &amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; (переназначения). Ещё раз напомню, что интерпретация символа &amp;quot;-&amp;quot; зависит от контекста, в котором он употребляется.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''-'''''&amp;lt;/big&amp;gt; — Знак минус в арифметических операциях.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''='''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Символ равно ('''''=''''').&amp;lt;/span&amp;gt;&lt;br /&gt;
Символ равно (&amp;lt;big&amp;gt;'''''='''''&amp;lt;/big&amp;gt;) выступает в качестве оператора присваивания.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
a=28&lt;br /&gt;
echo $a # 28&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В зависимости от контекста применения, символ &amp;lt;big&amp;gt;'''''='''''&amp;lt;/big&amp;gt; может выступать в качестве оператора сравнения.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''+'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Символ плюс ('''''+''''').&amp;lt;/span&amp;gt;&lt;br /&gt;
Символ плюс (&amp;lt;big&amp;gt;'''''+'''''&amp;lt;/big&amp;gt;) выступает в качестве оператора сложения в арифметических операциях. В зависимости от контекста применения, символ &amp;lt;big&amp;gt;'''''+'''''&amp;lt;/big&amp;gt; может выступать как оператор регулярного выражения.&lt;br /&gt;
&amp;lt;big&amp;gt;'''''+'''''&amp;lt;/big&amp;gt; -  Ключ (опция). Дополнительный флаг для ключей (опций) команд. Отдельные внешние и встроенные команды используют символ &amp;quot;+&amp;quot; для разрешения некоторой опции, а символ &amp;quot;-&amp;quot; — для запрещения.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''%'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Символ процента ('''''%''''').&amp;lt;/span&amp;gt;&lt;br /&gt;
Модуль (остаток от деления) — арифметическая операция. В зависимости от контекста применения, символ  &amp;lt;big&amp;gt;'''''%'''''&amp;lt;/big&amp;gt; может выступать в качестве шаблона.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''~'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Символ тильда ('''''~''''').&amp;lt;/span&amp;gt;&lt;br /&gt;
Соответствует содержимому внутренней переменной $HOME. ~bozo — домашний каталог пользователя bozo, а команда [[Ls_—_Команда_печати_содержимого_каталога|ls ~bozo]] выведет содержимое его домашнего каталога. '''~/''' — это домашний каталог текущего пользователя, а команда [[Ls_—_Команда_печати_содержимого_каталога|ls ~/]] выведет содержимое домашнего каталога текущего пользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo ~bozo&lt;br /&gt;
/home/bozo&lt;br /&gt;
bash$ echo ~/home/bozo&lt;br /&gt;
bash$ echo ~/&lt;br /&gt;
/home/bozo/&lt;br /&gt;
bash$ echo ~:&lt;br /&gt;
/home/bozo:&lt;br /&gt;
bash$ echo ~nonexistent-user&lt;br /&gt;
~nonexistent-user&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''~+'''''&amp;lt;/big&amp;gt; — текущий рабочий каталог. Соответствует содержимому внутренней переменной $PWD.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''''~-'''''&amp;lt;/big&amp;gt; — предыдущий рабочий каталог. Соответствует содержимому внутренней переменной $OLDPWD.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''^'''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Символ карет ('''''^''''').&amp;lt;/span&amp;gt;&lt;br /&gt;
Начало-строки. В регулярных выражениях символ &amp;quot;^&amp;quot; задает начало строки текста. Управляющий символ '''изменяет поведение терминала или управляет выводом текста'''. Управляющий символ набирается с клавиатуры как комбинация '''''CONTROL + &amp;lt;клавиша&amp;gt;'''''.&lt;br /&gt;
# '''''Ctrl-B''''' — Курсор — на одну позицию назад (без стирания символа).&lt;br /&gt;
# '''''Ctrl-C''''' — Прерывание выполнения процесса.&lt;br /&gt;
# '''''Ctrl-D''''' —  Выход из командного интерпретатора (log out) (аналог команды [[exit]]).&amp;quot;EOF&amp;quot; (признак конца файла). Этот символ может выступать в качестве завершающего привводе с ''stdin''.&lt;br /&gt;
# '''''Ctrl-G''''' — &amp;quot;BEL&amp;quot; (звуковой сигнал -- &amp;quot;звонок&amp;quot;).&lt;br /&gt;
# '''''Ctrl-H''''' — Backspace (&amp;quot;забой&amp;quot;) — удаление предыдущего символа. &lt;br /&gt;
# '''''Ctrl-I''''' — Горизонтальная табуляция.&lt;br /&gt;
# '''''Ctrl-J''''' — Перевод строки.&lt;br /&gt;
# '''''Ctrl-K''''' — Вертикальная табуляция.&lt;br /&gt;
# '''''Ctrl-L''''' — Перевод формата (очистка экрана (окна) терминала). Аналогична команде [[clear]].&lt;br /&gt;
# '''''Ctrl-M''''' — Возврат каретки.&lt;br /&gt;
# '''''Ctrl-Q''''' — Resume (XON). Эта комбинация &amp;quot;восстанавливает&amp;quot; работу ''stdin'' терминала.&lt;br /&gt;
# '''''Ctrl-S''''' — Suspend (XOFF). Эта комбинация &amp;quot;замораживает&amp;quot; ''stdin'' терминала. (Для восстановления &amp;quot;работоспособности&amp;quot; — используйте комбинацию '''''Ctrl-Q''''')&lt;br /&gt;
# '''''Ctrl-U''''' — Стирание строки ввода.&lt;br /&gt;
# '''''Ctrl-Z''''' — Приостановка процесса.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Вставка символа Ctl-H в строку.&lt;br /&gt;
a=&amp;quot;^H^H&amp;quot; # Два символа Ctl-H (backspace).&lt;br /&gt;
echo &amp;quot;abcdef&amp;quot;&lt;br /&gt;
# abcdef&lt;br /&gt;
echo -n &amp;quot;abcdef$a &amp;quot; &lt;br /&gt;
# abcd f&lt;br /&gt;
# Пробел в конце ^ ^ двойной шаг назад.&lt;br /&gt;
echo -n &amp;quot;abcdef$a&amp;quot; # abcdef&lt;br /&gt;
# Пробела в конце нет, backspace не работает (почему?).&lt;br /&gt;
# Результаты могут получиться совсем не те, что вы ожидаете.&lt;br /&gt;
echo; echo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 # Спасибо Lee Maschmeyer, за этот пример.&lt;br /&gt;
 read -n 1 -s -p $'Control-M — переводит курсор в начало этой же строки. Нажмите клавишу Enter. \x0d'&lt;br /&gt;
 # Разумеется, что, 'x0d' — это # шестнадцатиричный эквивалент  '''''Ctrl-M'''''.&lt;br /&gt;
 echo &amp;gt;&amp;amp;2 # Перевод строки &lt;br /&gt;
 read -n 1 -s -p $'Control-J — переводит курсор в начало другой строки. \x0a'&lt;br /&gt;
 echo &amp;gt;&amp;amp;2 # Control-J — это перевод строки.&lt;br /&gt;
 read -n 1 -s -p $'А Control-K\x0b — вниз.'&lt;br /&gt;
 echo &amp;gt;&amp;amp;2 # Control-K — это вертикальная табуляция.&lt;br /&gt;
 exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;''''' '''''&amp;lt;/big&amp;gt; — &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt; Символ пробела (''''' ''''').&amp;lt;/span&amp;gt;&lt;br /&gt;
Пробельный символ используется как разделитель команд или переменных. В качестве пробельного символа могут выступать — собственно пробел (space), символ табуляции, символ перевода строки, символ возврата каретки или комбинация из вышеперечисленных символов. В некоторых случаях, таких как присваивание значений переменным, использование пробельных символов недопустимо. Пустые строки никак не обрабатываются командным интерпретатором и могут свободно использоваться для визуального выделения отдельных блоков сценария. '''''$IFS''''' — переменная специального назначения. Содержит символы-разделители полей, используемые некоторыми командами. По-умолчанию — пробельные символы.&lt;br /&gt;
&lt;br /&gt;
== Переменные и параметры. Введение. ==&lt;br /&gt;
Переменные — это одна из основ любого языка программирования. Они участвуют в арифметических операциях, в синтаксическом анализе строк и совершенно необходимы для абстрагирования каких-либо величин с помощью символических имен. Физически переменные представляют собой ни что иное как участки памяти, в которые записана некоторая информация.&lt;br /&gt;
=== Подстановка переменных ===&lt;br /&gt;
Когда интерпретатор встречает в тексте сценария имя переменной, то он вместо него подставляет значение этой переменной. Поэтому ссылки на переменные называются подстановкой переменных.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''$'''''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Необходимо всегда помнить о различиях между именем переменной и её значением. Если variable1 — это имя переменной, то $variable1 — это ссылка на её значение. &amp;quot;Чистые&amp;quot; имена переменных, без префикса $, могут использоваться только при объявлении переменной, при присваивании переменной некоторого значения, при удалении (сбросе), при экспорте и в особых случаях — когда переменная представляет собой название сигнала. Присваивание может производится с помощью символа = (например: var1=27), инструкцией read и в заголовке цикла (for var2 in 1 2 3).&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Заключение ссылки на переменную в двойные кавычки (&amp;quot; &amp;quot;) никак не сказывается на работе механизма подстановки. Этот случай называется &amp;quot;частичные кавычки&amp;quot;, иногда можно встретить название &amp;quot;нестрогие кавычки&amp;quot;. Одиночные кавычки (' ') заставляют интерпретатор воспринимать ссылку на переменную как простой набор символов, потому в одинарных кавычках операции подстановки не производятся. Этот случай называется &amp;quot;полные&amp;quot;, или &amp;quot;строгие&amp;quot; кавычки.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Примечательно, что написание $variable фактически является упрощенной формой написания ${variable}. Более строгая форма записи ${variable} может с успехом использоваться в тех случаях, когда применение упрощенной формы записи порождает сообщения о синтаксических ошибках.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Присваивание значений переменным и подстановка значений переменных.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Присваивание значений переменным и подстановка значений переменных&lt;br /&gt;
a=375&lt;br /&gt;
hello=$a&lt;br /&gt;
#-------------------------------------------------------------------------&lt;br /&gt;
# Использование пробельных символов&lt;br /&gt;
# с обеих сторон символа &amp;quot;=&amp;quot; присваивания недопустимо.&lt;br /&gt;
# Если записать &amp;quot;VARIABLE =value&amp;quot;,&lt;br /&gt;
# то интерпретатор попытается выполнить команду &amp;quot;VARIABLE&amp;quot; с параметром &amp;quot;=value&amp;quot;.&lt;br /&gt;
# Если записать &amp;quot;VARIABLE= value&amp;quot;,&lt;br /&gt;
# то интерпретатор попытается установить переменную окружения &amp;quot;VARIABLE&amp;quot; в &amp;quot;&amp;quot;&lt;br /&gt;
# и выполнить команду &amp;quot;value&amp;quot;.&lt;br /&gt;
#-------------------------------------------------------------------------&lt;br /&gt;
echo hello # Это не ссылка на переменную, выведет строку &amp;quot;hello&amp;quot;.&lt;br /&gt;
echo $hello&lt;br /&gt;
echo ${hello} # Идентично предыдущей строке.&lt;br /&gt;
echo &amp;quot;$hello&amp;quot;&lt;br /&gt;
echo &amp;quot;${hello}&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
hello=&amp;quot;A B  C  D&amp;quot;&lt;br /&gt;
echo $hello &lt;br /&gt;
# A B C D&lt;br /&gt;
echo &amp;quot;$hello&amp;quot; # A B C D&lt;br /&gt;
# Здесь вы сможете наблюдать различия в выводе echo $hello и echo &amp;quot;$hello&amp;quot;.&lt;br /&gt;
# Заключение ссылки на переменную в кавычки сохраняет пробельные символы.&lt;br /&gt;
echo&lt;br /&gt;
echo '$hello' # $hello&lt;br /&gt;
# Внутри одинарных кавычек не производится подстановка значений переменных,&lt;br /&gt;
# т.е. &amp;quot;$&amp;quot; интерпретируется как простой символ.&lt;br /&gt;
# Обратите внимание на различия, существующие между этими типами кавычек.&lt;br /&gt;
hello= # Запись пустого значения в переменную.&lt;br /&gt;
echo &amp;quot;\$hello (пустое значение) = $hello&amp;quot;&lt;br /&gt;
# Обратите внимание: запись пустого значения — это не то же самое,&lt;br /&gt;
# что сброс переменной, хотя конечный результат — тот же.&lt;br /&gt;
# --------------------------------------------------------------&lt;br /&gt;
# Допускается присваивание нескольких переменных в одной строке,&lt;br /&gt;
# если они отделены пробельными символами.&lt;br /&gt;
# Внимание! Это может снизить читабельность сценария и оказаться непереносимым.&lt;br /&gt;
var1=variable1 var2=variable2 var3=variable3&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;var1=$var1 var2=$var2 var3=$var3&amp;quot;&lt;br /&gt;
# Могут возникнуть проблемы с устаревшими версиями &amp;quot;sh&amp;quot;.&lt;br /&gt;
# --------------------------------------------------------------&lt;br /&gt;
echo; echo&lt;br /&gt;
numbers=&amp;quot;один два три&amp;quot;&lt;br /&gt;
other_numbers=&amp;quot;1 2 3&amp;quot;&lt;br /&gt;
# Если в значениях переменных встречаются пробелы,&lt;br /&gt;
# то использование кавычек обязательно.&lt;br /&gt;
echo &amp;quot;numbers = $numbers&amp;quot;&lt;br /&gt;
echo &amp;quot;other_numbers = $other_numbers&amp;quot; # other_numbers = 1 2 3&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;uninitialized_variable = $uninitialized_variable&amp;quot;&lt;br /&gt;
# Неинициализированная переменная содержит &amp;quot;пустое&amp;quot; значение.&lt;br /&gt;
uninitialized_variable= # Объявление неинициализированной переменной (то же, что и присваивание пустого значения)&lt;br /&gt;
echo &amp;quot;uninitialized_variable = $uninitialized_variable&amp;quot; # Переменная содержит &amp;quot;пустое&amp;quot; значение.&lt;br /&gt;
uninitialized_variable=23 # Присваивание.&lt;br /&gt;
unset uninitialized_variable # Сброс.&lt;br /&gt;
echo &amp;quot;uninitialized_variable = $uninitialized_variable&amp;quot; # Переменная содержит &amp;quot;пустое&amp;quot; значение.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Неинициализированная переменная хранит &amp;quot;пустое&amp;quot; значение - не ноль! Использование неинициализированных переменных может приводить к ошибкам разного рода в процессе исполнения. Не смотря на это в арифметических операциях допускается использовать неинициализированные переменные.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;$uninitialized&amp;quot; # (пустая строка)&lt;br /&gt;
let &amp;quot;uninitialized += 5&amp;quot; # Прибавить 5.&lt;br /&gt;
echo &amp;quot;$uninitialized&amp;quot; # 5&lt;br /&gt;
# Заключение:&lt;br /&gt;
# Неинициализированные переменные не имеют значения, однако&lt;br /&gt;
# в арифметических операциях за значение таких переменных принимается число 0.&lt;br /&gt;
# Это недокументированная (и возможно непереносимая) возможность.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Присваивание значений переменным ===&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''='''''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Оператор присваивания (пробельные символы до и после оператора — недопустимы).&lt;br /&gt;
Не путайте с операторами сравнения ''='' и ''-eq''!&lt;br /&gt;
Обратите внимание: символ &amp;lt;big&amp;gt;'''''='''''&amp;lt;/big&amp;gt; может использоваться как в качестве оператора присваивания, так и в качестве оператора сравнения, конкретная интерпретация зависит от контекста применения.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простое присваивание.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Явные переменные&lt;br /&gt;
echo&lt;br /&gt;
# Когда перед именем переменной не употребляется символ '$'?&lt;br /&gt;
# В операциях присваивания.&lt;br /&gt;
# Присваивание&lt;br /&gt;
a=879&lt;br /&gt;
echo &amp;quot;Значение переменной \&amp;quot;a\&amp;quot; — $a.&amp;quot;&lt;br /&gt;
# Присваивание с помощью ключевого слова 'let'&lt;br /&gt;
let a=16+5&lt;br /&gt;
echo &amp;quot;Значение переменной \&amp;quot;a\&amp;quot; теперь стало равным: $a.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# В заголовке цикла 'for' (своего рода неявное присваивание)&lt;br /&gt;
echo -n &amp;quot;Значения переменной \&amp;quot;a\&amp;quot; в цикле: &amp;quot;&lt;br /&gt;
for a in 7 8 9 11&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
# При использовании инструкции 'read' (тоже одна из разновидностей присваивания)&lt;br /&gt;
echo -n &amp;quot;Введите значение переменной \&amp;quot;a\&amp;quot; &amp;quot;&lt;br /&gt;
read a&lt;br /&gt;
echo &amp;quot;Значение переменной \&amp;quot;a\&amp;quot; теперь стало равным: $a.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Присваивание значений переменным простое и замаскированное.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
a=23 # Простейший случай&lt;br /&gt;
echo $a&lt;br /&gt;
b=$a&lt;br /&gt;
echo $b &lt;br /&gt;
# Теперь немного более сложный вариант (подстановка команд).&lt;br /&gt;
a=`echo Hello!` # В переменную 'a' попадает результат работы команды 'echo'&lt;br /&gt;
echo $a&lt;br /&gt;
# Обратите внимание на восклицательный знак (!) в подстанавливаемой команде&lt;br /&gt;
# этот вариант не будет работать при наборе в командной строке,&lt;br /&gt;
# поскольку здесь используется механизм &amp;quot;истории команд&amp;quot; BASH&lt;br /&gt;
# Однако, в сценариях, механизм истории команд запрещен.&lt;br /&gt;
a=`ls -l` # В переменную 'a' записывается результат работы команды 'ls -l'&lt;br /&gt;
echo $a # Кавычки отсутствуют, удаляются лишние пробелы и пустые строки.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;$a&amp;quot; # Переменная в кавычках, все пробелы и пустые строки сохраняются&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Взято из /etc/rc.d/rc.local&lt;br /&gt;
R=$(cat /etc/redhat-release)&lt;br /&gt;
arch=$(uname -m)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Переменные Bash не имеют типа ===&lt;br /&gt;
В отличие от большинства других языков программирования, Bash не производит разделения переменных по &amp;quot;типам&amp;quot;. По сути, переменные Bash являются строковыми переменными, но, в зависимости от контекста, Bash допускает целочисленную арифметику с переменными. Определяющим фактором здесь служит содержимое переменных.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Целое число или строка?'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# int-or-string.sh: Целое число или строка?&lt;br /&gt;
a=2334 # Целое число.&lt;br /&gt;
let &amp;quot;a += 1&amp;quot;&lt;br /&gt;
echo &amp;quot;a = $a &amp;quot; # a = 2335&lt;br /&gt;
echo # Всё ещё целое число.&lt;br /&gt;
b=${a/23/BB} # замена &amp;quot;23&amp;quot; на &amp;quot;BB&amp;quot;.&lt;br /&gt;
# Происходит трансформация числа в строку.&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; &lt;br /&gt;
# b = BB35&lt;br /&gt;
declare -i b # Явное указание типа здесь не поможет.&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # b = BB35&lt;br /&gt;
let &amp;quot;b += 1&amp;quot; # BB35 + 1 =&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # b = 1&lt;br /&gt;
echo&lt;br /&gt;
c=BB34&lt;br /&gt;
echo &amp;quot;c = $c&amp;quot; # c = BB34&lt;br /&gt;
d=${c/BB/23} # замена &amp;quot;BB&amp;quot; на &amp;quot;23&amp;quot;. &lt;br /&gt;
# Переменная $d становится целочисленной.&lt;br /&gt;
echo &amp;quot;d = $d&amp;quot; # d = 2334&lt;br /&gt;
let &amp;quot;d += 1&amp;quot; # 2334 + 1 =&lt;br /&gt;
echo &amp;quot;d = $d&amp;quot; # d = 2335echo&lt;br /&gt;
echo&lt;br /&gt;
# А что происходит с &amp;quot;пустыми&amp;quot; переменными?&lt;br /&gt;
e=&amp;quot;&amp;quot;&lt;br /&gt;
echo &amp;quot;e = $e&amp;quot; # e =&lt;br /&gt;
let &amp;quot;e += 1&amp;quot; # Арифметические операции допускают использование &amp;quot;пустых&amp;quot; переменных?&lt;br /&gt;
echo &amp;quot;e = $e&amp;quot; # e = 1&lt;br /&gt;
echo # &amp;quot;Пустая&amp;quot; переменная становится целочисленной.&lt;br /&gt;
# А что происходит с необъявленными переменными?&lt;br /&gt;
echo &amp;quot;f = $f&amp;quot; # f =&lt;br /&gt;
let &amp;quot;f += 1&amp;quot; # Арифметические операции допустимы?&lt;br /&gt;
echo &amp;quot;f = $f&amp;quot; # f = 1&lt;br /&gt;
echo # Необъявленная переменная трансформируется в целочисленную.&lt;br /&gt;
# Переменные Bash не имеют типов.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Отсутствие типов — это и благословение и проклятие. С одной стороны — отсутствие типов делает сценарии более гибкими(чтобы повеситься — достаточно иметь веревку!) и облегчает чтение кода. С другой — является источником потенциальных ошибок и поощряет привычку к &amp;quot;неряшливому&amp;quot; программированию.&lt;br /&gt;
Бремя отслеживания типа той или иной переменной полностью лежит на плечах программиста. Bash не будет делать это за вас!&lt;br /&gt;
&lt;br /&gt;
=== Специальные типы переменных ===&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''локальные переменные'''''&amp;lt;/big&amp;gt;&lt;br /&gt;
Переменные, область видимости которых ограничена блоком кода или телом функции (см. также локальные переменные в функциях)&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''переменные окружения'''''&amp;lt;/big&amp;gt;&lt;br /&gt;
Переменные, которые затрагивают командную оболочку и порядок взаимодействия с пользователем.&lt;br /&gt;
 В более общем контексте, каждый процесс имеет некоторое &amp;quot;окружение&amp;quot; (среду исполнения), т.е. набор переменных, к которым процесс может &lt;br /&gt;
 обращаться за получением определенной информации. В этом смысле командная оболочка подобна любому другому процессу.&lt;br /&gt;
Каждый раз, когда запускается командный интерпретатор, для него создаются переменные, соответствующие переменным окружения. Изменение переменных или добавление новых переменных окружения заставляет оболочку обновить свои переменные, и все дочерние процессы (и команды, исполняемые ею)наследуют это окружение.&lt;br /&gt;
 Пространство, выделяемое под переменные окружения, ограничено. Создание слишком большого количества переменных &lt;br /&gt;
 окружения или одной переменной, которая занимает слишком большое пространство, может привести к возникновению определённых проблем.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ eval &amp;quot;`seq 10000 | sed -e 's/.*/export var&amp;amp;=ZZZZZZZZZZZZZZ/'`&amp;quot;&lt;br /&gt;
bash$ du&lt;br /&gt;
bash: /usr/bin/du: Argument list too long&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если сценарий изменяет переменные окружения, то они должны &amp;quot;экспортироваться&amp;quot;, т.е. передаваться окружению, локальному по отношению к сценарию. Эта функция возложена на команду ''export''.&lt;br /&gt;
 Сценарий может экспортировать переменные только дочернему процессу, т.е.командам и процессам запускаемым из данного сценария. &lt;br /&gt;
 Сценарий, запускаемый из командной строки '''''не может''''' экспортировать переменные &amp;quot;наверх&amp;quot; командной оболочке. Дочерний процесс не может &lt;br /&gt;
 экспортировать переменные родительскому процессу.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''''позиционные параметры'''''&amp;lt;/big&amp;gt;&lt;br /&gt;
Аргументы, передаваемые скрипту из командной строки — $0, $1, $2, $3..., где $0 — это название файла сценария, $1 — это первый аргумент, $2 — второй, $3 — третий и так далее. Аргументы, следующие за $9, должны заключаться в фигурные скобки, например: ${10}, ${11}, ${12}.&amp;lt;br /&amp;gt;&lt;br /&gt;
Специальные переменные '''''$*''''' и '''''$@''''' содержат все позиционные параметры (аргументы командной строки).&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Позиционные параметры.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Команда вызова сценария должна содержать по меньшей мере 10 параметров, например&lt;br /&gt;
# ./scriptname 1 2 3 4 5 6 7 8 9 10&lt;br /&gt;
MINPARAMS=10&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Имя файла сценария: \&amp;quot;$0\&amp;quot;.&amp;quot;&lt;br /&gt;
# Для текущего каталога добавит ./&lt;br /&gt;
echo &amp;quot;Имя файла сценария: \&amp;quot;`basename $0`\&amp;quot;.&amp;quot;&lt;br /&gt;
# Добавит путь к имени файла (см. 'basename')&lt;br /&gt;
echo&lt;br /&gt;
if [ -n &amp;quot;$1&amp;quot; ] # Проверяемая переменная заключена в кавычки.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Параметр #1: $1&amp;quot; # необходимы кавычки для экранирования символа #&lt;br /&gt;
fi&lt;br /&gt;
if [ -n &amp;quot;$2&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Параметр #2: $2&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if [ -n &amp;quot;$3&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Параметр #3: $3&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if [ -n &amp;quot;${10}&amp;quot; ] # Параметры, следующие за $9 должны заключаться в фигурные скобки&lt;br /&gt;
then &lt;br /&gt;
 echo &amp;quot;Параметр #10: ${10}&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;-----------------------------------&amp;quot;&lt;br /&gt;
echo &amp;quot;Все аргументы командной строки: &amp;quot;$*&amp;quot;&amp;quot;&lt;br /&gt;
if [ $# -lt &amp;quot;$MINPARAMS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo&lt;br /&gt;
echo &amp;quot;Количество аргументов командной строки должно быть не менее $MINPARAMS !&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
''Скобочная нотация'' позиционных параметров даёт довольно простой способ обращения к последнему аргументу, переданному в сценарий из командной строки. Такой способ подразумевает использование косвенной адресации.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
args=$# # Количество переданных аргументов.&lt;br /&gt;
lastarg=${!args} # Обратите внимание: lastarg=${!$#} неприменимо.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В сценарии можно предусмотреть различные варианты развития событий, в зависимости отимени сценария. Для этого сценарий должен проанализировать аргумент $0 -- имя файласценария. Это могут быть и имена символических ссылок на файл сценария.&lt;br /&gt;
 Если сценарий ожидает передачи аргументов в командной строке, то при их отсутствии он получит &amp;quot;пустые&amp;quot; переменные, что может вызвать нежелательный&lt;br /&gt;
 побочный эффект. Один из способов борьбы с подобными ошибками — добавить дополнительный символ в обеих частях операции присваивания, &lt;br /&gt;
 где используются аргументы командной строки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable1_=$1_# Это предотвратит появление ошибок, даже при отсутствии входного аргумента.&lt;br /&gt;
critical_argument01=$variable1_&lt;br /&gt;
# Дополнительные символы всегда можно &amp;quot;убрать&amp;quot; позднее.&lt;br /&gt;
# Это может быть сделано примерно так:&lt;br /&gt;
variable1=${variable1_/_/} # Побочный эффект возникает только если имя переменной # $variable1_ будет начинаться с символа &amp;quot;_&amp;quot;.&lt;br /&gt;
# Здесь используется один из вариантов подстановки параметров, обсуждаемых далее.&lt;br /&gt;
# Отсутствие шаблона замены приводит к удалению.&lt;br /&gt;
# Более простой способ заключается&lt;br /&gt;
# в обычной проверке наличия позиционного параметра.&lt;br /&gt;
if [ -z $1 ]; then &lt;br /&gt;
exit $POS_PARAMS_MISSING&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''wh, whois выяснение имени домена.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Команда 'whois domain-name' выясняет имя домена на одном из 3 серверов:&lt;br /&gt;
# ripe.net, cw.net, radb.net&lt;br /&gt;
# Разместите этот скрипт под именем 'wh' в каталоге /usr/local/bin&lt;br /&gt;
# Требуемые символические ссылки:&lt;br /&gt;
# ln -s /usr/local/bin/wh /usr/local/bin/wh-ripe&lt;br /&gt;
# ln -s /usr/local/bin/wh /usr/local/bin/wh-cw&lt;br /&gt;
# ln -s /usr/local/bin/wh /usr/local/bin/wh-radb&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` [domain-name]&amp;quot;&lt;br /&gt;
exit 65&lt;br /&gt;
fi&lt;br /&gt;
case `basename $0` in&lt;br /&gt;
# Проверка имени скрипта и, соответственно, имени сервера&lt;br /&gt;
&amp;quot;wh&amp;quot; ) whois $1@whois.ripe.net;;&lt;br /&gt;
&amp;quot;wh-ripe&amp;quot;) whois $1@whois.ripe.net;;&lt;br /&gt;
&amp;quot;wh-radb&amp;quot;) whois $1@whois.radb.net;;&lt;br /&gt;
&amp;quot;wh-cw&amp;quot; ) whois $1@whois.cw.net;;&lt;br /&gt;
* ) echo &amp;quot;Порядок использования: `basename $0` [domain-name]&amp;quot;;;&lt;br /&gt;
esac&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда shift &amp;quot;сдвигает&amp;quot; позиционные параметры, в результате чего парметры &amp;quot;сдвигаются&amp;quot; на одну позицию влево.&lt;br /&gt;
&amp;lt;br /&amp;gt;$1 &amp;lt;--- $2, $2 &amp;lt;--- $3, $3 &amp;lt;--- $4, и т.д.&amp;lt;br /&amp;gt;&lt;br /&gt;
Прежний аргумент $1 теряется, но аргумент $0 (имя файла сценария) остаётся без изменений. Если вашему сценарию передаётся большое количество входных аргументов, то команда shift позволит вам получить доступ к аргументам, с порядковым номером больше 9, без использования {фигурных скобок}.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование команды shift.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Использование команды 'shift' с целью перебора всех аргументов командной строки.&lt;br /&gt;
# Назовите файл с этим сценарием, например &amp;quot;shft&amp;quot;,&lt;br /&gt;
# и вызовите его с набором аргументов, например:&lt;br /&gt;
# ./shft a b c def 23 skidoo&lt;br /&gt;
until [ -z &amp;quot;$1&amp;quot; ] # До тех пор пока не будут разобраны все входные аргументы...&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$1 &amp;quot; &lt;br /&gt;
 shift&lt;br /&gt;
done&lt;br /&gt;
echo # Дополнительная пустая строка.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда ''shift'' может применяться и к входным аргументам функций.&lt;br /&gt;
&lt;br /&gt;
== Кавычки ==&lt;br /&gt;
Кавычки, ограничивающие строки с обеих сторон, служат для предотвращения интерпретации специальных символов, которые могут находиться в строке. Символ называется &amp;quot;специальным&amp;quot;, если он несет дополнительную смысловую нагрузку, например символ шаблона — &amp;lt;big&amp;gt;'''*'''&amp;lt;/big&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ls -l [Vv]*&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 324 Apr 2 15:05 VIEWDATA.BAT &lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 507 May 4 14:25 vartrace.sh &lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 539 Apr 14 17:11 viewdata.sh&lt;br /&gt;
bash$ ls -l '[Vv]*'&lt;br /&gt;
ls: [Vv]*: No such file or directory&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Некоторые программы и утилиты могут вызываться с дополнительными параметрами,содержащими специальными символы, поэтому очень важно предотвратить интерпретацию передаваемых параметров командной оболочкой, позволяя сделать это вызываемой программой.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep '[Пп]ервая' *.txt&lt;br /&gt;
file1.txt:Это первая строка в file1.txt. &lt;br /&gt;
file2.txt:Это Первая строка в file2.txt.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Примечательно, что &amp;quot;не окавыченный&amp;quot; вариант команды grep [Пп]ервая *.txt будет правильно исполняться в Bash, но не в tcsh.&lt;br /&gt;
Вообще, желательно использовать двойные кавычки (&amp;lt;big&amp;gt;&amp;quot; &amp;quot;&amp;lt;/big&amp;gt;) при обращении к переменным. Это предотвратит интерпретацию специальных символов, которые могут содержаться в именах переменных, за исключением &amp;lt;big&amp;gt;$&amp;lt;/big&amp;gt;, &amp;lt;big&amp;gt;`&amp;lt;/big&amp;gt;(обратная кавычка) и &amp;lt;big&amp;gt;\&amp;lt;/big&amp;gt; (escape — обратный слэш).&lt;br /&gt;
То, что символ &amp;lt;big&amp;gt;$&amp;lt;/big&amp;gt; попал в разряд исключений, позволяет выполнять обращение к переменным внутри строк, ограниченных двойными кавычками (&amp;quot;$variable&amp;quot;), т.е. выполнять подстановку значений переменных.&lt;br /&gt;
Двойные кавычки могут быть использованы для предотвращения разбиения строки на слова. Заключение строки в кавычки приводит к тому, что она передаётся как один аргумент, даже если она содержит пробельные символы-разделители.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable1=&amp;quot;a variable containing five words&amp;quot;&lt;br /&gt;
COMMAND This is $variable1 # Исполнение COMMAND с 7 входными аргументами:&lt;br /&gt;
# &amp;quot;This&amp;quot; &amp;quot;is&amp;quot; &amp;quot;a&amp;quot; &amp;quot;variable&amp;quot; &amp;quot;containing&amp;quot; &amp;quot;five&amp;quot; &amp;quot;words&amp;quot;&lt;br /&gt;
COMMAND &amp;quot;This is $variable1&amp;quot; &lt;br /&gt;
# Исполнение COMMAND с одним входным аргументом:# &amp;quot;This is a variable containing five words&amp;quot;&lt;br /&gt;
variable2=&amp;quot;&amp;quot; # Пустая переменная.&lt;br /&gt;
COMMAND $variable2 $variable2 $variable2 # Исполнение COMMAND без аргументов.&lt;br /&gt;
COMMAND &amp;quot;$variable2&amp;quot; &amp;quot;$variable2&amp;quot; &amp;quot;$variable2&amp;quot; # Исполнение COMMAND с 3 &amp;quot;пустыми&amp;quot; аргументами.&lt;br /&gt;
COMMAND &amp;quot;$variable2 $variable2 $variable2&amp;quot; # Исполнение COMMAND с 1 аргументом (и 2 пробелами).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Заключение в кавычки аргументов команды [[echo]] необходимо только в том случае, когда разбиение на отдельные слова сопряжено с определенными трудностями.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вывод &amp;quot;причудливых&amp;quot; переменных.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# weirdvars.sh: Вывод &amp;quot;причудливых&amp;quot; переменных&lt;br /&gt;
var=&amp;quot;'(]\\{}\$\&amp;quot;&amp;quot;&lt;br /&gt;
echo $var # '(]\{}$&amp;quot;&lt;br /&gt;
echo &amp;quot;$var&amp;quot; # '(]\{}$&amp;quot; Никаких различий.&lt;br /&gt;
echo&lt;br /&gt;
IFS='\'&lt;br /&gt;
echo $var # '(] {}$&amp;quot; \ символ-разделитель преобразован в пробел.&lt;br /&gt;
echo &amp;quot;$var&amp;quot; # '(]\{}$&amp;quot;&lt;br /&gt;
# Примеры выше предоставлены S.C.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Одиночные кавычки (&amp;lt;big&amp;gt;' '&amp;lt;/big&amp;gt;) схожи по своему действию с двойными кавычками, только не допускают обращение к переменным, поскольку специальный символ &amp;quot;$&amp;quot; внутри одинарных кавычек воспринимается как обычный символ. Внутри одиночных кавычек, любой специальный символ, заисключением ', интерпретируется как простой символ. Одиночные кавычки (&amp;quot;строгие, или полные кавычки&amp;quot;) следует рассматривать как более строгий вариант, чем двойные кавычки (&amp;quot;нестрогие, или неполные кавычки&amp;quot;).&lt;br /&gt;
Поскольку внутри одиночных кавычек даже экранирующий (&amp;lt;big&amp;gt;\&amp;lt;/big&amp;gt;) символ воспринимается как обычный символ, попытка вывести одиночную кавычку внутри строки, ограниченной одинарными кавычками, не даст желаемого результата.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;Why can't I write 's between single quotes&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Обходной метод.&lt;br /&gt;
echo 'Why can'\''t I write '&amp;quot;'&amp;quot;'s between single quotes'&lt;br /&gt;
# |-------| |----------| |-----------------------|&lt;br /&gt;
# Три строки, ограниченных одинарными кавычками,&lt;br /&gt;
# и экранированные одиночные кавычки между ними.&lt;br /&gt;
# Пример любезно предоставлен Stephane Chazelas.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Экранирование''''' — это способ заключения в кавычки одиночного символа. Экранирующий (escape)символ (&amp;lt;big&amp;gt;\&amp;lt;/big&amp;gt;) сообщает интерпретатору, что следующий за ним символ должен восприниматься как обычный символ. С отдельными командами и утилитами, такими как [[echo]] и [[sed]], экранирующий символ может применяться для получения обратного эффекта — когда обычные символы при экранировании приобретают специальное значение.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:black&amp;quot;&amp;gt; '''Специальное назначение некоторых экранированных символов, используемых совместно с [[echo]] и [[sed]]'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\n'''&amp;lt;/big&amp;gt; — перевод строки (новая строка)&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\r'''&amp;lt;/big&amp;gt; — перевод каретки&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\t'''&amp;lt;/big&amp;gt; — табуляция&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\v'''&amp;lt;/big&amp;gt; — вертикальная табуляция&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\b'''&amp;lt;/big&amp;gt; — забой (backspace)&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\a'''&amp;lt;/big&amp;gt; — &amp;quot;звонок&amp;quot; (сигнал)&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\0xx'''&amp;lt;/big&amp;gt; — ASCII-символ с кодом 0xx в восьмеричном виде&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Экранированные символы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# escaped.sh: экранированные символы&lt;br /&gt;
echo; echo&lt;br /&gt;
echo &amp;quot;\v\v\v\v&amp;quot; # Вывод последовательности символов \v\v\v\v.&lt;br /&gt;
# Для вывода экранированных символов следует использовать ключ -e.&lt;br /&gt;
echo &amp;quot;=============&amp;quot;&lt;br /&gt;
echo &amp;quot;ВЕРТИКАЛЬНАЯ ТАБУЛЯЦИЯ&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\v\v\v\v&amp;quot; # Вывод 4-х вертикальных табуляций.&lt;br /&gt;
echo &amp;quot;==============&amp;quot;&lt;br /&gt;
echo &amp;quot;КАВЫЧКИ&amp;quot;&lt;br /&gt;
echo -e &amp;quot;\042&amp;quot; # Выводит символ &amp;quot; (кавычки с восьмеричным кодом ASCII 42).&lt;br /&gt;
echo &amp;quot;==============&amp;quot;&lt;br /&gt;
# Конструкция $'\X' делает использование ключа -e необязательным.&lt;br /&gt;
echo; echo &amp;quot;НОВАЯ СТРОКА И ЗВОНОК&amp;quot;&lt;br /&gt;
echo $'\n' # Перевод строки.&lt;br /&gt;
echo $'\a' # Звонок (сигнал).&lt;br /&gt;
echo &amp;quot;===============&amp;quot;&lt;br /&gt;
echo &amp;quot;КАВЫЧКИ&amp;quot;&lt;br /&gt;
# Bash версии 2 и выше допускает использование конструкции $'\nnn'.&lt;br /&gt;
# Обратите внимание: здесь под '\nnn' подразумевается восьмеричное значение.&lt;br /&gt;
echo $'\t \042 \t' # Кавычки (&amp;quot;) окруженные табуляцией.&lt;br /&gt;
# В конструкции $'\xhhh' допускается использовать и шестнадцатеричные значения.&lt;br /&gt;
echo $'\t \x22 \t' # Кавычки (&amp;quot;) окруженные табуляцией.&lt;br /&gt;
# Спасибо Greg Keraunen, за это примечание.&lt;br /&gt;
# Ранние версии Bash допускали употребление конструкции в виде '\x022'.&lt;br /&gt;
echo &amp;quot;===============&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Запись ASCII-символов в переменную.&lt;br /&gt;
# ----------------------------------------&lt;br /&gt;
quote=$'\042' # запись символа &amp;quot; в переменную.&lt;br /&gt;
echo &amp;quot;$quote Эта часть строки ограничена кавычками, $quote а эта — нет.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Конкатенация ASCII-символов в переменную.&lt;br /&gt;
triple_underline=$'\137\137\137' # 137 — это восьмеричный код символа '_'.&lt;br /&gt;
echo &amp;quot;$triple_underline ПОДЧЕРКИВАНИЕ $triple_underline&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
ABC=$'\101\102\103\010' # 101, 102, 103 это A, B и C соответственно.&lt;br /&gt;
echo $ABC&lt;br /&gt;
echo; echo&lt;br /&gt;
escape=$'\033' # 033 — восьмеричный код экранирующего символа.&lt;br /&gt;
echo &amp;quot;\&amp;quot;escape\&amp;quot; выводится как $escape&amp;quot;&lt;br /&gt;
# вывод отсутствует.&lt;br /&gt;
echo; echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\&amp;quot;'''&amp;lt;/big&amp;gt; — кавычки&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;Привет&amp;quot; # Привет&lt;br /&gt;
echo &amp;quot;Он сказал: \&amp;quot;Привет\&amp;quot;.&amp;quot; # Он сказал: &amp;quot;Привет&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\$'''&amp;lt;/big&amp;gt; — символ доллара (если за комбинацией символов \$ следует имя переменной, то она не будет разыменована)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;\$variable01&amp;quot; # выведет $variable01&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''\\'''&amp;lt;/big&amp;gt; — обратный слэш&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;\\&amp;quot; # выведет \&lt;br /&gt;
# Тогда как...&lt;br /&gt;
echo &amp;quot;\&amp;quot; # Приведёт к выводу вторичного приглашения к вводу. &lt;br /&gt;
# В сценариях — порождает сообщение об ошибке.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Поведение символа &amp;lt;big&amp;gt;\&amp;lt;/big&amp;gt; сильно зависит от того экранирован ли он, ограничен ли кавычками или находится внутри конструкции подстановки команды или во вложенном документе.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Простое экранирование и кавычки&lt;br /&gt;
echo \z # z&lt;br /&gt;
echo \\z # \z&lt;br /&gt;
echo '\z' # \z&lt;br /&gt;
echo '\\z' # \\z&lt;br /&gt;
echo &amp;quot;\z&amp;quot; # \z&lt;br /&gt;
echo &amp;quot;\\z&amp;quot; # \z&lt;br /&gt;
# Подстановка команды&lt;br /&gt;
echo `echo \z` # z&lt;br /&gt;
echo `echo \\z` # z&lt;br /&gt;
echo `echo \\\z` # \z&lt;br /&gt;
echo `echo \\\\z` # \z&lt;br /&gt;
echo `echo \\\\\\z` # \z&lt;br /&gt;
echo `echo \\\\\\\z` # \\z&lt;br /&gt;
echo `echo &amp;quot;\z&amp;quot;` # \z&lt;br /&gt;
echo `echo &amp;quot;\\z&amp;quot;` # \z&lt;br /&gt;
# Встроенный документ&lt;br /&gt;
cat &amp;lt;&amp;lt;EOF&lt;br /&gt;
\z&lt;br /&gt;
EOF # \z&lt;br /&gt;
cat &amp;lt;&amp;lt;EOF&lt;br /&gt;
\\z&lt;br /&gt;
EOF # \z&lt;br /&gt;
# Эти примеры предоставил Stephane Chazelas.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отдельные символы в строке, которая записывается в переменную, могут быть экранированы, исключение составляет сам экранирующий символ.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable=\&lt;br /&gt;
echo &amp;quot;$variable&amp;quot;&lt;br /&gt;
# Не работает - дает сообщение об ошибке:&lt;br /&gt;
# test.sh: : command not found&lt;br /&gt;
# В &amp;quot;чистом&amp;quot; виде экранирующий (escape) символ не может быть записан в переменную.&lt;br /&gt;
# Фактически, в данном примере, происходит экранирование символа перевода строки&lt;br /&gt;
# в результате получается такая команда: variable=echo &amp;quot;$variable&amp;quot;&lt;br /&gt;
# ошибочное присваивание&lt;br /&gt;
variable=\&lt;br /&gt;
23skidoo&lt;br /&gt;
echo &amp;quot;$variable&amp;quot; # 23skidoo&lt;br /&gt;
# Здесь все в порядке, поскольку вторая строка &lt;br /&gt;
# является нормальным, с точки зрения присваивания, выражением.&lt;br /&gt;
variable=\&lt;br /&gt;
# \^ За escape-символом следует пробел&lt;br /&gt;
echo &amp;quot;$variable&amp;quot; # пробел&lt;br /&gt;
variable=\\  # \&lt;br /&gt;
variable=\\\&lt;br /&gt;
echo &amp;quot;$variable&amp;quot;&lt;br /&gt;
# Не работает - сообщение об ошибке:&lt;br /&gt;
# test.sh: \: command not found&lt;br /&gt;
#&lt;br /&gt;
# Первый escape-символ экранирует второй, а третий оказывается неэкранированным,&lt;br /&gt;
# результат тот же, что и в первом примере.&lt;br /&gt;
variable=\\\\&lt;br /&gt;
echo &amp;quot;$variable&amp;quot; # \\&lt;br /&gt;
# Второй и четвертый escape-символы экранированы.&lt;br /&gt;
# Это нормально.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Экранирование пробелов предотвращает разбиение списка аргументов командной строки на отдельные аргументы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
file_list=&amp;quot;/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7&amp;quot;&lt;br /&gt;
# Список файлов как аргумент(ы) командной строки.&lt;br /&gt;
# Добавить два файла в список и вывести список.&lt;br /&gt;
ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_listecho &amp;quot;-------------------------------------------------------------------------&amp;quot;&lt;br /&gt;
# Что произойдет, если экранировать пробелы в списке?&lt;br /&gt;
ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list&lt;br /&gt;
# Ошибка: первые три файла будут &amp;quot;слиты&amp;quot; воедино&lt;br /&gt;
# и переданы команде 'ls -l' как один аргумент&lt;br /&gt;
# потому что два пробела, разделяющие аргументы (слова) — экранированы.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Кроме того, escape-символ позволяет писать многострочные команды. Обычно, каждая команда занимает одну строку, но escape-символ позволяет экранировать символ перевода строки, в результате чего одна команда может занимать несколько строк.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(cd /source/directory &amp;amp;&amp;amp; tar cf - . ) | \&lt;br /&gt;
(cd /dest/directory &amp;amp;&amp;amp; tar xpvf -)&lt;br /&gt;
# Команда копирования дерева каталогов.&lt;br /&gt;
# Разбита на две строки для большей удобочитаемости.&lt;br /&gt;
# Альтернативный вариант:&lt;br /&gt;
tar cf - -C /source/directory . |&lt;br /&gt;
tar xpvf - -C /dest/directory&lt;br /&gt;
# См. примечание ниже.&lt;br /&gt;
# (Спасибо Stephane Chazelas.)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если строка сценария заканчивается символом создания конвейера &amp;lt;big&amp;gt;|&amp;lt;/big&amp;gt;, то необходимость в применении символа &amp;lt;big&amp;gt;\&amp;lt;/big&amp;gt;, для экранирования перевода строки, отпадает. Тем не менее, считается хорошим тоном, всегда использовать символ &amp;lt;big&amp;gt;\&amp;lt;/big&amp;gt; в конце промежуточных строк многострочных команд.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;foo&lt;br /&gt;
bar&amp;quot;&lt;br /&gt;
#foo&lt;br /&gt;
#bar&lt;br /&gt;
echo&lt;br /&gt;
echo 'foo&lt;br /&gt;
bar' # Никаких различий.&lt;br /&gt;
echo&lt;br /&gt;
echo foo\&lt;br /&gt;
bar # Перевод строки экранирован.&lt;br /&gt;
#foobar&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;foo\&lt;br /&gt;
bar&amp;quot; # Внутри &amp;quot;нестрогих&amp;quot; кавычек символ &amp;quot;\&amp;quot; интерпретируется как экранирующий.&lt;br /&gt;
#foobar&lt;br /&gt;
echo&lt;br /&gt;
echo 'foo\&lt;br /&gt;
bar' # В &amp;quot;строгих&amp;quot; кавычках обратный слэш воспринимается как обычный символ.&lt;br /&gt;
#foo\&lt;br /&gt;
#bar&lt;br /&gt;
# Примеры предложены Stephane Chazelas.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Завершение и код завершения ==&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
''...эта часть Bourne shell покрыта мраком, тем не менее все пользуются ею''. ©Chet Ramey&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
Команда [[exit]] может использоваться для завершения работы сценария, точно так же как и в программах на языке C. Кроме того, она может возвращать некоторое значение, которое может быть проанализировано вызывающим процессом. Каждая команда возвращает ''код завершения'' (иногда код завершения называют ''возвращаемым значением''). В случае успеха команда должна возвращать 0, а в случае ошибки — ненулевое значение, которое, как правило, интерпретируется как код ошибки. Практически все команды и утилиты Unix возвращают 0 в случае успешного завершения, но имеются и исключения из правил.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Аналогичным образом ведут себя функции, расположенные внутри сценария, и сам сценарий, возвращая код завершения. Код, возвращаемый функцией или сценарием, определяется кодом возврата последней команды. Команде [[exit]] можно явно указать код возврата, в виде: exit ''nnn'', где ''nnn'' — это код возврата (число в диапазоне 0 - 255).&lt;br /&gt;
Когда работа сценария завершается командой [[exit]] без параметров, то код возврата сценария определяется кодом завершения последней исполненной команды (не считая саму команду [[exit]]).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
COMMAND_1&lt;br /&gt;
...&lt;br /&gt;
# Сценарий вернет код завершения последней команды.&lt;br /&gt;
COMMAND_LAST&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Эквивалентный вариант — ''exit $?'' или можно вообще опустить команду [[exit]].&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
COMMAND_1&lt;br /&gt;
...&lt;br /&gt;
# Сценарий вернет код завершения последней команды.&lt;br /&gt;
COMMAND_LAST&lt;br /&gt;
exit $?&lt;br /&gt;
&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
COMMAND1&lt;br /&gt;
...&lt;br /&gt;
# Сценарий вернет код завершения последней команды.&lt;br /&gt;
COMMAND_LAST&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Код возврата последней команды хранится в специальной переменной &amp;lt;big&amp;gt;$?&amp;lt;/big&amp;gt;. После исполнения кодафункции, переменная &amp;lt;big&amp;gt;$?&amp;lt;/big&amp;gt; хранит код завершения последней команды, исполненной в функции. Таким способом в Bash передаётся &amp;quot;значение, возвращаемое&amp;quot; функцией. После завершения работы сценария, код возврата можно получить, обратившись из командной строки к переменной &amp;lt;big&amp;gt;$?&amp;lt;/big&amp;gt;, т.е. это будет код возврата последней команды, исполненной в сценарии.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Завершение / код завершения.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo hello&lt;br /&gt;
echo $? # код возврата = 0, поскольку команда выполнилась успешно.&lt;br /&gt;
lskdf # Несуществующая команда.&lt;br /&gt;
echo $? # Ненулевой код возврата, поскольку команду выполнить не удалось.&lt;br /&gt;
echo&lt;br /&gt;
exit 113 # Явное указание кода возврата 113.&lt;br /&gt;
# Проверить можно, если набрать в командной строке &amp;quot;echo $?&amp;quot;&lt;br /&gt;
# после выполнения этого примера.&lt;br /&gt;
# В соответствии с соглашениями, 'exit 0' указывает на успешное завершение,&lt;br /&gt;
# в то время как ненулевое значение означает ошибку.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Переменная &amp;lt;big&amp;gt;$?&amp;lt;/big&amp;gt; особенно полезна, когда необходимо проверить результат исполнения команды.&lt;br /&gt;
Символ &amp;lt;big&amp;gt;!&amp;lt;/big&amp;gt;, может выступать как логическое &amp;quot;''НЕ''&amp;quot; для инверсии кода возврата.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование символа &amp;quot;!&amp;quot; для логической инверсии кода возврата.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
true # встроенная команда &amp;quot;true&amp;quot;.&lt;br /&gt;
echo &amp;quot;код возврата команды \&amp;quot;true\&amp;quot; = $?&amp;quot; # 0&lt;br /&gt;
! true&lt;br /&gt;
echo &amp;quot;код возврата команды \&amp;quot;! true\&amp;quot; = $?&amp;quot; # 1&lt;br /&gt;
# Обратите внимание: символ &amp;quot;!&amp;quot; от команды необходимо отделять пробелом.&lt;br /&gt;
# !true вызовет сообщение об ошибке &amp;quot;command not found&amp;quot;&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В отдельных случаях коды возврата должны иметь предопределённые значения и не должны задаваться пользователем.&lt;br /&gt;
&lt;br /&gt;
== Проверка условий ==&lt;br /&gt;
Практически любой язык программирования включает в себя условные операторы, предназначенные для проверки условий, чтобы выбрать тот или иной путь развития событий в зависимости от этих условий. В Bash, для проверки условий, имеется команда [[test]], различного вида скобочные операторы и условный оператор '''''if/then'''''.&lt;br /&gt;
=== Конструкции проверки условий ===&lt;br /&gt;
* Оператор '''''if/then''''' проверяет — является ли код завершения списка команд 0 (поскольку 0 означает &amp;quot;успех&amp;quot;!), и если это так, то выполняет одну, или более, команд, следующие за словом '''''then'''''.&lt;br /&gt;
* Существует специальная команда — '''''[''''' (левая квадратная скобка). Она является синонимом команды [[test]], и является встроенной командой (т.е. более эффективной, в смысле производительности). Эта команда воспринимает свои аргументы как выражение сравнения или как файловую проверку и возвращает код завершения в соответствии с результатами проверки(0 — истина, 1 — ложь).&lt;br /&gt;
* Начиная с версии 2.02, Bash предоставляет в распоряжение программиста конструкцию '''''[[ ... ]]''''', расширенный вариант команды [[test]], которая выполняет сравнение способом более знакомым программистам, пишущим на других языках программирования. Обратите внимание: '''''[[''''' — это зарезервированное слово, а не команда!&lt;br /&gt;
Bash исполняет '''''&amp;lt;nowiki&amp;gt;[[ $a -lt $b ]]&amp;lt;/nowiki&amp;gt;''''' как один элемент, который имеет код возврата!&lt;br /&gt;
&amp;lt;br /&amp;gt;Круглые скобки '''''(( ... ))''''' и предложение '''''let ...''''' так же возвращают код 0, если результатом арифметического выражения является ненулевое значение. Таким образом, арифметические выражения могут участвовать в операциях сравнения.&lt;br /&gt;
&amp;lt;br /&amp;gt;''Предложение let &amp;quot;1&amp;lt;2&amp;quot; возвращает 0 (так как результат сравнения &amp;quot;1&amp;lt;2&amp;quot; — &amp;quot;1&amp;quot;, или &amp;quot;истина&amp;quot;)(( 0 &amp;amp;&amp;amp; 1 )) возвращает 1 (так как результат операции &amp;quot;0 &amp;amp;&amp;amp; 1&amp;quot; — &amp;quot;0&amp;quot;, или &amp;quot;ложь&amp;quot;)''&lt;br /&gt;
* Условный оператор ''if'' проверяет код завершения любой команды, а не только результат выражения, заключенного в квадратные скобки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if cmp a b &amp;amp;&amp;gt; /dev/null # Подавление вывода.&lt;br /&gt;
then echo &amp;quot;Файлы a и b идентичны.&amp;quot;&lt;br /&gt;
else echo &amp;quot;Файлы a и b имеют различия.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if grep -q Bash file&lt;br /&gt;
then echo &amp;quot;Файл содержит, как минимум, одно слово Bash.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
word=Linux&lt;br /&gt;
letter_sequence=inu&lt;br /&gt;
if echo &amp;quot;$word&amp;quot; | grep -q &amp;quot;$letter_sequence&amp;quot;&lt;br /&gt;
# Подавление вывода ключом &amp;quot;-q&amp;quot; в команде grep.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Последовательность $letter_sequence обнаружена в слове $word&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Последовательность $letter_sequence, в слове $word не найдена&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if COMMAND_WHOSE_EXIT_STATUS_IS_0_UNLESS_ERROR_OCCURRED&lt;br /&gt;
then echo &amp;quot;Команда выполнена успешно.&amp;quot;&lt;br /&gt;
else echo &amp;quot;Обнаружена ошибка при выполнении команды.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Оператор ''if/then'' допускает наличие вложенных проверок.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if echo &amp;quot;Следующий *if* находится внутри первого *if*.&amp;quot;&lt;br /&gt;
 if [[ $comparison = &amp;quot;integer&amp;quot; ]]&lt;br /&gt;
   then (( a &amp;lt; b ))&lt;br /&gt;
 else&lt;br /&gt;
   [[ $a &amp;lt; $b ]]&lt;br /&gt;
 fi&lt;br /&gt;
then&lt;br /&gt;
 echo '$a меньше $b'fi&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''''Это детальное описание конструкции &amp;quot;if-test&amp;quot; любезно предоставлено Stephane Chazelas.'''''&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Что есть &amp;quot;истина&amp;quot;?'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;0\&amp;quot;&amp;quot;&lt;br /&gt;
if [ 0 ] # ноль&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;0 — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;0 — это ложь.&amp;quot;&lt;br /&gt;
fi # 0 — это истина.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;1\&amp;quot;&amp;quot;&lt;br /&gt;
if [ 1 ] # единица&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;1 — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;1 — это ложь.&amp;quot;&lt;br /&gt;
fi # 1 — это ложь.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Testing \&amp;quot;-1\&amp;quot;&amp;quot;&lt;br /&gt;
if [ -1 ] # минус один&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;-1 — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;-1 — это ложь.&amp;quot;&lt;br /&gt;
fi # -1 — это истина.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;NULL\&amp;quot;&amp;quot;&lt;br /&gt;
if [ ] # NULL (пустое условие)&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;NULL — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;NULL — это ложь.&amp;quot;&lt;br /&gt;
fi # NULL — это ложь.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;xyz\&amp;quot;&amp;quot;&lt;br /&gt;
if [ xyz ] # строка&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Случайная строка — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Случайная строка — это ложь.&amp;quot;&lt;br /&gt;
fi # Случайная строка — это истина.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;\$xyz\&amp;quot;&amp;quot;&lt;br /&gt;
if [ $xyz ] # Проверка, если $xyz это null, но...&lt;br /&gt;
# только для неинициализированных переменных.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Неинициализированная переменная — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Неинициализированная переменная — это ложь.&amp;quot;&lt;br /&gt;
fi # Неинициализированная переменная — это ложь.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;-n \$xyz\&amp;quot;&amp;quot;&lt;br /&gt;
if [ -n &amp;quot;$xyz&amp;quot; ] # Более корректный вариант.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Неинициализированная переменная — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Неинициализированная переменная — это ложь.&amp;quot;&lt;br /&gt;
fi # Неинициализированная переменная — это ложь.&lt;br /&gt;
echo&lt;br /&gt;
xyz= # Инициализирована пустым значением.&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;-n \$xyz\&amp;quot;&amp;quot;&lt;br /&gt;
if [ -n &amp;quot;$xyz&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Пустая переменная — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Пустая переменная — это ложь.&amp;quot;&lt;br /&gt;
fi # Пустая переменная — это ложь.&lt;br /&gt;
echo &lt;br /&gt;
# Когда &amp;quot;ложь&amp;quot; истинна?&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;false\&amp;quot;&amp;quot;&lt;br /&gt;
if [ &amp;quot;false&amp;quot; ] # это обычная строка &amp;quot;false&amp;quot;.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;\&amp;quot;false\&amp;quot; — это истина.&amp;quot; # и она истинна.&lt;br /&gt;
else &lt;br /&gt;
echo &amp;quot;\&amp;quot;false\&amp;quot; — это ложь.&amp;quot;&lt;br /&gt;
fi # &amp;quot;false&amp;quot; — это истина.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверяется \&amp;quot;\$false\&amp;quot;&amp;quot; # Опять неинициализированная переменная.&lt;br /&gt;
if [ &amp;quot;$false&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;\&amp;quot;\$false\&amp;quot; — это истина.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;\&amp;quot;\$false\&amp;quot; — это ложь.&amp;quot;&lt;br /&gt;
fi # &amp;quot;$false&amp;quot; — это ложь.&lt;br /&gt;
# Теперь мы получили ожидаемый результат.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Упражнение'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Объясните результаты, полученные в примере ''Что есть &amp;quot;истина&amp;quot;?''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ condition-true ]&lt;br /&gt;
then &lt;br /&gt;
 command 1&lt;br /&gt;
 command 2 &lt;br /&gt;
 ...&lt;br /&gt;
else # Необязательная ветка (можно опустить, если в ней нет необходимости). &lt;br /&gt;
# Дополнительный блок кода, &lt;br /&gt;
# исполняемый в случае, когда результат проверки — &amp;quot;ложь&amp;quot;. &lt;br /&gt;
command 3 command 4 ...&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Когда ''if'' и ''then'' располагаются в одной строке, то конструкция ''if'' должна завершаться точкой с запятой. И ''if'', и ''then'' - это '''''зарезервированные слова'''''. '''''Зарезервированные слова''''' начинают инструкцию, которая должна быть завершена прежде, чем в той же строке появится новая инструкция.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ -x &amp;quot;$filename&amp;quot; ]; then&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Else if и elif&lt;br /&gt;
''elif'' — это краткая форма записи конструкции else if. Применяется для построения многоярусных инструкций ''if/then''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ condition1 ]&lt;br /&gt;
then&lt;br /&gt;
 command1 &lt;br /&gt;
 command2&lt;br /&gt;
 command3&lt;br /&gt;
elif [ condition2 ]&lt;br /&gt;
# То же самое, что и else if&lt;br /&gt;
then&lt;br /&gt;
 command4 &lt;br /&gt;
 command5&lt;br /&gt;
else&lt;br /&gt;
 default-command&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Конструкция ''if test condition-true'' является точным эквивалентом конструкции ''if [ condition-true]'', где левая квадратная скобка ''['' выполняет те же действия, что и команда [[test]]. Закрывающая правая квадратная скобка '']'' не является абсолютно необходимой, однако, более новые версии Bash требуют её наличие.&lt;br /&gt;
Команда [[test]] — это встроенная команда Bash, которая выполняет проверки файлов и производит сравнение строк. Таким образом, в Bash-скриптах, команда [[test]] не вызывает внешнюю ('''''/usr/bin/test''''') утилиту, которая является частью пакета sh-utils. Аналогично, ''['' не производит вызов утилиты '''''/usr/bin/[''''', которая является символической ссылкой на '''''/usr/bin/test'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ type test&lt;br /&gt;
test is a shell builtin&lt;br /&gt;
bash$ type '['&lt;br /&gt;
[ is a shell builtin&lt;br /&gt;
bash$ type '[['&lt;br /&gt;
[[ is a shell keyword&lt;br /&gt;
bash$ type ']]'&lt;br /&gt;
]] is a shell keyword&lt;br /&gt;
bash$ type ']'&lt;br /&gt;
bash: type: ]: not found&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Эквиваленты команды test — /usr/bin/test, [ ], и /usr/bin/['''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
if test -z &amp;quot;$1&amp;quot;&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Аргументы командной строки отсутствуют.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Первый аргумент командной строки: $1.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
if /usr/bin/test -z &amp;quot;$1&amp;quot; # Даёт тот же результат, что и встроенная команда &amp;quot;test&amp;quot;.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Аргументы командной строки отсутствуют.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Первый аргумент командной строки: $1.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ] # Функционально идентично вышеприведенному блоку кода.&lt;br /&gt;
# if [ -z &amp;quot;$1&amp;quot; эта конструкция должна работать, но...&lt;br /&gt;
# Bash выдает сообщение об отсутствующей закрывающей скобке.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Аргументы командной строки отсутствуют.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Первый аргумент командной строки: $1.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
if /usr/bin/[ -z &amp;quot;$1&amp;quot; # Функционально идентично вышеприведенному блоку кода.&lt;br /&gt;
# if /usr/bin/[ -z &amp;quot;$1&amp;quot; ] # Работает, но выдает сообщение об ошибке.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Аргументы командной строки отсутствуют.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Первый аргумент командной строки: $1.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Конструкция &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[[ ]]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; более универсальна, по сравнению с &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[ ]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; . Этот расширенный вариант команды [[test]] перекочевал в Bash из ''ksh88''. Внутри этой конструкции не производится никакой дополнительной интерпретации имён файлов и не производится разбиение аргументов на отдельные слова, но допускается подстановка параметров и команд.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
file=/etc/passwd&lt;br /&gt;
if [[ -e $file ]]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл паролей найден.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Конструкция &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[[...]]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; более предпочтительна, нежели &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[...]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt;, поскольку поможет избежать некоторых логических ошибок. Например, операторы '''''&amp;amp;&amp;amp;''''', '''''||''''', '''''&amp;lt;''''' и '''''&amp;gt;''''' внутри &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[[ ]]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; вполне допустимы, в то время как внутри &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[ ]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; порождают сообщения об ошибках!&lt;br /&gt;
Строго говоря, после оператора ''if'', ни команда [[test]], ни квадратные скобки ( &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; или &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;[[ ]]&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; ) не являются обязательными.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dir=/home/bozo&lt;br /&gt;
if cd &amp;quot;$dir&amp;quot; 2&amp;gt;/dev/null; then # &amp;quot;2&amp;gt;/dev/null&amp;quot; подавление вывода сообщений об ошибках.&lt;br /&gt;
 echo &amp;quot;Переход в каталог $dir выполнен.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Невозможно перейти в каталог $dir.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Инструкция ''if COMMAND'' возвращает код возврата команды ''COMMAND''. Точно так же, условие, находящееся внутри квадратных скобок может быть проверено без использования оператора ''if''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
var1=20&lt;br /&gt;
var2=22&lt;br /&gt;
[ &amp;quot;$var1&amp;quot; -ne &amp;quot;$var2&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;$var1 не равно $var2&amp;quot;&lt;br /&gt;
home=/home/bozo&lt;br /&gt;
[ -d &amp;quot;$home&amp;quot; ] || echo &amp;quot;каталог $home не найден.&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Внутри &amp;lt;big&amp;gt;&amp;lt;nowiki&amp;gt;(())&amp;lt;/nowiki&amp;gt;&amp;lt;/big&amp;gt; производится вычисление арифметического выражения. Если результатом вычислений является ноль, то возвращается 1, или &amp;quot;ложь&amp;quot;. Ненулевой результат даёт код возврата 0, или &amp;quot;истина&amp;quot;. То есть полная противоположность инструкциям [[test]] и [ ], обсуждавшимся выше.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Арифметические выражения внутри (( ))'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Проверка арифметических выражений.&lt;br /&gt;
# Инструкция (( ... )) вычисляет арифметические выражения.&lt;br /&gt;
# Код возврата противоположен коду возврата инструкции [ ... ] !&lt;br /&gt;
(( 0 ))&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 0 ))\&amp;quot;: $?.&amp;quot; # 1(( 1 ))&lt;br /&gt;
(( 1 ))&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 1 ))\&amp;quot;: $?.&amp;quot; # 0&lt;br /&gt;
(( 5 &amp;gt; 4 )) # true&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 5 &amp;gt; 4 ))\&amp;quot;: $?.&amp;quot; # 0&lt;br /&gt;
(( 5 &amp;gt; 9 )) # false&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 5 &amp;gt; 9 ))\&amp;quot;: $?.&amp;quot; # 1&lt;br /&gt;
(( 5 - 5 )) # 0&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 5 - 5 ))\&amp;quot;: $?.&amp;quot; # 1&lt;br /&gt;
(( 5 / 4 )) # Деление, всё в порядке&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 5 / 4 ))\&amp;quot;: $?.&amp;quot; # 0&lt;br /&gt;
(( 1 / 2 )) # Результат деления &amp;lt; 1.&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 1 / 2 ))\&amp;quot;: $?.&amp;quot; # Округляется до 0. #1&lt;br /&gt;
(( 1 / 0 )) 2&amp;gt;/dev/null # Деление на 0.&lt;br /&gt;
echo &amp;quot;Код возврата \&amp;quot;(( 1 / 0 ))\&amp;quot;: $?.&amp;quot; # 1&lt;br /&gt;
# Для чего нужна инструкция &amp;quot;2&amp;gt;/dev/null&amp;quot; ?&lt;br /&gt;
# Что произойдет, если её убрать?&lt;br /&gt;
# Попробуйте убрать её и выполнить сценарий.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Операции проверки файлов ===&lt;br /&gt;
Возвращает ''true'' если...&lt;br /&gt;
* &amp;lt;big&amp;gt;-e&amp;lt;/big&amp;gt; — файл существует&lt;br /&gt;
* &amp;lt;big&amp;gt;-f&amp;lt;/big&amp;gt; — ''обычный'' файл (не каталог и не файл устройства!)&lt;br /&gt;
* &amp;lt;big&amp;gt;-s&amp;lt;/big&amp;gt; — ненулевой размер файла&lt;br /&gt;
* &amp;lt;big&amp;gt;-d&amp;lt;/big&amp;gt; — файл является каталогом&lt;br /&gt;
* &amp;lt;big&amp;gt;-b&amp;lt;/big&amp;gt; — файл является блочным устройством (floppy, cdrom и т.п.)&lt;br /&gt;
* &amp;lt;big&amp;gt;-c&amp;lt;/big&amp;gt; — файл является символьным устройством (клавиатура, модем, звуковая карта и т.п.)&lt;br /&gt;
* &amp;lt;big&amp;gt;-p&amp;lt;/big&amp;gt; — файл является каналом&lt;br /&gt;
* &amp;lt;big&amp;gt;-h&amp;lt;/big&amp;gt; — файл является символической ссылкой&lt;br /&gt;
* &amp;lt;big&amp;gt;-L&amp;lt;/big&amp;gt; — файл является символической ссылкой&lt;br /&gt;
* &amp;lt;big&amp;gt;-S&amp;lt;/big&amp;gt; — файл является сокетом&lt;br /&gt;
* &amp;lt;big&amp;gt;-t&amp;lt;/big&amp;gt; — файл (дескриптор) связан с терминальным устройством&lt;br /&gt;
Этот ключ может использоваться для проверки — является ли файл стандартным устройством ввода ''stdin'' ([ -t 0 ]) или стандартным устройством вывода ''stdout'' ([ -t 1 ]). &lt;br /&gt;
* &amp;lt;big&amp;gt;-r&amp;lt;/big&amp;gt; — файл доступен для чтения (пользователю, запустившему сценарий)&lt;br /&gt;
* &amp;lt;big&amp;gt;-w&amp;lt;/big&amp;gt; — файл доступен для записи (пользователю, запустившему сценарий)&lt;br /&gt;
* &amp;lt;big&amp;gt;-x&amp;lt;/big&amp;gt; — файл доступен для исполнения (пользователю, запустившему сценарий)&lt;br /&gt;
* &amp;lt;big&amp;gt;-g&amp;lt;/big&amp;gt; — set-group-id (sgid) флаг для файла или каталога установлен&lt;br /&gt;
Если для каталога установлен флаг sgid, то файлы, создаваемые в таком каталоге, наследуют идентификатор группы каталога, который может не совпадать с идентификатором группы, к которой принадлежит пользователь, создавший файл. Это может быть полезно для каталогов, в которых хранятся файлы, общедоступные для группы пользователей.&lt;br /&gt;
* &amp;lt;big&amp;gt;-u&amp;lt;/big&amp;gt; — set-user-id (suid) флаг для файла установлен&lt;br /&gt;
Установленный флаг suid приводит к изменению привилегий запущенного процесса на привилегии владельца исполняемого файла. Исполняемые файлы, владельцем которых является root, с установленным флагом set-user-id запускаются с привилегиями root, даже если их запускает обычный пользователь.&lt;br /&gt;
Это может оказаться полезным для некоторых программ(таких как ''pppd'' и ''cdrecord''), которые осуществляют доступ к аппаратной части компьютера. В случае отсутствия флага suid, программы не смогут быть запущены рядовым пользователем, не обладающим привилегиями root.&lt;br /&gt;
 ''-rwsr-xr-t 1 root 178236 Oct 2 2000 /usr/sbin/pppd''&lt;br /&gt;
Файл с установленным флагом suid отображается с включенным флагом ''s'' в поле прав доступа.&lt;br /&gt;
* &amp;lt;big&amp;gt;-k&amp;lt;/big&amp;gt; — флаг sticky bit (бит фиксации) установлен&lt;br /&gt;
Общеизвестно, что флаг &amp;quot;sticky bit&amp;quot; — это специальный тип прав доступа к файлам. Программы сустановленным флагом &amp;quot;sticky bit&amp;quot; остаются в системном кэше после своего завершения,обеспечивая тем самым более быстрый запуск программы. Если флаг установлен для каталога, то это приводит к ограничению прав на запись. Установленный флаг &amp;quot;sticky bit&amp;quot; отображается в виде символа ''t'' в поле прав доступа.&lt;br /&gt;
 ''drwxrwxrwt 7 root 1024 May 19 21:26 tmp/''&lt;br /&gt;
Если пользователь не является владельцем каталога , с установленным &amp;quot;sticky bit&amp;quot;, но имеет право на запись в каталог, то он может удалять только те файлы в каталоге, владельцем которых он является. Это предотвращает удаление и перезапись &amp;quot;чужих&amp;quot; файлов в общедоступных каталогах, таких как /tmp.&lt;br /&gt;
* &amp;lt;big&amp;gt;-O&amp;lt;/big&amp;gt; — вы являетесь владельцем файла&lt;br /&gt;
* &amp;lt;big&amp;gt;-G&amp;lt;/big&amp;gt; — вы принадлежите к той же группе, что и файл&lt;br /&gt;
* &amp;lt;big&amp;gt;-N&amp;lt;/big&amp;gt; — файл был модифицирован с момента последнего чтения&lt;br /&gt;
* &amp;lt;big&amp;gt;f1 -nt f2&amp;lt;/big&amp;gt; — файл f1 более новый, чем f2&lt;br /&gt;
* &amp;lt;big&amp;gt;f1 -ot f2&amp;lt;/big&amp;gt; — файл f1 более старый, чем f2&lt;br /&gt;
* &amp;lt;big&amp;gt;f1 -ef f2&amp;lt;/big&amp;gt; — файлы f1 и f2 являются &amp;quot;жесткими&amp;quot; ссылками на один и тот же файл&lt;br /&gt;
* &amp;lt;big&amp;gt;!&amp;lt;/big&amp;gt; — &amp;quot;НЕ&amp;quot; — логическое отрицание (инверсия) результатов всех вышеприведенных проверок(возвращается ''true'' если условие отсутствует).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка &amp;quot;битых&amp;quot; ссылок.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# broken-link.sh&lt;br /&gt;
# Автор Lee Bigelow &amp;lt;ligelowbee@yahoo.com&amp;gt;&lt;br /&gt;
# Используется с его разрешения.&lt;br /&gt;
#Сценарий поиска &amp;quot;битых&amp;quot; ссылок и их вывод в &amp;quot;окавыченном&amp;quot; виде&lt;br /&gt;
#таким образом они могут передаваться утилите xargs для дальнейшей обработки :)&lt;br /&gt;
#например. broken-link.sh /somedir /someotherdir|xargs rm&lt;br /&gt;
#&lt;br /&gt;
#На всякий случай приведу лучший метод:&lt;br /&gt;
#&lt;br /&gt;
#find &amp;quot;somedir&amp;quot; -type l -print0|\&lt;br /&gt;
#xargs -r0 file|\&lt;br /&gt;
#grep &amp;quot;broken symbolic&amp;quot;|&lt;br /&gt;
#sed -e 's/^\|: *broken symbolic.*$/&amp;quot;/g'&lt;br /&gt;
#&lt;br /&gt;
#но это не чисто BASH-евский метод, а теперь сам сценарий.&lt;br /&gt;
#Внимание! будьте осторожны с файловой системой /proc и циклическими ссылками!&lt;br /&gt;
##############################################################&lt;br /&gt;
#Если скрипт не получает входных аргументов,&lt;br /&gt;
#то каталогом поиска является текущая директория&lt;br /&gt;
#В противном случае, каталог поиска задается из командной строки&lt;br /&gt;
####################&lt;br /&gt;
[ $# -eq 0 ] &amp;amp;&amp;amp; directorys=`pwd` || directorys=$@&lt;br /&gt;
#Функция linkchk проверяет каталог поиска&lt;br /&gt;
#на наличие в нём ссылок на несуществующие файлы, и выводит их имена.&lt;br /&gt;
#Если анализируемый файл является каталогом,&lt;br /&gt;
#то он передаётся функции linkcheck рекурсивно.&lt;br /&gt;
##########&lt;br /&gt;
linkchk () {&lt;br /&gt;
 for element in $1/*; do&lt;br /&gt;
 [ -h &amp;quot;$element&amp;quot; -a ! -e &amp;quot;$element&amp;quot; ] &amp;amp;&amp;amp; echo \&amp;quot;$element\&amp;quot;&lt;br /&gt;
 [ -d &amp;quot;$element&amp;quot; ] &amp;amp;&amp;amp; linkchk $element&lt;br /&gt;
 # Само собой, '-h' проверяет символические ссылки, '-d' -- каталоги.&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
#Вызов функции linkchk для каждого аргумента командной строки,&lt;br /&gt;
#если он является каталогом. Иначе выводится сообщение об ошибке&lt;br /&gt;
#и информация о порядке пользования скриптом.&lt;br /&gt;
################&lt;br /&gt;
for directory in $directorys; do&lt;br /&gt;
 if [ -d $directory ]&lt;br /&gt;
  then linkchk $directory&lt;br /&gt;
  else&lt;br /&gt;
    echo &amp;quot;$directory не является каталогом&amp;quot;&lt;br /&gt;
    echo &amp;quot;Порядок использования: $0 dir1 dir2 ...&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Операции сравнения ===&lt;br /&gt;
'''''Сравнение целых чисел''''':&lt;br /&gt;
* &amp;lt;big&amp;gt;-eq&amp;lt;/big&amp;gt; — равно&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -eq &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;-ne&amp;lt;/big&amp;gt; — не равно&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -ne &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;-gt&amp;lt;/big&amp;gt; — больше&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -gt &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;-ge&amp;lt;/big&amp;gt; — больше или равно&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -ge &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;-lt&amp;lt;/big&amp;gt; — меньше&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -lt &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;-le&amp;lt;/big&amp;gt; — меньше или равно&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -le &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;lt;&amp;lt;/big&amp;gt; — меньше (внутри двойных круглых скобок )&lt;br /&gt;
 ((&amp;quot;$a&amp;quot; &amp;lt; &amp;quot;$b&amp;quot;))&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;lt;=&amp;lt;/big&amp;gt; — меньше или равно (внутри двойных круглых скобок)&lt;br /&gt;
 ((&amp;quot;$a&amp;quot; &amp;lt;= &amp;quot;$b&amp;quot;))&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;gt;&amp;lt;/big&amp;gt; — больше (внутри двойных круглых скобок )&lt;br /&gt;
 ((&amp;quot;$a&amp;quot; &amp;gt; &amp;quot;$b&amp;quot;))&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;gt;=&amp;lt;/big&amp;gt; — больше или равно(внутри двойных круглых скобок )&lt;br /&gt;
 ((&amp;quot;$a&amp;quot; &amp;gt;= &amp;quot;$b&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
'''''Cравнение строк''''':&lt;br /&gt;
* &amp;lt;big&amp;gt;=&amp;lt;/big&amp;gt; — равно&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; = &amp;quot;$b&amp;quot; ]&lt;br /&gt;
* &amp;lt;big&amp;gt;==&amp;lt;/big&amp;gt; — равно. Синоним оператора =.&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; == &amp;quot;$b&amp;quot; ]&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
[[ $a == z* ]] # истина, если $a начинается с символа &amp;quot;z&amp;quot; (сравнение по шаблону)&lt;br /&gt;
[[ $a == &amp;quot;z*&amp;quot; ]] # истина, если $a равна z*&lt;br /&gt;
[ $a == z* ] # имеют место подстановка имён файлов и разбиение на слова&lt;br /&gt;
[ &amp;quot;$a&amp;quot; == &amp;quot;z*&amp;quot; ] # истина, если $a равна z*&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
* &amp;lt;big&amp;gt;!=&amp;lt;/big&amp;gt; — не равно&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; != &amp;quot;$b&amp;quot; ]&lt;br /&gt;
 Этот оператор используется при поиске по шаблону внутри [[ ... ]]&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;lt;&amp;lt;/big&amp;gt; — меньше, в смысле величины ASCII-кодов&lt;br /&gt;
 if [[ &amp;quot;$a&amp;quot; &amp;lt; &amp;quot;$b&amp;quot; ]]&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; \&amp;lt; &amp;quot;$b&amp;quot; ]&lt;br /&gt;
 Обратите внимание! Символ &amp;quot;&amp;lt;&amp;quot; необходимо экранировать внутри [ ]&lt;br /&gt;
* &amp;lt;big&amp;gt;&amp;gt;&amp;lt;/big&amp;gt; — больше, в смысле величины ASCII-кодов&lt;br /&gt;
 if [[ &amp;quot;$a&amp;quot; &amp;gt; &amp;quot;$b&amp;quot; ]]&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; \&amp;gt; &amp;quot;$b&amp;quot; ]&lt;br /&gt;
 Обратите внимание! Символ &amp;quot;&amp;gt;&amp;quot; необходимо экранировать внутри [ ]&lt;br /&gt;
* &amp;lt;big&amp;gt;-z&amp;lt;/big&amp;gt; — строка &amp;quot;пустая&amp;quot;, т.е. имеет нулевую длину&lt;br /&gt;
* &amp;lt;big&amp;gt;-n&amp;lt;/big&amp;gt; — строка не &amp;quot;пустая&amp;quot;&lt;br /&gt;
Оператор ''-n'' требует, чтобы строка была заключена в кавычки внутри квадратных скобок. Как правило, проверка строк, не заключенных в кавычки, оператором ''! -z'', или просто указание строки без кавычек внутри квадратных скобок, проходит нормально, однако это небезопасная, с точки зрения отказоустойчивости, практика. Всегда заключайте проверяемую строку в кавычки.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Операции сравнения.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
a=4&lt;br /&gt;
b=5&lt;br /&gt;
# Здесь переменные &amp;quot;a&amp;quot; и &amp;quot;b&amp;quot; могут быть как целыми числами, так и строками.&lt;br /&gt;
# Здесь наблюдается некоторое размывание границ&lt;br /&gt;
# между целочисленными и строковыми переменными,&lt;br /&gt;
# поскольку переменные в Bash не имеют типов.&lt;br /&gt;
# Bash выполняет целочисленные операции над теми переменными,&lt;br /&gt;
# которые содержат только цифры&lt;br /&gt;
# Будьте внимательны!&lt;br /&gt;
echo&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -ne &amp;quot;$b&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;$a не равно $b&amp;quot;&lt;br /&gt;
 echo &amp;quot;(целочисленное сравнение)&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; != &amp;quot;$b&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;$a не равно $b.&amp;quot;&lt;br /&gt;
 echo &amp;quot;(сравнение строк)&amp;quot;&lt;br /&gt;
 # &amp;quot;4&amp;quot; != &amp;quot;5&amp;quot;&lt;br /&gt;
 # ASCII 52 != ASCII 53&lt;br /&gt;
fi&lt;br /&gt;
# Оба варианта, &amp;quot;-ne&amp;quot; и &amp;quot;!=&amp;quot;, работают правильно.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка — является ли строка пустой'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# str-test.sh: Проверка пустых строк и строк, не заключенных в кавычки,&lt;br /&gt;
# Используется конструкция if [ ... ]&lt;br /&gt;
# Если строка не инициализирована, то она не имеет никакого определенного значения.&lt;br /&gt;
# Такое состояние называется &amp;quot;null&amp;quot; (пустая) (это не то же самое, что ноль).&lt;br /&gt;
if [ -n $string1 ] # $string1 не была объявлена или инициализирована.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; не пустая.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; пустая.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Неверный результат.&lt;br /&gt;
# Выводится сообщение о том, что $string1 не пустая,&lt;br /&gt;
# не смотря на то, что она не была инициализирована.&lt;br /&gt;
echo&lt;br /&gt;
# Попробуем ещё раз.&lt;br /&gt;
if [ -n &amp;quot;$string1&amp;quot; ] # На этот раз, переменная $string1 заключена в кавычки.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; не пустая.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; пустая.&amp;quot;&lt;br /&gt;
fi # Внутри квадратных скобок заключайте строки в кавычки!&lt;br /&gt;
echo&lt;br /&gt;
if [ $string1 ] # Опустим оператор -n.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; не пустая.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; пустая.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Всё работает прекрасно.&lt;br /&gt;
# Квадратные скобки — [ ], без посторонней помощи определяют, что строка пустая.&lt;br /&gt;
# Тем не менее, хорошим тоном считается заключать строки в кавычки (&amp;quot;$string1&amp;quot;).&lt;br /&gt;
# Как указывает Stephane Chazelas,&lt;br /&gt;
# if [ $string 1 ] один аргумент &amp;quot;]&amp;quot;&lt;br /&gt;
# if [ &amp;quot;$string 1&amp;quot; ] два аргумента, пустая &amp;quot;$string1&amp;quot; и &amp;quot;]&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
string1=initialized&lt;br /&gt;
if [ $string1 ] # Опять, попробуем строку без ничего.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; не пустая.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; пустая.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# И снова получим верный результат.&lt;br /&gt;
# И опять-таки, лучше поместить строку в кавычки (&amp;quot;$string1&amp;quot;), поскольку...&lt;br /&gt;
echo&lt;br /&gt;
string1=&amp;quot;a = b&amp;quot;&lt;br /&gt;
if [ $string1 ] # И снова, попробуем строку без ничего..&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; не пустая.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Строка \&amp;quot;string1\&amp;quot; пустая.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Строка без кавычек даёт неверный результат!&lt;br /&gt;
exit 0&lt;br /&gt;
# Спасибо Florian Wisser, за предупреждение.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''zmore'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
#Просмотр gz-файлов с помощью утилиты 'more'&lt;br /&gt;
NOARGS=65&lt;br /&gt;
NOTFOUND=66&lt;br /&gt;
NOTGZIP=67&lt;br /&gt;
if [ $# -eq 0 ] # то же, что и: if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
# $1 должен существовать, но может быть пустым: zmore &amp;quot;&amp;quot; arg2 arg3&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
 # Сообщение об ошибке на stderr.&lt;br /&gt;
 exit $NOARGS&lt;br /&gt;
 # Код возврата 65 (код ошибки).&lt;br /&gt;
fi&lt;br /&gt;
filename=$1&lt;br /&gt;
if [ ! -f &amp;quot;$filename&amp;quot; ] # Кавычки необходимы на тот случай, если имя файла содержит пробелы.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл $filename не найден!&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
 # Сообщение об ошибке на stderr.&lt;br /&gt;
exit $NOTFOUND&lt;br /&gt;
fi&lt;br /&gt;
if [ ${filename##*.} != &amp;quot;gz&amp;quot; ]&lt;br /&gt;
# Квадратные скобки нужны для выполнения подстановки значения переменной&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл $1 не является gz-файлом!&amp;quot;&lt;br /&gt;
exit $NOTGZIP&lt;br /&gt;
fi&lt;br /&gt;
zcat $1 | more&lt;br /&gt;
# Используется утилита 'more' (очень похожа на 'less').&lt;br /&gt;
# Последние версии 'more' могут просматривать сжатые файлы.&lt;br /&gt;
# Можно вставить 'more' или 'less', если пожелаете.&lt;br /&gt;
exit $? # Сценарий возвращает код возврата, полученный по конвейеру.&lt;br /&gt;
# На самом деле команда &amp;quot;exit $?&amp;quot; не является обязательной,&lt;br /&gt;
# так как работа скрипта завершится здесь в любом случае.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Построение сложных условий проверки''''':&lt;br /&gt;
* &amp;lt;big&amp;gt;-a&amp;lt;/big&amp;gt; —  логическое И (and)&lt;br /&gt;
 ''exp1 -a exp2'' возвращает ''true'', если оба выражения, и ''exp1'', и ''exp2'' истинны.&lt;br /&gt;
* &amp;lt;big&amp;gt;-o&amp;lt;/big&amp;gt; —  логическое ИЛИ (or)&lt;br /&gt;
 ''exp1 -o exp2'' возвращает ''true'', если хотябы одно из выражений, ''exp1'' или ''exp2'' истинно.&lt;br /&gt;
 Они похожи на операторы Bash '''&amp;amp;&amp;amp;''' и '''||''', употребляемые в двойных квадратных скобках.&lt;br /&gt;
 ''&amp;lt;nowiki&amp;gt;[[ condition1 &amp;amp;&amp;amp; condition2 ]]&amp;lt;/nowiki&amp;gt;''&lt;br /&gt;
 Операторы ''-o'' и ''-a'' употребляются совместно с командой [[test]] или внутри одинарных квадратных скобок.&lt;br /&gt;
 ''if [ &amp;quot;$exp1&amp;quot; -a &amp;quot;$exp2&amp;quot; ]''&lt;br /&gt;
&lt;br /&gt;
=== Вложенные условные операторы if/then ===&lt;br /&gt;
Операторы проверки условий ''if/then'' могут быть вложенными друг в друга. Конечный результат будет таким же как если бы результаты всех проверок были объединены оператором '''&amp;amp;&amp;amp;'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ condition1 ]&lt;br /&gt;
then&lt;br /&gt;
 if [ condition2 ]&lt;br /&gt;
  then&lt;br /&gt;
   do-something # Только если оба условия &amp;quot;condition1&amp;quot; и &amp;quot;condition2&amp;quot; истинны.&lt;br /&gt;
 fi&lt;br /&gt;
fi &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Проверка степени усвоения материала ===&lt;br /&gt;
Для запуска X-сервера может быть использован файл xinitrc. Этот файл содержит некоторое число операторов if/then. Ниже приводится отрывок из этого файла.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ -f $HOME/.Xclients ]; then&lt;br /&gt;
exec $HOME/.Xclients&lt;br /&gt;
 elif [ -f /etc/X11/xinit/Xclients ]; then&lt;br /&gt;
   exec /etc/X11/xinit/Xclients&lt;br /&gt;
else&lt;br /&gt;
# failsafe settings. Although we should never get here&lt;br /&gt;
# (we provide fallbacks in Xclients as well) it can't hurt.&lt;br /&gt;
 xclock -geometry 100x100-5+5 &amp;amp;&lt;br /&gt;
 xterm -geometry 80x50-50+150 &amp;amp;&lt;br /&gt;
 if [ -f /usr/bin/netscape -a -f /usr/share/doc/HTML/index.html ]; then&lt;br /&gt;
   netscape /usr/share/doc/HTML/index.html &amp;amp;&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Объясните действия условных операторов в вышеприведённом отрывке, затем просмотрите файл /etc/X11/xinit/xinitrc и проанализируйте его. Возможно вам придется обратиться&lt;br /&gt;
к разделам, посвящённым [[grep]], [[sed]] и регулярным выражениям.&lt;br /&gt;
&lt;br /&gt;
== Операции и смежные темы ==&lt;br /&gt;
=== Операторы ===&lt;br /&gt;
* &amp;lt;big&amp;gt;'''Присваивание'''&amp;lt;/big&amp;gt; &lt;br /&gt;
''variable assignment''&amp;lt;br /&amp;gt;&lt;br /&gt;
Инициализация переменной или изменение её значения.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''='''&amp;lt;/big&amp;gt; — Универсальный оператор присваивания, пригоден как для сравнения целых чисел, так и для сравнения строк.&lt;br /&gt;
Пусть вас не смущает, что оператор присваивания (&amp;quot;=&amp;quot;), по своему внешнему виду, совпадает с оператором сравнения (=).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Здесь знак &amp;quot;=&amp;quot; выступает в качестве оператора сравнения&lt;br /&gt;
if [ &amp;quot;$string1&amp;quot; = &amp;quot;$string2&amp;quot; ]&lt;br /&gt;
# if [ &amp;quot;X$string1&amp;quot; = &amp;quot;X$string2&amp;quot; ] более отказоустойчивый вариант,&lt;br /&gt;
# предохраняет от &amp;quot;сваливания&amp;quot; по ошибке в случае, когда одна из переменных пуста.&lt;br /&gt;
# (добавленные символы &amp;quot;X&amp;quot; компенсируют друг друга.)&lt;br /&gt;
then&lt;br /&gt;
 command&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''Арифметические операторы'''&amp;lt;/big&amp;gt; &lt;br /&gt;
&amp;lt;big&amp;gt;'''+'''&amp;lt;/big&amp;gt; — Сложение&lt;br /&gt;
&amp;lt;big&amp;gt;'''-'''&amp;lt;/big&amp;gt; — Вычитание&lt;br /&gt;
&amp;lt;big&amp;gt;'''*'''&amp;lt;/big&amp;gt; — Умножение&lt;br /&gt;
&amp;lt;big&amp;gt;'''/'''&amp;lt;/big&amp;gt; — Деление&lt;br /&gt;
&amp;lt;big&amp;gt;'''**'''&amp;lt;/big&amp;gt; — Возведение в степень&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# В Bash, начиная с версии 2.02, был введен оператор возведения в степень -- &amp;quot;**&amp;quot;.&lt;br /&gt;
let &amp;quot;z=5**3&amp;quot;&lt;br /&gt;
echo &amp;quot;z = $z&amp;quot; # z = 125&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''%'''&amp;lt;/big&amp;gt; — модуль (деление по модулю), возвращает остаток от деления&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo `expr 5 % 3`&lt;br /&gt;
2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Этот оператор может применяться в алгоритмах генерации псевдослучайных чисел в заданном диапазоне, для форматирования вывода на экран и даже для генерации простых чисел. На удивление часто операцию деления по модулю можно встретить в различных численных алгоритмах.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Наибольший общий делитель.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# gcd.sh: поиск наибольшего общего делителя&lt;br /&gt;
# по алгоритму Эвклида&lt;br /&gt;
# Под &amp;quot;наибольшим общим делителем&amp;quot; (нод) двух целых чисел&lt;br /&gt;
# понимается наибольшее целое число, которое делит оба делимых без остатка.&lt;br /&gt;
# Алгоритм Эвклида выполняет последовательное деление.&lt;br /&gt;
# В каждом цикле,&lt;br /&gt;
# делимое &amp;lt;--- делитель&lt;br /&gt;
# делитель &amp;lt;--- остаток&lt;br /&gt;
# до тех пор, пока остаток не станет равным нулю (остаток = 0).&lt;br /&gt;
# The gcd = dividend, on the final pass.&lt;br /&gt;
# Замечательное описание алгоритма Эвклида можно найти&lt;br /&gt;
# на сайте Jim Loy, http://www.jimloy.com/number/euclids.htm.&lt;br /&gt;
# ------------------------------------------------------&lt;br /&gt;
# Проверка входных параметров&lt;br /&gt;
ARGS=2E_B&lt;br /&gt;
ADARGS=65&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` первое-число второе-число&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
# ------------------------------------------------------&lt;br /&gt;
gcd ()&lt;br /&gt;
{&lt;br /&gt;
            # Начальное присваивание.&lt;br /&gt;
dividend=$1 # В сущности, не имеет значения&lt;br /&gt;
divisor=$2  # какой из них больше.&lt;br /&gt;
            # Почему?&lt;br /&gt;
remainder=1 # Если переменные не инициализировать,&lt;br /&gt;
            # то работа сценария будет прервана по ошибке&lt;br /&gt;
            # в первом же цикле.&lt;br /&gt;
until [ &amp;quot;$remainder&amp;quot; -eq 0 ]&lt;br /&gt;
do&lt;br /&gt;
 let &amp;quot;remainder = $dividend % $divisor&amp;quot;&lt;br /&gt;
 dividend=$divisor # Повторить цикл с новыми исходными данными&lt;br /&gt;
 divisor=$remainder&lt;br /&gt;
done       # алгоритм Эвклида&lt;br /&gt;
} # последнее $dividend и есть нод.&lt;br /&gt;
gcd $1 $2echo; &lt;br /&gt;
echo &amp;quot;НОД чисел $1 и $2 = $dividend&amp;quot;; echo&lt;br /&gt;
# Упражнение :&lt;br /&gt;
# --------&lt;br /&gt;
# Вставьте дополнительную проверку входных аргументов,&lt;br /&gt;
# и предусмотрите завершение работы сценария с сообщением об ошибке, если&lt;br /&gt;
# входные аргументы не являются целыми числами.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''+='''&amp;lt;/big&amp;gt; — &amp;quot;плюс-равно&amp;quot; (увеличивает значение переменной на заданное число). &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;let &amp;quot;var += 5&amp;quot;&amp;lt;/source&amp;gt; значение переменной ''var'' будет увеличено на 5.&lt;br /&gt;
&amp;lt;big&amp;gt;'''-='''&amp;lt;/big&amp;gt; — &amp;quot;минус-равно&amp;quot; (уменьшение значения переменной на заданное число).&lt;br /&gt;
&amp;lt;big&amp;gt;'''*='''&amp;lt;/big&amp;gt; — &amp;quot;умножить-равно&amp;quot; (умножить значение переменной на заданное число, результат записать в переменную). &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;let &amp;quot;var *= 4&amp;quot;&amp;lt;/source&amp;gt; значение переменной ''var'' будет увеличено в 4 раза.&lt;br /&gt;
&amp;lt;big&amp;gt;'''/='''&amp;lt;/big&amp;gt; — &amp;quot;слэш-равно&amp;quot; (уменьшение значения переменной в заданное число раз).&lt;br /&gt;
&amp;lt;big&amp;gt;'''%='''&amp;lt;/big&amp;gt; — &amp;quot;процент-равно&amp;quot; (найти остаток от деления значения переменной на заданное число, результат записать в переменную).&lt;br /&gt;
Арифметические операторы очень часто используются совместно с командами [[expr]] и [[let]].&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Арифметические операции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# От 1 до 6 пятью различными способами.&lt;br /&gt;
n=1; echo -n &amp;quot;$n &amp;quot;&lt;br /&gt;
let &amp;quot;n = $n + 1&amp;quot; # let &amp;quot;n = n + 1&amp;quot; тоже допустимо&lt;br /&gt;
echo -n &amp;quot;$n &amp;quot;&lt;br /&gt;
: $((n = $n + 1))&lt;br /&gt;
# оператор &amp;quot;:&amp;quot; обязателен, поскольку в противном случае, Bash будет&lt;br /&gt;
# интерпретировать выражение &amp;quot;$((n = $n + 1))&amp;quot; как команду.&lt;br /&gt;
echo -n &amp;quot;$n &amp;quot;&lt;br /&gt;
n=$(($n + 1))&lt;br /&gt;
echo -n &amp;quot;$n &amp;quot;&lt;br /&gt;
: $[ n = $n + 1 ]&lt;br /&gt;
# оператор &amp;quot;:&amp;quot; обязателен, поскольку в противном случае, Bash будет&lt;br /&gt;
# интерпретировать выражение &amp;quot;$[ n = $n + 1 ]&amp;quot; как команду.&lt;br /&gt;
# Не вызывает ошибки даже если &amp;quot;n&amp;quot; содержит строку.&lt;br /&gt;
echo -n &amp;quot;$n &amp;quot;&lt;br /&gt;
n=$[ $n + 1 ]&lt;br /&gt;
# Не вызывает ошибки даже если &amp;quot;n&amp;quot; содержит строку.&lt;br /&gt;
# Старайтесь избегать употребления такой конструкции,&lt;br /&gt;
# поскольку она уже давно устарела и не переносима.&lt;br /&gt;
echo -n &amp;quot;$n &amp;quot;; echo&lt;br /&gt;
# Спасибо Stephane Chazelas.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Целые числа в Bash фактически являются ''длинными целыми'' ('''32-бит''') со знаком, с диапазоном изменений от ''-2147483648'' до ''2147483647''. Если в результате какой либо операции эти пределы будут превышены, то результат получится ошибочным.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#НЕАКТУАЛЕН для версии Bash  4.2!&lt;br /&gt;
a=2147483646&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = 2147483646&lt;br /&gt;
let &amp;quot;a+=1&amp;quot; # Увеличить &amp;quot;a&amp;quot; на 1.&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = 2147483647&lt;br /&gt;
let &amp;quot;a+=1&amp;quot; # увеличить &amp;quot;a&amp;quot; ещё раз, с выходом за границы диапазона.&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = -2147483648&lt;br /&gt;
              # ОШИБКА! (выход за границы диапазона)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Версия Bash 2.05b, поддерживает 64-битные целые числа'''''. Bash ничего не знает о существовании чисел с плавающей запятой. Такие числа, из-за наличия символа десятичной точки, он воспринимает как строки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
a=1.5&lt;br /&gt;
let &amp;quot;b = $a + 1.3&amp;quot; # Ошибка.&lt;br /&gt;
# -bash: let: b = 1.5 + 1.3: syntax error: invalid arithmetic operator (error token is &amp;quot;.5 + 1.3&amp;quot;)&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # b=1&lt;br /&gt;
b=&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для работы с числами с плавающей запятой в сценариях можно использовать утилиту-калькулятор [[bc]].&lt;br /&gt;
* &amp;lt;big&amp;gt;'''Битовые операции'''&amp;lt;/big&amp;gt; &lt;br /&gt;
Битовые операции очень редко используются в сценариях командного интерпретатора. Их главное назначение, на мой взгляд, установка и проверка некоторых значений,читаемых из портов ввода-вывода и сокетов. &amp;quot;Битовые операции&amp;quot; гораздо более уместны в компилирующих языках программирования, таких как C и C++.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;lt;&amp;lt;'''&amp;lt;/big&amp;gt; — сдвигает на 1 бит влево (умножение на 2)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;lt;&amp;lt;='''&amp;lt;/big&amp;gt; — &amp;quot;сдвиг-влево-равно&amp;quot;. &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;let &amp;quot;var &amp;lt;&amp;lt;= 2&amp;quot;&amp;lt;/source&amp;gt; значение переменной ''var'' сдвигается влево на ''2 бита'' (умножается на 4).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;gt;&amp;gt;'''&amp;lt;/big&amp;gt; — сдвиг вправо на 1 бит (деление на 2)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;gt;&amp;gt;='''&amp;lt;/big&amp;gt; — &amp;quot;сдвиг-вправо-равно&amp;quot; (имеет смысл обратный &amp;lt;&amp;lt;=)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;amp;'''&amp;lt;/big&amp;gt; — по-битовое И (AND)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;amp;='''&amp;lt;/big&amp;gt; — по-битовое И-равно&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''|'''&amp;lt;/big&amp;gt; — по-битовое ИЛИ (OR)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''|='''&amp;lt;/big&amp;gt; — по-битовое ИЛИ-равно&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''~'''&amp;lt;/big&amp;gt; — по-битовая инверсия&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''!'''&amp;lt;/big&amp;gt; — по-битовое отрицание&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''^'''&amp;lt;/big&amp;gt; — по-битовое ИСКЛЮЧАЮЩЕЕ ИЛИ (XOR)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''^='''&amp;lt;/big&amp;gt; — по-битовое ИСКЛЮЧАЮЩЕЕ-ИЛИ-равно&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''Логические операции'''&amp;lt;/big&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''&amp;amp;&amp;amp;'''&amp;lt;/big&amp;gt; — логическое И (and)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ $condition1 ] &amp;amp;&amp;amp; [ $condition2 ]&lt;br /&gt;
# То же самое, что: if [ $condition1 -a $condition2 ]&lt;br /&gt;
# Возвращает true, если оба операнда condition1 и condition2 истинны...\&lt;br /&gt;
if [[ $condition1 &amp;amp;&amp;amp; $condition2 ]] # То же верно&lt;br /&gt;
# Обратите внимание: оператор &amp;amp;&amp;amp; не должен использоваться внутри [ ... ]!&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Оператор &amp;lt;big&amp;gt;'''&amp;amp;&amp;amp;'''&amp;lt;/big&amp;gt;, в зависимости от контекста, может так же использоваться в &amp;quot;И&amp;quot;-списках для построения составных команд.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''||'''&amp;lt;/big&amp;gt; — логическое ИЛИ (or)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ $condition1 ] || [ $condition2 ]&lt;br /&gt;
# То же самое, что: if [ $condition1 -o $condition2 ]&lt;br /&gt;
# Возвращает true, если хотя бы один из операндов истинен...&lt;br /&gt;
if [[ $condition1 || $condition2 ]] # Also works.&lt;br /&gt;
# Обратите внимание: оператор || не должен использоваться внутри [ ... ].&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Bash производит проверку кода возврата КАЖДОГО из операндов в логических выражениях.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Построение сложных условий, использующих &amp;amp;&amp;amp; и ||.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
a=24&lt;br /&gt;
b=47&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq 24 ] &amp;amp;&amp;amp; [ &amp;quot;$b&amp;quot; -eq 47 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Первая проверка прошла успешно.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Первая проверка не прошла.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# ОКА: if [ &amp;quot;$a&amp;quot; -eq 24 &amp;amp;&amp;amp; &amp;quot;$b&amp;quot; -eq 47 ]&lt;br /&gt;
# пытается выполнить ' [ &amp;quot;$a&amp;quot; -eq 24 '&lt;br /&gt;
# и терпит неудачу наткнувшись на ']'.&lt;br /&gt;
# if [[ $a -eq 24 &amp;amp;&amp;amp; $b -eq 24 ]] это правильный вариант&lt;br /&gt;
# (в строке 17 оператор &amp;quot;&amp;amp;&amp;amp;&amp;quot; имеет иной смысл, нежели в строке 6.)&lt;br /&gt;
# Спасибо Stephane Chazelas.&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq 98 ] || [ &amp;quot;$b&amp;quot; -eq 47 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Вторая проверка прошла успешно.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Вторая проверка не прошла.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Опции -a и -o предоставляют&lt;br /&gt;
# альтернативный механизм проверки условий.&lt;br /&gt;
# Спасибо Patrick Callahan.&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq 24 -a &amp;quot;$b&amp;quot; -eq 47 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Третья проверка прошла успешно.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Третья проверка не прошла.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq 98 -o &amp;quot;$b&amp;quot; -eq 47 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Четвертая проверка прошла успешно.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Четвертая проверка не прошла.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
a=rhino&lt;br /&gt;
b=crocodile&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; = rhino ] &amp;amp;&amp;amp; [ &amp;quot;$b&amp;quot; = crocodile ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Пятая проверка прошла успешно.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
echo &amp;quot;Пятая проверка не прошла.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Операторы &amp;lt;big&amp;gt;&amp;amp;&amp;amp;&amp;lt;/big&amp;gt; и &amp;lt;big&amp;gt;||&amp;lt;/big&amp;gt; могут использоваться и в арифметических вычислениях.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $(( 1 &amp;amp;&amp;amp; 2 )) $((3 &amp;amp;&amp;amp; 0)) $((4 || 0)) $((0 || 0))&lt;br /&gt;
1 0 1 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''Прочие операции'''&amp;lt;/big&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''','''&amp;lt;/big&amp;gt; — запятая&amp;lt;br /&amp;gt;&lt;br /&gt;
С помощью оператора запятая можно связать несколько арифметических в одну последовательность. При разборе таких последовательностей, командный интерпретатор вычисляет все выражения (которые могут иметь побочные эффекты) в последовательности и возвращает результат последнего.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
let &amp;quot;t1 = ((5 + 3, 7 - 1, 15 - 4))&amp;quot;&lt;br /&gt;
echo &amp;quot;t1 = $t1&amp;quot; # t1 = 11&lt;br /&gt;
let &amp;quot;t2 = ((a = 9, 15 / 3))&amp;quot; # Выполняется присваивание &amp;quot;a&amp;quot; = 9,&lt;br /&gt;
                             # а затем вычисляется &amp;quot;t2&amp;quot;.&lt;br /&gt;
echo &amp;quot;t2 = $t2 a = $a&amp;quot; # t2 = 5 a = 9&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Оператор запятая чаще всего находит применение в циклах ''for''.&lt;br /&gt;
&lt;br /&gt;
=== Числовые константы ===&lt;br /&gt;
Интерпретатор командной оболочки воспринимает числа как десятичные, в противном случае числу должен предшествовать специальный префикс, либо число должно быть записано в особой нотации. Числа, начинающиеся с символа 0, считаются восьмеричными. если числу предшествует префикс 0x, то число считается шестнадцатеричным. Число, в записи которого присутствует символ #, расценивается как запись числа с указанием основы счисления в виде ''ОСНОВА#ЧИСЛО''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Различные представления числовых констант.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# numbers.sh: Различные представления числовых констант.&lt;br /&gt;
# Десятичное: по-умолчанию&lt;br /&gt;
let &amp;quot;dec = 32&amp;quot;&lt;br /&gt;
echo &amp;quot;десятичное число = $dec&amp;quot; # 32&lt;br /&gt;
# В общем-то ничего необычного.&lt;br /&gt;
# Восьмеричное: числа начинаются с '0' (нуля)&lt;br /&gt;
let &amp;quot;oct = 032&amp;quot;&lt;br /&gt;
echo &amp;quot;восьмеричное число = $oct&amp;quot; # 26&lt;br /&gt;
# Результат печатается в десятичном виде.&lt;br /&gt;
# --------- ------ -- -------&lt;br /&gt;
# Шестнадцатиричное: числа начинаются с '0x' или '0X'&lt;br /&gt;
let &amp;quot;hex = 0x32&amp;quot;&lt;br /&gt;
echo &amp;quot;шестнадцатиричное число = $hex&amp;quot; # 50&lt;br /&gt;
# Результат печатается в десятичном виде.&lt;br /&gt;
# Другие основы счисления: ОСНОВА#ЧИСЛО&lt;br /&gt;
# ОСНОВА должна быть между 2 и 64.&lt;br /&gt;
# для записи ЧИСЛА должен использоваться соответствующий ОСНОВЕ диапазон символов,&lt;br /&gt;
# см. ниже.&lt;br /&gt;
let &amp;quot;bin = 2#111100111001101&amp;quot;&lt;br /&gt;
echo &amp;quot;двоичное число = $bin&amp;quot; # 31181&lt;br /&gt;
let &amp;quot;b32 = 32#77&amp;quot;&lt;br /&gt;
echo &amp;quot;32-ричное число = $b32&amp;quot; # 231&lt;br /&gt;
let &amp;quot;b64 = 64#@_&amp;quot;&lt;br /&gt;
echo &amp;quot;64-ричное число = $b64&amp;quot; # 4094&lt;br /&gt;
#&lt;br /&gt;
# Нотация ОСНОВА#ЧИСЛО может использоваться на ограниченном&lt;br /&gt;
# диапазоне основ счисления (от 2 до 64)&lt;br /&gt;
# 10 цифр + 26 символов в нижнем регистре + 26 символов в верхнем регистре + @ + _&lt;br /&gt;
echo&lt;br /&gt;
echo $((36#zz)) $((2#10101010)) $((16#AF16)) $((53#1aA))&lt;br /&gt;
                    # 1295 170 44822 3375&lt;br /&gt;
# Важное замечание:&lt;br /&gt;
# --------------&lt;br /&gt;
# Использование символов, для записи числа, выходящих за диапазон,&lt;br /&gt;
# соответствующий ОСНОВЕ счисления&lt;br /&gt;
# будет приводить к появлению сообщений об ошибках.&lt;br /&gt;
let &amp;quot;bad_oct = 081&amp;quot;&lt;br /&gt;
# numbers.sh: let: oct = 081: value too great for base (error token is &amp;quot;081&amp;quot;)&lt;br /&gt;
# Для записи восьмеричных чисел допускается использовать&lt;br /&gt;
#+ только цифры в диапазоне 0 - 7.&lt;br /&gt;
exit 0 # Спасибо Rich Bartell и Stephane Chazelas, за разъяснения.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Часть третья. Углублённый материал =&lt;br /&gt;
== К вопросу о переменных ==&lt;br /&gt;
Правильное использование переменных может придать сценариям дополнительную мощь и гибкость, а для этого необходимо изучить все тонкости и нюансы.&lt;br /&gt;
=== Внутренние переменные ===&lt;br /&gt;
* ''Встроенные переменные''&lt;br /&gt;
'''''$BASH''''' — путь к исполняемому файлу Bash&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $BASH&lt;br /&gt;
/bin/bash&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$BASH_VERSINFO[n]''''' — это массив, состоящий из 6 элементов, и содержащий информацию о версии Bash. Очень похожа на переменную ''$BASH_VERSION'', описываемую ниже.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Информация о версии Bash:&lt;br /&gt;
for n in 0 1 2 3 4 5&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# BASH_VERSINFO[0] = 2  # Major version no.&lt;br /&gt;
# BASH_VERSINFO[1] = 05 # Minor version no.&lt;br /&gt;
# BASH_VERSINFO[2] = 8  # Patch level.&lt;br /&gt;
# BASH_VERSINFO[3] = 1  # Build version.&lt;br /&gt;
# BASH_VERSINFO[4] = release # Release status.&lt;br /&gt;
# BASH_VERSINFO[5] = i386-redhat-linux-gnu # Architecture&lt;br /&gt;
                                    # (same as $MACHTYPE).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$BASH_VERSINFO''''' — версия Bash, установленного в системе&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $BASH_VERSION&lt;br /&gt;
2.04.12(1)-release&lt;br /&gt;
&lt;br /&gt;
tcsh% echo $BASH_VERSION&lt;br /&gt;
BASH_VERSION: Undefined variable.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Проверка переменной ''$BASH_VERSION'' — неплохой метод проверки типа командной оболочки, под которой исполняется скрипт. Переменная ''$SHELL'' не всегда даёт правильный ответ.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$DIRSTACK''''' — содержимое вершины стека каталогов (который управляется командами pushd и popd)&lt;br /&gt;
Эта переменная соответствует команде [[dirs]], за исключением того, что [[dirs]] показывает полное содержимое всего стека каталогов.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$EDITOR''''' — заданный по-умолчанию редактор, вызываемый скриптом, обычно '''vi''' или '''emacs'''&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$EUID''''' — &amp;quot;эффективный&amp;quot; идентификационный номер пользователя (Effective User ID)&lt;br /&gt;
Идентификационный номер пользователя, права которого были получены, возможно с помощью команды [[su]]. Значение переменной ''$EUID'' необязательно должно совпадать с содержимым переменной ''$UID''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$FUNCNAME''''' — имя текущей функции&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
xyz23 ()&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;Исполняется функция $FUNCNAME.&amp;quot; # Исполняется функция xyz23.&lt;br /&gt;
}&lt;br /&gt;
xyz23&lt;br /&gt;
echo &amp;quot;FUNCNAME = $FUNCNAME&amp;quot; # FUNCNAME =&lt;br /&gt;
                            # Пустое (Null) значение за пределами функций.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$GLOBIGNORE''''' — Перечень шаблонных символов, которые будут проигнорированы при выполнении подстановки имён файлов (globbing)&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$GROUPS''''' — группы, к которым принадлежит текущий пользователь&lt;br /&gt;
Это список групп (массив) идентификационных номеров групп для текущего пользователя, какэо записано в /etc/passwd.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root# echo $GROUPS&lt;br /&gt;
0&lt;br /&gt;
root# echo ${GROUPS[1]}&lt;br /&gt;
1&lt;br /&gt;
root# echo ${GROUPS[5]}&lt;br /&gt;
6&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$HOME''''' — домашний каталог пользователя, как правило это /home/username&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$HOSTNAME''''' — Сетевое имя хоста устанавливается командой hostname во время исполнения инициализирующих сценариев при загрузке системы. Внутренняя переменная ''$HOSTNAME'' Bash получает своё значение посредством вызова функции gethostname().&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$HOSTTYPE''''' — тип машины&lt;br /&gt;
Подобно ''$MACHTYPE'', идентифицирует аппаратную архитектуру.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $HOSTTYPE&lt;br /&gt;
i686&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$IFS''''' — разделитель полей во вводимой строке (IFS — Internal Field Separator)&lt;br /&gt;
Эта переменная управляет порядком выделения полей (задаёт символы-разделители) приразборе строки символов. По-умолчанию — пробельный символ (пробел, табуляция и перевод строки), но может быть изменён, например, для разбора строк, в которых отдельные поля разделены запятыми. Обратите внимание: при составлении содержимого переменной ''$*'', Bash использует первый символ из ''$IFS'' для разделения аргументов. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $IFS | cat -vte&lt;br /&gt;
$&lt;br /&gt;
bash$ bash -c 'set w x y z; IFS=&amp;quot;:-;&amp;quot;; echo &amp;quot;$*&amp;quot;'&lt;br /&gt;
w:x:y:z&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При всём при том следует помнить, что при использовании ''$IFS'' пробельные символы обрабатываются несколько иначе, чем все остальные.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''$IFS и пробельные символы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# При использовании $IFS, пробельные символы обрабатываются иначе, чем все остальные.&lt;br /&gt;
output_args_one_per_line()&lt;br /&gt;
{&lt;br /&gt;
 for arg&lt;br /&gt;
 do echo &amp;quot;[$arg]&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
echo; echo &amp;quot;IFS=\&amp;quot; \&amp;quot;&amp;quot;&lt;br /&gt;
echo &amp;quot;-------&amp;quot;&lt;br /&gt;
IFS=&amp;quot; &amp;quot;&lt;br /&gt;
var=&amp;quot; a b c &amp;quot;&lt;br /&gt;
output_args_one_per_line $var # output_args_one_per_line `echo &amp;quot; a b c &amp;quot;`&lt;br /&gt;
# [a]&lt;br /&gt;
# [b]&lt;br /&gt;
# [c]&lt;br /&gt;
echo; echo &amp;quot;IFS=:&amp;quot;&lt;br /&gt;
echo &amp;quot;-----&amp;quot;&lt;br /&gt;
IFS=:&lt;br /&gt;
var=&amp;quot;:a::b:c:::&amp;quot; # То же самое, только пробелы заменены символом &amp;quot;:&amp;quot;.&lt;br /&gt;
output_args_one_per_line $var&lt;br /&gt;
#&lt;br /&gt;
# []&lt;br /&gt;
# [a]&lt;br /&gt;
# []&lt;br /&gt;
# [b]&lt;br /&gt;
# [c]&lt;br /&gt;
# []&lt;br /&gt;
# []&lt;br /&gt;
# []&lt;br /&gt;
# То же самое происходит и с разделителем полей &amp;quot;FS&amp;quot; в awk.&lt;br /&gt;
# Спасибо Stephane Chazelas.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
#(Спасибо S. C., за разъяснения и примеры.)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$LC_COLLATE''''' — Чаще всего устанавливается в ''.bashrc'' или ''/etc/profile', эта переменная задаёт порядок сортировки символов, в операциях подстановки имён файлов и в поиске по шаблону. При неверной настройке переменной ''LC_COLLATE'' можно получить весьма неожиданные результаты. Начиная с версии 2.05, Bash, в операциях подстановки имён файлов, не делает различий между символами верхнего и нижнего регистров, в диапазонах символов в квадратных скобках. Например, ''ls [A-M]*'' выведет как File1.txt, так и file1.txt. Возврат к общепринятому стандарту поведения шаблонов вквадратных скобках выполняется установкой переменной ''LC_COLLATE'' в значение ''C''  командой ''export LC_COLLATE=C'' в файле ''/etc/profile'' и/или ''~/.bashrc''. &amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$LC_CTYPE''''' — Эта внутренняя переменная определяет кодировку символов. Используется в операциях подстановки и поиске по шаблону.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$LINENO''''' — Номер строки исполняемого сценария. Эта переменная имеет смысл только внутри исполняемого сценария и чаще всего применяется в отладочных целях.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# *** BEGIN DEBUG BLOCK ***&lt;br /&gt;
last_cmd_arg=$_ # Запомнить.&lt;br /&gt;
echo &amp;quot;Строка $LINENO: переменная \&amp;quot;v1\&amp;quot; = $v1&amp;quot;&lt;br /&gt;
echo &amp;quot;Последний аргумент командной строки = $last_cmd_arg&amp;quot;&lt;br /&gt;
# *** END DEBUG BLOCK ***&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$MACHTYPE''''' — аппаратная архитектура. Идентификатор аппаратной архитектуры.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $MACHTYPE&lt;br /&gt;
i686&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$OLDPWD''''' — прежний рабочий каталог (&amp;quot;OLD-Print-Working-Directory&amp;quot;)&lt;br /&gt;
'''''$OSTYPE''''' — тип операционной системы&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $OSTYPE&lt;br /&gt;
linux&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$PATH''''' — путь поиска, как правило включает в себя каталоги ''/usr/bin/'', ''/usr/X11R6/bin/'', ''/usr/local/bin'',и т.д.&lt;br /&gt;
Когда командный интерпретатор получает команду, то он автоматически пытается отыскать соответствующий исполняемый файл в указанном списке каталогов (в переменной ''$PATH''). Каталоги, в указанном списке, должны отделяться друг от друга двоеточиями. Обычно,переменная ''$PATH'' инициализируется в ''/etc/profile'' и/или в ''~/.bashrc''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $PATH&lt;br /&gt;
/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/sbin:/usr/sbin&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Инструкция ''PATH=${PATH}:/opt/bin'' добавляет каталог ''/opt/bin'' в конец текущего пути поиска.&lt;br /&gt;
Иногда может оказаться целесообразным, внутри сценария, временно добавить какой-либо каталог к пути поиска. По завершении работы скрипта, эти изменения будут утеряны(вспомните о том, что невозможно изменить переменные окружения вызывающего процесса). Текущий &amp;quot;рабочий каталог&amp;quot;, ./, обычно не включается в $PATH из соображений безопасности.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PIPESTATUS''''' — Код возврата канала (конвейера). Интересно, что это не то же самое, что код возврата последней исполненной команды.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $PIPESTATUS&lt;br /&gt;
0&lt;br /&gt;
bash$ ls -al | bogus_command&lt;br /&gt;
bash: bogus_command: command not found&lt;br /&gt;
bash$ echo $PIPESTATUS&lt;br /&gt;
141&lt;br /&gt;
bash$ ls -al | bogus_command&lt;br /&gt;
bash: bogus_command: command not found&lt;br /&gt;
bash$ echo $?&lt;br /&gt;
127&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Переменная ''$PIPESTATUS'' может давать неверные значения при вызове из командной строки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcsh% bash&lt;br /&gt;
bash$ who | grep nobody | sort&lt;br /&gt;
bash$ echo ${PIPESTATUS[*]}&lt;br /&gt;
0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если поместить эти строки в сценарий и исполнить его, то будут выведены верные значения 0 1 0. Спасибо Wayne Pollock за замечания и предоставленный пример.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PPID''''' — Переменная ''$PPID'' хранит PID (идентификатор) родительского процесса. Сравните с командой [[pidof]].&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PROMPT_COMMAND''''' — Переменная хранит команду, которая используется непосредственно для вывода первичного приглашения к вводу — ''$PS1''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PS1''''' — prompt, приглашение командной строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PS2''''' — Вторичное приглашение командной строки, выводится тогда, когда от пользователя ожидается дополнительный ввод. Отображается как &amp;quot;&amp;gt;&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PS3''''' — Третичное приглашение (prompt), выводится тогда, когда пользователь должен сделать выбор в операторе ''select''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PS4''''' — Приглашение (prompt) четвёртого уровня, выводится в начале каждой строки вывода тогда, когда сценарий вызывается с ключом ''-x''. Отображается как &amp;quot;+&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$PWD''''' — рабочий (текущий) каталог&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Аналог встроенной команды pwd.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
E_WRONG_DIRECTORY=73&lt;br /&gt;
clear # Очистка экрана.&lt;br /&gt;
TargetDirectory=/home/bozo/projects/GreatAmericanNovel&lt;br /&gt;
cd $TargetDirectory&lt;br /&gt;
echo &amp;quot;Удаление файлов в каталоге $TargetDirectory.&amp;quot;&lt;br /&gt;
if [ &amp;quot;$PWD&amp;quot; != &amp;quot;$TargetDirectory&amp;quot; ]&lt;br /&gt;
then # Защита от случайного удаления файлов не в том каталоге.&lt;br /&gt;
 echo &amp;quot;Неверный каталог!&amp;quot;&lt;br /&gt;
 echo &amp;quot;Переменная $PWD указывает на другой каталог!&amp;quot;&lt;br /&gt;
exit $E_WRONG_DIRECTORY&lt;br /&gt;
fi&lt;br /&gt;
rm -rf *&lt;br /&gt;
rm .[A-Za-z0-9]* # удалить &amp;quot;скрытые&amp;quot; файлы (начинающиеся с &amp;quot;.&amp;quot;)&lt;br /&gt;
# rm -f .[^.]* ..?* удалить файлы, чьи имена начинаются с нескольких точек.&lt;br /&gt;
# (shopt -s dotglob; rm -f *) тоже работает верно.&lt;br /&gt;
# Спасибо S.C. за замечание.&lt;br /&gt;
# Имена файлов могут содержать любые символы из диапазона 0-255, за исключением &amp;quot;/&amp;quot;.&lt;br /&gt;
# Оставляю вопрос удаления файлов с &amp;quot;необычными&amp;quot; символами для самостоятельного изучения.&lt;br /&gt;
# Здесь можно вставить дополнительные действия, по мере необходимости.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Конец.&amp;quot;&lt;br /&gt;
echo &amp;quot;Файлы, из каталога $TargetDirectory, удалены.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$REPLY''''' — переменная по-умолчанию, куда записывается ввод пользователя, выполненный с помощью команды ''read'', если явно не задана другая переменная. Так же может использоваться в операторе ''select'', для построения меню выбора.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
echo -n &amp;quot;Ваше любимое растение? &amp;quot;&lt;br /&gt;
read&lt;br /&gt;
echo &amp;quot;Ваше любимое растение: $REPLY.&amp;quot;&lt;br /&gt;
# REPLY хранит последнее значение, прочитанное командой &amp;quot;read&amp;quot; тогда, и только тогда&lt;br /&gt;
# когда команде &amp;quot;read&amp;quot; не передается имя переменной.&lt;br /&gt;
echo&lt;br /&gt;
echo -n &amp;quot;Ваш любимый фрукт? &amp;quot;&lt;br /&gt;
read fruit&lt;br /&gt;
echo &amp;quot;Ваш любимый фрукт $fruit.&amp;quot;&lt;br /&gt;
echo &amp;quot;но...&amp;quot;&lt;br /&gt;
echo &amp;quot;Значение переменной \$REPLY осталось равным $REPLY.&amp;quot;&lt;br /&gt;
# Переменная $REPLY не была перезаписана потому, что&lt;br /&gt;
# следующей команде &amp;quot;read&amp;quot;, в качестве аргумента была передана переменная $fruit&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$SECONDS''''' — Время паботы сценария в секундах&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Автор: Mendel Cooper&lt;br /&gt;
# Дополнен переводчиком.&lt;br /&gt;
TIME_LIMIT=10&lt;br /&gt;
INTERVAL=1&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Для прерывания работы сценария, ранее чем через $TIME_LIMIT секунд, нажмите Control-C.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$SECONDS&amp;quot; -le &amp;quot;$TIME_LIMIT&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
# Оригинальный вариант сценария содержал следующие строки&lt;br /&gt;
# if [ &amp;quot;$SECONDS&amp;quot; -eq 1 ]&lt;br /&gt;
# then&lt;br /&gt;
# units=second&lt;br /&gt;
# else&lt;br /&gt;
# units=seconds&lt;br /&gt;
# fi&lt;br /&gt;
# Однако, из-за того, что в русском языке для описания множественного числа&lt;br /&gt;
# существует большее число вариантов, чем в английском,&lt;br /&gt;
# переводчик позволил себе смелость несколько подправить сценарий&lt;br /&gt;
# (прошу ногами не бить! ;-) )&lt;br /&gt;
# === НАЧАЛО БЛОКА ИЗМЕНЕНИЙ, ВНЕСЕННЫХ ПЕРЕВОДЧИКОМ ===&lt;br /&gt;
let &amp;quot;last_two_sym = $SECONDS - $SECONDS / 100 * 100&amp;quot; # десятки и единицы&lt;br /&gt;
if [ &amp;quot;$last_two_sym&amp;quot; -ge 11 -a &amp;quot;$last_two_sym&amp;quot; -le 19 ]&lt;br /&gt;
then&lt;br /&gt;
 units=&amp;quot;секунд&amp;quot; # для чисел, которые заканчиваются на &amp;quot;...надцать&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 let &amp;quot;last_sym = $last_two_sym - $last_two_sym / 10 * 10&amp;quot; # единицы&lt;br /&gt;
 case &amp;quot;$last_sym&amp;quot; in&lt;br /&gt;
  &amp;quot;1&amp;quot; )&lt;br /&gt;
    units=&amp;quot;секунду&amp;quot; # для чисел, заканчивающихся на 1&lt;br /&gt;
    ;;&lt;br /&gt;
  &amp;quot;2&amp;quot; | &amp;quot;3&amp;quot; | &amp;quot;4&amp;quot; )&lt;br /&gt;
    units=&amp;quot;секунды&amp;quot; # для чисел, заканчивающихся на 2, 3 и 4&lt;br /&gt;
    ;;&lt;br /&gt;
  * )&lt;br /&gt;
   units=&amp;quot;секунд&amp;quot; # для всех остальных (0, 5, 6, 7, 8, 9)&lt;br /&gt;
   ;;&lt;br /&gt;
 esac&lt;br /&gt;
fi&lt;br /&gt;
# === КОНЕЦ БЛОКА ИЗМЕНЕНИЙ, ВНЕСЕННЫХ ПЕРЕВОДЧИКОМ ===&lt;br /&gt;
echo &amp;quot;Сценарий отработал $SECONDS $units.&amp;quot;&lt;br /&gt;
# В случае перегруженности системы, скрипт может перескакивать через отдельные&lt;br /&gt;
# значения счетчика&lt;br /&gt;
sleep $INTERVAL &lt;br /&gt;
done&lt;br /&gt;
echo -e &amp;quot;\a&amp;quot; # Сигнал!&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$SHELLOPTS''''' — список допустимых опций интерпретатора ''shell''. Переменная доступна только для чтения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $SHELLOPTS&lt;br /&gt;
braceexpand:hashall:histexpand:monitor:history:interactive-comments:emacs&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$SHLVL''''' — Уровень вложенности ''shell''. Если в командной строке ''echo $SHLVL'' даёт 1, то в сценарии значение этой переменной будет больше на 1, т.е. 2.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$TMOUT''''' — Если переменная окружения ''$TMOUT'' содержит ненулевое значение, то интерпретатор будет ожидать ввод не более чем заданное число секунд, что, в первичном приглашении (см.описание PS1 выше), может привести к автоматическому завершению сеанса работы. Начиная с версии 2.05b Bash, стало возможным использование $TMOUT в сценариях в комбинации с ''read''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Работает только в сценариях Bash, начиная с версии 2.05b.&lt;br /&gt;
TMOUT=3 # Ожидание ввода не более трех секунд.&lt;br /&gt;
echo &amp;quot;Ваша любимая песня?&amp;quot;&lt;br /&gt;
echo &amp;quot;Вводите быстрее, у Вас только $TMOUT секунды на обдумывание!&amp;quot;&lt;br /&gt;
read song&lt;br /&gt;
if [ -z &amp;quot;$song&amp;quot; ]&lt;br /&gt;
then &lt;br /&gt;
 song=&amp;quot;(ответ не получен)&amp;quot; &lt;br /&gt;
 # По-умолчанию.&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;Вам нравится $song.&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Возможны и более сложные варианты организации организации ограничения времени ожидания ввода. Как один из вариантов, можно предложить организовать прерывание цикла ожидания по сигналу. Но это потребует написание функции обработки сигналов командой ''trap''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ограничения времени ожидания ввода.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# timed-input.sh&lt;br /&gt;
# TMOUT=3 бесполезно в сценариях&lt;br /&gt;
TIMELIMIT=3 # Три секунды в данном случае, но может быть установлено и другое значение&lt;br /&gt;
PrintAnswer()&lt;br /&gt;
{&lt;br /&gt;
 if [ &amp;quot;$answer&amp;quot; = TIMEOUT ]&lt;br /&gt;
 then&lt;br /&gt;
  echo $answer&lt;br /&gt;
 else # Чтобы не спутать разные варианты вывода.&lt;br /&gt;
  echo &amp;quot;Ваше любимое растение $answer&amp;quot;&lt;br /&gt;
  kill $! # &amp;quot;Прибить&amp;quot; ненужную больше функцию TimerOn, запущенную в фоновом процессе.&lt;br /&gt;
          # $! — PID последнего процесса, запущенного в фоне.&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
TimerOn()&lt;br /&gt;
{&lt;br /&gt;
 sleep $TIMELIMIT &amp;amp;&amp;amp; kill -s 14 $$ &amp;amp;&lt;br /&gt;
 # Ждать 3 секунды, после чего выдать sigalarm сценарию.&lt;br /&gt;
}&lt;br /&gt;
Int14Vector()&lt;br /&gt;
{&lt;br /&gt;
 answer=&amp;quot;TIMEOUT&amp;quot;&lt;br /&gt;
 PrintAnswer&lt;br /&gt;
 exit 14&lt;br /&gt;
}&lt;br /&gt;
trap Int14Vector 14 # переназначить процедуру обработки прерывания от таймера (14)&lt;br /&gt;
echo &amp;quot;Ваше любимое растение? &amp;quot;&lt;br /&gt;
TimerOn&lt;br /&gt;
read answer&lt;br /&gt;
PrintAnswer# По общему признанию, это не очень хороший способ ограничения времени ожидания,&lt;br /&gt;
# По общему признанию, это не очень хороший способ ограничения времени ожидания,&lt;br /&gt;
# однако опция &amp;quot;-t&amp;quot; команды &amp;quot;read&amp;quot; упрощает задачу.&lt;br /&gt;
# См. &amp;quot;t-out.sh&amp;quot;, ниже.&lt;br /&gt;
# Если вам нужно что-то более элегантное...&lt;br /&gt;
# подумайте о написании программы на C или C++,&lt;br /&gt;
# с использованием соответствующих библиотечных функций, таких как 'alarm' и 'setitimer'.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В качестве альтернативы можно использовать stty.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ещё один пример ограничения времени ожидания ввода от пользователя'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
#timeout.sh&lt;br /&gt;
# Автор: Stephane Chazelas,&lt;br /&gt;
# дополнен автором документа.&lt;br /&gt;
INTERVAL=5 # предел времени ожидания&lt;br /&gt;
timedout_read()&lt;br /&gt;
{&lt;br /&gt;
 timeout=$1&lt;br /&gt;
 varname=$2&lt;br /&gt;
 old_tty_settings=`stty -g`&lt;br /&gt;
 stty -icanon min 0 time ${timeout}0&lt;br /&gt;
 eval read $varname # или просто read $varname&lt;br /&gt;
 stty &amp;quot;$old_tty_settings&amp;quot;&lt;br /&gt;
 # См. man stty.&lt;br /&gt;
}&lt;br /&gt;
echo; echo -n &amp;quot;Как Вас зовут? Отвечайте быстрее! &amp;quot;&lt;br /&gt;
timedout_read $INTERVAL your_name&lt;br /&gt;
# Такой прием может не работать на некоторых типах терминалов.&lt;br /&gt;
# Максимальное время ожидания зависит от терминала.&lt;br /&gt;
# (чаще всего это 25.5 секунд).&lt;br /&gt;
echo&lt;br /&gt;
if [ ! -z &amp;quot;$your_name&amp;quot; ] # Если имя было введено...&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Вас зовут $your_name.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Вы не успели ответить.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
# Алгоритм работы этого сценария отличается от &amp;quot;timed-input.sh&amp;quot;.&lt;br /&gt;
# Каждое нажатие на клавишу вызывает сброс счетчика в начальное состояние.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Возможно самый простой способ — использовать опцию -t команды ''read''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ограничение времени ожидания команды read'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# t-out.sh&lt;br /&gt;
TIMELIMIT=4 # 4 секунды&lt;br /&gt;
read -t $TIMELIMIT variable &amp;lt;&amp;amp;1&lt;br /&gt;
echo&lt;br /&gt;
if [ -z &amp;quot;$variable&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Время ожидания истекло.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;variable = $variable&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$UID''''' — user id number, UID (идентификатор) текущего пользователя, в соответствии с /etc/passwd&lt;br /&gt;
Это реальный UID текущего пользователя, даже если он временно приобрёл права другого пользователя с помощью su. Переменная $UID доступна только для чтения.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Я — root?'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# am-i-root.sh: Root я, или не root?&lt;br /&gt;
ROOT_UID=0 # $UID root-а всегда равен 0.&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -eq &amp;quot;$ROOT_UID&amp;quot; ] # Настоящий &amp;quot;root&amp;quot;?&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;- root!&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;простой пользователь (но мамочка вас тоже любит)!&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
# ============================================================= #&lt;br /&gt;
# Код, приведённый ниже, никогда не отработает,&lt;br /&gt;
# поскольку работа сценария уже завершилась выше&lt;br /&gt;
# Еще один способ отличить root-а от не root-а:&lt;br /&gt;
ROOTUSER_NAME=root&lt;br /&gt;
username=`id -nu` # Или... username=`whoami`&lt;br /&gt;
if [ &amp;quot;$username&amp;quot; = &amp;quot;$ROOTUSER_NAME&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Рутти-тутти. - root!&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Вы - лишь обычный юзер.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Переменные ''$ENV'', ''$LOGNAME'', ''$MAIL'', ''$TERM'', ''$USER'' и ''$USERNAME'', не являются встроенными переменными Bash. Тем не менее, они часто инициализируются как переменные окружения в одном из стартовых файлов Bash. Переменная ''$SHELL'', командная оболочка пользователя, может задаваться в ''/etc/passwd'' или в сценарии &amp;quot;init&amp;quot; и она тоже не является встроенной переменной Bash!&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tcsh% echo $LOGNAME&lt;br /&gt;
bozo&lt;br /&gt;
tcsh% echo $SHELL&lt;br /&gt;
/bin/tcsh&lt;br /&gt;
tcsh% echo $TERM&lt;br /&gt;
rxvt&lt;br /&gt;
bash$ echo $LOGNAME&lt;br /&gt;
bozo&lt;br /&gt;
bash$ echo $SHELL&lt;br /&gt;
/bin/tcsh&lt;br /&gt;
bash$ echo $TERM&lt;br /&gt;
rxvt&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* ''Позиционные параметры (аргументы)''&lt;br /&gt;
'''''$0''''', '''''$1''''', '''''$2''''' и т.д. — аргументы передаются... из командной строки в сценарий, функциям или команде set&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$#''''' — Количество аргументов командной строки, или позиционных параметров&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$*''''' — Все аргументы (позиционные параметры), в виде одной строки (слова)&lt;br /&gt;
&amp;quot;$*&amp;quot; — необходимо заключать в кавычки.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$@''''' — То же самое, что и &amp;quot;$*&amp;quot;, но при этом каждый параметр представлен как отдельная строка(слово), т.е. параметры не подвергаются какой-либо интерпретации.&lt;br /&gt;
&amp;quot;$@&amp;quot; -- необходимо заключать в кавычки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Я — root?'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Вызовите сценарий с несколькими аргументами, например: &amp;quot;один два три&amp;quot;.&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
if [ ! -n &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` argument1 argument2 и т.д.&amp;quot;&lt;br /&gt;
exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
index=1&lt;br /&gt;
echo &amp;quot;Список аргументов в переменной \&amp;quot;\$*\&amp;quot;:&amp;quot;&lt;br /&gt;
for arg in &amp;quot;$*&amp;quot; # Работает некорректно, если &amp;quot;$*&amp;quot; не ограничена кавычками.&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Аргумент #$index = $arg&amp;quot;&lt;br /&gt;
 let &amp;quot;index+=1&amp;quot;&lt;br /&gt;
done # $* воспринимает все аргументы как одну строку.&lt;br /&gt;
echo &amp;quot;Полный список аргументов выглядит как одна строка.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
index=1&lt;br /&gt;
echo &amp;quot;Список аргументов в переменной \&amp;quot;\$@\&amp;quot;:&amp;quot;&lt;br /&gt;
for arg in &amp;quot;$@&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
echo &amp;quot;Аргумент #$index = $arg&amp;quot;&lt;br /&gt;
let &amp;quot;index+=1&amp;quot;&lt;br /&gt;
done # $@ воспринимает аргументы как отдельные строки (слова).&lt;br /&gt;
echo &amp;quot;Список аргументов выглядит как набор различных строк (слов).&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
После команды ''shift'' (сдвиг), первый аргумент, в переменной &amp;quot;$@&amp;quot;, теряется, а остальные сдвигаются на одну позицию &amp;quot;вниз&amp;quot; (или &amp;quot;влево&amp;quot;, если хотите).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Вызовите сценарий в таком виде: ./scriptname 1 2 3 4 5&lt;br /&gt;
echo &amp;quot;$@&amp;quot; # 1 2 3 4 5&lt;br /&gt;
shift&lt;br /&gt;
echo &amp;quot;$@&amp;quot; # 2 3 4 5&lt;br /&gt;
shift&lt;br /&gt;
echo &amp;quot;$@&amp;quot; # 3 4 5&lt;br /&gt;
# Каждая из команд &amp;quot;shift&amp;quot; приводит к потере аргумента $1,&lt;br /&gt;
# но остальные аргументы остаются в &amp;quot;$@&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Специальная переменная $@ может быть использована для выбора типа ввода в сценария. Команда cat &amp;quot;$@&amp;quot; позволяет выполнять ввод как со стандартного устройства ввода ''stdin'', так ииз файла, имя которого передаётся сценарию из командной строки. Переменные '''''$*''''' и '''''$@''''', в отдельных случаях, могут содержать противоречивую информацию! Это зависит от содержимого переменной '''''$IFS'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Противоречия в переменных $* и $@'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Демонстрация противоречивости содержимого внутренних переменных &amp;quot;$*&amp;quot; и &amp;quot;$@&amp;quot;,&lt;br /&gt;
# которая проявляется при изменении порядка заключения параметров в кавычки.&lt;br /&gt;
# Демонстрация противоречивости, проявляющейся при изменении&lt;br /&gt;
# содержимого переменной IFS.&lt;br /&gt;
set -- &amp;quot;Первый один&amp;quot; &amp;quot;второй&amp;quot; &amp;quot;третий:один&amp;quot; &amp;quot;&amp;quot; &amp;quot;Пятый: :один&amp;quot;&lt;br /&gt;
# Установка аргументов $1, $2, и т.д.&lt;br /&gt;
echo&lt;br /&gt;
echo 'IFS по-умолчанию, переменная &amp;quot;$*&amp;quot;'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$*&amp;quot; # в кавычках&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot; # Эта строка остается без изменений во всех циклах.&lt;br /&gt;
                          # Вывод аргументов.&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS по-умолчанию, переменная $*'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $* # без кавычек&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS по-умолчанию, переменная &amp;quot;$@&amp;quot;'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$@&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS по-умолчанию, переменная $@'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $@&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
IFS=:&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная &amp;quot;$*&amp;quot;'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$*&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная $*'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $*&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
var=$*&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная &amp;quot;$var&amp;quot; (var=$*)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$var&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная $var (var=$*)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $var&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
var=&amp;quot;$*&amp;quot;&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная $var (var=&amp;quot;$*&amp;quot;)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $var&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная &amp;quot;$var&amp;quot; (var=&amp;quot;$*&amp;quot;)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$var&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная &amp;quot;$@&amp;quot;'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$@&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная $@'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $@&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
var=$@&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная $var (var=$@)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $var&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная &amp;quot;$var&amp;quot; (var=$@)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$var&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
var=&amp;quot;$@&amp;quot;&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная &amp;quot;$var&amp;quot; (var=&amp;quot;$@&amp;quot;)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in &amp;quot;$var&amp;quot;&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo ---&lt;br /&gt;
echo 'IFS=&amp;quot;:&amp;quot;, переменная $var (var=&amp;quot;$@&amp;quot;)'&lt;br /&gt;
c=0&lt;br /&gt;
for i in $var&lt;br /&gt;
do echo &amp;quot;$((c+=1)): [$i]&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo# Попробуйте запустить этот сценарий под ksh или zsh -y.&lt;br /&gt;
exit 0&lt;br /&gt;
# Это сценарий написан Stephane Chazelas,&lt;br /&gt;
# Незначительные изменения внесены автором документа.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Различия между $@ и $* наблюдаются только тогда, когда они помещаются в двойные кавычки!'''''&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Содержимое $* и $@, когда переменная $IFS — пуста'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Если переменная $IFS инициализирована &amp;quot;пустым&amp;quot; значением,&lt;br /&gt;
# то &amp;quot;$*&amp;quot; и &amp;quot;$@&amp;quot; содержат аргументы не в том виде, в каком ожидается.&lt;br /&gt;
mecho () # Вывод аргументов.&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;$1,$2,$3&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
IFS=&amp;quot;&amp;quot; # Инициализация &amp;quot;пустым&amp;quot; значением.&lt;br /&gt;
set a b c # Установка аргументов.&lt;br /&gt;
mecho &amp;quot;$*&amp;quot; # abc,,&lt;br /&gt;
mecho $* # a,b,c&lt;br /&gt;
mecho $@ # a,b,c&lt;br /&gt;
mecho &amp;quot;$@&amp;quot; # a,b,c&lt;br /&gt;
# Поведение переменных $* и $@, при &amp;quot;пустой&amp;quot; $IFS, зависит&lt;br /&gt;
# от версии командной оболочки, Bash или sh.&lt;br /&gt;
# Поэтому, было бы неразумным пользоваться этой &amp;quot;фичей&amp;quot; в своих сценариях.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* ''Прочие специальные переменные''&lt;br /&gt;
'''''$-''''' — Список флагов, переданных сценарию (командой ''set'')&lt;br /&gt;
Эта конструкция изначально была введена в ksh, откуда перекочевала в Bash и, похоже, работает в Bash не совсем надежно. Единственное возможное применение — проверка запущен ли сценарий в интерактивном режиме.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$!''''' — PID последнего, запущенного в фоне, процесса&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
LOG=$0.log&lt;br /&gt;
COMMAND1=&amp;quot;sleep 100&amp;quot;&lt;br /&gt;
echo &amp;quot;Запись в лог всех PID фоновых процессов, запущенных из сценария: $0&amp;quot; &amp;gt;&amp;gt; &amp;quot;$LOG&amp;quot;&lt;br /&gt;
# Таким образом возможен мониторинг и удаление процессов по мере необходимости.&lt;br /&gt;
echo &amp;gt;&amp;gt; &amp;quot;$LOG&amp;quot;&lt;br /&gt;
# Команды записи в лог.&lt;br /&gt;
echo -n &amp;quot;PID of \&amp;quot;$COMMAND1\&amp;quot;: &amp;quot; &amp;gt;&amp;gt; &amp;quot;$LOG&amp;quot;&lt;br /&gt;
${COMMAND1} &amp;amp;&lt;br /&gt;
echo $! &amp;gt;&amp;gt; &amp;quot;$LOG&amp;quot;&lt;br /&gt;
# PID процесса &amp;quot;sleep 100&amp;quot;: 1506&lt;br /&gt;
# Спасибо Jacques Lederer за предложенный пример.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$_''''' — Специальная переменная, содержит последний аргумент предыдущей команды.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Переменная &amp;quot;подчеркивание&amp;quot;'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo $_ # /bin/bash&lt;br /&gt;
        # Для запуска сценария был вызван /bin/bash.&lt;br /&gt;
du &amp;gt;/dev/null # Подавление вывода.&lt;br /&gt;
echo $_ # du&lt;br /&gt;
ls -al &amp;gt;/dev/null # Подавление вывода.&lt;br /&gt;
echo $_ # -al (последний аргумент)&lt;br /&gt;
:&lt;br /&gt;
echo $_ # :&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''$?''''' — Код возврата команды, функции или скрипта&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''$$''''' — PID самого процесса-сценария. Переменная ''$$'' часто используется при генерации &amp;quot;уникальных&amp;quot; имён для временных файлов. Обычно это проще, чем вызов [[mktemp]].&lt;br /&gt;
&lt;br /&gt;
=== Работа со строками ===&lt;br /&gt;
Bash поддерживает на удивление большое количество операций над строками. К сожалению, этот раздел Bash испытывает недостаток унификации. Одни операции являются подмножеством операций подстановки параметров, а другие — совпадают с функциональностью команды Unix — expr. Это приводит к противоречиям в синтаксисе команд и перекрытию функциональных возможностей, не говоря уже о возникающей путанице.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Длина строки:'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
${#string}&lt;br /&gt;
expr length $string&lt;br /&gt;
expr &amp;quot;$string&amp;quot; : '.*'&lt;br /&gt;
stringZ=abcABC123ABCabcecho ${#stringZ} # 15&lt;br /&gt;
echo `expr length $stringZ` # 15&lt;br /&gt;
echo `expr &amp;quot;$stringZ&amp;quot; : '.*'`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вставка пустых строк между параграфами в текстовом файле.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# paragraph-space.sh&lt;br /&gt;
# Вставка пустых строк между параграфами в текстовом файле.&lt;br /&gt;
MINLEN=45 # Возможно потребуется изменить это значение.&lt;br /&gt;
# Строки, содержащие количество символов меньшее, чем $MINLEN&lt;br /&gt;
# принимаются за последнюю строку параграфа.&lt;br /&gt;
while read line # Построчное чтение файла от начала до конца...&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$line&amp;quot; # Вывод строки.&lt;br /&gt;
 len=${#line}&lt;br /&gt;
 if [ &amp;quot;$len&amp;quot; -lt &amp;quot;$MINLEN&amp;quot; ]&lt;br /&gt;
  then echo # Добавление пустой строки после последней строки параграфа.&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Длина подстроки в строке (подсчёт совпадающих символов ведётся с начала строки):'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr match &amp;quot;$string&amp;quot; '$substring' ''&amp;lt;/big&amp;gt;, где $substring — регулярное выражение.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr &amp;quot;$string&amp;quot; : '$substring' ''&amp;lt;/big&amp;gt;, где $substring — регулярное выражение.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
#       |------|&lt;br /&gt;
echo `expr match &amp;quot;$stringZ&amp;quot; 'abc[A-Z]*.2'` # 8&lt;br /&gt;
echo `expr &amp;quot;$stringZ&amp;quot; : 'abc[A-Z]*.2'` # 8&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Index:'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Номер позиции первого совпадения в ''$string'' c первым символом в ''$substring'':&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr index $string $substring''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
echo `expr index &amp;quot;$stringZ&amp;quot; C12` # 6&lt;br /&gt;
                                 # позиция символа C.&lt;br /&gt;
echo `expr index &amp;quot;$stringZ&amp;quot; 1c` # 3&lt;br /&gt;
# символ 'c' (в #3 позиции) совпал раньше, чем '1'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Эта функция довольно близка к функции strchr() в языке C.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Извлечение подстроки:'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string:position}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Извлекает подстроку из ''$string'', начиная с позиции ''$position''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Если строка ''$string'' — &amp;quot;&amp;lt;big&amp;gt;'''*'''&amp;lt;/big&amp;gt;&amp;quot; или &amp;quot;&amp;lt;big&amp;gt;'''@'''&amp;lt;/big&amp;gt;&amp;quot;, то извлекается позиционный параметр (аргумент), с номером ''$position''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string:position:length}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Извлекает ''$length'' символов из ''$string'', начиная с позиции ''$position''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
# 0123456789.....&lt;br /&gt;
# Индексация начинается с 0.&lt;br /&gt;
echo ${stringZ:0} # abcABC123ABCabc&lt;br /&gt;
echo ${stringZ:1} # bcABC123ABCabc&lt;br /&gt;
echo ${stringZ:7} # 23ABCabc&lt;br /&gt;
echo ${stringZ:7:3} # 23A&lt;br /&gt;
                    # Извлекает 3 символа.&lt;br /&gt;
# Возможна ли индексация с &amp;quot;правой&amp;quot; стороны строки?&lt;br /&gt;
echo ${stringZ:-4} # abcABC123ABCabc&lt;br /&gt;
# По-умолчанию выводится полная строка.&lt;br /&gt;
# Однако ...&lt;br /&gt;
echo ${stringZ:(-4)} # Cabc&lt;br /&gt;
echo ${stringZ: -4} # Cabc&lt;br /&gt;
# Теперь выводится правильно.&lt;br /&gt;
# Круглые скобки или дополнительный пробел &amp;quot;экранируют&amp;quot; параметр позиции.&lt;br /&gt;
# Спасибо Dan Jacobson, за разъяснения.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если $string — &amp;quot;&amp;lt;big&amp;gt;'''*'''&amp;lt;/big&amp;gt;&amp;quot; или &amp;quot;&amp;lt;big&amp;gt;'''@'''&amp;lt;/big&amp;gt;&amp;quot;, то извлекается до ''$length'' позиционных параметров (аргументов), начиная с ''$position''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo ${*:2} # Вывод 2-го и последующих аргументов.&lt;br /&gt;
echo ${@:2} # То же самое.&lt;br /&gt;
echo ${*:2:3} # Вывод 3-х аргументов, начиная со 2-го.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr substr $string $position $length''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Извлекает ''$length'' символов из ''$string'', начиная с позиции ''$position''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc # 123456789......# Индексация начинается с 1.&lt;br /&gt;
echo `expr substr $stringZ 1 2` # ab&lt;br /&gt;
echo `expr substr $stringZ 4 3` # ABC&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr match &amp;quot;$string&amp;quot; '\($substring\)' ''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Находит и извлекает первое совпадение ''$substring'' в ''$string'', где ''$substring'' — это регулярное выражение.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr &amp;quot;$string&amp;quot; : '\($substring\)' ''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Находит и извлекает первое совпадение ''$substring'' в ''$string'', где ''$substring'' — это регулярное выражение.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
# =======&lt;br /&gt;
echo `expr match &amp;quot;$stringZ&amp;quot; '\(.[b-c]*[A-Z]..[0-9]\)'` # abcABC1&lt;br /&gt;
echo `expr &amp;quot;$stringZ&amp;quot; : '\(.[b-c]*[A-Z]..[0-9]\)'` # abcABC1&lt;br /&gt;
echo `expr &amp;quot;$stringZ&amp;quot; : '\(.......\)'` # abcABC1&lt;br /&gt;
# Все вышеприведённые операции дают один и тот же результат.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr match &amp;quot;$string&amp;quot; '.*\($substring\)' ''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Находит и извлекает первое совпадение ''$substring'' в ''$string'', где ''$substring'' — это регулярное выражение. Поиск начинается с конца ''$string''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''expr &amp;quot;$string&amp;quot; : '.*\($substring\)' ''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Находит и извлекает первое совпадение ''$substring'' в ''$string'', где ''$substring'' — это регулярное выражение. Поиск начинается с конца ''$string''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc# ======&lt;br /&gt;
echo `expr match &amp;quot;$stringZ&amp;quot; '.*\([A-C][A-C][A-C][a-c]*\)'` # ABCabc&lt;br /&gt;
echo `expr &amp;quot;$stringZ&amp;quot; : '.*\(......\)'` # ABCabc&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Удаление части строки:'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string#substring}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаление самой короткой, из найденных, подстроки ''$substring'' в строке ''$string''. Поиск ведётся с начала строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string##substring}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаление самой длинной, из найденных, подстроки ''$substring'' в строке ''$string''. Поиск ведётся сначала строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
#       |----|&lt;br /&gt;
#       |----------|&lt;br /&gt;
echo ${stringZ#a*C} # 123ABCabc&lt;br /&gt;
# Удаление самой короткой подстроки.&lt;br /&gt;
echo ${stringZ##a*C} # abc&lt;br /&gt;
# Удаление самой длинной подстроки.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string%substring}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаление самой короткой, из найденных, подстроки ''$substring'' в строке ''$string''. Поиск ведётся с конца строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string%%substring}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаление самой длинной, из найденных, подстроки ''$substring'' в строке ''$string''. Поиск ведётся с конца строки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
                     #||&lt;br /&gt;
#         |------------|&lt;br /&gt;
echo ${stringZ%b*c} # abcABC123ABCa&lt;br /&gt;
# Удаляется самое короткое совпадение. Поиск ведётся с конца $stringZ.&lt;br /&gt;
echo ${stringZ%%b*c} # a&lt;br /&gt;
# Удаляется самое длинное совпадение. Поиск ведётся с конца $stringZ.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Преобразование графических файлов из одного формата в другой, с изменением имени файла.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# cvt.sh:&lt;br /&gt;
# Преобразование всех файлов в заданном каталоге,&lt;br /&gt;
# из графического формата MacPaint, в формат &amp;quot;pbm&amp;quot;.&lt;br /&gt;
# Используется утилита &amp;quot;macptopbm&amp;quot;, входящая в состав пакета &amp;quot;netpbm&amp;quot;,&lt;br /&gt;
# который сопровождается Brian Henderson (bryanh@giraffe-data.com).&lt;br /&gt;
# Netpbm — стандартный пакет для большинства дистрибутивов Linux.&lt;br /&gt;
OPERATION=macptopbm&lt;br /&gt;
SUFFIX=pbm # Новое расширение файла.&lt;br /&gt;
if [ -n &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 directory=$1 # Если каталог задан в командной строке при вызове сценария&lt;br /&gt;
else&lt;br /&gt;
 directory=$PWD # Иначе просматривается текущий каталог.&lt;br /&gt;
fi&lt;br /&gt;
# Все файлы в каталоге, имеющие расширение &amp;quot;.mac&amp;quot;, считаются файлами&lt;br /&gt;
# формата MacPaint.&lt;br /&gt;
for file in $directory/* # Подстановка имен файлов.&lt;br /&gt;
do&lt;br /&gt;
 filename=${file%.*c} # Удалить расширение &amp;quot;.mac&amp;quot; из имени файла&lt;br /&gt;
                      # ( с шаблоном '.*c' совпадают все подстроки&lt;br /&gt;
                      # начинающиеся с '.' и заканчивающиеся 'c',&lt;br /&gt;
 $OPERATION $file &amp;gt; &amp;quot;$filename.$SUFFIX&amp;quot;&lt;br /&gt;
                      # Преобразование с перенаправлением в файл с новым именем&lt;br /&gt;
 rm -f $file          # Удаление оригинального файла после преобразования.&lt;br /&gt;
 echo &amp;quot;$filename.$SUFFIX&amp;quot; # Вывод на stdout.&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Сейчас этот сценарий конвертирует *все* файлы в каталоге&lt;br /&gt;
# Измените его так, чтобы он конвертировал *только* те файлы,&lt;br /&gt;
# которые имеют расширение &amp;quot;.mac&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Замена подстроки:'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string/substring/replacement}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Замещает первое вхождение ''$substring'' строкой ''$replacement''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string//substring/replacement}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Замещает все вхождения ''$substring'' строкой ''$replacement''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
echo ${stringZ/abc/xyz}  # xyzABC123ABCabc&lt;br /&gt;
                         # Замена первой подстроки 'abc' строкой 'xyz'.&lt;br /&gt;
echo ${stringZ//abc/xyz} # xyzABC123ABCxyz&lt;br /&gt;
                         # Замена всех подстрок 'abc' строкой 'xyz'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string/#substring/replacement}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подстановка строки ''$replacement'' вместо ''$substring'', если строка ''$string'' начинается найденным соответствием. Поиск ведётся с начала строки ''$string''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''${string/%substring/replacement}''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подстановка строки ''$replacement'' вместо ''$substring'', если строка ''$string'' заканчивается найденным соответствием. Поиск ведётся с конца строки ''$string''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
echo ${stringZ/#abc/XYZ} # XYZABC123ABCabc&lt;br /&gt;
                         # Поиск ведется с начала строки&lt;br /&gt;
echo ${stringZ/%abc/XYZ} # abcABC123ABCXYZ&lt;br /&gt;
                         # Поиск ведется с конца строки&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Использование awk при работе со строками:'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В качестве альтернативы, Bash-скрипты могут использовать средства [[awk]] при работе со строками.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Альтернативный способ извлечения подстрок.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# substring-extraction.sh&lt;br /&gt;
String=23skidoo1&lt;br /&gt;
# 012345678 Bash&lt;br /&gt;
# 123456789 awk&lt;br /&gt;
# Обратите внимание на различия в индексации:&lt;br /&gt;
# Bash начинает индексацию с '0'.&lt;br /&gt;
# Awk начинает индексацию с '1'.&lt;br /&gt;
echo ${String:2:4} # с 3 позиции (0-1-2), 4 символа&lt;br /&gt;
                   # skid&lt;br /&gt;
# В эквивалент в awk: substr(string,pos,length).&lt;br /&gt;
echo | awk '&lt;br /&gt;
{ print substr(&amp;quot;'&amp;quot;${String}&amp;quot;'&amp;quot;,3,4) }' # skid&lt;br /&gt;
# Передача пустого &amp;quot;echo&amp;quot; по каналу в awk, означает фиктивный ввод,&lt;br /&gt;
# делая, тем самым, ненужным предоставление имени файла.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Подстановка параметров ===&lt;br /&gt;
&amp;lt;big&amp;gt;'''Работа с переменными и/или подстановка их значений'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${parameter}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;То же самое, что и '''''$parameter''''', т.е. значение переменной ''parameter''. В отдельных случаях, при возникновении неоднозначности интерпретации, корректно будет работать только такая форма записи: '''''${parameter}'''''. Может использоваться для конкатенации (слияния) строковых переменных.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
your_id=${USER}-on-${HOSTNAME}&lt;br /&gt;
echo &amp;quot;$your_id&amp;quot;&lt;br /&gt;
#&lt;br /&gt;
echo &amp;quot;Старый \$PATH = $PATH&amp;quot;&lt;br /&gt;
PATH=${PATH}:/opt/bin #Добавление /opt/bin в $PATH.&lt;br /&gt;
echo &amp;quot;Новый \$PATH = $PATH&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${parameter-default}, ${parameter:-default}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Если параметр отсутствует, то используется значение по-умолчанию.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo ${username-`whoami`}&lt;br /&gt;
# Вывод результата работы команды `whoami`, если переменная $username не установлена.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Формы записи '''''${parameter-default}''''' и '''''${parameter:-default}''''' в большинстве случаев можно считать эквивалентными. Дополнительный символ : имеет значение только тогда, когда ''parameter'' определён, но имеет &amp;quot;пустое&amp;quot; (null)значение.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
username0=&lt;br /&gt;
# переменная username0 объявлена, но инициализирована &amp;quot;пустым&amp;quot; значением.&lt;br /&gt;
echo &amp;quot;username0 = ${username0-`whoami`}&amp;quot;&lt;br /&gt;
# Вывод после символа &amp;quot;=&amp;quot; отсутствует.&lt;br /&gt;
echo &amp;quot;username1 = ${username1-`whoami`}&amp;quot;&lt;br /&gt;
# Переменная username1 не была объявлена.&lt;br /&gt;
# Выводится имя пользователя, выданное командой `whoami`.&lt;br /&gt;
username2=&lt;br /&gt;
# переменная username2 объявлена, но инициализирована &amp;quot;пустым&amp;quot; значением.&lt;br /&gt;
echo &amp;quot;username2 = ${username2:-`whoami`}&amp;quot;&lt;br /&gt;
# Выводится имя пользователя, выданное командой `whoami`, поскольку&lt;br /&gt;
# здесь употребляется конструкция &amp;quot;:-&amp;quot; , а не &amp;quot;-&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
''Параметры по-умолчанию'' очень часто находят применение в случаях, когда сценарию необходимы какие-либо входные аргументы, передаваемые из командной строки, но такие аргументы не были переданы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
DEFAULT_FILENAME=generic.data&lt;br /&gt;
filename=${1:-$DEFAULT_FILENAME}&lt;br /&gt;
# Если имя файла не задано явно, то последующие операторы будут работать&lt;br /&gt;
# с файлом &amp;quot;generic.data&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${parameter=default},${parameter:=default}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Если значения параметров не заданы явно, то они принимают значения по-умолчанию. Оба метода задания значений по-умолчанию до определенной степени идентичны. Символ '':'' имеет значение только когда ''$parameter'' был инициализирован &amp;quot;пустым&amp;quot; (null) значением, как показано выше.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo ${username=`whoami`}&lt;br /&gt;
# Переменная &amp;quot;username&amp;quot; принимает значение, возвращаемое командой `whoami`.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${parameter+alt_value},${parameter:+alt_value}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Если параметр имеет какое-либо значение, то используется ''alt_value'', иначе — null (&amp;quot;пустая&amp;quot; строка).&lt;br /&gt;
Оба варианта до определенной степени идентичны. Символ '':'' имеет значение только если ''parameter'' объявлен и &amp;quot;пустой&amp;quot;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;###### \${parameter+alt_value} ########&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
a=${param1+xyz}&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a =&lt;br /&gt;
param2=&lt;br /&gt;
a=${param2+xyz}&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = xyz&lt;br /&gt;
param3=123&lt;br /&gt;
a=${param3+xyz}&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = xyz&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;###### \${parameter:+alt_value} ########&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
a=${param4:+xyz}&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a =&lt;br /&gt;
param5=&lt;br /&gt;
a=${param5:+xyz}&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a =&lt;br /&gt;
# Вывод отличается от a=${param5+xyz}&lt;br /&gt;
param6=123&lt;br /&gt;
a=${param6+xyz}&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = xyz&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${parameter?err_msg},${parameter:?err_msg}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Если ''parameter'' инициализирован, то используется его значение, в противном случае — выводится ''err_msg''.&lt;br /&gt;
Обе формы записи можно, до определенной степени, считать идентичными. Символ '':'' имеет значение только когда ''parameter'' инициализирован &amp;quot;пустым&amp;quot; значением.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Подстановка параметров и сообщения об ошибках.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Проверка отдельных переменных окружения.&lt;br /&gt;
# Если переменная, к примеру $USER, не установлена,&lt;br /&gt;
# то выводится сообщение об ошибке.&lt;br /&gt;
: ${HOSTNAME?} ${USER?} ${HOME?} ${MAIL?}&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Имя машины: $HOSTNAME.&amp;quot;&lt;br /&gt;
echo &amp;quot;Ваше имя: $USER.&amp;quot;&lt;br /&gt;
echo &amp;quot;Ваш домашний каталог: $HOME.&amp;quot;&lt;br /&gt;
echo &amp;quot;Ваш почтовый ящик: $MAIL.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Если перед Вами появилось это сообщение,&amp;quot;&lt;br /&gt;
echo &amp;quot;то это значит, что все критические переменные окружения установлены.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
# ------------------------------------------------------&lt;br /&gt;
# Конструкция ${variablename?} так же выполняет проверку&lt;br /&gt;
# наличия переменной в сценарии.&lt;br /&gt;
ThisVariable=Value-of-ThisVariable&lt;br /&gt;
# Обратите внимание, в строковые переменные могут быть записаны&lt;br /&gt;
# символы, которые запрещено использовать в именах переменных.&lt;br /&gt;
: ${ThisVariable?}&lt;br /&gt;
echo &amp;quot;Value of ThisVariable is $ThisVariable&amp;quot;.&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
: ${ZZXy23AB?&amp;quot;Переменная ZZXy23AB не инициализирована.&amp;quot;}&lt;br /&gt;
# Если ZZXy23AB не инициализирована,&lt;br /&gt;
# то сценарий завершается с сообщением об ошибке.&lt;br /&gt;
# Текст сообщения об ошибке можно задать свой.&lt;br /&gt;
# : ${ZZXy23AB?&amp;quot;Переменная ZZXy23AB не инициализирована.&amp;quot;}&lt;br /&gt;
# То же самое: dummy_variable=${ZZXy23AB?}&lt;br /&gt;
#              dummy_variable=${ZZXy23AB?&amp;quot;Переменная ZXy23AB не инициализирована.&amp;quot;}&lt;br /&gt;
#              echo ${ZZXy23AB?} &amp;gt;/dev/null&lt;br /&gt;
echo &amp;quot;Это сообщение не будет напечатано, поскольку сценарий завершится раньше.&amp;quot;&lt;br /&gt;
HERE=0&lt;br /&gt;
exit $HERE # Сценарий завершит работу не здесь.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Подстановка параметров и сообщение о &amp;quot;порядке использования&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# usage-message.sh&lt;br /&gt;
: ${1?&amp;quot;Порядок использования: $0 ARGUMENT&amp;quot;}&lt;br /&gt;
# Сценарий завершит свою работу здесь, если входные аргументы отсутствуют,&lt;br /&gt;
# со следующим сообщением.&lt;br /&gt;
# usage-message.sh: 1: Порядок использования: usage-message.sh ARGUMENT&lt;br /&gt;
echo &amp;quot;Эти две строки появятся, только когда задан аргумент в командной строке.&amp;quot;&lt;br /&gt;
echo &amp;quot;Входной аргумент командной строки = \&amp;quot;$1\&amp;quot;&amp;quot;&lt;br /&gt;
exit 0 # Точка выхода находится здесь, только когда задан аргумент командной строки.&lt;br /&gt;
# Проверьте код возврата в обеих случаях, с и без аргумента командной строки.&lt;br /&gt;
# Если аргумент задан, то код возврата будет равен 0.&lt;br /&gt;
# Иначе — 1.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Подстановка параметров и/или экспансия.'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Следующие выражения могут служить дополнениями оператора ''match'' команды ''expr'', применяемой к строкам. Как правило, они используются при разборе имён файлов и каталогов.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;'''Длина переменной/Удаление подстроки.'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${#var}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;''String length'' (число символов в переменной ''$var''). В случае массивов, команда ''${#array}'' возвращает длину первого элемента массива.&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''Исключения:'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''${#*}''' и '''${#@}''' возвращает количество аргументов (позиционных параметров).&lt;br /&gt;
* Для массивов, '''${#array[*]}''' и '''${#array[@]}''' возвращает количество элементов в массиве.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Длина переменной.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# length.sh&lt;br /&gt;
E_NO_ARGS=65if [ $# -eq 0 ] # Для работы скрипта необходим хотя бы один входной параметр.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Вызовите сценарий с одним или более параметром командной строки.&amp;quot;&lt;br /&gt;
 exit $E_NO_ARGS&lt;br /&gt;
fi&lt;br /&gt;
var01=abcdEFGH28ij&lt;br /&gt;
echo &amp;quot;var01 = ${var01}&amp;quot;&lt;br /&gt;
echo &amp;quot;Length of var01 = ${#var01}&amp;quot;&lt;br /&gt;
echo &amp;quot;Количество входных параметров = ${#@}&amp;quot;&lt;br /&gt;
echo &amp;quot;Количество входных параметров = ${#*}&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var#Pattern},${var##Pattern}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаляет из переменной ''$var'' наименьшую/наибольшую подстроку, совпадающую с шаблоном ''$Pattern''. Поиск ведётся с начала строки ''$var''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Функция из сценария &amp;quot;days-between.sh&amp;quot;.&lt;br /&gt;
95&lt;br /&gt;
# Удаляет нули, стоящие в начале аргумента-строки.&lt;br /&gt;
strip_leading_zero () # Ведущие нули, которые могут находиться в номере дня/месяца, лучше удалить&lt;br /&gt;
{                     # В противном случае Bash будет интерпретировать числа как восьмеричные &lt;br /&gt;
return=${1#0}         # &amp;quot;1&amp;quot; — это аргумент &amp;quot;$1&amp;quot;.&lt;br /&gt;
}                     # &amp;quot;0&amp;quot; — это то, что удаляется из &amp;quot;$1&amp;quot; — ведущие нули.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''Manfred Schwarb''' предложил более сложный вариант вышеприведенного кода:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
strip_leading_zero2 () # Удалить ведущие нули.&lt;br /&gt;
{&lt;br /&gt;
shopt -s extglob               # Переход в режим расширенной подстановки.&lt;br /&gt;
local val=${1##+(0)}           # Поиск самой длинной последовательности нулей.&lt;br /&gt;
shopt -u extglob               # выход из режима расширенной подстановки.&lt;br /&gt;
_strip_leading_zero2=${val:-0}&lt;br /&gt;
                               # Если был введен 0, то возвращается 0, а не &amp;quot;&amp;quot;.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Другой пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo `basename $PWD`   # Имя текущего рабочего каталога.&lt;br /&gt;
echo &amp;quot;${PWD##*/}&amp;quot;      # Имя текущего рабочего каталога.&lt;br /&gt;
echo&lt;br /&gt;
echo `basename $0`     # Имя файла-сценария.&lt;br /&gt;
echo $0                # Имя файла-сценария.&lt;br /&gt;
echo &amp;quot;${0##*/}&amp;quot;        # Имя файла-сценария.&lt;br /&gt;
echo&lt;br /&gt;
filename=test.data&lt;br /&gt;
echo &amp;quot;${filename##*.}&amp;quot; # data&lt;br /&gt;
                       # Расширение файла.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var%Pattern},${var%%Pattern}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Удаляет из переменной ''$var'' наименьшую/наибольшую подстроку, совпадающую с шаблоном ''$Pattern''. Поиск ведётся с конца строки ''$var''.Bash версии 2 имеет ряд дополнительных возможностей.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Поиск по шаблону в подстановке параметров.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Поиск по шаблону в операциях подстановки параметров # ## % %%.&lt;br /&gt;
var1=abcd12345abc6789&lt;br /&gt;
pattern1=a*c # * (символ шаблона), означает любые символы между a и c.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;var1 = $var1&amp;quot; # abcd12345abc6789&lt;br /&gt;
echo &amp;quot;var1 = ${var1}&amp;quot; # abcd12345abc6789 (альтернативный вариант)&lt;br /&gt;
echo &amp;quot;Число символов в ${var1} = ${#var1}&amp;quot;&lt;br /&gt;
echo &amp;quot;pattern1 = $pattern1&amp;quot; # a*c (между 'a' и 'c' могут быть любые символы)&lt;br /&gt;
echo&lt;br /&gt;
echo '${var1#$pattern1} =' &amp;quot;${var1#$pattern1}&amp;quot; # d12345abc6789&lt;br /&gt;
# Наименьшая подстрока, удаляются первые 3 символа abcd12345abc6789&lt;br /&gt;
                                  ^^^^^^           |-|&lt;br /&gt;
echo '${var1##$pattern1} =' &amp;quot;${var1##$pattern1}&amp;quot; # 6789&lt;br /&gt;
# Наибольшая подстрока, удаляются первые 12 символов abcd12345abc6789&lt;br /&gt;
#                                           ^^^^^^   |----------|&lt;br /&gt;
echo; echo&lt;br /&gt;
pattern2=b*9 # все, что между 'b' и '9'&lt;br /&gt;
echo &amp;quot;var1 = $var1&amp;quot; # abcd12345abc6789&lt;br /&gt;
echo &amp;quot;pattern2 = $pattern2&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo '${var1%pattern2} =' &amp;quot;${var1%$pattern2}&amp;quot; # abcd12345a&lt;br /&gt;
# Наименьшая подстрока, удаляются последние 6 символов abcd12345abc6789&lt;br /&gt;
#                                 ^^^^^^^^^                      |----|&lt;br /&gt;
echo '${var1%%pattern2} =' &amp;quot;${var1%%$pattern2}&amp;quot; # a&lt;br /&gt;
# Наибольшая подстрока, удаляются последние 12 символов abcd12345abc6789&lt;br /&gt;
#                                 ^^^^^^^^^              |-------------|&lt;br /&gt;
# Запомните, # и ## используются для поиска с начала строки,&lt;br /&gt;
# % и %% используются для поиска с конца строки.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Изменение расширений в именах файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# rfe&lt;br /&gt;
# ---&lt;br /&gt;
# Изменение расширений в именах файлов.&lt;br /&gt;
#&lt;br /&gt;
# rfe old_extension new_extension&lt;br /&gt;
# Пример:&lt;br /&gt;
# Изменить все расширения *.gif в именах файлов на *.jpg, в текущем каталоге&lt;br /&gt;
# rfe gif jpg&lt;br /&gt;
ARGS=2&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` old_file_suffix new_file_suffix&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
for filename in *.$1&lt;br /&gt;
# Цикл прохода по списку имен файлов, имеющих расширение равное первому аргументу.&lt;br /&gt;
do&lt;br /&gt;
mv $filename ${filename%$1}$2&lt;br /&gt;
# Удалить первое расширение и добавить второе,&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;'''Подстановка значений переменных / Замена подстроки'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Эти конструкции перекочевали в Bash из ksh.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var:pos}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Подставляется значение переменной ''var'', начиная с позиции ''pos''.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var:pos:len}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Подставляется значение переменной ''var'', начиная с позиции ''pos'', не более ''len'' символов.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var/Pattern/Replacement}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Первое совпадение с шаблоном ''Pattern'', в переменной ''var'' замещается подстрокой ''Replacement''. Если подстрока ''Replacement'' отсутствует, то найденное совпадение будет удалено.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var//Pattern/Replacement}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''Глобальная замена'''. Все найденные совпадения с шаблоном ''Pattern'', в переменной ''var'', будут замещены подстрокой ''Replacement''. Как и в первом случае, если подстрока ''Replacement'' отсутствует, то все найденные совпадения будут удалены.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Поиск по шаблону при анализе произвольных строк.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
var1=abcd-1234-defg&lt;br /&gt;
echo &amp;quot;var1 = $var1&amp;quot;&lt;br /&gt;
t=${var1#*-*}&lt;br /&gt;
echo &amp;quot;var1 (все, от начала строки по первый символ \&amp;quot;-\&amp;quot;, включительно, удаляется) = $t&amp;quot;&lt;br /&gt;
# t=${var1#*-} то же самое,&lt;br /&gt;
# поскольку оператор # ищет кратчайшее совпадение,&lt;br /&gt;
# а * соответствует любым предшествующим символам, включая пустую строку.&lt;br /&gt;
# (Спасибо S. C. за разъяснения.)&lt;br /&gt;
t=${var1##*-*}&lt;br /&gt;
echo &amp;quot;Если var1 содержит \&amp;quot;-\&amp;quot;, то возвращается пустая строка... var1 = $t&amp;quot;&lt;br /&gt;
t=${var1%*-*}&lt;br /&gt;
echo &amp;quot;var1 (все, начиная с последнего \&amp;quot;-\&amp;quot; удаляется) = $t&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# -------------------------------------------&lt;br /&gt;
path_name=/home/bozo/ideas/thoughts.for.today&lt;br /&gt;
# -------------------------------------------&lt;br /&gt;
echo &amp;quot;path_name = $path_name&amp;quot;&lt;br /&gt;
t=${path_name##/*/}&lt;br /&gt;
echo &amp;quot;Из path_name удален путь к файлу = $t&amp;quot;&lt;br /&gt;
# В данном случае, тот эе эффект можно получить так: t=`basename $path_name`&lt;br /&gt;
# t=${path_name%/}; t=${t##*/} более общее решение,&lt;br /&gt;
# но имеет некоторые ограничения.&lt;br /&gt;
# Если $path_name заканчивается символом перевода строки, то `basename $path_name` не будет работать,&lt;br /&gt;
# но для данного случая вполне применимо.&lt;br /&gt;
# (Спасибо S.C.)&lt;br /&gt;
t=${path_name%/*.*}&lt;br /&gt;
# Тот же эффект дает t=`dirname $path_name`&lt;br /&gt;
echo &amp;quot;Из path_name удалено имя файла = $t&amp;quot;&lt;br /&gt;
# Этот вариант будет терпеть неудачу в случаях: &amp;quot;../&amp;quot;, &amp;quot;/foo////&amp;quot;, # &amp;quot;foo/&amp;quot;, &amp;quot;/&amp;quot;.&lt;br /&gt;
# Удаление имени файла, особенно когда его нет,&lt;br /&gt;
# использование dirname имеет свои особенности.&lt;br /&gt;
# (Спасибо S.C.)&lt;br /&gt;
echo&lt;br /&gt;
t=${path_name:11}&lt;br /&gt;
echo &amp;quot;Из $path_name удалены первые 11 символов = $t&amp;quot;&lt;br /&gt;
t=${path_name:11:5}&lt;br /&gt;
echo &amp;quot;Из $path_name удалены первые 11 символов, выводится 5 символов = $t&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
t=${path_name/bozo/clown}&lt;br /&gt;
echo &amp;quot;В $path_name подстрока \&amp;quot;bozo\&amp;quot; заменена на \&amp;quot;clown\&amp;quot; = $t&amp;quot;&lt;br /&gt;
t=${path_name/today/}&lt;br /&gt;
echo &amp;quot;В $path_name подстрока \&amp;quot;today\&amp;quot; удалена = $t&amp;quot;&lt;br /&gt;
t=${path_name//o/O}&lt;br /&gt;
echo &amp;quot;В $path_name все символы \&amp;quot;o\&amp;quot; переведены в верхний регистр, = $t&amp;quot;&lt;br /&gt;
t=${path_name//o/}&lt;br /&gt;
echo &amp;quot;Из $path_name удалены все символы \&amp;quot;o\&amp;quot; = $t&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var/#Pattern/Replacement}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Если в переменной ''var'' найдено совпадение с ''Pattern'', причём совпадающая подстрока расположена в начале строки (префикс), то оно заменяется на ''Replacement''. Поиск ведётся сначала строки.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${var/%Pattern/Replacement}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Если в переменной ''var'' найдено совпадение с ''Pattern'', причём совпадающая подстрока расположена в конце строки (суффикс), то оно заменяется на ''Replacement''. Поиск ведётся с конца строки.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Поиск префиксов и суффиксов с заменой по шаблону.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Поиск с заменой по шаблону.&lt;br /&gt;
v0=abc1234zip1234abc # Начальное значение переменной.&lt;br /&gt;
echo &amp;quot;v0 = $v0&amp;quot;      # abc1234zip1234abc&lt;br /&gt;
echo&lt;br /&gt;
# Поиск совпадения с начала строки.&lt;br /&gt;
v1=${v0/#abc/ABCDEF} # abc1234zip1234abc&lt;br /&gt;
                     # |-|&lt;br /&gt;
echo &amp;quot;v1 = $v1&amp;quot;      # ABCDE1234zip1234abc&lt;br /&gt;
                     # |---|&lt;br /&gt;
# Поиск совпадения с конца строки.&lt;br /&gt;
v2=${v0/%abc/ABCDEF} # abc1234zip123abc&lt;br /&gt;
#                                   |-|&lt;br /&gt;
echo &amp;quot;v2 = $v2&amp;quot;      # abc1234zip1234ABCDEF&lt;br /&gt;
#                                    |----|&lt;br /&gt;
echo&lt;br /&gt;
# ----------------------------------------------------&lt;br /&gt;
# Если совпадение находится не с начала/конца строки,&lt;br /&gt;
# то замена не производится.&lt;br /&gt;
# ----------------------------------------------------&lt;br /&gt;
v3=${v0/#123/000}    # Совпадение есть, но не в начале строки.&lt;br /&gt;
echo &amp;quot;v3 = $v3&amp;quot;      # abc1234zip1234abc&lt;br /&gt;
                     # ЗАМЕНА НЕ ПРОИЗВОДИТСЯ!&lt;br /&gt;
v4=${v0/%123/000}    # Совпадение есть, но не в конце строки.&lt;br /&gt;
echo &amp;quot;v4 = $v4&amp;quot;      # abc1234zip1234abc&lt;br /&gt;
                     # ЗАМЕНА НЕ ПРОИЗВОДИТСЯ!&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''${!varprefix*},${!varprefix@}'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;Поиск по шаблону всех, ранее объявленных переменных, имена которых начинаются с ''varprefix''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
xyz23=whatever&lt;br /&gt;
xyz24=&lt;br /&gt;
a=${!xyz*}         # Подстановка имен объявленных переменных, которые начинаются с &amp;quot;xyz&amp;quot;.&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot;      # a = xyz23 xyz24&lt;br /&gt;
a=${!xyz@}         # То же самое.&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot;      # a = xyz23 xyz24&lt;br /&gt;
# Эта возможность была добавлена в Bash, в версии 2.04.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Объявление переменных: declare и typeset ===&lt;br /&gt;
Инструкции '''declare''' и '''typeset''' являются встроенными инструкциями (они абсолютно идентичны друг другу и являются синонимами) и предназначена для наложения ограничений на переменные. Это очень слабая попытка контроля над типами, которая имеется во многих языках программирования. Инструкция '''declare''' появилась в Bash, начиная с версии 2. Кроме того, инструкция '''typeset''' может использоваться и в ksh-сценариях.&lt;br /&gt;
&amp;lt;big&amp;gt;'''Ключи инструкций declare/typeset'''&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;lt;big&amp;gt;-r&amp;lt;/big&amp;gt; readonly (только для чтения)'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -r var1'''''&lt;br /&gt;
&amp;lt;br /&amp;gt;(declare -r var1 аналогично объявлению readonly var1). &lt;br /&gt;
&amp;lt;br /&amp;gt;Это грубый эквивалент констант (''const'') в языке C. Попытка изменения таких переменных завершается сообщением об ошибке.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;lt;big&amp;gt;-i&amp;lt;/big&amp;gt; integer'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -i number'''''&lt;br /&gt;
 # Сценарий интерпретирует переменную &amp;quot;number&amp;quot; как целое число.&lt;br /&gt;
 number=3&lt;br /&gt;
 echo &amp;quot;number = $number&amp;quot;  # number = 3&lt;br /&gt;
 number=three&lt;br /&gt;
 echo &amp;quot;number = $number&amp;quot;  # number = 0&lt;br /&gt;
 # Строка &amp;quot;three&amp;quot; интерпретируется как целое число.&lt;br /&gt;
Допускается выполнение некоторых арифметических операций над переменными, объявленными как integer, не прибегая к инструкциям ''expr'' или ''let''.&lt;br /&gt;
 n=6/3&lt;br /&gt;
 echo &amp;quot;n = $n&amp;quot; # n = 6/3&lt;br /&gt;
 declare -i n&lt;br /&gt;
 n=6/3&lt;br /&gt;
 echo &amp;quot;n = $n&amp;quot; # n = 2&lt;br /&gt;
&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;lt;big&amp;gt;-a&amp;lt;/big&amp;gt; array'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -a indices'''''&lt;br /&gt;
&amp;lt;br /&amp;gt;Переменная ''indices'' объявляется массивом.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;lt;big&amp;gt;-f&amp;lt;/big&amp;gt; functions'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -f'''''&lt;br /&gt;
&amp;lt;br /&amp;gt;Инструкция ''declare -f'', без аргументов, приводит к выводу списка ранее объявленных функций в сценарии.&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -f function_name'''''&lt;br /&gt;
&amp;lt;br /&amp;gt;Инструкция ''declare -f function_name'' выводит имя функции ''function_name'', если она была объявлена ранее.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;lt;big&amp;gt;-x&amp;lt;/big&amp;gt; export'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -x var3'''''&lt;br /&gt;
&amp;lt;br /&amp;gt;Эта инструкция объявляет переменную, как доступную для экспорта.&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;big&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;lt;big&amp;gt;-x&amp;lt;/big&amp;gt; var=$value'''''&amp;lt;/span&amp;gt;&amp;lt;/big&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;'''''declare -x var3=373'''''&lt;br /&gt;
&amp;lt;br /&amp;gt;Инструкция ''declare'' допускает совмещение объявления и присваивания значения переменной одновременно.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Объявление переменных с помощью инструкции declare.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
func1 ()&lt;br /&gt;
{&lt;br /&gt;
echo Это функция.&lt;br /&gt;
}&lt;br /&gt;
declare -f               # Список функций, объявленных выше.&lt;br /&gt;
echo&lt;br /&gt;
declare -i var1          # var1 — целочисленная переменная.&lt;br /&gt;
var1=2367&lt;br /&gt;
echo &amp;quot;переменная var1 объявлена как $var1&amp;quot;&lt;br /&gt;
var1=var1+1              # Допустимая арифметическая операция над целочисленными переменными.&lt;br /&gt;
echo &amp;quot;переменная var1 увеличена на 1 = $var1.&amp;quot;&lt;br /&gt;
                         # Допустимая операция для целочисленных переменных&lt;br /&gt;
echo &amp;quot;Возможно ли записать дробное число 2367.1 в var1?&amp;quot;&lt;br /&gt;
var1=2367.1              # Сообщение об ошибке, переменная не изменяется.&lt;br /&gt;
echo &amp;quot;значение переменной var1 осталось прежним = $var1&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
declare -r var2=13.36    # инструкция 'declare' допускает установку свойств переменной&lt;br /&gt;
                         # и одновременно присваивать значение.&lt;br /&gt;
echo &amp;quot;var2 declared as $var2&amp;quot; # Допускается ли изменять значение readonly переменных?&lt;br /&gt;
var2=13.37               # Сообщение об ошибке и завершение работы сценария.&lt;br /&gt;
echo &amp;quot;значение переменной var2 осталось прежним $var2&amp;quot; # Эта строка никогда не будет выполнена.&lt;br /&gt;
exit 0                   # Сценарий завершит работу выше.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Косвенные ссылки на переменные ===&lt;br /&gt;
Предположим, что значение одной переменной — есть имя второй переменной. Возможно ли получить значение второй переменной через обращение к первой?&amp;lt;br /&amp;gt; Например, пусть ''a=letter_of_alphabet'' и ''letter_of_alphabet=z'', тогда вопрос будет звучать так:&amp;lt;br /&amp;gt;&amp;quot;Возможно ли получить значение ''z'', обратившись к переменной ''a''?&amp;quot;. &amp;lt;br /&amp;gt;В действительности это возможно и это называется ''косвенной ссылкой''. Для этого необходимо прибегнуть к несколько необычной нотации ''eval var1=\$$var2''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Косвенные ссылки.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Косвенные ссылки на переменные.&lt;br /&gt;
a=letter_of_alphabet&lt;br /&gt;
letter_of_alphabet=z&lt;br /&gt;
echo&lt;br /&gt;
# Прямое обращение к переменной.&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot;&lt;br /&gt;
# Косвенное обращение к переменной.&lt;br /&gt;
eval a=\$$a&lt;br /&gt;
echo &amp;quot;А теперь a = $a&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Теперь попробуем изменить переменную, на которую делается ссылка.&lt;br /&gt;
t=table_cell_3&lt;br /&gt;
table_cell_3=24&lt;br /&gt;
echo &amp;quot;\&amp;quot;table_cell_3\&amp;quot; = $table_cell_3&amp;quot;&lt;br /&gt;
echo -n &amp;quot;разыменование (получение ссылки) \&amp;quot;t\&amp;quot; = &amp;quot;; eval echo \$$t&lt;br /&gt;
# В данном, простом, случае,&lt;br /&gt;
# eval t=\$$t; echo &amp;quot;\&amp;quot;t\&amp;quot; = $t&amp;quot;&lt;br /&gt;
# даёт тот же результат (почему?).&lt;br /&gt;
echo&lt;br /&gt;
t=table_cell_3&lt;br /&gt;
NEW_VAL=387&lt;br /&gt;
table_cell_3=$NEW_VAL&lt;br /&gt;
echo &amp;quot;Значение переменной \&amp;quot;table_cell_3\&amp;quot; изменено на $NEW_VAL.&amp;quot;&lt;br /&gt;
echo &amp;quot;Теперь \&amp;quot;table_cell_3\&amp;quot; = $table_cell_3&amp;quot;&lt;br /&gt;
echo -n &amp;quot;разыменование (получение ссылки) \&amp;quot;t\&amp;quot; = &amp;quot;; eval echo \$$t&lt;br /&gt;
# инструкция &amp;quot;eval&amp;quot; принимает два аргумента &amp;quot;echo&amp;quot; и &amp;quot;\$$t&amp;quot; (назначает равным $table_cell_3)&lt;br /&gt;
echo&lt;br /&gt;
# (Спасибо S.C. за разъяснения.)&lt;br /&gt;
# Ещё один способ — нотация ${!t}, будет обсуждаться в разделе &amp;quot;Bash, версия 2&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача косвенных ссылок в awk.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Другая версия сценария &amp;quot;column totaler&amp;quot;&lt;br /&gt;
# который суммирует заданную колонку (чисел) в заданном файле.&lt;br /&gt;
# Здесь используются косвенные ссылки.&lt;br /&gt;
ARGS=2&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ] # Проверка количества входных аргументов.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename column-number&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
filename=$1&lt;br /&gt;
column_number=$2&lt;br /&gt;
#===== До этой строки идентично первоначальному варианту сценария =====#&lt;br /&gt;
# Многострочные скрипты awk вызываются конструкцией awk ' ..... '&lt;br /&gt;
# Начало awk-сценария.&lt;br /&gt;
# ------------------------------------------------&lt;br /&gt;
awk &amp;quot;&lt;br /&gt;
{ total += \$${column_number} # косвенная ссылка&lt;br /&gt;
}&lt;br /&gt;
END {  &lt;br /&gt;
      print total&lt;br /&gt;
    }&lt;br /&gt;
   &amp;quot; &amp;quot;$filename&amp;quot;&lt;br /&gt;
# ------------------------------------------------&lt;br /&gt;
# Конец awk-сценария.&lt;br /&gt;
# Косвенные ссылки делают возможным бесконфликтное&lt;br /&gt;
# обращение к переменным shell внутри вложенных сценариев awk.&lt;br /&gt;
# Спасибо Stephane Chazelas.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Такой метод обращения к переменным имеет свои особенности. Если переменная, на которую делается ссылка, меняет свое значение, то переменная которая ссылается, должна быть должным образом разыменована, т.е. должна быть выполнена операция получения ссылки, как это делается в примере выше. К счастью, нотация ''${!variable}'', введённая в Bash, начиная с версии 2 позволяет выполнять косвенные ссылки более интуитивно понятным образом.&lt;br /&gt;
&lt;br /&gt;
=== $RANDOM: генерация псевдослучайных целых чисел ===&lt;br /&gt;
'''$RANDOM''' — внутренняя функция Bash (не константа), которая возвращает ''псевдослучайные целые числа'' в диапазоне 0—32767. Функция '''$RANDOM''' ''не должна'' использоваться для генерации ключей шифрования.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Генерация случайных чисел.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# $RANDOM возвращает различные случайные числа при каждом обращении к ней.&lt;br /&gt;
# Диапазон изменения: 0—32767 (16-битовое целое со знаком).&lt;br /&gt;
MAXCOUNT=10&lt;br /&gt;
count=1&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;$MAXCOUNT случайных чисел:&amp;quot;&lt;br /&gt;
echo &amp;quot;-----------------&amp;quot;&lt;br /&gt;
while [ &amp;quot;$count&amp;quot; -le $MAXCOUNT ] # Генерация 10 ($MAXCOUNT) случайных чисел.&lt;br /&gt;
do&lt;br /&gt;
 number=$RANDOM&lt;br /&gt;
 echo $number&lt;br /&gt;
 let &amp;quot;count += 1&amp;quot; # Нарастить счетчик.&lt;br /&gt;
done&lt;br /&gt;
echo &amp;quot;-----------------&amp;quot;&lt;br /&gt;
# Если вам нужны случайные числа не превышающие определенного числа,&lt;br /&gt;
# воспользуйтесь оператором деления по модулю (остаток от деления).&lt;br /&gt;
RANGE=500&lt;br /&gt;
echo&lt;br /&gt;
number=$RANDOM&lt;br /&gt;
let &amp;quot;number %= $RANGE&amp;quot;&lt;br /&gt;
echo &amp;quot;Случайное число меньше $RANGE —— $number&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Если вы желаете ограничить диапазон &amp;quot;снизу&amp;quot;,&lt;br /&gt;
# то просто производите генерацию псевдослучайных чисел в цикле до тех пор,&lt;br /&gt;
# пока не получите число большее нижней границы.&lt;br /&gt;
FLOOR=200&lt;br /&gt;
number=0 # инициализация&lt;br /&gt;
while [ &amp;quot;$number&amp;quot; -le $FLOOR ]&lt;br /&gt;
do&lt;br /&gt;
 number=$RANDOM&lt;br /&gt;
done&lt;br /&gt;
echo &amp;quot;Случайное число, большее $FLOOR —— $number&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Эти два способа могут быть скомбинированы.&lt;br /&gt;
number=0 #initialize&lt;br /&gt;
while [ &amp;quot;$number&amp;quot; -le $FLOOR ]&lt;br /&gt;
do&lt;br /&gt;
 number=$RANDOM&lt;br /&gt;
 let &amp;quot;number %= $RANGE&amp;quot; # Ограничение &amp;quot;сверху&amp;quot; числом $RANGE.&lt;br /&gt;
done&lt;br /&gt;
echo &amp;quot;Случайное число в диапазоне от $FLOOR до $RANGE —— $number&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Генерация случайных &amp;quot;true&amp;quot; и &amp;quot;false&amp;quot; значений.&lt;br /&gt;
BINARY=2&lt;br /&gt;
number=$RANDOMT=1&lt;br /&gt;
let &amp;quot;number %= $BINARY&amp;quot;&lt;br /&gt;
# let &amp;quot;number &amp;gt;&amp;gt;= 14&amp;quot; даёт более равномерное распределение&lt;br /&gt;
# (сдвиг вправо смещает старший бит на нулевую позицию, остальные биты&lt;br /&gt;
обнуляются).&lt;br /&gt;
if [ &amp;quot;$number&amp;quot; -eq $T ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;TRUE&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;FALSE&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
# Можно имитировать бросание 2-х игровых кубиков.&lt;br /&gt;
SPOTS=7 # остаток от деления на 7 дает диапазон 0 - 6.&lt;br /&gt;
ZERO=0&lt;br /&gt;
die1=0&lt;br /&gt;
die2=0&lt;br /&gt;
# Кубики &amp;quot;выбрасываются&amp;quot; раздельно.&lt;br /&gt;
while [ &amp;quot;$die1&amp;quot; -eq $ZERO ] # Пока на &amp;quot;кубике&amp;quot; ноль.&lt;br /&gt;
do&lt;br /&gt;
 let &amp;quot;die1 = $RANDOM % $SPOTS&amp;quot; # Имитировать бросок первого кубика.&lt;br /&gt;
done&lt;br /&gt;
while [ &amp;quot;$die2&amp;quot; -eq $ZERO ]&lt;br /&gt;
do&lt;br /&gt;
 let &amp;quot;die2 = $RANDOM % $SPOTS&amp;quot; # Имитировать бросок второго кубика.&lt;br /&gt;
done&lt;br /&gt;
let &amp;quot;throw = $die1 + $die2&amp;quot;&lt;br /&gt;
echo &amp;quot;Результат броска кубиков = $throw&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Выбор случайной карты из колоды.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# pick-card.sh&lt;br /&gt;
# Пример выбора случайного элемента массива.&lt;br /&gt;
# Выбор случайной карты из колоды.&lt;br /&gt;
Suites=&amp;quot;Треф &lt;br /&gt;
Бубей &lt;br /&gt;
Червей &lt;br /&gt;
Пик&amp;quot;&lt;br /&gt;
Denominations=&amp;quot;2&lt;br /&gt;
3&lt;br /&gt;
4&lt;br /&gt;
5&lt;br /&gt;
6&lt;br /&gt;
7&lt;br /&gt;
8&lt;br /&gt;
9&lt;br /&gt;
10&lt;br /&gt;
Валет&lt;br /&gt;
Дама&lt;br /&gt;
Король&lt;br /&gt;
Туз&amp;quot;&lt;br /&gt;
# Инициализация массивов.&lt;br /&gt;
suite=($Suites) &lt;br /&gt;
denomination=($Denominations)&lt;br /&gt;
num_suites=${#suite[*]} # Количество элементов массивов.&lt;br /&gt;
num_denominations=${#denomination[*]}&lt;br /&gt;
echo -n &amp;quot;${denomination[$((RANDOM%num_denominations))]} &amp;quot;&lt;br /&gt;
echo ${suite[$((RANDOM%num_suites))]}&lt;br /&gt;
# $bozo sh pick-cards.sh&lt;br /&gt;
# Валет Треф&lt;br /&gt;
# Спасибо &amp;quot;jipe,&amp;quot; за пояснения по работе с $RANDOM.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Jipe''''' подсказал ещё один способ генерации случайных чисел из заданного диапазона.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Генерация случайных чисел в диапазоне 6—30.&lt;br /&gt;
rnumber=$((RANDOM%25+6))&lt;br /&gt;
# Генерируется случайное число из диапазона 6—30,&lt;br /&gt;
# но при этом число должно делиться на 3 без остатка.&lt;br /&gt;
rnumber=$(((RANDOM%30/3+1)*3))&lt;br /&gt;
# Примечательно, если $RANDOM возвращает 0&lt;br /&gt;
# то это приводит к возникновению ошибки.&lt;br /&gt;
# Упражнение: Попробуйте разобраться с выражением самостоятельно.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Bill Gradwohl''''' предложил усовершенствованную формулу генерации положительных псевдослучайных чисел в заданном диапазоне.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rnumber=$(((RANDOM%(max-min+divisibleBy))/divisibleBy*divisibleBy+min))&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В сценарии ниже, '''''Bill''''' представил универсальную функцию, которая возвращает псевдослучайное число из заданного диапазона.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Псевдослучайное число из заданного диапазона.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# random-between.sh&lt;br /&gt;
# Псевдослучайное число из заданного диапазона.&lt;br /&gt;
# Автор: Bill Gradwohl,&lt;br /&gt;
# незначительные изменения внесены автором документа.&lt;br /&gt;
# Используется с разрешения автора сценария.&lt;br /&gt;
randomBetween() {&lt;br /&gt;
# Генерация положительных и отрицательных псевдослучайных чисел,&lt;br /&gt;
# в диапазоне от $min до $max,&lt;br /&gt;
# которые кратны числу $divisibleBy.&lt;br /&gt;
#&lt;br /&gt;
# Bill Gradwohl — Oct 1, 2003&lt;br /&gt;
syntax() {&lt;br /&gt;
# Вложенная функция.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Порядок вызова: randomBetween [min] [max] [multiple]&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Функция ожидает до 3-х входных аргументов, но они не являются обязательными.&amp;quot;&lt;br /&gt;
echo &amp;quot;min — нижняя граница диапазона&amp;quot;&lt;br /&gt;
echo &amp;quot;max — верхняя граница диапазона&amp;quot;&lt;br /&gt;
echo &amp;quot;multiple — делитель, на который должен делиться результат без остатка.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Если какой либо из параметров отсутствует, по-умолчанию принимаются значения: 0 32767 1&amp;quot;&lt;br /&gt;
echo &amp;quot;В случае успеха функция возвращает 0, иначе — 1&amp;quot;&lt;br /&gt;
echo &amp;quot;и это сообщение о порядке вызова.&amp;quot;&lt;br /&gt;
echo &amp;quot;Результат возвращается в глобальной переменной randomBetweenAnswer&amp;quot;&lt;br /&gt;
echo &amp;quot;Входные параметры, имеющие отрицательные значения, обрабатываются корректно.&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
local min=${1:-0}&lt;br /&gt;
local max=${2:-32767}&lt;br /&gt;
local divisibleBy=${3:-1}&lt;br /&gt;
# При отсутствии какого-либо из входных параметров, они принимают значения по-умолчанию.&lt;br /&gt;
local x&lt;br /&gt;
local spread&lt;br /&gt;
# Делитель должен быть положительным числом.&lt;br /&gt;
[ ${divisibleBy} -lt 0 ] &amp;amp;&amp;amp; divisibleBy=$((0-divisibleBy))&lt;br /&gt;
# Проверка корректности входных параметров.&lt;br /&gt;
if [ $# -gt 3 -o ${divisibleBy} -eq 0 -o ${min} -eq ${max} ]; then&lt;br /&gt;
 syntax&lt;br /&gt;
 return 1&lt;br /&gt;
fi&lt;br /&gt;
# Если min больше чем max, то поменять их местами.&lt;br /&gt;
if [ ${min} -gt ${max} ]; then&lt;br /&gt;
 # Поменять местами.&lt;br /&gt;
 x=${min}&lt;br /&gt;
 min=${max}&lt;br /&gt;
 max=${x}&lt;br /&gt;
fi&lt;br /&gt;
# Если min не делится без остатка на $divisibleBy,&lt;br /&gt;
# то привести его к ближайшему подходящему числу из заданного диапазона.&lt;br /&gt;
if [ $((min/divisibleBy*divisibleBy)) -ne ${min} ]; then&lt;br /&gt;
 if [ ${min} -lt 0 ]; then&lt;br /&gt;
  min=$((min/divisibleBy*divisibleBy))&lt;br /&gt;
 else&lt;br /&gt;
  min=$((((min/divisibleBy)+1)*divisibleBy))&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
# Если max не делится без остатка на $divisibleBy,&lt;br /&gt;
# то привести его к ближайшему подходящему числу из заданного диапазона.&lt;br /&gt;
if [ $((max/divisibleBy*divisibleBy)) -ne ${max} ]; then&lt;br /&gt;
 if [ ${max} -lt 0 ]; then&lt;br /&gt;
  max=$((((max/divisibleBy)-1)*divisibleBy))&lt;br /&gt;
 else&lt;br /&gt;
  max=$((max/divisibleBy*divisibleBy))&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
# ---------------------------------------------------------------------&lt;br /&gt;
# А теперь собственно нахождение псевдослучайного числа.&lt;br /&gt;
# Обратите внимание: чтобы получить псевдослучайное число в конце диапазона&lt;br /&gt;
# необходимо рассматривать диапазон от 0 до&lt;br /&gt;
# abs(max-min)+divisibleBy, а не abs(max-min)+1.&lt;br /&gt;
# Этим превышением верхней границы диапазона можно пренебречь&lt;br /&gt;
# поскольку эта новая граница никогда не будет достигнута.&lt;br /&gt;
&lt;br /&gt;
# Если использовать при вычислении формулу abs(max-min)+1,&lt;br /&gt;
# то будут получаться вполне корректные значения, но при этом,&lt;br /&gt;
# возвращаемые значения будут значительно ниже&lt;br /&gt;
# верхней границы диапазона.&lt;br /&gt;
# ---------------------------------------------------------------------&lt;br /&gt;
spread=$((max-min))&lt;br /&gt;
[ ${spread} -lt 0 ] &amp;amp;&amp;amp; spread=$((0-spread))&lt;br /&gt;
let spread+=divisibleBy&lt;br /&gt;
randomBetweenAnswer=$(((RANDOM%spread)/divisibleBy*divisibleBy+min))&lt;br /&gt;
return 0&lt;br /&gt;
}&lt;br /&gt;
# Проверка функции.&lt;br /&gt;
min=-14&lt;br /&gt;
max=20&lt;br /&gt;
divisibleBy=3&lt;br /&gt;
# Создадим массив, который будет содержать счетчики встречаемости каждого из чисел&lt;br /&gt;
# в заданном диапазоне.&lt;br /&gt;
declare -a answer&lt;br /&gt;
minimum=${min}&lt;br /&gt;
maximum=${max}&lt;br /&gt;
if [ $((minimum/divisibleBy*divisibleBy)) -ne ${minimum} ]; then&lt;br /&gt;
 if [ ${minimum} -lt 0 ]; then&lt;br /&gt;
  minimum=$((minimum/divisibleBy*divisibleBy))&lt;br /&gt;
 else&lt;br /&gt;
  minimum=$((((minimum/divisibleBy)+1)*divisibleBy))&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Если max не делится без остатка на $divisibleBy,&lt;br /&gt;
# то привести его к ближайшему подходящему числу из заданного диапазона.&lt;br /&gt;
if [ $((maximum/divisibleBy*divisibleBy)) -ne ${maximum} ]; then&lt;br /&gt;
 if [ ${maximum} -lt 0 ]; then&lt;br /&gt;
  maximum=$((((maximum/divisibleBy)-1)*divisibleBy))&lt;br /&gt;
 else&lt;br /&gt;
  maximum=$((maximum/divisibleBy*divisibleBy))&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Необходимое условие при работе с массивами —&lt;br /&gt;
# индекс массива должен быть положительным числом,&lt;br /&gt;
# поэтому введена дополнительная переменная displacement, которая&lt;br /&gt;
# гарантирует положительность индексов.&lt;br /&gt;
displacement=$((0-minimum))&lt;br /&gt;
for ((i=${minimum}; i&amp;lt;=${maximum}; i+=divisibleBy)); do&lt;br /&gt;
 answer[i+displacement]=0&lt;br /&gt;
done&lt;br /&gt;
# Цикл с большим количеством итераций, чтобы посмотреть - что мы получаем.&lt;br /&gt;
loopIt=1000 # Автор сценария предложил 100000 итераций,&lt;br /&gt;
            # но в этом случае цикл работает чересчур долго.&lt;br /&gt;
for ((i=0; i&amp;lt;${loopIt}; ++i)); do&lt;br /&gt;
# Обратите внимание: числа min и max передаются функции в обратном порядке,&lt;br /&gt;
# чтобы продемонстрировать, что функция обрабатывает их корректно.&lt;br /&gt;
 randomBetween ${max} ${min} ${divisibleBy}&lt;br /&gt;
# Вывод сообщения об ошибке, если функция вернула некорректное значение.&lt;br /&gt;
 [ ${randomBetweenAnswer} -lt ${min} -o ${randomBetweenAnswer} -gt ${max} ] &amp;amp;&amp;amp; echo \&lt;br /&gt;
 &amp;quot;Выход за границы диапазона MIN..MAX&amp;quot; - ${randomBetweenAnswer}!&lt;br /&gt;
 [ $((randomBetweenAnswer%${divisibleBy})) -ne 0 ] &amp;amp;&amp;amp; echo Число не делится на заданный делитель без остатка - ${randomBetweenAnswer}!&lt;br /&gt;
# Записать полученное число в массив.&lt;br /&gt;
 answer[randomBetweenAnswer+displacement]=$((answer[randomBetweenAnswer+displacement]+1))&lt;br /&gt;
done&lt;br /&gt;
# Проверим полученные результаты&lt;br /&gt;
for ((i=${minimum}; i&amp;lt;=${maximum}; i+=divisibleBy)); do&lt;br /&gt;
 [ ${answer[i+displacement]} -eq 0 ] &amp;amp;&amp;amp; echo &amp;quot;Число $i не было получено ни разу.&amp;quot; || echo \&lt;br /&gt;
 &amp;quot;Число ${i} встречено ${answer[i+displacement]} раз.&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Насколько случайны числа, возвращаемые функцией $RANDOM? Лучший способ оценить&amp;quot;случайность&amp;quot; генерируемых чисел — это написать сценарий, который будет имитировать бросание игрального кубика достаточно большое число раз, а затем выведет количество выпадений каждой из граней...&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Имитация бросания кубика с помощью RANDOM.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Случайные ли числа возвращает RANDOM?&lt;br /&gt;
RANDOM=$$ # Инициализация генератора случайных чисел числом PID процесса-сценария.&lt;br /&gt;
PIPS=6 # Кубик имеет 6 граней.&lt;br /&gt;
MAXTHROWS=600 # Можете увеличить, если не знаете куда девать свое время.&lt;br /&gt;
throw=0 # Счётчик бросков.&lt;br /&gt;
zeroes=0 # Обнулить счётчики выпадения отдельных граней.&lt;br /&gt;
ones=0 # т.к. неинициализированные переменные - &amp;quot;пустые&amp;quot;, и не равны нулю!.&lt;br /&gt;
twos=0&lt;br /&gt;
threes=0&lt;br /&gt;
fours=0&lt;br /&gt;
fives=0&lt;br /&gt;
sixes=0&lt;br /&gt;
&lt;br /&gt;
print_result ()&lt;br /&gt;
{&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;единиц = $ones&amp;quot;&lt;br /&gt;
 echo &amp;quot;двоек = $twos&amp;quot;&lt;br /&gt;
 echo &amp;quot;троек = $threes&amp;quot;&lt;br /&gt;
 echo &amp;quot;четвёрок = $fours&amp;quot;&lt;br /&gt;
 echo &amp;quot;пятёрок = $fives&amp;quot;&lt;br /&gt;
 echo &amp;quot;шестёрок = $sixes&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
update_count()&lt;br /&gt;
{&lt;br /&gt;
 case &amp;quot;$1&amp;quot; in&lt;br /&gt;
  0) let &amp;quot;ones += 1&amp;quot;;; # 0 соответствует грани &amp;quot;1&amp;quot;.&lt;br /&gt;
  1) let &amp;quot;twos += 1&amp;quot;;; # 1 соответствует грани &amp;quot;2&amp;quot;, и так далее&lt;br /&gt;
  2) let &amp;quot;threes += 1&amp;quot;;;&lt;br /&gt;
  3) let &amp;quot;fours += 1&amp;quot;;;&lt;br /&gt;
  4) let &amp;quot;fives += 1&amp;quot;;;&lt;br /&gt;
  5) let &amp;quot;sixes += 1&amp;quot;;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$throw&amp;quot; -lt &amp;quot;$MAXTHROWS&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 let &amp;quot;die1 = RANDOM % $PIPS&amp;quot;&lt;br /&gt;
 update_count $die1&lt;br /&gt;
 let &amp;quot;throw += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
print_result&lt;br /&gt;
# Количество выпадений каждой из граней должно быть примерно одинаковым, если считать RANDOM достаточно случайным.&lt;br /&gt;
# Для $MAXTHROWS = 600, каждая грань должна выпасть примерно 100 раз (плюс-минус 20).&lt;br /&gt;
#&lt;br /&gt;
# Имейте ввиду, что RANDOM - это генератор ПСЕВДОСЛУЧАЙНЫХ чисел,&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ---------------&lt;br /&gt;
# Перепишите этот сценарий так, чтобы он имитировал 1000 бросков монеты.&lt;br /&gt;
# Перепишите этот сценарий так, чтобы он имитировал 1000 бросков монеты.&lt;br /&gt;
# На каждом броске возможен один из двух вариантов выпадения — &amp;quot;ОРЁЛ&amp;quot; или &amp;quot;РЕШКА&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Как видно из последнего примера, неплохо было бы производить переустановку начального числа генератора случайных чисел RANDOM перед тем, как начать работу с ним. Если используется одно и тоже начальное число, то генератор RANDOM будет выдавать одну и ту же последовательность чисел.(Это совпадает с поведением функции random() в языке C.)&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Переустановка RANDOM.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# seeding-random.sh: Переустановка переменной RANDOM.&lt;br /&gt;
MAXCOUNT=25 # Длина генерируемой последовательности чисел.&lt;br /&gt;
&lt;br /&gt;
random_numbers ()&lt;br /&gt;
{&lt;br /&gt;
 count=0&lt;br /&gt;
 while [ &amp;quot;$count&amp;quot; -lt &amp;quot;$MAXCOUNT&amp;quot; ]&lt;br /&gt;
 do&lt;br /&gt;
  number=$RANDOM&lt;br /&gt;
  echo -n &amp;quot;$number &amp;quot;&lt;br /&gt;
  let &amp;quot;count += 1&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo; echo&lt;br /&gt;
RANDOM=1 # Переустановка начального числа генератора случайных чисел RANDOM.&lt;br /&gt;
random_numbers&lt;br /&gt;
echo; echo&lt;br /&gt;
RANDOM=1 # То же самое начальное число...&lt;br /&gt;
random_numbers # ...в результате получается та же последовательность чисел.&lt;br /&gt;
               # В каких случаях может оказаться полезной генерация совпадающих серий?&lt;br /&gt;
echo; echo&lt;br /&gt;
RANDOM=2 # Ещё одна попытка, но с другим начальным числом...&lt;br /&gt;
random_numbers # получим другую последовательность.&lt;br /&gt;
echo; echo&lt;br /&gt;
# RANDOM=$$ в качестве начального числа выбирается PID процесса-сценария.&lt;br /&gt;
# Вполне допустимо взять в качестве начального числа результат работы команд 'time' или 'date'.&lt;br /&gt;
# Немного воображения...&lt;br /&gt;
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }')&lt;br /&gt;
# Псевдослучайное число забирается&lt;br /&gt;
# из системного генератора псевдослучайных чисел /dev/urandom,&lt;br /&gt;
# затем конвертируется в восьмеричное число командой &amp;quot;od&amp;quot;,&lt;br /&gt;
# и наконец &amp;quot;awk&amp;quot; возвращает единственное число для переменной SEED.&lt;br /&gt;
RANDOM=$SEED&lt;br /&gt;
random_numbers&lt;br /&gt;
echo; echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Системный генератор ''/dev/urandom'' даёт последовательность псевдослучайных чисел с более равномерным распределением, чем $RANDOM. Команда ''[[dd]] if=/dev/urandom of=targetfile bs=1count=XX'' создаёт файл, содержащий последовательность псевдослучайных чисел. Однако, эти числа требуют дополнительной обработки, например с помощью команды [[od]] (этот приём используется в примере выше) или [[dd]]. Есть и другие способы генерации псевдослучайных последовательностей в сценариях. [[Awk]] имеет для этого достаточно удобные средства.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Получение псевдослучайных чисел с помощью awk.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# random2.sh: Генерация псевдослучайных чисел в диапазоне 0 - 1.&lt;br /&gt;
# Используется функция rand() из awk.&lt;br /&gt;
AWKSCRIPT=' { srand(); print rand() } '&lt;br /&gt;
# Команды/параметры, передаваемые awk&lt;br /&gt;
# Обратите внимание, функция srand() переустанавливает начальное число генератора случайных чисел&lt;br /&gt;
echo -n &amp;quot;Случайное число в диапазоне от 0 до 1 = &amp;quot;&lt;br /&gt;
echo | awk &amp;quot;$AWKSCRIPT&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ---------&lt;br /&gt;
# 1) С помощью оператора цикла выведите 10 различных случайных чисел.&lt;br /&gt;
# (Подсказка: вам потребуется вызвать функцию &amp;quot;srand()&amp;quot;&lt;br /&gt;
# в каждом цикле с разными начальными числами.&lt;br /&gt;
# Что произойдет, если этого не сделать?)&lt;br /&gt;
# 2) Заставьте сценарий генерировать случайные числа в диапазоне 10 - 100&lt;br /&gt;
# используя целочисленный множитель, как коэффициент масштабирования&lt;br /&gt;
# 3) То же самое, что и во втором упражнении,&lt;br /&gt;
# но на этот раз случайные числа должны быть целыми.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Кроме того, команда [[date]] так же может использоваться для генерации ''псевдослучайных целых чисел''.&lt;br /&gt;
Также при необходимости сгенерировать несколько целых чисел в shell-скрипте можно воспользоваться командой &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;shuf&amp;lt;/span&amp;gt;.&lt;br /&gt;
Следующая команда сгенерирует одно целое число в диапазоне от 100000 до 999999:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shuf -i 100000-999999 -n 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
После ключа '''-n''' может быть любое положительное число, задающее количество(!) генерируемых чисел.&lt;br /&gt;
&lt;br /&gt;
=== Двойные круглые скобки ===&lt;br /&gt;
Эта конструкция во многом похожа на инструкцию [[let]], внутри '''((...))''' вычисляются арифметические выражения и возвращается их результат. В простейшем случае, конструкция ''a=$(( 5 + 3 ))'' присвоит переменной &amp;quot;a&amp;quot; значение выражения &amp;quot;5 + 3&amp;quot;, или 8. Но, кроме того, двойные круглые скобки позволяют работать с переменными в стиле языка C.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Работа с переменными в стиле языка C.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
(( a = 23 )) # Присвоение переменной в стиле C, с обоих строн от &amp;quot;=&amp;quot; стоят пробелы.&lt;br /&gt;
echo &amp;quot;a (начальное значение) = $a&amp;quot;&lt;br /&gt;
(( a++ )) # Пост-инкремент 'a', в стиле C.&lt;br /&gt;
echo &amp;quot;a (после a++) = $a&amp;quot;&lt;br /&gt;
(( a-- )) # Пост-декремент 'a', в стиле C.&lt;br /&gt;
echo &amp;quot;a (после a--) = $a&amp;quot;&lt;br /&gt;
(( ++a )) # Пред-инкремент 'a', в стиле C.&lt;br /&gt;
echo &amp;quot;a (после ++a) = $a&amp;quot;&lt;br /&gt;
(( --a )) # Пред-декремент 'a', в стиле C.&lt;br /&gt;
echo &amp;quot;a (после --a) = $a&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
(( t = a&amp;lt;45?7:11 )) # Трехместный оператор в стиле языка C.&lt;br /&gt;
echo &amp;quot;If a &amp;lt; 45, then t = 7, else t = 11.&amp;quot;&lt;br /&gt;
echo &amp;quot;t = $t &amp;quot; # Да!&lt;br /&gt;
echo# См. так же описание ((...)) в циклах &amp;quot;for&amp;quot; и &amp;quot;while&amp;quot;.&lt;br /&gt;
# Эта конструкция доступна в Bash, начиная с версии 2.04.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Циклы и ветвления ==&lt;br /&gt;
Управление ходом исполнения — один из ключевых моментов структурной организации сценариев на языке командной оболочки. Циклы и переходы являются теми инструментальными средствами, которые обеспечивают управление порядком исполнения команд.&lt;br /&gt;
=== Циклы ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;''Цикл''&amp;lt;/span&amp;gt; — это блок команд, который исполняется многократно до тех пор, пока не будет выполнено условие выхода из цикла.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''Циклы for'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''for (in)'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Это одна из основных разновидностей циклов. И она значительно отличается от аналога в языке C.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 for arg in [list]&lt;br /&gt;
 do &lt;br /&gt;
  команда(ы)...&lt;br /&gt;
 done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
На каждом проходе цикла, переменная-аргумент цикла ''arg'' последовательно,одно за другим, принимает значения из списка ''list''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
for arg in &amp;quot;$var1&amp;quot; &amp;quot;$var2&amp;quot; &amp;quot;$var3&amp;quot; ... &amp;quot;$varN&amp;quot;&lt;br /&gt;
# На первом проходе, $arg = $var1&lt;br /&gt;
# На втором проходе, $arg = $var2&lt;br /&gt;
# На третьем проходе, $arg = $var3&lt;br /&gt;
# ...&lt;br /&gt;
# На N-ном проходе, $arg = $varN&lt;br /&gt;
# Элементы списка заключены в кавычки для того, чтобы предотвратить возможное разбиение их на отдельные аргументы (слова).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Элементы списка могут включать в себя шаблонные символы. Если ключевое слово '''do''' находится в одной строке со словом '''for''', то после списка аргументов(перед '''do''') необходимо ставить точку с запятой.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
for arg in [list] ; do&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простой цикл for.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Список планет.&lt;br /&gt;
for planet in Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун Плутон&lt;br /&gt;
do&lt;br /&gt;
 echo $planet&lt;br /&gt;
done&lt;br /&gt;
echo # Если 'список аргументов' заключить в кавычки, то он будет восприниматься как единственный аргумент.&lt;br /&gt;
for planet in &amp;quot;Меркурий Венера Земля Марс Юпитер Сатурн Уран Нептун Плутон&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
 echo $planet&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Каждый из элементов [списка] может содержать несколько аргументов. Это бывает полезным при обработке групп параметров. В этом случае, для принудительного разбора каждого из аргументов в списке, необходимо использовать инструкцию ''set''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Цикл for с двумя параметрами в каждом из элементов списка.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Список планет.&lt;br /&gt;
# Имя каждой планеты ассоциировано с расстоянием от планеты до Солнца (млн. миль).&lt;br /&gt;
for planet in &amp;quot;Меркурий 36&amp;quot; &amp;quot;Венера 67&amp;quot; &amp;quot;Земля 93&amp;quot; &amp;quot;Марс 142&amp;quot; &amp;quot;Юпитер 483&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
 set -- $planet # Разбиение переменной &amp;quot;planet&amp;quot; на множество аргументов (позиционных параметров).&lt;br /&gt;
# Конструкция &amp;quot;--&amp;quot; предохраняет от неожиданностей, если $planet &amp;quot;пуста&amp;quot; или начинается с символа &amp;quot;-&amp;quot;.&lt;br /&gt;
# Если каждый из аргументов потребуется сохранить, поскольку на следующем проходе они будут &amp;quot;забиты&amp;quot; новыми значениями,&lt;br /&gt;
# То можно поместить их в массив,&lt;br /&gt;
# original_params=(&amp;quot;$@&amp;quot;)&lt;br /&gt;
echo &amp;quot;$1 в $2,000,000 миль от Солнца&amp;quot;&lt;br /&gt;
#----две табуляции---к параметру $2 добавлены нули&lt;br /&gt;
done&lt;br /&gt;
#(Спасибо S.C., за разъяснения.)&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В качестве списка, в цикле ''for'', можно использовать переменную.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Fileinfo: обработка списка файлов, находящегося в переменной.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# fileinfo.sh&lt;br /&gt;
FILES=&amp;quot;/usr/sbin/privatepw&lt;br /&gt;
/usr/sbin/pwck&lt;br /&gt;
/usr/sbin/go500gw&lt;br /&gt;
/usr/bin/fakefile&lt;br /&gt;
/sbin/mkreiserfs&lt;br /&gt;
/sbin/ypbind&amp;quot; # Список интересующих нас файлов.&lt;br /&gt;
              # В список добавлен фиктивный файл /usr/bin/fakefile.&lt;br /&gt;
echo&lt;br /&gt;
for file in $FILES&lt;br /&gt;
do&lt;br /&gt;
 if [ ! -e &amp;quot;$file&amp;quot; ] # Проверка наличия файла.&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Файл $file не найден.&amp;quot;; echo&lt;br /&gt;
  continue # Переход к следующей итерации.&lt;br /&gt;
 fi&lt;br /&gt;
 ls -l $file | awk '{ print $8 &amp;quot; размер: &amp;quot; $5 }' # Печать 2 полей.&lt;br /&gt;
 whatis `basename $file` # Информация о файле.&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В [списке] цикла ''for'' могут быть использованы имена файлов, которые в свою очередь могут содержать символы-шаблоны.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Обработка списка файлов в цикле for.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# list-glob.sh: Создание список файлов в цикле for с использованием&lt;br /&gt;
# операции подстановки имён файлов (&amp;quot;globbing&amp;quot;).&lt;br /&gt;
echo&lt;br /&gt;
for file in *&lt;br /&gt;
do&lt;br /&gt;
 ls -l &amp;quot;$file&amp;quot; # Список всех файлов в $PWD (текущем каталоге).&lt;br /&gt;
 # Напоминаю, что символу &amp;quot;*&amp;quot; соответствует любое имя файла,&lt;br /&gt;
 # однако, в операциях подстановки имён файлов (&amp;quot;globbing&amp;quot;),&lt;br /&gt;
 # имеются исключения — имена файлов, начинающиеся с точки.&lt;br /&gt;
 # Если в каталоге нет ни одного файла, соответствующего шаблону,&lt;br /&gt;
 # то за имя файла принимается сам шаблон.&lt;br /&gt;
 # Чтобы избежать этого, используйте ключ nullglob&lt;br /&gt;
 # (shopt -s nullglob).&lt;br /&gt;
 # Спасибо S.C.&lt;br /&gt;
done&lt;br /&gt;
echo; echo&lt;br /&gt;
for file in [jx]*&lt;br /&gt;
do&lt;br /&gt;
 rm -f $file # Удаление файлов, начинающихся с &amp;quot;j&amp;quot; или &amp;quot;x&amp;quot; в $PWD.&lt;br /&gt;
 echo &amp;quot;Удален файл \&amp;quot;$file\&amp;quot;&amp;quot;.&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если [список] в цикле ''for'' не задан, то в качестве оного используется переменная '''$@''' — список аргументов командной строки.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Цикл for без списка аргументов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Попробуйте вызвать этот сценарий с аргументами и без них и посмотреть на результаты.&lt;br /&gt;
for a &lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done # Список аргументов не задан, поэтому цикл работает с переменной '$@'&lt;br /&gt;
# (список аргументов командной строки, включая пробельные символы).&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При создании списка аргументов, в цикле ''for'' допускается пользоваться подстановкой команд.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание списка аргументов в цикле for с помощью операции подстановки команд.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Цикл for со [списком], созданным с помощью подстановки команд.&lt;br /&gt;
NUMBERS=&amp;quot;9 7 3 8 37.53&amp;quot;&lt;br /&gt;
for number in `echo $NUMBERS` # for number in 9 7 3 8 37.53\&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$number &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Более сложный пример использования подстановки команд при создании списка аргументов цикла.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''grep для бинарных файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# bin-grep.sh: Поиск строк в двоичных файлах.&lt;br /&gt;
# замена &amp;quot;grep&amp;quot; для бинарных файлов.&lt;br /&gt;
# Аналогично команде &amp;quot;grep -a&amp;quot;&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
E_NOFILE=66if [ $# -ne 2 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` string filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ ! -f &amp;quot;$2&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$2\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOFILE&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
for word in $( strings &amp;quot;$2&amp;quot; | grep &amp;quot;$1&amp;quot; )&lt;br /&gt;
# Инструкция &amp;quot;strings&amp;quot; возвращает список строк в двоичных файлах.&lt;br /&gt;
# Который затем передается по конвейеру команде &amp;quot;grep&amp;quot;, для выполнения поиска.&lt;br /&gt;
do&lt;br /&gt;
 echo $word&lt;br /&gt;
done&lt;br /&gt;
# Как указывает S.C., вышеприведённое объявление цикла for может быть упрощено&lt;br /&gt;
# strings &amp;quot;$2&amp;quot; | grep &amp;quot;$1&amp;quot; | tr -s &amp;quot;$IFS&amp;quot; '[\n*]'&lt;br /&gt;
# Попробуйте что нибудь подобное: &amp;quot;./bin-grep.sh mem /bin/ls&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ещё один пример.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Список всех пользователей системы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# userlist.sh&lt;br /&gt;
PASSWORD_FILE=/etc/passwd&lt;br /&gt;
n=1 # Число пользователей&lt;br /&gt;
for name in $(awk 'BEGIN{FS=&amp;quot;:&amp;quot;}{print $1}' &amp;lt; &amp;quot;$PASSWORD_FILE&amp;quot; )&lt;br /&gt;
# Разделитель полей = :  ^^^^^^&lt;br /&gt;
# Вывод первого поля             ^^^^^^^^&lt;br /&gt;
# Данные берутся из файла паролей             ^^^^^^^^^^^^^^^^^&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Пользователь #$n = $name&amp;quot;&lt;br /&gt;
 let &amp;quot;n += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# Пользователь #1 = root&lt;br /&gt;
# Пользователь #2 = bin&lt;br /&gt;
# Пользователь #3 = daemon&lt;br /&gt;
# ...&lt;br /&gt;
# Пользователь #30 = bozo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
И заключительный пример использования подстановки команд при создании [списка].&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка авторства всех бинарных файлов в текущем каталоге.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# findstring.sh:&lt;br /&gt;
# Поиск заданной строки в двоичном файле.&lt;br /&gt;
directory=/usr/local/bin/&lt;br /&gt;
fstring=&amp;quot;Free Software Foundation&amp;quot; # Поиск файлов от FSF.&lt;br /&gt;
for file in $( find $directory -type f -name '*' | sort )&lt;br /&gt;
do&lt;br /&gt;
 strings -f $file | grep &amp;quot;$fstring&amp;quot; | sed -e &amp;quot;s%$directory%%&amp;quot;&lt;br /&gt;
 # Команде &amp;quot;sed&amp;quot; передается выражение (ключ -e),&lt;br /&gt;
 # для того, чтобы изменить обычный разделитель &amp;quot;/&amp;quot; строки поиска и строки замены&lt;br /&gt;
 # поскольку &amp;quot;/&amp;quot; - один из отфильтровываемых символов.&lt;br /&gt;
 # Использование такого символа порождает сообщение об ошибке (попробуйте).&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ---------------&lt;br /&gt;
# Измените сценарий таким образом, чтобы он брал&lt;br /&gt;
# $directory и $fstring из командной строки.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Результат работы цикла ''for'' может передаваться другим командам по конвейеру.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Список символических ссылок в каталоге.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# symlinks.sh: Список символических ссылок в каталоге.&lt;br /&gt;
&lt;br /&gt;
directory=${1-`pwd`}&lt;br /&gt;
# По-умолчанию в текущем каталоге,&lt;br /&gt;
# Блок кода, который выполняет аналогичные действия.&lt;br /&gt;
# ----------------------------------------------------------&lt;br /&gt;
# ARGS=1 # Ожидается один аргумент командной строки.&lt;br /&gt;
# if [ $# -ne &amp;quot;$ARGS&amp;quot; ] # Если каталог поиска не задан...&lt;br /&gt;
# then&lt;br /&gt;
# directory=`pwd` &lt;br /&gt;
# текущий каталог&lt;br /&gt;
# else&lt;br /&gt;
# directory=$1&lt;br /&gt;
# fi&lt;br /&gt;
# ----------------------------------------------------------&lt;br /&gt;
echo &amp;quot;символические ссылки в каталоге \&amp;quot;$directory\&amp;quot;&amp;quot;&lt;br /&gt;
for file in &amp;quot;$( find $directory -type l )&amp;quot;         # -type l = символические ссылки&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$file&amp;quot;&lt;br /&gt;
done | sort                                        # В противном случае получится неотсортированный список.&lt;br /&gt;
# Как отмечает Dominik 'Aeneas' Schnitzer,&lt;br /&gt;
# в случае отсутствия кавычек для $( find $directory -type l )&lt;br /&gt;
# сценарий &amp;quot;подавится&amp;quot; именами файлов, содержащими пробелы.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Вывод цикла может быть перенаправлен с ''stdout'' в файл, ниже приводится немного модифицированный вариант предыдущего примера, демонстрирующий эту возможность.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Список символических ссылок в каталоге, сохраняемый в файле.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# symlinks.sh: Список символических ссылок в каталоге.&lt;br /&gt;
OUTFILE=symlinks.list &lt;br /&gt;
# файл со списком&lt;br /&gt;
directory=${1-`pwd`}&lt;br /&gt;
# По-умолчанию — текущий каталог,&lt;br /&gt;
echo &amp;quot;символические ссылки в каталоге \&amp;quot;$directory\&amp;quot;&amp;quot; &amp;gt; &amp;quot;$OUTFILE&amp;quot;&lt;br /&gt;
echo &amp;quot;---------------------------&amp;quot; &amp;gt;&amp;gt; &amp;quot;$OUTFILE&amp;quot;&lt;br /&gt;
for file in &amp;quot;$( find $directory -type l )&amp;quot; # -type l = символические ссылки&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$file&amp;quot;&lt;br /&gt;
done | sort &amp;gt;&amp;gt; &amp;quot;$OUTFILE&amp;quot;    #  перенаправление вывода&lt;br /&gt;
#            ^^^^^^^^^^^^^      в файл.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Оператор цикла ''for'' имеет и альтернативный синтаксис записи — очень похожий на синтаксис оператора ''for'' в языке C. Для этого используются двойные круглые скобки.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''C-подобный синтаксис оператора цикла for.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Два варианта оформления цикла.&lt;br /&gt;
echo&lt;br /&gt;
# Стандартный синтаксис.&lt;br /&gt;
for a in 1 2 3 4 5 6 7 8 9 10&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo; echo&lt;br /&gt;
# +==========================================+&lt;br /&gt;
# А теперь C-подобный синтаксис.&lt;br /&gt;
LIMIT=10&lt;br /&gt;
for ((a=1; a &amp;lt;= LIMIT ; a++)) # Двойные круглые скобки и &amp;quot;LIMIT&amp;quot; без &amp;quot;$&amp;quot;.&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done                          # Конструкция заимствована из 'ksh93'.&lt;br /&gt;
echo; echo&lt;br /&gt;
# +=========================================================================+&lt;br /&gt;
# Попробуем и C-шный оператор &amp;quot;запятая&amp;quot;.&lt;br /&gt;
for ((a=1, b=1; a &amp;lt;= LIMIT ; a++, b++)) # Запятая разделяет две операции, которые выполняются совместно.&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a-$b &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo; echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
А сейчас пример сценария, который может найти &amp;quot;реальное&amp;quot; применение.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Работа с командой efax в пакетном режиме.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
EXPECTED_ARGS=2&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
if [ $# -ne $EXPECTED_ARGS ]&lt;br /&gt;
# Проверка наличия аргументов командной строки.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` phone# text-file&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ ! -f &amp;quot;$2&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл $2 не является текстовым файлом&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
fax make $2             # Создать fax-файлы из текстовых файлов.&lt;br /&gt;
for file in $(ls $2.0*) # Все файлы, получившиеся в результате преобразования.&lt;br /&gt;
                        # Используется шаблонный символ в списке.&lt;br /&gt;
do&lt;br /&gt;
 fil=&amp;quot;$fil $file&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
efax -d /dev/ttyS3 -o1 -t &amp;quot;T$1&amp;quot; $fil # отправить.&lt;br /&gt;
# Как указывает S.C., в цикл for может быть вставлена сама команда отправки в виде:&lt;br /&gt;
# efax -d /dev/ttyS3 -o1 -t &amp;quot;T$1&amp;quot; $2.0*&lt;br /&gt;
# но это не так поучительно [;-)].&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''Циклы while'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''while'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Оператор ''while'' проверяет условие перед началом каждой итерации и если условие истинно(если код возврата равен 0), то управление передаётся в тело цикла. В отличие от циклов ''for'', циклы ''while'' используются в тех случаях, когда количество итераций заранее не известно.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
while [condition]&lt;br /&gt;
do&lt;br /&gt;
 command...&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Как и в случае с циклами ''for/in'', при размещении ключевого слова ''do'' в одной строке с объявлением цикла, необходимо вставлять символ &amp;quot;;&amp;quot; перед ''do''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt; while [condition] ; do&amp;lt;/source&amp;gt;&lt;br /&gt;
Обратите внимание: в отдельных случаях, таких как использование конструкции ''getopts'' совместно с оператором ''while'', синтаксис несколько отличается от приводимого здесь.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простой цикл while.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
var0=0&lt;br /&gt;
LIMIT=10&lt;br /&gt;
while [ &amp;quot;$var0&amp;quot; -lt &amp;quot;$LIMIT&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$var0 &amp;quot; # -n подавляет перевод строки.&lt;br /&gt;
 var0=`expr $var0 + 1` # допускается var0=$(($var0+1)).&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Другой пример цикла while.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$var1&amp;quot; != &amp;quot;end&amp;quot; ] # возможна замена на while test &amp;quot;$var1&amp;quot; != &amp;quot;end&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Введите значение переменной #1 (end - выход) &amp;quot;&lt;br /&gt;
 read var1 # Конструкция 'read $var1' недопустима (почему?).&lt;br /&gt;
 echo &amp;quot;переменная #1 = $var1&amp;quot; # кавычки обязательны, потому что имеется символ &amp;quot;#&amp;quot;.&lt;br /&gt;
 # Если введено слово 'end', то оно тоже выводится на экран.&lt;br /&gt;
 # потому, что проверка переменной выполняется в начале итерации (перед вводом).&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Оператор ''while'' может иметь несколько условий. Но только последнее из них определяет возможность продолжения цикла. В этом случае синтаксис оператора цикла должен быть несколько иным.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Цикл while с несколькими условиями.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
var1=unset&lt;br /&gt;
previous=$var1&lt;br /&gt;
while echo &amp;quot;предыдущее значение = $previous&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
 previous=$var1 # запомнить предыдущее значение&lt;br /&gt;
 [ &amp;quot;$var1&amp;quot; != end ]&lt;br /&gt;
 # В операторе &amp;quot;while&amp;quot; присутствуют 4 условия, но только последнее управляет циклом.&lt;br /&gt;
 # *последнее* условие - единственное, которое вычисляется.&lt;br /&gt;
do&lt;br /&gt;
echo &amp;quot;Введите значение переменной #1 (end - выход) &amp;quot;&lt;br /&gt;
 read var1&lt;br /&gt;
 echo &amp;quot;текущее значение = $var1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# попробуйте самостоятельно разобраться в сценарии works.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Как и в случае с ''for'', цикл ''while'' может быть записан в C-подобной нотации, с использованием двойных круглых скобок.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''C-подобный синтаксис оформления цикла while.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# wh-loopc.sh: Цикл перебора от 1 до 10.&lt;br /&gt;
LIMIT=10&lt;br /&gt;
a=1&lt;br /&gt;
while [ &amp;quot;$a&amp;quot; -le $LIMIT ]&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
 let &amp;quot;a+=1&amp;quot;&lt;br /&gt;
done # Пока ничего особенного.&lt;br /&gt;
echo; echo&lt;br /&gt;
# +=================================================================+&lt;br /&gt;
# А теперь оформим в стиле языка C.&lt;br /&gt;
((a = 1)) # a=1&lt;br /&gt;
# Двойные скобки допускают наличие лишних пробелов в выражениях.&lt;br /&gt;
while (( a &amp;lt;= LIMIT )) # В двойных скобках символ &amp;quot;$&amp;quot; перед переменными опускается.&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
 ((a += 1)) # let &amp;quot;a+=1&amp;quot;&lt;br /&gt;
# Двойные скобки позволяют наращивание переменной в стиле языка C.&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
# Теперь, программисты, пишущие на C, могут чувствовать себя в Bash как дома.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Стандартное устройство ввода ''stdin'', для цикла ''while'', можно перенаправить на файл с помощью команды перенаправления '''''&amp;lt;''''' в конце цикла.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''Циклы until'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''until'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Оператор цикла ''until'' проверяет условие в начале каждой итерации, но в отличие от ''while'' итерация возможна только в том случае, если условие ложно.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
until [condition-is-true]&lt;br /&gt;
do &lt;br /&gt;
 command...&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Обратите внимание: оператор ''until'' проверяет условие завершения цикла '''''ПЕРЕД''''' очередной итерацией, а не после, как это принято в некоторых языках программирования.&lt;br /&gt;
Как и в случае с циклами ''for/in'', при размещении ключевого слова ''do'' в одной строке с объявлением цикла, необходимо вставлять символ &amp;quot;;&amp;quot; перед ''do''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;until [condition-is-true] ; do&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Цикл until.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
until [ &amp;quot;$var1&amp;quot; = end ] # Проверка условия производится в начале итерации.&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Введите значение переменной #1 &amp;quot;&lt;br /&gt;
 echo &amp;quot;(end - выход)&amp;quot;&lt;br /&gt;
 read var1&lt;br /&gt;
 echo &amp;quot;значение переменной #1 = $var1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Вложенные циклы ===&lt;br /&gt;
Цикл называется вложенным, если он размещается внутри другого цикла. На первом проходе, внешний цикл вызывает внутренний, который исполняется до своего завершения, после чего управление передаётся в тело внешнего цикла. На втором проходе внешний цикл опять вызывает внутренний. И так до тех пор, пока не завершится внешний цикл. Само собой, как внешний, так и внутренний циклы могут быть прерваны командой ''break''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вложенный цикл'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Вложенные циклы &amp;quot;for&amp;quot;.&lt;br /&gt;
outer=1 # Счетчик внешнего цикла.&lt;br /&gt;
# Начало внешнего цикла.&lt;br /&gt;
for a in 1 2 3 4 5&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Итерация #$outer внешнего цикла.&amp;quot;&lt;br /&gt;
 echo &amp;quot;---------------------&amp;quot;&lt;br /&gt;
 inner=1 # Сброс счетчика вложенного цикла.&lt;br /&gt;
# Начало вложенного цикла.&lt;br /&gt;
 for b in 1 2 3 4 5&lt;br /&gt;
 do&lt;br /&gt;
  echo &amp;quot;Итерация #$inner вложенного цикла.&amp;quot;&lt;br /&gt;
  let &amp;quot;inner+=1&amp;quot; # Увеличить счетчик итераций вложенного цикла.&lt;br /&gt;
 done&lt;br /&gt;
# Конец вложенного цикла.&lt;br /&gt;
 let &amp;quot;outer+=1&amp;quot; # Увеличить счетчик итераций внешнего цикла.&lt;br /&gt;
 echo # Пустая строка для отделения итераций внешнего цикла.&lt;br /&gt;
done&lt;br /&gt;
# Конец внешнего цикла.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Управление ходом выполнения цикла ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''break, continue'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для управления ходом выполнения цикла служат команды ''break'' и ''continue''и точно соответствуют своим аналогам в других языках программирования. Команда ''break'' прерывает &lt;br /&gt;
исполнение цикла, в то время как ''continue'' передает управление в начало цикло, минуя все последующие команды в теле цикла.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Команды break и continue в цикле.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
LIMIT=19 # Верхний предел&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Печать чисел от 1 до 20 (исключая 3 и 11).&amp;quot;&lt;br /&gt;
a=0&lt;br /&gt;
while [ $a -le &amp;quot;$LIMIT&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 a=$(($a+1))&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -eq 3 ] || [ &amp;quot;$a&amp;quot; -eq 11 ] # Исключить 3 и 11&lt;br /&gt;
 then&lt;br /&gt;
  continue # Переход в начало цикла.&lt;br /&gt;
 fi&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# Почему число 20 тоже выводится?&lt;br /&gt;
echo; echo&lt;br /&gt;
echo Печать чисел от 1 до 20, но взгляните, что происходит после вывода числа 2&lt;br /&gt;
##################################################################&lt;br /&gt;
# Тот же цикл, только 'continue' заменено на 'break'.&lt;br /&gt;
a=0&lt;br /&gt;
while [ &amp;quot;$a&amp;quot; -le &amp;quot;$LIMIT&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 a=$(($a+1))&lt;br /&gt;
 if [ &amp;quot;$a&amp;quot; -gt 2 ]&lt;br /&gt;
 then&lt;br /&gt;
  break # Завершение работы цикла.&lt;br /&gt;
 fi&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo; echo; echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команде ''break'' может быть передан необязательный параметр. Команда ''break'' без параметра прерывает тот цикл, в который она вставлена, а ''break N'' прерывает цикл, стоящий на N уровней выше (причем 1-й уровень — это уровень текущего цикла, прим. перев.).&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Прерывание многоуровневых циклов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# break-levels.sh: Прерывание циклов.&lt;br /&gt;
# &amp;quot;break N&amp;quot; прерывает исполнение цикла, стоящего на N уровней выше текущего.&lt;br /&gt;
for outerloop in 1 2 3 4 5&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;Группа $outerloop: &amp;quot;&lt;br /&gt;
 for innerloop in 1 2 3 4 5&lt;br /&gt;
 do&lt;br /&gt;
  echo -n &amp;quot;$innerloop &amp;quot;&lt;br /&gt;
  if [ &amp;quot;$innerloop&amp;quot; -eq 3 ]&lt;br /&gt;
  then&lt;br /&gt;
   break # Попробуйте &amp;quot;break 2&amp;quot;,&lt;br /&gt;
         # тогда будут прерываться как вложенный, так и внешний циклы&lt;br /&gt;
  fi&lt;br /&gt;
 done&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда ''continue'', как и команда ''break'', может иметь необязательный параметр. В простейшем случае, команда ''continue'' передаёт управление в начало текущего цикла, а команда ''continue N'' прерывает исполнение текущего цикла и передаёт управление в начало внешнего цикла, отстоящего от текущего на N уровней (причем 1-й уровень — это уровень текущего цикла,прим. перев.).&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача управления в начало внешнего цикла.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Команда &amp;quot;continue N&amp;quot; передаёт управление в начало внешнего цикла, отстоящего от текущего на N уровней.&lt;br /&gt;
for outer in I II III IV V # внешний цикл&lt;br /&gt;
do&lt;br /&gt;
 echo; echo -n &amp;quot;Группа $outer: &amp;quot;&lt;br /&gt;
 for inner in 1 2 3 4 5 6 7 8 9 10 # вложенный цикл&lt;br /&gt;
 do&lt;br /&gt;
  if [ &amp;quot;$inner&amp;quot; -eq 7 ]&lt;br /&gt;
  then&lt;br /&gt;
   continue 2 # Передача управления в начало цикла 2-го уровня.&lt;br /&gt;
              # попробуйте убрать параметр 2 команды &amp;quot;continue&amp;quot;&lt;br /&gt;
  fi&lt;br /&gt;
  echo -n &amp;quot;$inner &amp;quot; # 8 9 10 никогда не будут напечатаны.&lt;br /&gt;
 done&lt;br /&gt;
done&lt;br /&gt;
echo; echo&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# Подумайте, где реально можно использовать &amp;quot;continue N&amp;quot; в сценариях.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Живой пример использования &amp;quot;continue N&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Albert Reiner привёл пример использования &amp;quot;continue N&amp;quot;:&lt;br /&gt;
# ---------------------------------------------------------&lt;br /&gt;
# Допустим, у меня есть большое количество задач, обрабатывающие некоторые данные,&lt;br /&gt;
# которые хранятся в некоторых файлах, с именами, задаваемыми по шаблону,&lt;br /&gt;
# в заданном каталоге.&lt;br /&gt;
# Есть несколько машин, которым открыт доступ к этому каталогу&lt;br /&gt;
# и я хочу распределить обработку информации между машинами.&lt;br /&gt;
# тогда я обычно для каждой машины пишу нечто подобное:&lt;br /&gt;
while true&lt;br /&gt;
do&lt;br /&gt;
 for n in .iso.*&lt;br /&gt;
 do&lt;br /&gt;
  [ &amp;quot;$n&amp;quot; = &amp;quot;.iso.opts&amp;quot; ] &amp;amp;&amp;amp; continue&lt;br /&gt;
  beta=${n#.iso.}&lt;br /&gt;
  [ -r .Iso.$beta ] &amp;amp;&amp;amp; continue&lt;br /&gt;
  [ -r .lock.$beta ] &amp;amp;&amp;amp; sleep 10 &amp;amp;&amp;amp; continue&lt;br /&gt;
  lockfile -r0 .lock.$beta || continue&lt;br /&gt;
  echo -n &amp;quot;$beta: &amp;quot; `date`&lt;br /&gt;
  run-isotherm $beta&lt;br /&gt;
  date&lt;br /&gt;
  ls -alF .Iso.$beta&lt;br /&gt;
  [ -r .Iso.$beta ] &amp;amp;&amp;amp; rm -f .lock.$beta&lt;br /&gt;
  continue 2&lt;br /&gt;
 done&lt;br /&gt;
 break&lt;br /&gt;
done&lt;br /&gt;
# Конкретная реализация цикла, особенно sleep N, зависит от конкретных применений,&lt;br /&gt;
# но в общем случае он строится по такой схеме:&lt;br /&gt;
while true&lt;br /&gt;
do&lt;br /&gt;
 for job in {шаблон}&lt;br /&gt;
 do&lt;br /&gt;
  {файл уже обработан или обрабатывается} &amp;amp;&amp;amp; continue&lt;br /&gt;
  {пометить файл как обрабатываемый, обработать, пометить как обработанный}&lt;br /&gt;
  continue 2&lt;br /&gt;
 done&lt;br /&gt;
 break # Или что нибудь подобное `sleep 600', чтобы избежать завершения.&lt;br /&gt;
done&lt;br /&gt;
# Этот сценарий завершит работу после того как все данные будут обработаны&lt;br /&gt;
# (включая данные, которые поступили во время обработки). Использование&lt;br /&gt;
# соответствующих lock-файлов позволяет вести обработку на нескольких машинах&lt;br /&gt;
# одновременно, не производя дублирующих вычислений [которые, в моем случае,&lt;br /&gt;
# выполняются в течении нескольких часов, так что для меня это очень важно].&lt;br /&gt;
# Кроме того, поскольку поиск необработанных файлов всегда начинается с&lt;br /&gt;
# самого начала, можно задавать приоритеты в именах файлов. Конечно, можно&lt;br /&gt;
# обойтись и без `continue 2', но тогда придется ввести дополнительную&lt;br /&gt;
# проверку — действительно ли был обработан тот или иной файл&lt;br /&gt;
# (чтобы перейти к поиску следующего необработанного файла).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Конструкция ''continue N'' довольно сложна в понимании и применении, поэтому, вероятно лучше будет постараться избегать её использования.&lt;br /&gt;
&lt;br /&gt;
=== Операторы выбора ===&lt;br /&gt;
Инструкции ''case'' и ''select'' технически не являются циклами, поскольку не предусматривают многократное исполнение блока кода. Однако, они, как и циклы, управляют ходом исполнения программы, в зависимости от начальных или конечных условий.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''case (in) / esac'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конструкция ''case'' эквивалентна конструкции ''switch'' в языке C/C++. Она позволяет выполнять тот или иной участок кода, в зависимости от результатов проверки условий. Она является, своего рода, краткой формой записи большого количества операторов ''if/then/else'' и может быть неплохим инструментом при создании разного рода меню.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
case &amp;quot;$variable&amp;quot; in&lt;br /&gt;
&amp;quot;$condition1&amp;quot; )&lt;br /&gt;
 command...&lt;br /&gt;
;;&lt;br /&gt;
&amp;quot;$condition2&amp;quot; )&lt;br /&gt;
 command...&lt;br /&gt;
;;&lt;br /&gt;
esac&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Заключать переменные в кавычки необязательно, поскольку здесь не производится разбиения на отдельные слова.&lt;br /&gt;
* Каждая строка с условием должна завершаться правой (закрывающей)круглой скобкой — &amp;lt;big&amp;gt;''')'''&amp;lt;/big&amp;gt;.&lt;br /&gt;
* Каждый блок команд, отрабатывающих по заданному условию, должен завершаться двумя символами точка-с-запятой — &amp;lt;big&amp;gt;''';;'''&amp;lt;/big&amp;gt;.&lt;br /&gt;
* Блок ''case'' должен завершаться ключевым словом ''esac'' (''case'' записанное в обратном порядке).&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование case.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo; echo &amp;quot;Нажмите клавишу и затем клавишу Return.&amp;quot;&lt;br /&gt;
read Keypress&lt;br /&gt;
case &amp;quot;$Keypress&amp;quot; in&lt;br /&gt;
 [a-z] ) echo &amp;quot;буква в нижнем регистре&amp;quot;;;&lt;br /&gt;
 [A-Z] ) echo &amp;quot;Буква в верхнем регистре&amp;quot;;;&lt;br /&gt;
 [0-9] ) echo &amp;quot;Цифра&amp;quot;;;&lt;br /&gt;
     * ) echo &amp;quot;Знак пунктуации, пробел или что-то другое&amp;quot;;;&lt;br /&gt;
esac # Допускается указывать диапазоны символов в [квадратных скобках].&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Сейчас сценарий считывает нажатую клавишу и завершается.&lt;br /&gt;
# Измените его так, чтобы сценарий продолжал отвечать на нажатия клавиш,&lt;br /&gt;
# но завершался бы только после ввода символа &amp;quot;X&amp;quot;.&lt;br /&gt;
# Подсказка: заключите всё в цикл &amp;quot;while&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание меню с помощью case.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Грубый пример базы данных&lt;br /&gt;
clear # Очистка экрана&lt;br /&gt;
echo &amp;quot;          Список&amp;quot;&lt;br /&gt;
echo &amp;quot;          ------&amp;quot;&lt;br /&gt;
echo &amp;quot;Выберите интересующую Вас персону:&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;[E]vans, Roland&amp;quot;&lt;br /&gt;
echo &amp;quot;[J]ones, Mildred&amp;quot;&lt;br /&gt;
echo &amp;quot;[S]mith, Julie&amp;quot;&lt;br /&gt;
echo &amp;quot;[Z]ane, Morris&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
read person&lt;br /&gt;
case &amp;quot;$person&amp;quot; in # Обратите внимание: переменная взята в кавычки.&lt;br /&gt;
 &amp;quot;E&amp;quot; | &amp;quot;e&amp;quot; )&lt;br /&gt;
  # Пользователь может ввести как заглавную, так и строчную букву.&lt;br /&gt;
  echo&lt;br /&gt;
  echo &amp;quot;Roland Evans&amp;quot;&lt;br /&gt;
  echo &amp;quot;4321 Floppy Dr.&amp;quot;&lt;br /&gt;
  echo &amp;quot;Hardscrabble, CO 80753&amp;quot;&lt;br /&gt;
  echo &amp;quot;(303) 734-9874&amp;quot; &lt;br /&gt;
  echo &amp;quot;(303) 734-9892 fax&amp;quot; &lt;br /&gt;
  echo &amp;quot;revans@zzy.net&amp;quot;&lt;br /&gt;
  echo &amp;quot;Старый друг и партнер по бизнесу&amp;quot;&lt;br /&gt;
  ;;&lt;br /&gt;
# Обратите внимание: блок кода, анализирующий конкретный выбор, завершается&lt;br /&gt;
# двумя символами &amp;quot;точка-с-запятой&amp;quot;.&lt;br /&gt;
 &amp;quot;J&amp;quot; | &amp;quot;j&amp;quot; )&lt;br /&gt;
  echo&lt;br /&gt;
  echo &amp;quot;Mildred Jones&amp;quot;&lt;br /&gt;
  echo &amp;quot;249 E. 7th St., Apt. 19&amp;quot; &lt;br /&gt;
  echo &amp;quot;New York, NY 10009&amp;quot; &lt;br /&gt;
  echo &amp;quot;(212) 533-2814&amp;quot; &lt;br /&gt;
  echo &amp;quot;(212) 533-9972 fax&amp;quot; &lt;br /&gt;
  echo &amp;quot;milliej@loisaida.com&amp;quot;&lt;br /&gt;
  echo &amp;quot;Подружка&amp;quot;&lt;br /&gt;
  echo &amp;quot;День рождения: 11 февраля&amp;quot;&lt;br /&gt;
  ;;&lt;br /&gt;
# Информация о Smith и Zane будет добавлена позднее.&lt;br /&gt;
 * )&lt;br /&gt;
# Выбор по-умолчанию.&lt;br /&gt;
# &amp;quot;Пустой&amp;quot; ввод тоже обрабатывается здесь.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Нет данных.&amp;quot;&lt;br /&gt;
  ;;&lt;br /&gt;
esac&lt;br /&gt;
echo&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Измените этот сценарий таким образом, чтобы он не завершал работу&lt;br /&gt;
# после вывода информации о персоне, а переходил на ожидание нового&lt;br /&gt;
# ввода от пользователя.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Очень хороший пример использования ''case'' для анализа аргументов, переданных из командной строки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
case &amp;quot;$1&amp;quot; in&lt;br /&gt;
 &amp;quot;&amp;quot;) echo &amp;quot;Порядок использования: ${0##*/} &amp;lt;filename&amp;gt;&amp;quot;; exit 65;; # Параметры командной строки отсутствуют,&lt;br /&gt;
                                                                  # или первый параметр — &amp;quot;пустой&amp;quot;.&lt;br /&gt;
# Обратите внимание на ${0##*/} это подстановка параметра ${var##pattern}. В результате получается $0.&lt;br /&gt;
 -*) FILENAME=./$1;; # Если имя файла (аргумент $1) начинается с &amp;quot;-&amp;quot;,&lt;br /&gt;
                     # то заменить его на ./$1&lt;br /&gt;
                     # тогда параметр не будет восприниматься как ключ команды.&lt;br /&gt;
 * ) FILENAME=$1;;   # В противном случае — $1.&lt;br /&gt;
esac&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Оператор case допускает использовать подстановку команд вместо анализируемой переменной.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Подстановка команд в &amp;quot;case&amp;quot;.&lt;br /&gt;
case $( arch ) in # команда &amp;quot;arch&amp;quot; возвращает строку, описывающую аппаратную апхитектуру.&lt;br /&gt;
 i386 ) echo &amp;quot;Машина на базе процессора 80386&amp;quot;;;&lt;br /&gt;
 i486 ) echo &amp;quot;Машина на базе процессора 80486&amp;quot;;;&lt;br /&gt;
 i586 ) echo &amp;quot;Машина на базе процессора Pentium&amp;quot;;;&lt;br /&gt;
 i686 ) echo &amp;quot;Машина на базе процессора Pentium2 или выше&amp;quot;;;&lt;br /&gt;
 * ) echo &amp;quot;Машина на другом типе процессора&amp;quot;;;&lt;br /&gt;
esac&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Оператор ''case'' допускает использование шаблонных конструкций.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простой пример сравнения строк.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# match-string.sh: простое сравнение строк&lt;br /&gt;
match_string ()&lt;br /&gt;
{&lt;br /&gt;
 MATCH=0&lt;br /&gt;
 NOMATCH=90&lt;br /&gt;
 PARAMS=2 # Функция требует два входных аргумента.&lt;br /&gt;
 BAD_PARAMS=91&lt;br /&gt;
 [ $# -eq $PARAMS ] || return $BAD_PARAMS&lt;br /&gt;
 case &amp;quot;$1&amp;quot; in&lt;br /&gt;
 &amp;quot;$2&amp;quot;) return $MATCH;;&lt;br /&gt;
 * ) return $NOMATCH;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
a=one&lt;br /&gt;
b=two&lt;br /&gt;
c=three&lt;br /&gt;
d=two&lt;br /&gt;
match_string $a # неверное число аргументов&lt;br /&gt;
echo $? # 91&lt;br /&gt;
match_string $a $b # не равны&lt;br /&gt;
echo $? # 90&lt;br /&gt;
match_string $b $d # равны&lt;br /&gt;
echo $? # 0&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка ввода.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# isalpha.sh: Использование &amp;quot;case&amp;quot; для анализа строк.&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
FAILURE=-1&lt;br /&gt;
isalpha () # Проверка - является ли первый символ строки символом алфавита.&lt;br /&gt;
{&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; ] # Вызов функции без входного аргумента?&lt;br /&gt;
 then&lt;br /&gt;
  return $FAILURE&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
case &amp;quot;$1&amp;quot; in&lt;br /&gt;
 [a-zA-Z] *) return $SUCCESS;; # Первый символ - буква?&lt;br /&gt;
 * ) return $FAILURE;;&lt;br /&gt;
esac&lt;br /&gt;
} # Сравните с функцией &amp;quot;isalpha ()&amp;quot; в языке C.&lt;br /&gt;
&lt;br /&gt;
isalpha2 () # Проверка - состоит ли вся строка только из символов алфавита.&lt;br /&gt;
{&lt;br /&gt;
 [ $# -eq 1 ] || return $FAILURE&lt;br /&gt;
 &lt;br /&gt;
 case $1 in&lt;br /&gt;
 *[!a-zA-Z]*|&amp;quot;&amp;quot;) return $FAILURE;;&lt;br /&gt;
 *) return $SUCCESS;;&lt;br /&gt;
esac&lt;br /&gt;
}&lt;br /&gt;
isdigit () # Проверка - состоит ли вся строка только из цифр.&lt;br /&gt;
{ # Другими словами - является ли строка целым числом.&lt;br /&gt;
 [ $# -eq 1 ] || return $FAILURE&lt;br /&gt;
 case $1 in&lt;br /&gt;
  *[!0-9]*|&amp;quot;&amp;quot;) return $FAILURE;;&lt;br /&gt;
  *) return $SUCCESS;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
check_var () # Интерфейс к isalpha{&lt;br /&gt;
{&lt;br /&gt;
 if isalpha &amp;quot;$@&amp;quot;&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;\&amp;quot;$*\&amp;quot; начинается с алфавитного символа.&amp;quot;&lt;br /&gt;
  if isalpha2 &amp;quot;$@&amp;quot;&lt;br /&gt;
  then # Дальнейшая проверка не имеет смысла, если первй символ не буква.&lt;br /&gt;
   echo &amp;quot;\&amp;quot;$*\&amp;quot; содержит только алфавитные символы.&amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
   echo &amp;quot;\&amp;quot;$*\&amp;quot; содержит по меньшей мере один не алфавитный символ.&amp;quot;&lt;br /&gt;
  fi&lt;br /&gt;
 else&lt;br /&gt;
  echo &amp;quot;\&amp;quot;$*\&amp;quot; начинается с не алфавитного символа .&amp;quot;&lt;br /&gt;
  # Если функция вызвана без входного параметра,&lt;br /&gt;
  # то считается, что строка содержит &amp;quot;не алфавитной&amp;quot; символ.&lt;br /&gt;
 fi&lt;br /&gt;
echo&lt;br /&gt;
}&lt;br /&gt;
digit_check () # Интерфейс к isdigit ().&lt;br /&gt;
{&lt;br /&gt;
 if isdigit &amp;quot;$@&amp;quot;&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;\&amp;quot;$*\&amp;quot; содержит только цифры [0 - 9].&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
  echo &amp;quot;\&amp;quot;$*\&amp;quot; содержит по меньшей мере один не цифровой символ.&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
echo&lt;br /&gt;
}&lt;br /&gt;
a=23skidoo&lt;br /&gt;
b=H3llo&lt;br /&gt;
c=-What?&lt;br /&gt;
d=What?&lt;br /&gt;
e=`echo $b` # Подстановка команды.&lt;br /&gt;
f=AbcDef&lt;br /&gt;
g=27234&lt;br /&gt;
h=27a34&lt;br /&gt;
i=27.34&lt;br /&gt;
check_var $a&lt;br /&gt;
check_var $b&lt;br /&gt;
check_var $c&lt;br /&gt;
check_var $d&lt;br /&gt;
check_var $e&lt;br /&gt;
check_var $f&lt;br /&gt;
check_var # Вызов без параметра, что произойдет?&lt;br /&gt;
#&lt;br /&gt;
digit_check $g&lt;br /&gt;
digit_check $h&lt;br /&gt;
digit_check $i&lt;br /&gt;
exit 0 # Сценарий дополнен S.C.&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Напишите функцию 'isfloat ()', которая проверяла бы вещественные числа.&lt;br /&gt;
# Подсказка: Эта функция подобна функции 'isdigit ()',&lt;br /&gt;
# надо лишь добавить анализ наличия десятичной точки.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''select'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Оператор select был заимствован из Korn Shell, и является еще одним инструментом,используемым при создании меню.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
select variable [in list]&lt;br /&gt;
do&lt;br /&gt;
 command...&lt;br /&gt;
 break&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Этот оператор предлагает пользователю выбрать один из представленных вариантов.Примечательно, что ''select'' по-умолчанию использует в качестве приглашения к вводу (prompt)— ''PS3'' ('''#?'''), который легко изменить.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание меню с помощью select.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
PS3='Выберите ваш любимый овощ: ' # строка приглашения к вводу (prompt)&lt;br /&gt;
echo&lt;br /&gt;
select vegetable in &amp;quot;бобы&amp;quot; &amp;quot;морковь&amp;quot; &amp;quot;картофель&amp;quot; &amp;quot;лук&amp;quot; &amp;quot;брюква&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Вы предпочитаете $vegetable.&amp;quot;&lt;br /&gt;
 echo &amp;quot;;-))&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
 break # если 'break' убрать, то получится бесконечный цикл.&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если в операторе '''select''' список ''in list'' не задан, то в качестве списка будет использоваться список аргументов ('''''$@'''''), передаваемый сценарию или функции.&lt;br /&gt;
Сравните это с поведением оператора цикла&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;for variable [in list]&amp;lt;/source&amp;gt;&lt;br /&gt;
в котором не задан список аргументов.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание меню с помощью select в функции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
PS3='Выберите ваш любимый овощ: '&lt;br /&gt;
echo&lt;br /&gt;
choice_of()&lt;br /&gt;
{&lt;br /&gt;
 select vegetable # список выбора [in list] отсутствует, поэтому 'select' использует входные аргументы функции.&lt;br /&gt;
 do&lt;br /&gt;
  echo&lt;br /&gt;
  echo &amp;quot;Вы предпочитаете $vegetable.&amp;quot;&lt;br /&gt;
  echo &amp;quot;;-))&amp;quot;&lt;br /&gt;
  echo&lt;br /&gt;
  break&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
choice_of бобы рис морковь редис томат шпинат &lt;br /&gt;
#          $1  $2    $3     $4    $5     $6 &lt;br /&gt;
# передача списка выбора в функцию choice_of()&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Внутренние команды ==&lt;br /&gt;
'''''Внутренняя команда''''' — это '''команда''', которая встроена непосредственно в Bash. Команды делаются встроенными либо из соображений производительности — встроенные команды исполняются быстрее,чем внешние, которые, как правило, запускаются в дочернем процессе, либо из-за необходимости прямого доступа к внутренним структурам командного интерпретатора.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
| Действие, когда какая либо команда или сама командная оболочка инициирует (порождает) новый подпроцесс, что бы выполнить какую-либо работу, называется ветвлением ('''forking''') процесса. Новый процесс называется &amp;quot;дочерним&amp;quot; (или &amp;quot;потомком&amp;quot;), а породивший его процесс — &amp;quot;родительским&amp;quot; (или &amp;quot;предком&amp;quot;). В результате и потомок и предок продолжают исполняться одновременно — параллельно друг другу. В общем случае, встроенные команды Bash, при исполнении внутри сценария, не порождают новый подпроцесс, в то время как вызов внешних команд, как правило, приводит к созданию нового подпроцесса.&lt;br /&gt;
|}&lt;br /&gt;
Внутренние команды могут иметь внешние аналоги. Например, внутренняя команда Bash — ''echo'' имеет внешний аналог ''/bin/echo'' и их поведение практически идентично.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo &amp;quot;Эта строка выводится внутренней командой \&amp;quot;echo\&amp;quot;.&amp;quot;&lt;br /&gt;
/bin/echo &amp;quot;А эта строка выводится внешней командой /bin/echo.&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''Ключевое слово''''' ('''''keyword''''') — это зарезервированное слово, синтаксический элемент (''token'') или оператор. Ключевые слова имеют специальное назначение для командного интерпретатора, и фактически являются элементами синтаксиса языка командной оболочки. В качестве примера можно привести &amp;quot;for&amp;quot;, &amp;quot;while&amp;quot;, &amp;quot;do&amp;quot;, &amp;quot;!&amp;quot;, которые являются ключевыми (или зарезервированными) словами. Подобно встроенным командам, ключевые слова жёстко зашиты в Bash, но в отличие от встроенных команд, ключевые слова не являются командами как таковыми, хотя при этом могут являться их составной частью.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Ввод/вывод'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''echo'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит (на ''stdout'') выражение или содержимое переменной.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo Hello&lt;br /&gt;
echo $a&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для вывода экранированных символов, '''echo''' требует наличие ключа ''-e''.&lt;br /&gt;
Обычно, команда '''echo''' выводит в конце символ перевода строки. Подавить вывод это символа можно ключом ''-n''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''echo''' может использоваться для передачи информации по конвейеру другим командам:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if echo &amp;quot;$VAR&amp;quot; | grep -q txt # if [[ $VAR = *txt* ]]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;$VAR содержит подстроку \&amp;quot;txt\&amp;quot;&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Кроме того, команда '''echo''', в комбинации с подстановкой команд может участвовать в операции присвоения значения переменной.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
a=`echo &amp;quot;HELLO&amp;quot; | tr A-Z a-z`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Следует запомнить, что команда '''echo `command`''' удалит все символы перевода строки, которые будут выведены командой ''`command`''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Переменная &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''''$IFS'''''&amp;lt;/span&amp;gt; обычно содержит символ перевода строки ''\n'', как один из вариантов пробельного символа. Bash разобьёт вывод команды ''`command`'', по пробельным символам, на аргументы и передаст их команде '''echo''', которая выведет эти аргументы, разделённые пробелами.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ls -l /usr/share/apps/kjezz/sounds&lt;br /&gt;
-rw-r--r-- 1 root root 1407 Nov 7 2000 reflect.au&lt;br /&gt;
-rw-r--r-- 1 root root 362 Nov 7 2000 seconds.au&lt;br /&gt;
bash$ echo `ls -l /usr/share/apps/kjezz/sounds`&lt;br /&gt;
total 40 -rw-r--r-- 1 root root 716 Nov 7 2000 reflect.au -rw-r--r-- 1 root root 362 Nov 7 2000 seconds.au&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Это встроенная команда Bash и имеет внешний аналог '''''/bin/echo'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ type -a echo&lt;br /&gt;
echo is a shell builtin&lt;br /&gt;
echo is /bin/echo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''printf'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''printf'''&amp;lt;/big&amp;gt; — команда форматированного вывода, расширенный вариант команды '''echo''' и ограниченный вариант библиотечной функции ''printf()'' в языке C, к тому же синтаксис их несколько отличается друг от друга.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''printf'''  ''format-string''... ''parameter''...&amp;lt;br /&amp;gt;&lt;br /&gt;
Это встроенная команда Bash. Имеет внешний аналог '''''/bin/printf''''' или '''''/usr/bin/printf'''''. За более подробной информацией обращайтесь к страницам справочного руководства ''man 1 printf'' по системным командам.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''!'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;Старые версии Bash могут не поддерживать команду '''''printf'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''printf в действии.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# printf demo&lt;br /&gt;
# От переводчика:&lt;br /&gt;
# Считаю своим долгом напомнить, что в качестве разделителя дробной и целой&lt;br /&gt;
# частей в вещественных числах, может использоваться символ &amp;quot;запятая&amp;quot;&lt;br /&gt;
# (в русских локалях), поэтому данный сценарий может выдавать сообщение&lt;br /&gt;
# об ошибке (у меня так и произошло) при выводе числа PI.&lt;br /&gt;
# Тогда попробуйте заменить в определении числа PI десятичную точку&lt;br /&gt;
# на запятую — это должно помочь. ;-)&lt;br /&gt;
PI=3,14159265358979&lt;br /&gt;
DecimalConstant=31373&lt;br /&gt;
Message1=&amp;quot;Поздравляю,&amp;quot;&lt;br /&gt;
Message2=&amp;quot;Землянин.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
printf &amp;quot;Число пи с точностью до 2 знака после запятой = %1.2f&amp;quot; $PI&lt;br /&gt;
echo&lt;br /&gt;
printf &amp;quot;Число пи с точностью до 9 знака после запятой = %1.9f&amp;quot; $PI &lt;br /&gt;
# Даже округляет правильно.&lt;br /&gt;
printf &amp;quot;\n&amp;quot;                                  # Перевод строки,&lt;br /&gt;
printf &amp;quot;Константа = \t%d\n&amp;quot; $DecimalConstant # Вставлен символ табуляции (\t)&lt;br /&gt;
printf &amp;quot;%s %s \n&amp;quot; $Message1 $Message2&lt;br /&gt;
echo&lt;br /&gt;
# ==========================================#&lt;br /&gt;
# Эмуляция функции 'sprintf' в языке C.&lt;br /&gt;
# Запись форматированной строки в переменную.&lt;br /&gt;
echo&lt;br /&gt;
Pi12=$(printf &amp;quot;%1.12f&amp;quot; $PI)&lt;br /&gt;
echo &amp;quot;Число пи с точностью до 12 знака после запятой = $Pi12&amp;quot;&lt;br /&gt;
Msg=`printf &amp;quot;%s %s \n&amp;quot; $Message1 $Message2`&lt;br /&gt;
echo $Msg; echo $Msg&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Одно из полезных применений команды '''''printf''''' — форматированный вывод сообщений об ошибках.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
E_BADDIR=65&lt;br /&gt;
var=nonexistent_directory&lt;br /&gt;
error()&lt;br /&gt;
{&lt;br /&gt;
 printf &amp;quot;$@&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
 # Форматированный вывод аргументов на stderr.&lt;br /&gt;
 echo&lt;br /&gt;
 exit $E_BADDIR&lt;br /&gt;
}&lt;br /&gt;
cd $var || error $&amp;quot;Невозможно перейти в каталог %s.&amp;quot; &amp;quot;$var&amp;quot;&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''read'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;quot;Читает&amp;quot; значение переменной с устройства стандартного ввода — stdin, в интерактивном режиме это означает клавиатуру. Ключ ''-a'' позволяет записывать значения в массивы.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ввод значений переменных с помощью read.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo -n &amp;quot;Введите значение переменной 'var1': &amp;quot;&lt;br /&gt;
# Ключ -n подавляет вывод символа перевода строки.&lt;br /&gt;
read var1&lt;br /&gt;
# Обратите внимание — перед именем переменной отсутствует символ '$'.&lt;br /&gt;
echo &amp;quot;var1 = $var1&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# Одной командой 'read' можно вводить несколько переменных.&lt;br /&gt;
echo -n &amp;quot;Введите значения для переменных 'var2' и 'var3' (через пробел или табуляцию): &amp;quot;&lt;br /&gt;
read var2 var3&lt;br /&gt;
echo &amp;quot;var2 = $var2 var3 = $var3&amp;quot;&lt;br /&gt;
# Если было введено значение только одной переменной, то вторая останется &amp;quot;пустой&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если команде '''''read''''' не была передано ни одной переменной, то ввод будет осуществлён в переменную &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''''$REPLY'''''&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример использования команды read без указания переменной для ввода.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
# -------------------------- #&lt;br /&gt;
# Первый блок кода.&lt;br /&gt;
echo -n &amp;quot;Введите значение: &amp;quot;&lt;br /&gt;
read var&lt;br /&gt;
echo &amp;quot;\&amp;quot;var\&amp;quot; = &amp;quot;$var&amp;quot;&amp;quot;&lt;br /&gt;
# Здесь нет ничего неожиданного.&lt;br /&gt;
# -------------------------- #&lt;br /&gt;
echo&lt;br /&gt;
echo -n &amp;quot;Введите другое значение: &amp;quot;&lt;br /&gt;
read       # Команда 'read' употребляется без указания переменной для ввода,&lt;br /&gt;
           # тем не менее...&lt;br /&gt;
           # По-умолчанию ввод осуществляется в переменную $REPLY.&lt;br /&gt;
var=&amp;quot;$REPLY&amp;quot;&lt;br /&gt;
echo &amp;quot;\&amp;quot;var\&amp;quot; = &amp;quot;$var&amp;quot;&amp;quot;&lt;br /&gt;
# Эта часть сценария эквивалентна первому блоку, выделенному выше.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Обычно, при вводе в окне терминала с помощью команды '''''read''''', символ ''\'' служит для экранирования символа перевода строки. Ключ ''-r'' заставляет интерпретировать символ ''\'' как обычный символ.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ввод многострочного текста с помощью read.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Введите строку, завершающуюся символом \\, и нажмите ENTER.&amp;quot;&lt;br /&gt;
echo &amp;quot;Затем введите вторую строку, и снова нажмите ENTER.&amp;quot;&lt;br /&gt;
read var1     # При чтении, символ &amp;quot;\&amp;quot; экранирует перевод строки.&lt;br /&gt;
              # первая строка \&lt;br /&gt;
              # вторая строка&lt;br /&gt;
echo &amp;quot;var1 = $var1&amp;quot;&lt;br /&gt;
# var1 = первая строка вторая строка&lt;br /&gt;
# После ввода каждой строки, завершающейся символом &amp;quot;\&amp;quot;,&lt;br /&gt;
# вы можете продолжать ввод на другой строке.&lt;br /&gt;
echo; echo&lt;br /&gt;
echo &amp;quot;Введите другую строку, завершающуюся символом \\, и нажмите ENTER.&amp;quot;&lt;br /&gt;
read -r var2 # Ключ -r заставляет команду &amp;quot;read&amp;quot; воспринимать &amp;quot;\&amp;quot;&lt;br /&gt;
             # как обычный символ.&lt;br /&gt;
             # первая строка \&lt;br /&gt;
echo &amp;quot;var2 = $var2&amp;quot;&lt;br /&gt;
# var2 = первая строка \&lt;br /&gt;
# Ввод данных прекращается сразу же после первого нажатия на клавишу ENTER.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''''read''''' имеет ряд очень любопытных опций, которые позволяют выводить подсказку — приглашение ко вводу (prompt), и даже читать данные не дожидаясь нажатия на клавишу ''ENTER''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Чтение данных, не дожидаясь нажатия на клавишу ENTER.&lt;br /&gt;
read -s -n1 -p &amp;quot;Нажмите клавишу &amp;quot; keypress&lt;br /&gt;
echo; echo &amp;quot;Была нажата клавиша &amp;quot;\&amp;quot;$keypress\&amp;quot;&amp;quot;.&amp;quot;&lt;br /&gt;
# -s — подавляет эхо-вывод, т.е. ввод с клавиатуры не отображается на экране.&lt;br /&gt;
# -n N — ввод завершается автоматически, сразу же после ввода N-го символа.&lt;br /&gt;
# -p — задает вид строки подсказки - приглашения к вводу (prompt).&lt;br /&gt;
# Использование этих ключей немного осложняется тем, что они должны следовать в определенном порядке.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ключ ''-n'', кроме всего прочего, позволяет команде '''''read''''' обнаруживать нажатие курсорных и некоторых других служебных клавиш.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Обнаружение нажатия на курсорные клавиши.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# arrow-detect.sh: Обнаружение нажатия на курсорные клавиши, и не только...&lt;br /&gt;
# Спасибо Sandro Magi за то что показал мне — как.&lt;br /&gt;
# --------------------------------------------&lt;br /&gt;
# Коды клавиш.&lt;br /&gt;
arrowup='\[A'&lt;br /&gt;
arrowdown='\[B'&lt;br /&gt;
arrowrt='\[C'&lt;br /&gt;
arrowleft='\[D'&lt;br /&gt;
insert='\[2'&lt;br /&gt;
delete='\[3'&lt;br /&gt;
# --------------------------------------------&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
OTHER=65&lt;br /&gt;
echo -n &amp;quot;Нажмите на клавишу... &amp;quot;&lt;br /&gt;
# Может потребоваться нажать на ENTER, если была нажата клавиша&lt;br /&gt;
# не входящая в список выше.&lt;br /&gt;
read -n3 key # Прочитать 3 символа.&lt;br /&gt;
echo -n &amp;quot;$key&amp;quot; | grep &amp;quot;$arrowup&amp;quot; #Определение нажатой клавиши.&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Нажата клавиша \&amp;quot;.&amp;quot;&lt;br /&gt;
 exit $SUCCESS&lt;br /&gt;
fi&lt;br /&gt;
echo -n &amp;quot;$key&amp;quot; | grep &amp;quot;$arrowdown&amp;quot;&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Нажата клавиша \&amp;quot;&lt;br /&gt;
 exit $SUCCESS&lt;br /&gt;
fi&lt;br /&gt;
echo -n &amp;quot;$key&amp;quot; | grep &amp;quot;$arrowrt&amp;quot;&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Нажата клавиша \&amp;quot;О\&amp;quot;.&amp;quot;&lt;br /&gt;
 exit $SUCCESS&lt;br /&gt;
fi&lt;br /&gt;
echo -n &amp;quot;$key&amp;quot; | grep &amp;quot;$arrowleft&amp;quot;&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Нажата клавиша \&amp;quot;.&amp;quot;&lt;br /&gt;
 exit $SUCCESS&lt;br /&gt;
fi&lt;br /&gt;
echo -n &amp;quot;$key&amp;quot; | grep &amp;quot;$insert&amp;quot;&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Нажата клавиша \&amp;quot;Insert\&amp;quot;.&amp;quot;&lt;br /&gt;
 exit $SUCCESS&lt;br /&gt;
fi&lt;br /&gt;
echo -n &amp;quot;$key&amp;quot; | grep &amp;quot;$delete&amp;quot;&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Нажата клавиша \&amp;quot;Delete\&amp;quot;.&amp;quot;&lt;br /&gt;
 exit $SUCCESS&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot; Нажата какая-то другая клавиша.&amp;quot;&lt;br /&gt;
exit $OTHER&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ---------&lt;br /&gt;
# 1) Упростите сценарий, заменив множество if-ов&lt;br /&gt;
# одной конструкцией 'case'.&lt;br /&gt;
# 2) Добавьте определение нажатий на клавиши &amp;quot;Home&amp;quot;, &amp;quot;End&amp;quot;, &amp;quot;PgUp&amp;quot; и &amp;quot;PgDn&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ключ ''-t'' позволяет ограничивать время ожидания ввода командой '''''read'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''read''''' может считывать значения для переменных из файла, перенаправленного на ''stdin''. Если файл содержит не одну строку, то переменной будет присвоена только первая строка. Если команде '''''read''''' будет передано несколько переменных, то первая строка файла будет разбита, по пробелам, на несколько подстрок, каждая из которых будет записана в свою переменную. Будьте осторожны!&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Чтение командой read из файла через перенаправление.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
read var1 &amp;lt;data-file&lt;br /&gt;
echo &amp;quot;var1 = $var1&amp;quot;&lt;br /&gt;
# Первая строка из &amp;quot;data-file&amp;quot; целиком записывается в переменную var1&lt;br /&gt;
read var2 var3 &amp;lt; data-file&lt;br /&gt;
echo &amp;quot;var2 = $var2 var3 = $var3&amp;quot;&lt;br /&gt;
# Обратите внимание!&lt;br /&gt;
# Поведение команды &amp;quot;read&amp;quot; далеко от ожидаемого!&lt;br /&gt;
# 1) Произошел возврат к началу файла.&lt;br /&gt;
# 2) Вместо того, чтобы последовательно читать строки из файла,&lt;br /&gt;
#    по числу переменных, первая строка файла была разбита на подстроки,&lt;br /&gt;
#    разделенные пробелами, которые и были записаны в переменные.&lt;br /&gt;
# 3) В последнюю переменную была записана вся оставшаяся часть строки.&lt;br /&gt;
# 4) Если команде &amp;quot;read&amp;quot; будет передано большее число переменных, чем подстрок&lt;br /&gt;
# в первой строке файла, то последние переменные останутся &amp;quot;пустыми&amp;quot;.&lt;br /&gt;
echo &amp;quot;------------------------------------------------&amp;quot;&lt;br /&gt;
# Эта проблема легко разрешается с помощью цикла:&lt;br /&gt;
while read line&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$line&amp;quot;&lt;br /&gt;
done &amp;lt; data-file# Спасибо Heiner Steven за разъяснения.&lt;br /&gt;
echo &amp;quot;------------------------------------------------&amp;quot;&lt;br /&gt;
# Разбор строки, разделенной на поля&lt;br /&gt;
# Для задания разделителя полей, используется переменная $IFS,&lt;br /&gt;
echo &amp;quot;Список всех пользователей:&amp;quot;&lt;br /&gt;
OIFS=$IFS; IFS=:      # В файле /etc/passwd, в качестве разделителя полей&lt;br /&gt;
                      # используется символ &amp;quot;:&amp;quot;.&lt;br /&gt;
while read name passwd uid gid fullname ignore&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$name ($fullname)&amp;quot;&lt;br /&gt;
done &amp;lt; /etc/passwd    # перенаправление ввода.&lt;br /&gt;
IFS=$OIFS             # Восстановление предыдущего состояния переменной $&lt;br /&gt;
# Эту часть кода написал Heiner Steven.&lt;br /&gt;
# Если переменная $IFS устанавливается внутри цикла,&lt;br /&gt;
# то отпадает необходимость сохранения её первоначального значения&lt;br /&gt;
# во временной переменной.&lt;br /&gt;
# Спасибо Dim Segebart за разъяснения.&lt;br /&gt;
echo &amp;quot;------------------------------------------------&amp;quot;&lt;br /&gt;
echo &amp;quot;Список всех пользователей:&amp;quot;&lt;br /&gt;
while IFS=: read name passwd uid gid fullname ignore&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$name ($fullname)&amp;quot;&lt;br /&gt;
done &amp;lt; /etc/passwd    # перенаправление ввода.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Значение переменной \$IFS осталось прежним: $IFS&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Передача информации, выводимой командой '''''echo''''', по конвейеру команде '''''read''''', будет вызывать ошибку. Тем не менее, передача данных по конвейеру от [[cat]], кажется срабатывает.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat file1 file2 |&lt;br /&gt;
while read line&lt;br /&gt;
do&lt;br /&gt;
 echo $line&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Не смотря на это, как указывает Bjon Eriksson:&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проблемы чтения данных из канала (конвейера).'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
# readpipe.sh&lt;br /&gt;
# Этот сценарий предоставил Bjon Eriksson.&lt;br /&gt;
last=&amp;quot;(null)&amp;quot;&lt;br /&gt;
cat $0 |&lt;br /&gt;
while read line&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;{$line}&amp;quot;&lt;br /&gt;
 last=$line&lt;br /&gt;
done&lt;br /&gt;
printf &amp;quot;\nКонец, последняя строка:$last\n&amp;quot;&lt;br /&gt;
exit 0 # Конец сценария.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Далее следует результат (частично) работы сценария.&amp;lt;br /&amp;gt;&lt;br /&gt;
 ./readpipe.sh&lt;br /&gt;
 {#!/bin/sh}&lt;br /&gt;
 {last=&amp;quot;(null)&amp;quot;}&lt;br /&gt;
 {cat $0 |}&lt;br /&gt;
 {while read line}&lt;br /&gt;
 {do}&lt;br /&gt;
 {echo &amp;quot;{$line}&amp;quot;}&lt;br /&gt;
 {last=$line}&lt;br /&gt;
 {done}&lt;br /&gt;
 {printf &amp;quot;nКонец, последняя строка:$last\n&amp;quot;}&lt;br /&gt;
 Конец, последняя строка:(null)&lt;br /&gt;
 Переменная (last) инициализируется в подоболочке, поэтому она оказывается не инициализированной за его пределами.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Файловая система'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cd'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Уже знакомая нам команда [[cd — Команда смены директории|cd]], изменяющая текущий каталог, может быть использована в случаях, когда некоторую команду необходимо запустить только находясь в определённом каталоге.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;(cd /source/directory &amp;amp;&amp;amp; tar cf - . ) | (cd /dest/directory &amp;amp;&amp;amp; tar xpvf -)&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда [[cd — Команда смены директории|cd]] с ключом ''-P\'' (''physical'') игнорирует символические ссылки. Команда &amp;quot;cd -&amp;quot; выполняет переход в каталог &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$OLDPWD&amp;lt;/blue&amp;gt; — предыдущий рабочий каталог. Неожиданным образом выполняется команда [[cd — Команда смены директории|cd]], если ей передать, в качестве каталога назначения, два слэша.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cd //&lt;br /&gt;
bash$ pwd&lt;br /&gt;
//&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Само собой разумеется, это должен был бы быть каталог ''/''. Эта проблема наблюдается как в командной строке, так и в сценариях.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''pwd'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит название текущего рабочего каталога (Print Working Directory). Кроме того, имя текущего каталога хранится во внутренней переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$PWD&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''pushd,popd,dirs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Этот набор команд является составной частью механизма &amp;quot;закладок&amp;quot; на каталоги и позволяет перемещаться по каталогам вперед и назад в заданном порядке. Для хранения имён каталогов используется стек (LIFO — &amp;quot;последний вошёл, первый вышел&amp;quot;).&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''pushd''''' ''dir-name'' — помещает имя текущего каталога в стек и осуществляет переход в каталог ''dir-name''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''popd''''' — выталкивает, находящееся на вершине стека, имя каталога и одновременно осуществляет переход в каталог, оказавшийся на вершине стека.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''dirs''''' — выводит содержимое стека каталогов (сравните с переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$DIRSTACK&amp;lt;/span&amp;gt;). В случае успеха, обе команды — '''''pushd''''' и '''''popd''''' автоматически вызывают '''''dirs'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Эти команды могут оказаться весьма полезными, когда в сценарии нужно производить частую смену каталогов, но при этом не хочется жестко &amp;quot;зашивать&amp;quot; имена каталогов. Обратите внимание: содержимое стека каталогов постоянно хранится в переменной-массиве - &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$DIRSTACK&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Смена текущего каталога.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
dir1=/usr/local&lt;br /&gt;
dir2=/var/spool&lt;br /&gt;
pushd $dir1      # Команда 'dirs' будет вызвана автоматически (на stdout будет выведено содержимое стека).&lt;br /&gt;
echo &amp;quot;Выполнен переход в каталог `pwd`.&amp;quot; # Обратные одиночные кавычки.&lt;br /&gt;
# Теперь можно выполнить какие либо действия в каталоге 'dir1'.&lt;br /&gt;
pushd $dir2&lt;br /&gt;
echo &amp;quot;Выполнен переход в каталог `pwd`.&amp;quot;&lt;br /&gt;
# Теперь можно выполнить какие либо действия в каталоге 'dir2'.&lt;br /&gt;
echo &amp;quot;На вершине стека находится: $DIRSTACK.&amp;quot;&lt;br /&gt;
popd&lt;br /&gt;
echo &amp;quot;Возврат в каталог `pwd`.&amp;quot;&lt;br /&gt;
# Теперь можно выполнить какие либо действия в каталоге 'dir1'.&lt;br /&gt;
popd&lt;br /&gt;
echo &amp;quot;Возврат в первоначальный рабочий каталог `pwd`.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''Переменные'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''let'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''let''''' производит арифметические операции над переменными. В большинстве случаев, её можно считать упрощенным вариантом команды '''''expr'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Команда let, арифметические операции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
let a=11      # То же, что и 'a=11'&lt;br /&gt;
let a=a+5     # Эквивалентно &amp;quot;a = a + 5&amp;quot;&lt;br /&gt;
              # (Двойные кавычки и дополнительные пробелы делают код более удобочитаемым)&lt;br /&gt;
echo &amp;quot;11 + 5 = $a&amp;quot;&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;a &amp;lt;&amp;lt;= 3&amp;quot; # Эквивалентно let &amp;quot;a = a &amp;lt;&amp;lt; 3&amp;quot;&lt;br /&gt;
echo &amp;quot;\&amp;quot;\$a\&amp;quot; (=16) после сдвига влево на 3 разряда = $a&amp;quot;&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;a /= 4&amp;quot; # Эквивалентно let &amp;quot;a = a / 4&amp;quot;&lt;br /&gt;
echo &amp;quot;128 / 4 = $a&amp;quot;&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;a -= 5&amp;quot; # Эквивалентно let &amp;quot;a = a - 5&amp;quot;&lt;br /&gt;
echo &amp;quot;32 - 5 = $a&amp;quot;&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;a = a * 10&amp;quot; # Эквивалентно let &amp;quot;a = a * 10&amp;quot;&lt;br /&gt;
echo &amp;quot;27 * 10 = $a&amp;quot;&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;a %= 8&amp;quot; # Эквивалентно let &amp;quot;a = a % 8&amp;quot;&lt;br /&gt;
echo &amp;quot;270 mod 8 = $a (270 / 8 = 33, остаток = $a)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''eval'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''eval''''' ''arg1'' [''arg2''] ... [''argN'']&amp;lt;br /&amp;gt;&lt;br /&gt;
Транслирует список аргументов, из списка, в команды.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Демонстрация команды eval.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
y=`eval ls -l` # Подобно y=`ls -l`&lt;br /&gt;
echo $y # но символы перевода строки не выводятся, поскольку имя переменной не в кавычках.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;$y&amp;quot; # Если имя переменной записать в кавычках — символы перевода строки сохраняются.&lt;br /&gt;
echo; echo&lt;br /&gt;
y=`eval df` # Аналогично y=`df`&lt;br /&gt;
# Когда производится подавление вывода символов LF (перевод строки), то анализ&lt;br /&gt;
# результатов различными утилитами, такими как awk, можно сделать проще.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Принудительное завершение сеанса.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
y=`eval ps ax | sed -n '/ppp/p' | awk '{ print $1 }'`&lt;br /&gt;
# Выяснить PID процесса 'ppp'.&lt;br /&gt;
kill -9 $y # &amp;quot;Прихлопнуть&amp;quot; его&lt;br /&gt;
# Предыдущие строки можно заменить одной строкой&lt;br /&gt;
# kill -9 `ps ax | awk '/ppp/ { print $1 }'&lt;br /&gt;
chmod 666 /dev/ttyS3    # Завершённый, по сигналу SIGKILL, ppp изменяет права доступа&lt;br /&gt;
                        # к последовательному порту. Вернуть их в первоначальное состояние.&lt;br /&gt;
rm /var/lock/LCK..ttyS3 # Удалить lock-файл последовательного порта.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Шифрование по алгоритму &amp;quot;rot13&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Реализация алгоритма шифрования &amp;quot;rot13&amp;quot; с помощью 'eval'.&lt;br /&gt;
# Сравните со сценарием &amp;quot;rot13.sh&amp;quot;.&lt;br /&gt;
setvar_rot_13()            # Криптование по алгоритму &amp;quot;rot13&amp;quot;&lt;br /&gt;
{&lt;br /&gt;
 local varname=$1 varvalue=$2&lt;br /&gt;
 eval $varname='$(echo &amp;quot;$varvalue&amp;quot; | tr a-z n-za-m)'&lt;br /&gt;
}&lt;br /&gt;
setvar_rot_13 var &amp;quot;foobar&amp;quot; # Пропустить слово &amp;quot;foobar&amp;quot; через rot13.&lt;br /&gt;
echo $var                  # sbbone&lt;br /&gt;
echo $var | tr a-z n-za-m  # foobar&lt;br /&gt;
                           # Расшифровывание.&lt;br /&gt;
# Пример предоставил Stephane Chazelas.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Rory Winston представил следующий пример, как образец практического использования команды '''''eval'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Замена имени переменной на её значение, в исходном тексте программы на языке Perl, с помощью eval.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;perl&amp;quot;&amp;gt;&lt;br /&gt;
В программе &amp;quot;test.pl&amp;quot;, на языке Perl:&lt;br /&gt;
          ...&lt;br /&gt;
          my $WEBROOT = &amp;lt;WEBROOT_PATH&amp;gt;;&lt;br /&gt;
          ...&lt;br /&gt;
Эта попытка подстановки значения переменной вместо её имени:&lt;br /&gt;
          $export WEBROOT_PATH=/usr/local/webroot&lt;br /&gt;
          $sed 's/&amp;lt;WEBROOT_PATH&amp;gt;/$WEBROOT_PATH/' &amp;lt; test.pl &amp;gt; out &lt;br /&gt;
даст такой результат:&lt;br /&gt;
          my $WEBROOT = $WEBROOT_PATH;&lt;br /&gt;
Тем не менее:&lt;br /&gt;
          $export WEBROOT_PATH=/usr/local/webroot&lt;br /&gt;
          $eval sed 's/&amp;lt;WEBROOT_PATH&amp;gt;/$WEBROOT_PATH/' &amp;lt; test.pl &amp;gt; out&lt;br /&gt;
# ====&lt;br /&gt;
Этот вариант дал желаемый результат — имя переменной, в тексте программы,&lt;br /&gt;
благополучно было заменено на её значение:&lt;br /&gt;
          my $WEBROOT = /usr/local/webroot&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''''eval''''' может быть небезопасна. Если существует приемлемая альтернатива, то желательно воздерживаться от использования '''''eval'''''. Так, '''''eval''''' ''$COMMANDS'' исполняет код, который записан в переменную ''COMMANDS'', которая, в свою очередь, может содержать весьма неприятные сюрпризы, например '''rm -rf *'''. Использование команды '''''eval''''', для исполнения кода неизвестного происхождения, крайне опасно!&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''set'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''set''''' изменяет значения внутренних переменных сценария. Она может использоваться для переключения опций (ключей, флагов), определяющих поведение скрипта. Ещё одно применение — сброс/установка позиционных параметров (аргументов), значения которых будут восприняты как результат работы команды ('''''set `command`''''').&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Установка значений аргументов с помощью команды set.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# script &amp;quot;set-test&amp;quot;&lt;br /&gt;
# Вызовите сценарий с тремя аргументами командной строки,&lt;br /&gt;
# например: &amp;quot;./set-test one two three&amp;quot;.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Аргументы перед вызовом set \`uname -a\` :&amp;quot;&lt;br /&gt;
echo &amp;quot;Аргумент #1 = $1&amp;quot;&lt;br /&gt;
echo &amp;quot;Аргумент #2 = $2&amp;quot;&lt;br /&gt;
echo &amp;quot;Аргумент #3 = $3&amp;quot;&lt;br /&gt;
set `uname -a` # Изменение аргументов&lt;br /&gt;
               # значения которых берутся из результата работы `uname -a`&lt;br /&gt;
echo $_&lt;br /&gt;
echo &amp;quot;Аргументы после вызова set \`uname -a\` :&amp;quot;&lt;br /&gt;
# $1, $2, $3 и т.д. будут переустановлены в соответствии с выводом&lt;br /&gt;
# команды `uname -a`&lt;br /&gt;
echo &amp;quot;Поле #1 'uname -a' = $1&amp;quot;&lt;br /&gt;
echo &amp;quot;Поле #2 'uname -a' = $2&amp;quot;&lt;br /&gt;
echo &amp;quot;Поле #3 'uname -a' = $3&amp;quot;&lt;br /&gt;
echo ---&lt;br /&gt;
echo $_ # ---&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Вызов '''''set''''' без параметров просто выводит список инициализированных переменных окружения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ set&lt;br /&gt;
 AUTHORCOPY=/home/bozo/posts&lt;br /&gt;
 BASH=/bin/bash&lt;br /&gt;
 BASH_VERSION=$'2.05.8(1)-release'&lt;br /&gt;
 ...&lt;br /&gt;
 XAUTHORITY=/home/bozo/.Xauthority&lt;br /&gt;
 _=/etc/bashrc&lt;br /&gt;
 variable22=abc&lt;br /&gt;
 variable23=xzy&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если команда '''''set''''' используется с ключом &amp;quot;--&amp;quot;, после которого следует переменная, то значение переменной переносится в позиционные параметры (аргументы). Если имя переменной отсутствует, то эта команда приводит к сбросу позиционных параметров.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Изменение значений позиционных параметров (аргументов).'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
variable=&amp;quot;one two three four five&amp;quot;&lt;br /&gt;
set -- $variable &lt;br /&gt;
# Значения позиционных параметров берутся из &amp;quot;$variable&amp;quot;.&lt;br /&gt;
first_param=$1&lt;br /&gt;
second_param=$2&lt;br /&gt;
shift; shift # сдвиг двух первых параметров.&lt;br /&gt;
remaining_params=&amp;quot;$*&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;первый параметр = $first_param&amp;quot;          # one&lt;br /&gt;
echo &amp;quot;второй параметр = $second_param&amp;quot;         # two&lt;br /&gt;
echo &amp;quot;остальные параметры = $remaining_params&amp;quot; # three four five&lt;br /&gt;
echo; echo&lt;br /&gt;
# Снова.&lt;br /&gt;
set -- $variable&lt;br /&gt;
first_param=$1&lt;br /&gt;
second_param=$2&lt;br /&gt;
echo &amp;quot;первый параметр = $first_param&amp;quot;          # one&lt;br /&gt;
echo &amp;quot;второй параметр = $second_param&amp;quot;         # two&lt;br /&gt;
&lt;br /&gt;
# ======================================================&lt;br /&gt;
&lt;br /&gt;
set --&lt;br /&gt;
# Позиционные параметры сбрасываются, если не задано имя переменной.&lt;br /&gt;
&lt;br /&gt;
first_param=$1&lt;br /&gt;
second_param=$2&lt;br /&gt;
echo &amp;quot;первый параметр = $first_param&amp;quot;          # (пустое значение)&lt;br /&gt;
echo &amp;quot;второй параметр = $second_param&amp;quot;         # (пустое значение)&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''unset'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''unset''''' удаляет переменную, фактически — устанавливает её значение в ''null''. Обратите внимание: эта команда не может сбрасывать позиционные параметры (аргументы)!&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ unset PATH&lt;br /&gt;
bash$ echo $PATH&lt;br /&gt;
&lt;br /&gt;
bash$&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;quot;Сброс&amp;quot; переменной.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# unset.sh: Сброс переменной.&lt;br /&gt;
variable=hello                       # Инициализация.&lt;br /&gt;
echo &amp;quot;variable = $variable&amp;quot;&lt;br /&gt;
unset variable                       # Сброс.&lt;br /&gt;
                                     # Тот же эффект даёт variable=&lt;br /&gt;
echo &amp;quot;(unset) variable = $variable&amp;quot;  # $variable = null.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''export'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''export''' экспортирует переменную, делая её доступной дочерним процессам. К сожалению, невозможно экспортировать переменную родительскому процессу. В качестве примера использования команды '''export''' можно привести ''сценарии инициализации системы'', вызываемые в процессе загрузки, которые инициализируют и экспортируют ''переменные окружения'', делая их доступными для пользовательских процессов.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача переменных во вложенный сценарий awk, с помощью export.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Ещё одна версия сценария &amp;quot;column totaler&amp;quot; (col-totaler.sh)&lt;br /&gt;
# который суммирует заданную колонку (чисел) в заданном файле.&lt;br /&gt;
# Здесь используются переменные окружения, которые передаются сценарию 'awk'.&lt;br /&gt;
ARGS=2&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ] # Проверка количества входных аргументов.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename column-number&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
filename=$1&lt;br /&gt;
column_number=$2&lt;br /&gt;
#===== До этой строки идентично первоначальному варианту сценария =====#&lt;br /&gt;
export column_number&lt;br /&gt;
# Экспорт номера столбца.&lt;br /&gt;
# Начало awk-сценария.&lt;br /&gt;
# ------------------------------------------------&lt;br /&gt;
awk '{ total += $ENVIRON[&amp;quot;column_number&amp;quot;]&lt;br /&gt;
}&lt;br /&gt;
END { print total }' $filename&lt;br /&gt;
# ------------------------------------------------&lt;br /&gt;
# Конец awk-сценария.&lt;br /&gt;
# Спасибо Stephane Chazelas.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Допускается объединение инициализации и экспорта переменной в одну инструкцию: '''''export var1=xxx'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Однако, как заметил ''Greg Keraunen'', в некоторых ситуациях такая комбинация может давать иной результат, нежели раздельная инициализация и экспорт.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ export var=(a b); echo ${var[0]}&lt;br /&gt;
(a b)&lt;br /&gt;
bash$ var=(a b); export var; echo ${var[0]}&lt;br /&gt;
a&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''declare,typeset'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команды ''declare'' и ''typeset'' задают и/или накладывают ограничения на переменные.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''readonly'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
То же самое, что и '''''declare -r''''', делает переменную доступной только для чтения, т.е. переменная становится подобна константе. При попытке изменить значение такой переменной выводится сообщение об ошибке. Эта команда может расцениваться как квалификатор типа ''const'' в языке ''C''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''getopts'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Мощный инструмент, используемый для разбора аргументов, передаваемых сценарию из командной строки. Это встроенная команда Bash, но имеется и её &amp;quot;внешний&amp;quot; аналог '''''/usr/bin/getopt''''', а так же программистам, пишущим на ''C'', хорошо знакома похожая библиотечная функция ''getopt''. Она позволяет обрабатывать серии опций, объединённых в один аргумент и дополнительные аргументы, передаваемые сценарию (например, ''scriptname -abc -e/usr/local'').&amp;lt;br /&amp;gt;&lt;br /&gt;
С командой '''''getopts''''' очень тесно взаимосвязаны скрытые переменные. ''$OPTIND'' — указатель на аргумент (OPTion INDex) и ''$OPTARG'' (OPTion ARGument) — дополнительный аргумент опции. Символ двоеточия, следующий за именем опции, указывает на то, что она имеет дополнительный аргумент.&amp;lt;br /&amp;gt;&lt;br /&gt;
Обычно '''''getopts''''' упаковывается в цикл ''while'', в каждом проходе цикла извлекается очередная опция и её аргумент (если он имеется), обрабатывается, затем уменьшается на 1 скрытая переменная ''$OPTIND'' и выполняется переход к началу новой итерации.&lt;br /&gt;
# Опциям (ключам), передаваемым в сценарий из командной строки, должен предшествовать символ &amp;quot;минус&amp;quot; (-) или &amp;quot;плюс&amp;quot; (+). Этот префикс (- или +) позволяет '''''getopts''''' отличать опции (ключи) от прочих аргументов. Фактически, '''''getopts''''' не будет обрабатывать аргументы, если им не предшествует символ - или +, выделение опций будет прекращено как только встретится первый аргумент.&lt;br /&gt;
# Типичная конструкция цикла ''while'' с '''''getopts''''' несколько отличается от стандартной из-за отсутствия квадратных скобок, проверяющих условие продолжения цикла.&lt;br /&gt;
# Пример '''''getopts''''', заменившей не рекомендуемую к использованию, внешнюю команду '''''getopt'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
while getopts &amp;quot;:abcde:fg&amp;quot; Option&lt;br /&gt;
# Начальное объявление цикла анализа опций.&lt;br /&gt;
# a, b, c, d, e, f, g -- это возможные опции (ключи).&lt;br /&gt;
# Символ : после опции 'e' указывает на то, что с данной опцией может идти&lt;br /&gt;
# дополнительный аргумент.&lt;br /&gt;
do&lt;br /&gt;
 case $Option in&lt;br /&gt;
  a ) # Действия, предусмотренные опцией 'a'.&lt;br /&gt;
  b ) # Действия, предусмотренные опцией 'b'.&lt;br /&gt;
  ...&lt;br /&gt;
  e) # Действия, предусмотренные опцией 'e', а так же необходимо обработать $OPTARG,&lt;br /&gt;
     # в которой находится дополнительный аргумент этой опции.&lt;br /&gt;
  ...&lt;br /&gt;
  g ) # Действия, предусмотренные опцией 'g'.&lt;br /&gt;
 esac&lt;br /&gt;
done&lt;br /&gt;
shift $(($OPTIND - 1))&lt;br /&gt;
# Перейти к следующей опции.&lt;br /&gt;
# Всё не так сложно, как может показаться ;-)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Приём опций/аргументов, передаваемых сценарию, с помощью getopts.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ex33.sh&lt;br /&gt;
# Обработка опций командной строки с помощью 'getopts'.&lt;br /&gt;
# Попробуйте вызвать этот сценарий как:&lt;br /&gt;
# 'scriptname -mn'&lt;br /&gt;
# 'scriptname -oq qOption' (qOption может быть любой произвольной строкой.)&lt;br /&gt;
# 'scriptname -qXXX -r'&lt;br /&gt;
# 'scriptname -qr' - Неожиданный результат: &amp;quot;r&amp;quot; будет воспринят как дополнительный аргумент опции &amp;quot;q&amp;quot;&lt;br /&gt;
# 'scriptname -q -r' - То же самое, что и выше&lt;br /&gt;
# Если опция ожидает дополнительный аргумент (&amp;quot;flag:&amp;quot;), то следующий параметр&lt;br /&gt;
# в командной строке, будет воспринят как дополнительный аргумент этой опции.&lt;br /&gt;
NO_ARGS=0&lt;br /&gt;
E_OPTERROR=65&lt;br /&gt;
if [ $# -eq &amp;quot;$NO_ARGS&amp;quot; ] # Сценарий вызван без аргументов?&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` options (-mnopqrs)&amp;quot;&lt;br /&gt;
 exit $E_OPTERROR # Если аргументы отсутствуют — выход с сообщением&lt;br /&gt;
                  # о порядке использования скрипта&lt;br /&gt;
fi&lt;br /&gt;
# Порядок использования: scriptname -options&lt;br /&gt;
# Обратите внимание: дефис (-) обязателенwhile getopts &amp;quot;:mnopq:rs&amp;quot; Option&lt;br /&gt;
do&lt;br /&gt;
echo $OPTIND&lt;br /&gt;
 case $Option in&lt;br /&gt;
  m ) echo &amp;quot;Сценарий #1: ключ -m-&amp;quot;;;&lt;br /&gt;
  n | o ) echo &amp;quot;Сценарий #2: ключ -$Option-&amp;quot;;;&lt;br /&gt;
  p ) echo &amp;quot;Сценарий #3: ключ -p-&amp;quot;;;&lt;br /&gt;
  q ) echo &amp;quot;Сценарий #4: ключ -q-, с аргументом \&amp;quot;$OPTARG\&amp;quot;&amp;quot;;;&lt;br /&gt;
  # Обратите внимание: с ключом 'q' должен передаваться дополнительный аргумент,&lt;br /&gt;
  # в противном случае отработает выбор &amp;quot;по-умолчанию&amp;quot;.&lt;br /&gt;
  r | s ) echo &amp;quot;Сценарий #5: ключ -$Option-&amp;quot;'';;&lt;br /&gt;
  * ) echo &amp;quot;Выбран недопустимый ключ.&amp;quot;;; # ПО-УМОЛЧАНИЮ&lt;br /&gt;
 esac&lt;br /&gt;
done&lt;br /&gt;
shift $(($OPTIND - 1))&lt;br /&gt;
# Переход к очередному параметру командной строки.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Управление сценарием'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''source, .(точка)'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Когда эта команда вызывается из командной строки, то это приводит к запуску указанного сценария. Внутри сценария, команда ''source'' '''file-name''' загружает файл '''file-name'''. Таким образом она очень напоминает директиву препроцессора языка C/C++ — &amp;quot;#include&amp;quot;. Может найти применение в ситуациях, когда несколько сценариев пользуются одним файлом с данными или библиотекой функций.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;quot;Подключение&amp;quot; внешнего файла.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
. data-file # Загрузка файла с данными.&lt;br /&gt;
# Тот же эффект даёт &amp;quot;source data-file&amp;quot;, но этот вариант более переносим.&lt;br /&gt;
# Файл &amp;quot;data-file&amp;quot; должен находиться в текущем каталоге,&lt;br /&gt;
# т.к. путь к нему не указан.&lt;br /&gt;
# Теперь, выведем некоторые переменные из этого файла.&lt;br /&gt;
echo &amp;quot;variable1 (из data-file) = $variable1&amp;quot;&lt;br /&gt;
echo &amp;quot;variable3 (из data-file) = $variable3&amp;quot;&lt;br /&gt;
let &amp;quot;sum = $variable2 + $variable4&amp;quot;&lt;br /&gt;
echo &amp;quot;Сумма variable2 + variable4 (из data-file) = $sum&amp;quot;&lt;br /&gt;
echo &amp;quot;message1 (из data-file): \&amp;quot;$message1\&amp;quot;&amp;quot;&lt;br /&gt;
# Обратите внимание: кавычки экранированы&lt;br /&gt;
# print_message Вызвана функция вывода сообщений, находящаяся в data-file.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Файл data-file для пример, представленного выше, должен находиться в том же каталоге.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Этот файл подключается к сценарию.&lt;br /&gt;
# Подключаемые файлы могут содержать об&amp;quot;явления переменных, функций и т.п.&lt;br /&gt;
# Загружаться может командой 'source' или '.' .&lt;br /&gt;
# Инициализация некоторых переменных.&lt;br /&gt;
variable1=22&lt;br /&gt;
variable2=474&lt;br /&gt;
variable3=5&lt;br /&gt;
variable4=97&lt;br /&gt;
message1=&amp;quot;Привет! Как поживаете?&amp;quot;&lt;br /&gt;
message2=&amp;quot;Досвидания!&amp;quot;&lt;br /&gt;
print_message ()&lt;br /&gt;
{&lt;br /&gt;
# Вывод сообщения переданного в эту функцию.&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return 1&lt;br /&gt;
  # Ошибка, если аргумент отсутствует.&lt;br /&gt;
 fi&lt;br /&gt;
 echo&lt;br /&gt;
 until [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
 do&lt;br /&gt;
  # Цикл по всем аргументам функции.&lt;br /&gt;
  echo -n &amp;quot;$1&amp;quot;&lt;br /&gt;
  # Вывод аргумента с подавлением символа перевода строки.&lt;br /&gt;
  echo -n &amp;quot; &amp;quot;&lt;br /&gt;
  # Вставить пробел, для разделения выводимых аргументов.&lt;br /&gt;
  shift&lt;br /&gt;
  # Переход к следующему аргументу.&lt;br /&gt;
 done&lt;br /&gt;
 echo&lt;br /&gt;
 return 0&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Сценарий может подключить даже самого себя, только этому едва ли можно найти какое-либо практическое применение.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример (бесполезный) сценария, который подключает себя самого.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# self-source.sh: сценарий, который рекурсивно подключает себя самого.&amp;quot;&lt;br /&gt;
# Из &amp;quot;Бестолковые трюки&amp;quot;, том II.&lt;br /&gt;
MAXPASSCNT=100 # Максимальное количество проходов.&lt;br /&gt;
echo -n &amp;quot;$pass_count &amp;quot;&lt;br /&gt;
# На первом проходе выведет два пробела,&lt;br /&gt;
# т.к. $pass_count еще не инициализирована.&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;pass_count += 1&amp;quot;&lt;br /&gt;
# Операция инкремента не инициализированной переменной $pass_count&lt;br /&gt;
# на первом проходе вполне допустима.&lt;br /&gt;
# Этот прием срабатывает в Bash и pdksh, но,&lt;br /&gt;
# при переносе сценария в другие командные оболочки,&lt;br /&gt;
# он может оказаться неработоспособным или даже опасным.&lt;br /&gt;
# Лучшим выходом из положения, будет присвоить переменной $pass_count&lt;br /&gt;
# значение 0, если она не инициализирована.&lt;br /&gt;
while [ &amp;quot;$pass_count&amp;quot; -le $MAXPASSCNT ]&lt;br /&gt;
do&lt;br /&gt;
 . $0 # &amp;quot;Подключение&amp;quot; самого себя.&lt;br /&gt;
      # ./$0 (истинная рекурсия) в данной ситуации не сработает.&lt;br /&gt;
done&lt;br /&gt;
# Происходящее здесь фактически не является рекурсией как таковой,&lt;br /&gt;
# т.к. сценарий как бы &amp;quot;расширяет&amp;quot; себя самого&lt;br /&gt;
# (добавляя новый блок кода)&lt;br /&gt;
# на каждом проходе цикла 'while',&lt;br /&gt;
# командой 'source' в строке 22.&lt;br /&gt;
#&lt;br /&gt;
# Само собой разумеется, что первая строка (#!), вновь подключенного сценария,&lt;br /&gt;
# интерпретируется как комментарий, а не как начало нового сценария (sha-bang)&lt;br /&gt;
echo&lt;br /&gt;
exit 0 # The net effect is counting from 1 to 100.&lt;br /&gt;
       # Very impressive.&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ----------&lt;br /&gt;
# Напишите сценарий, который использовал бы этот трюк для чего либо полезного.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''exit'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Безусловное завершение работы сценария. Команде '''''exit''''' можно передать целое число, которое будет возвращено вызывающему процессу как код завершения. Вообще, считается хорошей практикой завершать работу сценария, за исключением простейших случаев, командой ''exit 0'', чтобы проинформировать родительский процесс об успешном завершении.&lt;br /&gt;
Если сценарий завершается командой ''exit'' без аргументов, то в качестве кода завершения сценария принимается код завершения последней выполненной команды, не считая самой команды ''exit''.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''exec'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Это встроенная команда интерпретатора ''shell'', заменяет текущий процесс новым процессом,запускаемым командой '''''exec'''''. Обычно, когда командный интерпретатор встречает эту команду, то он порождает дочерний процесс, чтобы исполнить команду. При использовании встроенной команды '''''exec''''', оболочка не порождает ещё один процесс, а заменяет текущий процесс другим. Для сценария это означает его завершение сразу после исполнения команды '''''exec'''''. По этой причине, если вам встретится '''''exec''''' в сценарии, то, скорее всего это будет последняя команда в сценарии.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Команда exec.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
exec echo &amp;quot;Завершение \&amp;quot;$0\&amp;quot;.&amp;quot; # Это завершение работы сценария.&lt;br /&gt;
# ----------------------------------&lt;br /&gt;
# Следующие ниже строки никогда не будут исполнены&lt;br /&gt;
echo &amp;quot;Эта строка никогда не будет выведена на экран.&amp;quot;&lt;br /&gt;
exit 99     # Сценарий завершит работу не здесь.&lt;br /&gt;
            # Проверьте код завершения сценария&lt;br /&gt;
            # командой 'echo $?'.&lt;br /&gt;
            # Он точно не будет равен 99.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий, который запускает себя самого.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# self-exec.sh&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Эта строка в сценарии единственная, но она продолжает выводиться раз за разом.&amp;quot;&lt;br /&gt;
echo &amp;quot;PID остался равным $$.&amp;quot;&lt;br /&gt;
# Демонстрация того, что команда exec не порождает дочерний процесс.&lt;br /&gt;
echo &amp;quot;==================== Для завершения - нажмите Ctl-C ====================&amp;quot;&lt;br /&gt;
sleep 1&lt;br /&gt;
exec $0 # Запуск очередного экземпляра этого же сценария&lt;br /&gt;
# который замещает предыдущий.&lt;br /&gt;
echo &amp;quot;Эта строка никогда не будет выведена!&amp;quot; # Почему?&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''''exec''''' так же может использоваться для перенаправления. Так, команда ''exec &amp;lt; zzz-file'' заменит стандартное устройство ввода (''stdin'') файлом ''zzz-file''.&lt;br /&gt;
Ключ ''-exec'' команды [[find]] — это не то же самое, что встроенная команда '''''exec'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''shopt'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда позволяет изменять ключи (опции) оболочки на лету. Её часто можно встретить в стартовых файлах, но может использоваться и в обычных сценариях. Требует Bash версии 2 или выше.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
shopt -s cdspell&lt;br /&gt;
# Исправляет незначительные орфографические ошибки в именах каталогов в команде 'cd'&lt;br /&gt;
cd /hpme # Oops! Имелось ввиду '/home'.&lt;br /&gt;
pwd      # /home&lt;br /&gt;
         # Shell исправил опечатку.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Команды'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''true'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда возвращает код завершения — ноль, или успешное завершение, и ничего больше.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Бесконечный цикл&lt;br /&gt;
while true # вместо &amp;quot;:&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
 operation-1&lt;br /&gt;
 operation-2&lt;br /&gt;
 ...&lt;br /&gt;
 operation-n&lt;br /&gt;
 # Следует предусмотреть способ завершения цикла иначе сценарий &amp;quot;зависнет&amp;quot;.&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''false'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Возвращает код завершения, свидетельствующий о неудаче, и ничего более.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Цикл, который никогда не будет исполнен&lt;br /&gt;
while false&lt;br /&gt;
do&lt;br /&gt;
 # Следующий код не будет исполнен никогда.&lt;br /&gt;
 operation-1&lt;br /&gt;
 operation-2&lt;br /&gt;
 ...&lt;br /&gt;
 operation-n&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''type [cmd]'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Очень похожа на внешнюю команду '''''which''''', '''''type cmd''''' выводит полный путь к &amp;quot;cmd&amp;quot;. В отличие от '''''which''''', '''''type''''' является внутренней командой Bash. С опцией ''-a'' не только различает ключевые слова и внутренние команды, но и определяет местоположение внешних команд с именами, идентичными внутренним.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ type '['&lt;br /&gt;
[ is a shell builtin&lt;br /&gt;
bash$ type -a '['&lt;br /&gt;
[ is a shell builtin&lt;br /&gt;
[ is /usr/bin/[&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''hash [cmds]'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Запоминает путь к заданной команде (в хэш-таблице командной оболочки), благодаря чему, при повторном обращении к ней, оболочка или сценарий уже не будет искать путь к команде в ''$PATH''. При вызове команды '''''hash''''' без аргументов, просто выводит содержимое хэш-таблицы. С ключом ''-r'' — очищает хэш-таблицу.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''help'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''help COMMAND''''' — выводит краткую справку по использованию внутренней команды ''COMMAND''. Аналог команды '''''whatis''''', только для внутренних команд.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ help exit&lt;br /&gt;
exit: exit [n]&lt;br /&gt;
 Exit the shell with a status of N. If N is omitted, the exit status&lt;br /&gt;
 is that of the last command executed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Команды управления заданиями ===&lt;br /&gt;
Некоторые из нижеследующих команд принимают, в качестве аргумента, &amp;quot;идентификатор задания&amp;quot; .См. таблицу в конце главы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''jobs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список заданий, исполняющихся в фоне. Команда [[ps]] более информативна.&lt;br /&gt;
''Задания'' и ''процессы'' легко спутать. Некоторые внутренние команды, такие как [[kill]], [[disown]] и [[wait]] принимают в качестве параметра либо номер задания, либо номер процесса. Команды [[fg]], [[bg]] и [[jobs]] принимают только номер задания.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ sleep 100 &amp;amp;&lt;br /&gt;
[1] 1384&lt;br /&gt;
bash $ jobs&lt;br /&gt;
[1]+ Running sleep 100 &amp;amp;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;quot;1&amp;quot; — это номер задания (управление заданиями осуществляет текущий командный интерпретатор), а &amp;quot;1384&amp;quot; — номер процесса (управление процессами осуществляется системой). Завершить задание/процесс (&amp;quot;прихлопнуть&amp;quot;) можно либо командой '''''kill %1''''', либо '''''kill 1384'''''. Спасибо S.C.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''disown'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаляет задание из таблицы активных заданий командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fg,bg'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''fg''''' переводит задание из фона на передний план. Команда '''''bg''''' перезапускает приостановленное задание в фоновом режиме. Если эти команды были вызваны без указания номера задания, то они воздействуют на текущее исполняющееся задание.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''wait'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Останавливает работу сценария до тех пор пока не будут завершены все фоновые задания или пока не будет завершено задание/процесс с указанным номером задания/PID процесса. Возвращает код завершения указанного задания/процесса. Вы можете использовать команду '''''wait''''' для предотвращения преждевременного завершения сценария до того, как завершит работу фоновое задание.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ожидание завершения процесса перед тем как продолжить работу.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
ROOT_UID=0 # Только пользователь с $UID = 0 имеет привилегии root.&lt;br /&gt;
E_NOTROOT=65&lt;br /&gt;
E_NOPARAMS=66&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Для запуска этого сценария вы должны обладать привилегиями root.&amp;quot;&lt;br /&gt;
 exit $E_NOTROOT&lt;br /&gt;
fi&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя-файла&amp;quot;&lt;br /&gt;
 exit $E_NOPARAMS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Обновляется база данных 'locate'...&amp;quot;&lt;br /&gt;
echo &amp;quot;Это может занять продолжительное время.&amp;quot;&lt;br /&gt;
updatedb /usr &amp;amp; # Должна запускаться с правами root.&lt;br /&gt;
wait&lt;br /&gt;
# В этом месте сценарий приостанавливает свою работу до тех пор, пока не отработает 'updatedb'.&lt;br /&gt;
# Желательно обновить базу данных перед тем как выполнить поиск файла.&lt;br /&gt;
locate $1&lt;br /&gt;
# В худшем случае, без команды wait, сценарий завершил бы свою работу до того,&lt;br /&gt;
# как завершила бы работу утилита 'updatedb',&lt;br /&gt;
# сделав из неё &amp;quot;осиротевший&amp;quot; процесс.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''''wait''''' может принимать необязательный параметр — номер задания/процесса,например, ''wait %1'' или ''wait $PPID''. См. таблицу идентификации заданий.&lt;br /&gt;
При запуске команды в фоне из сценария может возникнуть ситуация, когда сценарий приостанавливает свою работу до тех пор, пока не будет нажата клавиша ''ENTER''. Это, кажется, происходит с командами, делающими вывод на ''stdout''. Такое поведение может вызывать раздражение у пользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# test.sh&lt;br /&gt;
&lt;br /&gt;
ls -l &amp;amp;&lt;br /&gt;
echo &amp;quot;Done.&amp;quot;&lt;br /&gt;
bash$ ./test.sh&lt;br /&gt;
Done.&lt;br /&gt;
[bozo@localhost test-scripts]$ total 1&lt;br /&gt;
-rwxr-xr-x 1 bozo bozo 34 Oct 11 15:09 test.sh&lt;br /&gt;
_&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Разместив команду '''''wait''''', после запуска фонового задания, можно предотвратить такое поведение сценария.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# test.sh&lt;br /&gt;
&lt;br /&gt;
ls -l &amp;amp;&lt;br /&gt;
echo &amp;quot;Done.&amp;quot;&lt;br /&gt;
wait&lt;br /&gt;
bash$ ./test.sh&lt;br /&gt;
Done.&lt;br /&gt;
[bozo@localhost test-scripts]$ total 1&lt;br /&gt;
-rwxr-xr-x 1 bozo bozo 34 Oct 11 15:09 test.sh&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Перенаправление вывода в файл или даже на устройство ''/dev/null'' также снимает эту проблему.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''suspend'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Действует аналогично нажатию на комбинацию клавиш ''Control+Z'', за исключением того, что она приостанавливает работу командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''logout'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Завершает сеанс работы командной оболочки, можно указать необязательный код завершения.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''times'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выдаёт статистику исполнения команд в единицах системного времени, в следующем виде:&amp;lt;br /&amp;gt;&lt;br /&gt;
''0m0.020s 0m0.020s''&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Имеет весьма ограниченную сферу применения, так как сценарии крайне редко подвергаются профилированию.&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''kill'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Принудительное завершение процесса путем передачи ему соответствующего сигнала.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий, завершающий себя сам с помощью команды kill.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# self-destruct.sh&lt;br /&gt;
kill $$ # Сценарий завершает себя сам.&lt;br /&gt;
        # Надеюсь вы ещё не забыли, что &amp;quot;$$&amp;quot; — это PID сценария.&lt;br /&gt;
echo &amp;quot;Эта строка никогда не будет выведена.&amp;quot;&lt;br /&gt;
# Вместо него на stdout будет выведено сообщение &amp;quot;Terminated&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
# Какой код завершения вернет сценарий?&lt;br /&gt;
#sh self-destruct.sh&lt;br /&gt;
# echo $?&lt;br /&gt;
# 143&lt;br /&gt;
#&lt;br /&gt;
# 143 = 128 + 15&lt;br /&gt;
# сигнал TERM&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда ''kill -l'' выведет список всех сигналов. Команда ''kill -9'' — это &amp;quot;жёсткий kill&amp;quot;, она используется, как правило, для завершения зависших процессов, которые упорно отказываются &amp;quot;умирать&amp;quot;, отвергая простой '''''kill'''''. Иногда достаточно подать команду ''kill -15''. &amp;quot;Процессы-зомби&amp;quot;, т.е. процессы, &amp;quot;родители&amp;quot; которых уже завершили работу, не могут быть &amp;quot;убиты&amp;quot; таким способом (невозможно &amp;quot;убить&amp;quot; &amp;quot;мертвого&amp;quot;), рано или поздно с ними&amp;quot;расправится&amp;quot; процесс '''''init'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''command'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Директива '''''command COMMAND''''' запрещает использование псевдонимов и функций с именем &amp;quot;COMMAND&amp;quot;.&lt;br /&gt;
Это одна из трёх директив командного интерпретатора, которая влияет на обработку команд. Другие две — ''builtin'' и ''enable''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''builtin'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конструкция ''builtin BUILTIN_COMMAND'' запускает внутреннюю команду &amp;quot;BUILTIN_COMMAND&amp;quot;, на время запрещая использование функций и внешних системных команд с тем же именем.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''enable'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Либо запрещает, либо разрешает вызов внутренних команд. Например, '''''enable -n kill''''' запрещает использование внутренней команды ''kill'', в результате, когда интерпретатор встретит команду ''kill'', то он вызовет внешнюю команду ''kill'', т.е. ''/bin/kill''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда ''enable -a'' выведет список всех внутренних команд, указывая для каждой — действительно ли она разрешена. Команда ''enable -f filename'' загрузит внутренние команды как разделяемую библиотеку (DLL) из указанного объектного файла.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''autoload'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Перенесена в Bash из ksh. Если функция объявлена как '''''autoload''''', то она будет загружена из внешнего файла в момент первого вызова. Такой приём помогает экономить системные ресурсы. Обратите внимание: '''''autoload''''' не является частью ядра Bash. Её необходимо загрузить с помощью команды ''enable -f'' (см. выше).&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица. Идентификация заданий'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 300px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Нотация !! Описание&lt;br /&gt;
|-&lt;br /&gt;
| %N || Номер задания [N]&lt;br /&gt;
|-&lt;br /&gt;
| %S || Вызов (командная строка) задания, которая начинается со строки S&lt;br /&gt;
|-&lt;br /&gt;
| %?S || Вызов (командная строка) задания, которая содержит строку S&lt;br /&gt;
|-&lt;br /&gt;
| %% || &amp;quot;текущее&amp;quot; задание (последнее задание приостановленное на переднем плане или запущенное в фоне)&lt;br /&gt;
|-&lt;br /&gt;
| %+ || &amp;quot;текущее&amp;quot; задание (последнее задание приостановленное на переднем плане или запущенное в фоне)&lt;br /&gt;
|-&lt;br /&gt;
| %- || Последнее задание&lt;br /&gt;
|-&lt;br /&gt;
| $! || Последний фоновый процесс&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Внешние команды, программы и утилиты ==&lt;br /&gt;
Благодаря стандартизации набора команд Unix-систем, сценарии, на языке командной оболочки,могут быть легко перенесены из системы в систему практически без изменений. Мощь сценариев складывается из наборов системных команд и директив командной оболочки с простыми программными конструкциями.&lt;br /&gt;
=== Базовые команды ===&lt;br /&gt;
'''Первая команда, с которой сталкиваются новички'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ls'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда вывода &amp;quot;списка&amp;quot; файлов. Многие недооценивают всю мощь этой скромной команды. Например, с ключом -R, рекурсивный обход дерева каталогов, команда [[ls]] выводит содержимое каталогов в виде древовидной структуры. Вот ещё ряд любопытных ключей (опций) команды [[ls]]: ''-S'' — сортировка по размеру файлов, ''-t'' — сортировка по времени последней модификации файла и ''-i'' — выводит список файлов с их ''inode''&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание оглавления диска для записи CD-R, с помощью команды ls.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# burn-cd.sh&lt;br /&gt;
# Сценарий, автоматизирующий процесс прожигания CD-R.&lt;br /&gt;
SPEED=2 # Если ваше &amp;quot;железо&amp;quot; поддерживает более высокую скорость записи — можете увеличить этот параметр&lt;br /&gt;
IMAGEFILE=cdimage.iso&lt;br /&gt;
CONTENTSFILE=contents&lt;br /&gt;
DEFAULTDIR=/opt # В этом каталоге находятся файлы, которые будут записаны на CD.&lt;br /&gt;
                # Каталог должен существовать.&lt;br /&gt;
# Используется пакет &amp;quot;cdrecord&amp;quot; от Joerg Schilling.&lt;br /&gt;
# (http://www.fokus.gmd.de/nthp/employees/schilling/cdrecord.html)&lt;br /&gt;
&lt;br /&gt;
# Если этот сценарий предполагается запускать с правами обычного пользователя,&lt;br /&gt;
# то необходимо установить флаг suid на cdrecord&lt;br /&gt;
# (chmod u+s /usr/bin/cdrecord, эта команда должна быть выполнена root-ом).&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 IMAGE_DIRECTORY=$DEFAULTDIR&lt;br /&gt;
 # Каталог по-умолчанию, если иной каталог не задан из командной строки.&lt;br /&gt;
else&lt;br /&gt;
 IMAGE_DIRECTORY=$1&lt;br /&gt;
fi&lt;br /&gt;
# Создать файл &amp;quot;table of contents&amp;quot;.&lt;br /&gt;
ls -lRF $IMAGE_DIRECTORY &amp;gt; $IMAGE_DIRECTORY/$CONTENTSFILE&lt;br /&gt;
# Ключ &amp;quot;l&amp;quot; — &amp;quot;расширенный&amp;quot; формат вывода списка файлов.&lt;br /&gt;
# Ключ &amp;quot;R&amp;quot; — рекурсивный обход дерева каталогов.&lt;br /&gt;
# Ключ &amp;quot;F&amp;quot; -- добавляет дополнительные метки к именам файлов (к именам каталогов добавляет оконечный символ /).&lt;br /&gt;
echo &amp;quot;Создано оглавление.&amp;quot;&lt;br /&gt;
# Создать iso-образ.&lt;br /&gt;
mkisofs -r -o $IMAGFILE $IMAGE_DIRECTORY&lt;br /&gt;
echo &amp;quot;Создан iso-образ файловой системы ISO9660 ($IMAGEFILE).&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;Прожигание&amp;quot; CD-R.&lt;br /&gt;
cdrecord -v -isosize speed=$SPEED dev=0,0 $IMAGEFILE&lt;br /&gt;
echo &amp;quot;Запись диска.&amp;quot;&lt;br /&gt;
echo &amp;quot;Наберитесь терпения, это может потребовать некоторого времени.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cat,tac'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[cat]] — это акроним от ''concatenate'', выводит содержимое списка файлов на ''stdout''. Для объединения файлов в один файл может использоваться в комбинации с операциями перенаправления (''&amp;gt;'' или ''&amp;gt;&amp;gt;'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Порядок работы с 'cat'&lt;br /&gt;
cat filename                          # Вывод содержимого файла.&lt;br /&gt;
cat file.1 file.2 file.3 &amp;gt; file.123   # Объединение содержимого 3-х файлов в одном.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ключ ''-n'', команды [[cat]], вставляет порядковые номера строк в выходном файле. Ключ ''-b'' — нумерует только не пустые строки. Ключ ''-v'' выводит непечатаемые символы в нотации с&lt;br /&gt;
символом ''^''. Ключ ''-s'' заменяет несколько пустых строк, идущих подряд, одной пустой строкой.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''tac''''' — выводит содержимое файлов в обратном порядке, от последней строки к первой.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rev'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит все строки файла задом наперёд на ''stdout''. Это не то же самое, что '''''tac'''''. Команда '''''rev''''' сохраняет порядок следования строк, но переворачивает каждую строку задом наперёд.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat file1.txt &lt;br /&gt;
Это строка 1.&lt;br /&gt;
Это строка 2.&lt;br /&gt;
bash$ tac file1.txt&lt;br /&gt;
Это строка 2.&lt;br /&gt;
Это строка 1.&lt;br /&gt;
bash$ rev file1.txt.&lt;br /&gt;
.1 акортс отЭ&lt;br /&gt;
.2 акортс отЭ&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда копирования файлов. ''cp file1 file2'' скопирует ''file1'' в ''file2'', перезаписав file2, если он уже существовал.&amp;lt;br /&amp;gt;&lt;br /&gt;
С флагами ''-a'' и ''-r'', или ''-R'' выполняет копирование дерева каталогов.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mv'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда перемещения файла. Эквивалентна комбинации команд ''cp'' и ''rm''. Может использоваться для перемещения большого количества файлов или для переименования каталогов.&lt;br /&gt;
При использовании в неинтерактивных сценариях, команде [[mv]] следует передавать ключ ''-f'', чтобы подавить запрос подтверждения на перемещение.&amp;lt;br /&amp;gt;&lt;br /&gt;
Если в качестве каталога назначения указан существующий каталог, то перемещаемый каталог становится подкаталогом каталога назначения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ mv source_directory target_directory&lt;br /&gt;
bash$ ls -lF target_directory&lt;br /&gt;
total 1&lt;br /&gt;
drwxrwxr-x 2 bozo bozo 1024 May 28 19:20 source_directory/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаляет (remove) файл(ы). Ключ ''-f'' позволяет удалять даже файлы ТОЛЬКО-ДЛЯ-ЧТЕНИЯ и подавляет запрос подтверждения на удаление.&lt;br /&gt;
При попытке удаления файлов, чьи имена начинаются с символа &amp;quot;-&amp;quot; (дефис), команда [[rm]] будет давать сообщение об ошибке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ rm -badname&lt;br /&gt;
rm: invalid option — b&lt;br /&gt;
Try `rm --help' for more information.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Как вариант можно предложить предварять имена таких файлов точкой-со-слэшем — &amp;quot;./&amp;quot; (путь к файлу в текущем каталоге).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ rm ./-badname&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
С ключом ''-r'', удалит все файлы в подкаталогах, начиная с текущего.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rmdir'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаляет каталог. Удаляемый каталог не должен содержать файлов, включая &amp;quot;скрытые файлы&amp;quot;, иначе каталог не будет удалён.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mkdir'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создаёт новый каталог, например:&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''mkdir -p project/programs/December'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
создаёт каталог с заданным именем в требуемом каталоге. Ключ ''-p'' позволяет создавать промежуточные родительские каталоги.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''chmod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Изменяет атрибуты существующего файла.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
chmod +x filename&lt;br /&gt;
# Делает файл &amp;quot;filename&amp;quot; доступным для исполнения всем пользователям.&lt;br /&gt;
&lt;br /&gt;
chmod u+s filename&lt;br /&gt;
# Устанавливается бит &amp;quot;suid&amp;quot; для &amp;quot;filename&amp;quot;.&lt;br /&gt;
# В результате, любой пользователь сможет запустить &amp;quot;filename&amp;quot; с привилегиями владельца файла.&lt;br /&gt;
# (Это не относится к файлам-сценариям на языке командной оболочки.)&lt;br /&gt;
&lt;br /&gt;
chmod 644 filename&lt;br /&gt;
# Выдаёт право на запись/чтение владельцу файла &amp;quot;filename&amp;quot;, и право на чтение всем остальным (восьмеричное число).&lt;br /&gt;
&lt;br /&gt;
chmod 1777 directory-name&lt;br /&gt;
# Выдаёт право на чтение, запись и исполнение файлов в каталоге,&lt;br /&gt;
# дополнительно устанавливает &amp;quot;sticky bit&amp;quot;.&lt;br /&gt;
# Это означает, что удалять файлы в этом каталоге могут только владельцы файлов,&lt;br /&gt;
# владелец каталога и, само собой разумеется, root.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''chattr'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Изменяет атрибуты файла. Эта команда подобна команде '''''chmod''''', за исключением синтаксиса вызова, и работает исключительно в файловой системе ext2.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ln'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создаёт ссылку на существующий файл. Позволяет задавать несколько имён одному и тому же файлу и представляет из себя превосходную альтернативу &amp;quot;псевдонимам&amp;quot; (алиасам).&lt;br /&gt;
Размер файла-ссылки, создаваемого командой [[ln]], имеет длину всего в несколько байт.&amp;lt;br /&amp;gt;&lt;br /&gt;
Чаще всего команда [[ln]] используется с ключом ''-s'', который служит для создания ''символической''(''symbolic''), или ''&amp;quot;мягкой&amp;quot;'' (''&amp;quot;soft&amp;quot;'') ссылки. Без этого флага, команда создает полноценную копию имени файла. С ключом ''--'' только ссылку, указывающую на заданный файл. Дополнительное преимущество ключа ''-s'' состоит в том, что он позволяет создавать ссылки на файлы, расположенные в других файловых системах.&amp;lt;br /&amp;gt;&lt;br /&gt;
Синтаксис команды достаточно прост. Например, команда:&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''ln -s oldfile newfile'''''&lt;br /&gt;
создаст ссылку, с именем ''newfile'', на существующий файл ''oldfile'', если файл с именем ''newfile'' уже существует, то он будет удален командой [[ln]].&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Какого типа ссылки лучше использовать?&lt;br /&gt;
|-&lt;br /&gt;
| John Macdonald дает свой ответ на этот вопрос:&lt;br /&gt;
Без сомнения, оба варианта ссылок предоставляют возможность обращаться к файлу (к его содержимому). Так, если вы редактируете содержимое файла, загрузив его в редактор по имени ссылки, то внесённые изменения вы увидите, если откроете файл с использованием его оригинального имени. Различия между &amp;quot;жёсткими&amp;quot; и &amp;quot;мягкими&amp;quot; ссылками начинают проявляться когда вы поднимаетесь на более высокий уровень. Удаление или переименование файла, на который имеется &amp;quot;жёсткая&amp;quot; ссылка, никак не воздействует на ссылку. Она по прежнему продолжает ссылаться на файл (файл физически удаляется с диска только тогда, когда будет удалена последняя &amp;quot;жёсткая&amp;quot; ссылка на него, прим. перев.). В случае же с &amp;quot;мягкой&amp;quot; ссылкой всё наоборот — файл удаляется (переименовывается), а ссылка продолжает ссылаться на прежнее имя файла (так получаются &amp;quot;битые&amp;quot; ссылки, прим. перев.). Но главное преимущество &amp;quot;мягких&amp;quot; ссылок перед &amp;quot;жёсткими&amp;quot; состоит в том, что они могут указывать на файлы в других файловых системах (фактически, &amp;quot;мягкие&amp;quot; ссылки ссылаются не на дисковые блоки, где расположен файл, а на имя этого файла).&lt;br /&gt;
|}&lt;br /&gt;
Ссылки дают возможность запускать одну и ту же программу или сценарий, использую различные имена. В этом случае программист может предусмотреть свой вариант развития событий для каждого из имён.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Здравствуй или Прощай.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# hello.sh: Говорит &amp;quot;hello&amp;quot; или &amp;quot;goodbye&amp;quot;&lt;br /&gt;
# в зависимости от того под каким именем был вызван сценарий.&lt;br /&gt;
# Создайте ссылку на этот сценарий:&lt;br /&gt;
# ln -s hello.sh goodbye&lt;br /&gt;
# И попробуйте вызвать его под разными именами:&lt;br /&gt;
# ./hello.sh&lt;br /&gt;
# ./goodbye&lt;br /&gt;
HELLO_CALL=65&lt;br /&gt;
GOODBYE_CALL=66&lt;br /&gt;
if [ $0 = &amp;quot;./goodbye&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Пока!&amp;quot;&lt;br /&gt;
 # Можете вставить свой вариант прощания.&lt;br /&gt;
 exit $GOODBYECALL&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;Привет!&amp;quot;&lt;br /&gt;
# Можете вставить свой вариант приветствия.&lt;br /&gt;
exit $HELLO_CALL&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''man,info'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команды доступа к справочным и информационным страницам по системным командам и установленным программам и утилитам. Как правило, страницы '''''info''''' содержат более подробную информацию, чем '''''man'''''.&lt;br /&gt;
&lt;br /&gt;
=== Более сложные команды ===&lt;br /&gt;
'''Команды для более опытных пользователей'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''find'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''-exec''''' ''COMMAND \'';&amp;lt;br /&amp;gt;&lt;br /&gt;
Для каждого найденного файла, соответствующего заданному шаблону поиска, выполняет команду ''COMMAND''. Командная строка должна завершаться последовательностью символов ''\;'' (здесь символ &amp;quot;;&amp;quot; экранирован обратным слэшем, чтобы информировать командную оболочку о том, что символ &amp;quot;;&amp;quot; должен быть передан команде [[find]] как обычный символ). Если ''COMMAND'' содержит ''{}'', то [[find]] подставляет полное имя найденного файла вместо &amp;quot;{}&amp;quot;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ find ~/ -name '*.txt'&lt;br /&gt;
/home/bozo/.kde/share/apps/karm/karmdata.txt&lt;br /&gt;
/home/bozo/misc/irmeyc.txt&lt;br /&gt;
/home/bozo/test-scripts/1.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
find /home/bozo/projects -mtime 1# Найти все файлы в каталоге /home/bozo/projects и вложенных подкаталогах,&lt;br /&gt;
# Найти все файлы в каталоге /home/bozo/projects и вложенных подкаталогах,&lt;br /&gt;
# которые изменялись в течение последних суток.&lt;br /&gt;
# mtime = время последнего изменения файла&lt;br /&gt;
# ctime = время последнего изменения атрибутов файла (через 'chmod' или как-то иначе)&lt;br /&gt;
# atime = время последнего обращения к файлу&lt;br /&gt;
DIR=/home/bozo/junk_files&lt;br /&gt;
find &amp;quot;$DIR&amp;quot; -type f -atime +5 -exec rm {} \;&lt;br /&gt;
# Удалить все файлы в каталоге &amp;quot;/home/bozo/junk_files&amp;quot;&lt;br /&gt;
# к которым не было обращений в течение последних 5 дней.&lt;br /&gt;
# &amp;quot;-type filetype&amp;quot;, где&lt;br /&gt;
# f = обычный файл&lt;br /&gt;
# d = каталог, и т.п.&lt;br /&gt;
# (Полный список ключей вы найдете в 'man find'.)&lt;br /&gt;
find /etc -exec grep '[0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*[.][0-9][0-9]*' {} \;&lt;br /&gt;
# Поиск всех IP-адресов (xxx.xxx.xxx.xxx) в файлах каталога /etc.&lt;br /&gt;
# Однако эта команда выводит не только IP-адреса, как этого избежать?&lt;br /&gt;
# Примерно так:&lt;br /&gt;
find /etc -type f -exec cat '{}' \; | tr -c '.[:digit:]' '\n' \&lt;br /&gt;
| grep '^[^.][^.]*\.[^.][^.]*\.[^.][^.]*\.[^.][^.]*$'&lt;br /&gt;
# [:digit:] — один из символьных классов&lt;br /&gt;
# введен в стандарт POSIX 1003.2.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Не следует путать опцию ''-exec'' команды [[find]] с внутренней командой Bash — exec.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Badname, удаление файлов в текущем каталоге, имена которых содержат недопустимые символы и пробелы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Удаление файлов в текущем каталоге, чьи имена содержат недопустимые символы.&lt;br /&gt;
for filename in *&lt;br /&gt;
do&lt;br /&gt;
 badname=`echo &amp;quot;$filename&amp;quot; | sed -n /[\+\{\;\&amp;quot;\\\=\?~\(\)\&amp;lt;\&amp;gt;\&amp;amp;\*\|\$]/p`&lt;br /&gt;
 # Недопустимые символы в именах файлов: + { ; &amp;quot; \ = ? ~ ( ) &amp;lt; &amp;gt; &amp;amp; * | $&lt;br /&gt;
 rm $badname 2&amp;gt;/dev/null # Сообщения об ошибках &amp;quot;выстреливаются&amp;quot; в никуда.&lt;br /&gt;
done&lt;br /&gt;
# Теперь &amp;quot;позаботимся&amp;quot; о файлах, чьи имена содержат пробельные символы.&lt;br /&gt;
find . -name &amp;quot;* *&amp;quot; -exec rm -f {} \;&lt;br /&gt;
# На место &amp;quot;{}&amp;quot;, find подставит полное имя файла.&lt;br /&gt;
# Символ '\' указывает на то, что ';' интерпретируется как обычный символ, а не как конец команды.&lt;br /&gt;
exit 0&lt;br /&gt;
#---------------------------------------------------------------------&lt;br /&gt;
# Строки, приведённые ниже, не будут выполнены, т.к. выше стоит команда &amp;quot;exit&amp;quot;.&lt;br /&gt;
# Альтернативный вариант сценария:&lt;br /&gt;
find . -name '*[+{;&amp;quot;\\=?~()&amp;lt;&amp;gt;&amp;amp;*|$ ]*' -exec rm -f '{}' \;&lt;br /&gt;
exit 0&lt;br /&gt;
# (Спасибо S.C.)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Удаление файла по его номеру inode.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# idelete.sh: Удаление файла по номеру inode.&lt;br /&gt;
# Этот прием используется в тех случаях, когда имя файла начинается с недопустимого символа,&lt;br /&gt;
# например, ? или -.&lt;br /&gt;
ARGCOUNT=1                   # Имя файла должно быть передано в сценарий.&lt;br /&gt;
E_WRONGARGS=70&lt;br /&gt;
E_FILE_NOT_EXIST=71&lt;br /&gt;
E_CHANGED_MIND=72&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGCOUNT&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
if [ ! -e &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;&amp;quot;$1&amp;quot;\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_FILE_NOT_EXIST&lt;br /&gt;
fi&lt;br /&gt;
inum=`ls -i | grep &amp;quot;$1&amp;quot; | awk '{print $1}'`&lt;br /&gt;
# inum = номер inode (index node) файла&lt;br /&gt;
# Каждый файл имеет свой inode, где хранится информация о физическом расположении файла.&lt;br /&gt;
echo; echo -n &amp;quot;Вы совершенно уверены в том, что желаете удалить \&amp;quot;$1\&amp;quot; (y/n)? &amp;quot;&lt;br /&gt;
# Ключ '-v' в команде 'rm' тоже заставит команду вывести подобный запрос.&lt;br /&gt;
read answer&lt;br /&gt;
case &amp;quot;$answer&amp;quot; in&lt;br /&gt;
 [nN]) echo &amp;quot;Передумали?&amp;quot;&lt;br /&gt;
       exit $E_CHANGED_MIND&lt;br /&gt;
       ;;&lt;br /&gt;
 *) echo &amp;quot;Удаление файла \&amp;quot;$1\&amp;quot;.&amp;quot;;;&lt;br /&gt;
esac&lt;br /&gt;
find . -inum $inum -exec rm {} \;&lt;br /&gt;
echo &amp;quot;Файл &amp;quot;\&amp;quot;$1&amp;quot;\&amp;quot; удалён!&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Дополнительные примеры по использованию команды [[find]] вы найдете в страницах справочного руководства (''man find'') вы найдете более подробную информацию об этой достаточно сложной и мощной команде.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''xargs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда передачи аргументов указанной команде. Она разбивает поток аргументов на отдельные составляющие и поочередно передаёт их заданной команде для обработки. Эта команда может рассматриваться как мощная замена обратным одинарным кавычкам. Зачастую, когда команды, заключенные в обратные одиночные кавычки, завершаются с ошибкой ''too many arguments'' (слишком много аргументов), использование '''''xargs''''' позволяет обойти это ограничение. Обычно, ''xargs'' считывает список аргументов со стандартного устройства ввода ''stdin'' или из канала (конвейера), но может считывать информацию и из файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
Если команда не задана, то по-умолчанию выполняется [[echo]]. При передаче аргументов по конвейеру, '''''xargs''''' допускает наличие пробельных символов и символов перевода строки, которые затем автоматически отбрасываются.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ls -l&lt;br /&gt;
total 0&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file2&lt;br /&gt;
bash$ ls -l | xargs&lt;br /&gt;
total 0 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58 file1 -rw-rw-r-- 1 bozo bozo 0 Jan 29 23:58&lt;br /&gt;
file2&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;ls | xargs -p -l gzip&amp;lt;/source&amp;gt; — упакует с помощью [[gzip]] все файлы в текущем каталоге, выводя запрос на подтверждение для каждого файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''xargs''''' имеет очень любопытный ключ ''-n NN'', который ограничивает количество передаваемых аргументов за один &amp;quot;присест&amp;quot; числом ''NN''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;ls | xargs -n 8 echo&amp;lt;/source&amp;gt; — выведет список файлов текущего каталога в 8 колонок.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё одна полезная опция — -0, в комбинации с '''''find -print 0''''' или '''''grep -lZ''''' позволяет обрабатывать аргументы, содержащие пробелы и кавычки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;find / -type f -print0 | xargs -0 grep -liwZ GUI | xargs -0 rm -f&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;grep -rliwZ GUI / | xargs -0 rm -f&amp;lt;/source&amp;gt;&lt;br /&gt;
Обе вышеприведенные команды удалят все файлы, содержащие в своём имени комбинацию символов &amp;quot;GUI&amp;quot;. (Спасибо S.C.)&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование команды xargs для мониторинга системного журнала.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Создание временного файла мониторинга в текущем каталоге,&lt;br /&gt;
# куда переписываются несколько последних строк из /var/log/messages.&lt;br /&gt;
# Обратите внимание: если сценарий запускается обычным пользователем,&lt;br /&gt;
# то файл /var/log/messages должен быть доступен на чтение этому пользователю.&lt;br /&gt;
# #root chmod 644 /var/log/messages&lt;br /&gt;
LINES=5( date; uname -a ) &amp;gt;&amp;gt;logfile&lt;br /&gt;
# Время и информация о системе&lt;br /&gt;
echo --------------------------------------------------------------------- &amp;gt;&amp;gt;logfile&lt;br /&gt;
tail -$LINES /var/log/messages | xargs | fmt -s &amp;gt;&amp;gt;logfile&lt;br /&gt;
echo &amp;gt;&amp;gt;logfile&lt;br /&gt;
echo &amp;gt;&amp;gt;logfileexit 0&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Измените сценарий таким образом, чтобы он мог отслеживать изменения в /var/log/messages&lt;br /&gt;
# с интервалом в 20 минут.&lt;br /&gt;
# Подсказка: воспользуйтесь командой &amp;quot;watch&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''copydir, копирование файлов из текущего каталога в другое место.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Копирует все файлы из текущего каталога&lt;br /&gt;
# в каталог, указанный в командной строке.&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ] # Выход, если каталог назначения не задан.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` directory-to-copy-to&amp;quot;&lt;br /&gt;
exit 65&lt;br /&gt;
fi&lt;br /&gt;
ls . | xargs -i -t cp ./{} $1 # Этот сценария является точным эквивалентом&lt;br /&gt;
# cp * $1&lt;br /&gt;
# если в именах файлов не содержатся пробельные символы.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Завершение работы процесса по его имени.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# kill-byname.sh: Завершение работы процесса по его имени.&lt;br /&gt;
# Сравните этот сценарий с kill-process.sh.&lt;br /&gt;
# Пример,&lt;br /&gt;
# Попробуйте запустить команду &amp;quot;./kill-byname.sh xterm&amp;quot; —&lt;br /&gt;
#+ и понаблюдайте как закроются все окна xterm.&lt;br /&gt;
# Внимание:&lt;br /&gt;
# --------&lt;br /&gt;
# Этот сценарий может представлять определенную угрозу.&lt;br /&gt;
# Запуск этого сценария (особенно с правами root)&lt;br /&gt;
# может привести к потере несохранённых данных и другим неожиданным эффектам.&lt;br /&gt;
E_BADARGS=66&lt;br /&gt;
if test -z &amp;quot;$1&amp;quot; # Проверка — задано ли имя процесса &lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` останавливаемый(ые)_процесс(ы)&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
# ---------------------------------------------------------&lt;br /&gt;
# Примечание:&lt;br /&gt;
# Ключ -i команды xargs — это &amp;quot;замена строки&amp;quot; .&lt;br /&gt;
# Фигурные скобки — это замещаемая строка.&lt;br /&gt;
# 2&amp;amp;&amp;gt;/dev/null — подавляет вывод сообщений об ошибках.&lt;br /&gt;
# ---------------------------------------------------------&lt;br /&gt;
PROCESS_NAME=&amp;quot;$1&amp;quot;&lt;br /&gt;
ps ax | grep &amp;quot;$PROCESS_NAME&amp;quot; | awk '{print $1}' | xargs -i kill {} 2&amp;amp;&amp;gt;/dev/null&lt;br /&gt;
exit $?&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Подсчёт частоты встречаемости слов using xargs.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# wf2.sh: Грубый подсчёт частоты встречаемости слова в текстовом файле.&lt;br /&gt;
# Команда 'xargs' используется для выделения отдельных слов из строки.&lt;br /&gt;
# Сравните этот сценарий с &amp;quot;wf.sh&amp;quot;.&lt;br /&gt;
# Проверка — задано ли имя файла из командной строки.&lt;br /&gt;
ARGS=1&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
E_NOFILE=66&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
# Передано корректное число аргументов?&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя_файла&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
if [ ! -f &amp;quot;$1&amp;quot; ] # Проверка наличия файла.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$1\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOFILE&lt;br /&gt;
fi&lt;br /&gt;
#######################################################&lt;br /&gt;
cat &amp;quot;$1&amp;quot; | xargs -n1 | \&lt;br /&gt;
# Вывод содержимого файла, по одному слову в строке.&lt;br /&gt;
tr A-Z a-z | \&lt;br /&gt;
# Преобразование в нижний регистр.&lt;br /&gt;
sed -e 's/\.//g' -e 's/\,//g' -e 's/ /\&lt;br /&gt;
/g' | \&lt;br /&gt;
# Отбросить точки и запятые и&lt;br /&gt;
# заменить пробелы символами перевода строки,&lt;br /&gt;
sort | uniq -c | sort -nr # В заключение — подсчитать и отсортировать по частоте встречаемости.&lt;br /&gt;
#######################################################&lt;br /&gt;
# Этот сценарий выполняет те же действия, что и &amp;quot;wf.sh&amp;quot;,&lt;br /&gt;
# но он более &amp;quot;тяжелый&amp;quot; и работает значительно медленнее.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''expr'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Универсальный обработчик выражений: вычисляет заданное выражение (аргументы должны отделяться пробелами). Выражения могут быть арифметическими, логическими или строковыми.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;expr 3 + 5&amp;lt;/source&amp;gt;&lt;br /&gt;
возвратит 8&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;expr 5 % 3&amp;lt;/source&amp;gt;&lt;br /&gt;
возвратит 2&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;expr 5 \* 3&amp;lt;/source&amp;gt;&lt;br /&gt;
возвратит 15&lt;br /&gt;
В арифметических выражениях, оператор умножения обязательно должен экранироваться обратным слэшем.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;y=`expr $y + 1`&amp;lt;/source&amp;gt;&lt;br /&gt;
Операция инкремента переменной, то же самое, что и let y=y+1, или y=$(($y+1)). Пример подстановки арифметических выражений.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;z=`expr substr $string $position $length`&amp;lt;/source&amp;gt;&lt;br /&gt;
Извлекает подстроку длиной $length символов, начиная с позиции $position.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример работы с expr.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Демонстрация некоторых приемов работы с командой 'expr'&lt;br /&gt;
# =======================================&lt;br /&gt;
echo&lt;br /&gt;
# Арифметические операции&lt;br /&gt;
# ----------------------&lt;br /&gt;
echo &amp;quot;Арифметические операции&amp;quot;&lt;br /&gt;
echo &lt;br /&gt;
a=`expr 5 + 3`&lt;br /&gt;
echo &amp;quot;5 + 3 = $a&amp;quot;&lt;br /&gt;
a=`expr $a + 1`&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;a + 1 = $a&amp;quot;&lt;br /&gt;
echo &amp;quot;(инкремент переменной)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
a=`expr 5 % 3`&lt;br /&gt;
# остаток от деления (деление по модулю)&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;5 mod 3 = $a&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo# Логические операции&lt;br /&gt;
# ------------------&lt;br /&gt;
&lt;br /&gt;
# Возвращает 1 если выражение истинно, 0 — если ложно,&lt;br /&gt;
# в противоположность соглашениям, принятым в Bash.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Логические операции&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
x=24&lt;br /&gt;
y=25&lt;br /&gt;
b=`expr $x = $y` # Сравнение.&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # 0 ( $x -ne $y )&lt;br /&gt;
echo&lt;br /&gt;
a=3b=`expr $a \&amp;gt; 10`&lt;br /&gt;
echo 'b=`expr $a \&amp;gt; 10`, поэтому...'&lt;br /&gt;
echo &amp;quot;Если a &amp;gt; 10, то b = 0 (ложь)&amp;quot;&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # 0 ( 3 ! -gt 10 )&lt;br /&gt;
echo&lt;br /&gt;
b=`expr $a \&amp;lt; 10`&lt;br /&gt;
echo &amp;quot;Если a &amp;lt; 10, то b = 1 (истина)&amp;quot;&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # 1 ( 3 -lt 10 )&lt;br /&gt;
echo&lt;br /&gt;
# Обратите внимание на необходимость экранирования операторов.&lt;br /&gt;
b=`expr $a \&amp;lt;= 3`&lt;br /&gt;
echo &amp;quot;Если a &amp;lt;= 3, то b = 1 (истина)&amp;quot;&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # 1 ( 3 -le 3 )&lt;br /&gt;
# Существует еще оператор &amp;quot;\&amp;gt;=&amp;quot; (больше или равно).&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
# Операции сравнения&lt;br /&gt;
#-----------------&lt;br /&gt;
echo &amp;quot;Операции сравнения&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
a=zipper&lt;br /&gt;
echo &amp;quot;a is $a&amp;quot;&lt;br /&gt;
if [ `expr $a = snap` ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;a -- это не zipper&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Операции со строками&lt;br /&gt;
#------------------&lt;br /&gt;
echo &amp;quot;Операции со строками&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
a=1234&lt;br /&gt;
zipper43231&lt;br /&gt;
echo &amp;quot;Строка над которой производятся операции: \&amp;quot;$a\&amp;quot;.&amp;quot;&lt;br /&gt;
# length: длина строки&lt;br /&gt;
b=`expr length $a`&lt;br /&gt;
echo &amp;quot;длина строки \&amp;quot;$a\&amp;quot; равна $b.&amp;quot;&lt;br /&gt;
# index: позиция первого символа подстроки в строке&lt;br /&gt;
b=`expr index $a 23`&lt;br /&gt;
echo &amp;quot;Позиция первого символа \&amp;quot;2\&amp;quot; в строке \&amp;quot;$a\&amp;quot; : \&amp;quot;$b\&amp;quot;.&amp;quot;&lt;br /&gt;
# substr: извлечение подстроки, начиная с заданной позиции, указанной длины&lt;br /&gt;
b=`expr substr $a 2 6`&lt;br /&gt;
echo &amp;quot;Подстрока в строке \&amp;quot;$a\&amp;quot;, начиная с позиции 2,\&lt;br /&gt;
и длиной в 6 символов: \&amp;quot;$b\&amp;quot;.&amp;quot;&lt;br /&gt;
# При выполнении поиска по шаблону, по-умолчанию поиск&lt;br /&gt;
# начинается с ***начала*** строки.&lt;br /&gt;
#&lt;br /&gt;
# Использование регулярных выражений&lt;br /&gt;
b=`expr match &amp;quot;$a&amp;quot; '[0-9]*'` # Подсчёт количества цифр.&lt;br /&gt;
echo Количество цифр с начала строки \&amp;quot;$a\&amp;quot; : $b.&lt;br /&gt;
b=`expr match &amp;quot;$a&amp;quot; '\([0-9]*\)'` # Обратите внимание на экранирование круглых скобок&lt;br /&gt;
# == ==&lt;br /&gt;
echo &amp;quot;Цифры, стоящие в начале строки \&amp;quot;$a\&amp;quot; : \&amp;quot;$b\&amp;quot;.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Вместо оператора '''''match''''' можно использовать оператор '':'' . Например, команда&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;b=`expr $a : [0-9]*`&amp;lt;/source&amp;gt;&lt;br /&gt;
является точным эквивалентом для &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;b=`expr match $a [0-9]*`&amp;lt;/source&amp;gt; в примере, рассмотренном выше.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Операции над строками с использованием конструкции \&amp;quot;expr \$string : \&amp;quot;&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&amp;quot;========================================================================&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
a=1234zipper5FLIPPER43231&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Строка, над которой выполняются операции: \&amp;quot;`expr &amp;quot;$a&amp;quot; : '\(.*\)'`\&amp;quot;.&amp;quot;&lt;br /&gt;
# Экранирование круглых скобок в шаблоне                         == ==&lt;br /&gt;
&lt;br /&gt;
# Если скобки не экранировать...&lt;br /&gt;
# то 'expr' преобразует строковый операнд в целое число.&lt;br /&gt;
echo &amp;quot;Длина строки \&amp;quot;$a\&amp;quot; равна `expr &amp;quot;$a&amp;quot; : '.*'`.&amp;quot; &lt;br /&gt;
# Длина строки&lt;br /&gt;
echo &amp;quot;Количество цифр с начала строки \&amp;quot;$a\&amp;quot; равно `expr &amp;quot;$a&amp;quot; : '[0-9]*'`.&amp;quot;&lt;br /&gt;
# -------------------------------------------------------------------------&lt;br /&gt;
#&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Цифры, стоящие в начале строки \&amp;quot;$a\&amp;quot; : `expr &amp;quot;$a&amp;quot; : '\([0-9]*\)'`.&amp;quot;&lt;br /&gt;
#                                                              ==      ==&lt;br /&gt;
echo &amp;quot;Первые 7 символов в строке \&amp;quot;$a\&amp;quot; : `expr &amp;quot;$a&amp;quot; : '\(.......\)'`.&amp;quot;&lt;br /&gt;
#     ======                                           ==       ==&lt;br /&gt;
# Опять же, необходимо экранировать круглые скобки в шаблоне.&lt;br /&gt;
#&lt;br /&gt;
echo &amp;quot;Последние 7 символов в строке \&amp;quot;$a\&amp;quot; : `expr &amp;quot;$a&amp;quot; : '.*\(.......\)'`.&amp;quot;&lt;br /&gt;
#     =========                      оператор конца строки ^^&lt;br /&gt;
# (фактически означает переход через любое количество символов, пока&lt;br /&gt;
# не будет найдена требуемая подстрока)&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Этот пример демонстрирует необходимость экранирования оператора группировки — ''\( ... \)'' в регулярных выражениях, при поиске по шаблону командой '''''expr'''''.&lt;br /&gt;
Perl, [[sed]] и [[awk]] имеют в своем распоряжении более мощный аппарат анализа строк. Коротенький скрипт на [[sed]] или [[awk]], внутри сценария — значительно более привлекательная альтернатива использованию '''''expr''''' при анализе строк.&lt;br /&gt;
&lt;br /&gt;
=== Команды для работы с датой и временем ===&lt;br /&gt;
'''Время/дата и измерение интервалов времени'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''date'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда [[date]] без параметров выводит дату и время на стандартное устройство вывода ''stdout''. Она становится гораздо интереснее при использовании дополнительных ключей форматирования вывода.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Команда date.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Примеры использования команды 'date'echo &amp;quot;Количество дней, прошедших с начала года: `date +%j`.&amp;quot;&lt;br /&gt;
# Символ '+' обязателен при использовании форматирующего аргумента&lt;br /&gt;
# %j, возвращающего количество дней, прошедших с начала года.&lt;br /&gt;
echo &amp;quot;Количество секунд, прошедших с 01/01/1970 : `date +%s`.&amp;quot;&lt;br /&gt;
# %s количество секунд, прошедших с начала &amp;quot;эпохи UNIX&amp;quot;,&lt;br /&gt;
# но насколько этот ключ полезен?&lt;br /&gt;
&lt;br /&gt;
prefix=tempsuffix=`eval date +%s` &lt;br /&gt;
# Ключ &amp;quot;+%s&amp;quot; характерен для GNU-версии 'date'.&lt;br /&gt;
filename=$prefix.$suffix&lt;br /&gt;
echo $filename&lt;br /&gt;
# Прекрасный способ получения &amp;quot;уникального&amp;quot; имени для временного файла,&lt;br /&gt;
# даже лучше, чем с использованием $$.&lt;br /&gt;
# Дополнительную информацию вы найдете в 'man date'.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ключ ''-u'' даёт UTC время (Universal Coordinated Time — время по Гринвичу).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ date&lt;br /&gt;
Fri Mar 29 21:07:39 MST 2002&lt;br /&gt;
bash$ date -u&lt;br /&gt;
Sat Mar 30 04:07:42 UTC 2002&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''''date''''' имеет ряд дополнительных ключей форматирования вывода. Например, ''%N'' выводит долю наносекунд текущего времени. Этому ключу формата можно привести одно весьма любопытное применение — ''генерация шестизначных псевдослучайных целых чисел''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
date +%N | sed -e 's/000$//' -e 's/^0//'&lt;br /&gt;
#          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;br /&gt;
# Удаление ведущих и завершающих нулей, если таковые присутствуют.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''zdump'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Отображает время для указанной временной зоны.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ zdump EST&lt;br /&gt;
EST Tue Sep 18 22:09:22 2001 EST&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''time'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит подробную статистику по исполнению некоторой команды.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;time ls -l / &amp;lt;/source&amp;gt;&lt;br /&gt;
даст нечто подобное:&amp;lt;br /&amp;gt;&lt;br /&gt;
'' 0.00 user 0.01 system 0:00.05 elapsed 16% CPU (0 avgtext + 0a vgdata 0 maxresident) k 0 inputs + 0 outputs (149 major + 27 minor) page faults 0 swaps''&amp;lt;br /&amp;gt;&lt;br /&gt;
Начиная с версии 2.0 Bash, команда '''''time''''' стала зарезервированным словом интерпретатора, с несколько изменённым поведением в конвейере.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''touch'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита устанавливает время последнего обращения/изменения файла в текущее системное время или в заданное время, но так же может использоваться для создания нового пустого файла. Команда '''''touch zzz''''' создаст новый пустой файл с именем ''zzz'', если перед этим файл ''zzz'' отсутствовал. Кроме того, такие пустые файлы могут использоваться для индикации, например, времени последнего изменения в проекте.&amp;lt;br /&amp;gt;&lt;br /&gt;
Эквивалентом команды [[touch — Команда создания пустого файла и модификации времени последнего изменения файла | touch]] могут служить ''''': &amp;gt;&amp;gt; newfile''''' или '''''&amp;gt;&amp;gt; newfile''''' (для обычных файлов).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''at'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''at''''' — используется для запуска заданий в заданное время. В общих чертах она напоминает ''cron'', однако, '''''at''''' используется для однократного запуска набора команд.&lt;br /&gt;
''at 2pm January 15'' — попросит ввести набор команд, которые необходимо запустить в указанное время. Эти команды должны быть совместимыми со сценариями командной оболочки. Ввод завершается нажатием комбинации клавиш ''Ctl-D''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''-f'' или операция перенаправления ввода (''&amp;lt;''), заставляет '''''at''''' прочитать список команд из файла. Этот файл должен представлять из себя обычный сценарий, на языке командной оболочки и, само собой разумеется, такой сценарий должен быть неинтерактивным. Может использоваться совместно с командой ''run-parts'' для запуска различных наборов сценариев.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;bash$ at 2:30 am Friday &amp;lt; at-jobs.listjob 2 at 2000-10-27 02:30&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''batch'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''batch''''', управляющая запуском заданий, напоминает команду '''''at''''', но запускает список команд только тогда, когда загруженность системы упадет ниже ''.8''. Подобно команде '''''at''''', с ключом ''-f'', может считывать набор команд из файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cal'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит на ''stdout'' аккуратно отформатированный календарь на текущий месяц. Может выводить календарь за определенный год.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sleep'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Приостанавливает исполнение сценария на заданное количество секунд, ничего не делая. Может использоваться для синхронизации процессов, запущенных в фоне, проверяя наступление ожидаемого события так часто, как это необходимо.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;sleep 3      # Пауза, длительностью в 3 секунды.&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда '''''sleep''''' по-умолчанию принимает количество секунд, но ей можно передать и количество часов и минут и даже дней.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;sleep 3 h          # Приостановка на 3 часа!&amp;lt;/source&amp;gt;&lt;br /&gt;
Для запуска команд через заданные интервалы времени лучше использовать '''''watch'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''usleep'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Microsleep (здесь символ &amp;quot;u&amp;quot; должен читаться как буква греческого алфавита — &amp;quot;мю&amp;quot;, или префикс микро). Это то же самое, что и sleep, только интервал времени задается в микросекундах. Может использоваться для очень тонкой синхронизации процессов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;usleep 30         # Приостановка на 30 микросекунд.&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда является частью пакета initscripts/rc-scripts в дистрибутиве Red Hat. Команда '''''usleep''''' не обеспечивает особую точность соблюдения интервалов, и поэтому она не подходит для применений, критичных ко времени.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''hwclock,clock'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''hwclock''''' используется для получения доступа или коррекции аппаратных часов компьютера. С некоторыми ключами требует наличия привилегий root. Сценарий /etc/rc.d/rc.sysinit использует команду '''''hwclock''''' для установки системного времени во время загрузки.&lt;br /&gt;
Команда '''''clock''''' — это синоним команды '''''hwclock'''''.&lt;br /&gt;
&lt;br /&gt;
=== Команды обработки текста ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sort'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сортирует содержимое файла, часто используется как промежуточный фильтр в конвейерах. Эта команда сортирует поток текста в порядке убывания или возрастания, в зависимости от заданных опций. Ключ ''-m'' используется для сортировки и объединения входных файлов. В странице '''''info''''' перечислено большое количество возможных вариантов ключей.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tsort'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Топологическая сортировка, считывает пары строк, разделённых пробельными символами, и выполняет сортировку, в зависимости от заданного шаблона.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''uniq'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаляет повторяющиеся строки из отсортированного файла. Эту команду часто можно встретить в конвейере с командой '''''sort'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat list-1 list-2 list-3 | sort | uniq &amp;gt; final.list&lt;br /&gt;
# Содержимое файлов, сортируется,&lt;br /&gt;
# затем удаляются повторяющиеся строки,&lt;br /&gt;
# и результат записывается в выходной файл final.list.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ключ ''-c'' выводит количество повторяющихся строк.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat testfile&lt;br /&gt;
Эта строка встречается только один раз.&lt;br /&gt;
Эта строка встречается дважды.&lt;br /&gt;
Эта строка встречается дважды.&lt;br /&gt;
Эта строка встречается трижды.&lt;br /&gt;
Эта строка встречается трижды.&lt;br /&gt;
Эта строка встречается трижды.&lt;br /&gt;
&lt;br /&gt;
bash$ uniq -c testfile&lt;br /&gt;
1 Эта строка встречается только один раз.&lt;br /&gt;
2 Эта строка встречается дважды.&lt;br /&gt;
3 Эта строка встречается трижды.&lt;br /&gt;
&lt;br /&gt;
bash$ sort testfile | uniq -c | sort -nr&lt;br /&gt;
3 Эта строка встречается трижды.&lt;br /&gt;
2 Эта строка встречается дважды.&lt;br /&gt;
1 Эта строка встречается только один раз.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Команда '''''sort INPUTFILE | uniq -c | sort -nr''''' выводит статистику встречаемости строк в файле INPUTFILE (ключ ''-nr'', в команде '''''sort''''', означает сортировку в порядке убывания). Этот шаблон может с успехом использоваться при анализе файлов системного журнала, словарей и везде, где необходимо проанализировать лексическую структуру документа.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Частота встречаемости отдельных слов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# wf.sh: &amp;quot;Сырой&amp;quot; анализ частоты встречаемости слова в текстовом файле.&lt;br /&gt;
ARGS=1&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
E_NOFILE=66&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ] # Файл для анализа задан?&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
if [ ! -f &amp;quot;$1&amp;quot; ] # Проверка существования файла.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$1\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOFILE&lt;br /&gt;
fi&lt;br /&gt;
########################################################&lt;br /&gt;
# main ()&lt;br /&gt;
sed -e 's/\.//g' -e 's/ /\&lt;br /&gt;
/g' &amp;quot;$1&amp;quot; | tr 'A-Z' 'a-z' | sort | uniq -c | sort -nr&lt;br /&gt;
#                           =========================&lt;br /&gt;
#                           Подсчёт количества вхождений&lt;br /&gt;
# Точки и пробелы заменяются&lt;br /&gt;
# символами перевода строки,&lt;br /&gt;
# затем символы переводятся в нижний регистр&lt;br /&gt;
# и наконец подсчитывается количество вхождений,&lt;br /&gt;
# и выполняется сортировка по числу вхождений.&lt;br /&gt;
########################################################&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ---------&lt;br /&gt;
# 1) Добавьте команду 'sed' для отсечения других знаков пунктуации, например, запятых.&lt;br /&gt;
# 2) Добавьте удаление лишних пробелов и других пробельных символов.&lt;br /&gt;
# 3) Добавьте дополнительную сортировку так, чтобы слова с одинаковой частотой встречаемости&lt;br /&gt;
# сортировались бы в алфавитном порядке.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat testfile&lt;br /&gt;
Эта строка встречается только один раз.&lt;br /&gt;
Эта строка встречается дважды.&lt;br /&gt;
Эта строка встречается дважды.&lt;br /&gt;
Эта строка встречается трижды.&lt;br /&gt;
Эта строка встречается трижды.&lt;br /&gt;
Эта строка встречается трижды.&lt;br /&gt;
&lt;br /&gt;
bash$ ./wf.sh testfile&lt;br /&gt;
6 Эта&lt;br /&gt;
6 встречается&lt;br /&gt;
6 строка&lt;br /&gt;
3 трижды&lt;br /&gt;
2 дважды&lt;br /&gt;
1 только&lt;br /&gt;
1 один&lt;br /&gt;
1 раз&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''expand,unexpand'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''expand''''' преобразует символы табуляции в пробелы. Часто используется в конвейерной обработке текста.&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''unexpand''''' преобразует пробелы в символы табуляции. Т.е. она является обратной по отношению к команде '''''expand'''''.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cut'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Предназначена для извлечения отдельных полей из текстовых файлов. Напоминает команду ''print $N'' в [[awk]], но более ограничена в своих возможностях. В простейших случаях может быть неплохой заменой [[awk]] в сценариях. Особую значимость, для команды '''''cut''''', представляют ключи ''-d'' (разделитель полей) и ''-f'' (номер(а) поля(ей)).&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование команды '''''cut''''' для получения списка смонтированных файловых систем:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat /etc/mtab | cut -d ' ' -f1,2&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование команды '''''cut''''' для получения версии ОС и ядра:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;uname -a | cut -d&amp;quot; &amp;quot; -f1,3,11,12&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование команды '''''cut''''' для извлечения заголовков сообщений из электронных писем:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep '^Subject:' read-messages | cut -c10-80&lt;br /&gt;
Re: Linux suitable for mission-critical apps?&lt;br /&gt;
MAKE MILLIONS WORKING AT HOME3&lt;br /&gt;
Spam complaint&lt;br /&gt;
Re: Spam complaint&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование команды cut при разборе текстового файла:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Список пользователей в /etc/passwd.&lt;br /&gt;
FILENAME=/etc/passwd&lt;br /&gt;
for user in $(cut -d: -f1 $FILENAME)&lt;br /&gt;
do&lt;br /&gt;
 echo $user&lt;br /&gt;
done# Спасибо Oleg Philon за этот пример.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''cut -d ' ' -f2,3 filename''''' эквивалентно '''''awk -F'[ ]' '{ print $2, $3 }' filename'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''paste'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Используется для объединения нескольких файлов в один многоколоночный файл.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''join'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Может рассматриваться как команда, родственная команде '''''paste'''''. Эта мощная утилита позволяет объединять два файла по общему полю, что представляет собой упрощённую версию реляционной базы данных.&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''join''''' оперирует только двумя файлами и объединяет только те строки, которые имеют общее поле (обычно числовое), результат объединения выводится на ''stdout''. Объединяемые файлы должны быть отсортированы по ключевому полю.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
File: 1.data&lt;br /&gt;
100 Shoes&lt;br /&gt;
200 Laces&lt;br /&gt;
300 Socks&lt;br /&gt;
&lt;br /&gt;
File: 2.data&lt;br /&gt;
100 $40.00&lt;br /&gt;
200 $1.00&lt;br /&gt;
300 $2.00&lt;br /&gt;
&lt;br /&gt;
bash$ join 1.data 2.data&lt;br /&gt;
File: 1.data 2.data&lt;br /&gt;
100 Shoes $40.00&lt;br /&gt;
200 Laces $1.00&lt;br /&gt;
300 Socks $2.00&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
На выходе ключевое поле встречается только один раз.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''head'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит начальные строки из файла на ''stdout'' (по-умолчанию — 10 строк, но это число можно задать иным). Эта команда имеет ряд интересных ключей.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Какие из файлов являются сценариями?'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# script-detector.sh: Отыскивает файлы сценариев в каталоге.&lt;br /&gt;
TESTCHARS=2 # Проверяются первые два символа.&lt;br /&gt;
SHABANG='#!' # Сценарии как правило начинаются с &amp;quot;sha-bang.&amp;quot;&lt;br /&gt;
for file in * # Обход всех файлов в каталоге.&lt;br /&gt;
do&lt;br /&gt;
 if [[ `head -c$TESTCHARS &amp;quot;$file&amp;quot;` = &amp;quot;$SHABANG&amp;quot; ]]&lt;br /&gt;
 # head -c2 #!&lt;br /&gt;
 # Ключ '-c' в команде &amp;quot;head&amp;quot; выводит заданное&lt;br /&gt;
 # количество символов, а не строк.&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Файл \&amp;quot;$file\&amp;quot; -- сценарий.&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
  echo &amp;quot;Файл \&amp;quot;$file\&amp;quot; не является сценарием.&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Генератор 10-значных случайных чисел.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# rnd.sh: Генератор 10-значных случайных чисел&lt;br /&gt;
# Автор: Stephane Chazelas.&lt;br /&gt;
head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p'&lt;br /&gt;
# =================================================================== #&lt;br /&gt;
# Описание&lt;br /&gt;
# --------&lt;br /&gt;
# head:&lt;br /&gt;
# -c4 — первые 4 байта.&lt;br /&gt;
# od:&lt;br /&gt;
# -N4 ограничивает вывод 4-мя байтами.&lt;br /&gt;
# -tu4 беззнаковый десятичный формат вывода.&lt;br /&gt;
# sed:&lt;br /&gt;
# -n, в комбинации с флагом &amp;quot;p&amp;quot;, в команде &amp;quot;s&amp;quot;,&lt;br /&gt;
# выводит только совпадающие с шаблоном строки.&lt;br /&gt;
&lt;br /&gt;
# Автор сценария описывает действия 'sed' таким образом:&lt;br /&gt;
# head -c4 /dev/urandom | od -N4 -tu4 | sed -ne '1s/.* //p'&lt;br /&gt;
# ----------------------------------&amp;gt; |&lt;br /&gt;
# Передаёт вывод в &amp;quot;sed&amp;quot;    --------&amp;gt; |&lt;br /&gt;
# пусть это будет 0000000 1198195154\n&lt;br /&gt;
# sed начинает читать символы: 0000000 1198195154\n.&lt;br /&gt;
# Здесь он находит символ перевода строки,&lt;br /&gt;
# таким образом он получает строку (0000000 1198195154).&lt;br /&gt;
# Затем он просматривает &amp;lt;диапазон&amp;gt;&amp;lt;действие&amp;gt;. Первый и единственный — это&lt;br /&gt;
# диапазон действие# 1 s/.* //p&lt;br /&gt;
# Номер строки попадает в заданный диапазон, так что теперь он приступает к выполнению действия:&lt;br /&gt;
# пытается заменить наибольшую подстроку, заканчивающуюся пробелом&lt;br /&gt;
# (&amp;quot;0000000 &amp;quot;) &amp;quot;ничем&amp;quot; (//), и если замена произведена — выводит результат&lt;br /&gt;
# (&amp;quot;p&amp;quot; -- это флаг команды &amp;quot;s&amp;quot;, а не команда &amp;quot;p&amp;quot;, которая имеет иное значение).&lt;br /&gt;
# теперь sed готов продолжить чтение входного потока. (Обратите внимание:&lt;br /&gt;
# если опустить ключ -n, то sed выведет строку ещё раз)&lt;br /&gt;
# Теперь sed дочитывает остаток строки.&lt;br /&gt;
# Он готов приступить к анализу 2-й строки (которая отмечена '$'&lt;br /&gt;
# как последняя).&lt;br /&gt;
# Поскольку строка не попадает в заданный &amp;lt;диапазон&amp;gt;, на этом обработка прекращается.&lt;br /&gt;
# Проще говоря, команда sed означает:&lt;br /&gt;
# &amp;quot;В первой строке удалить любые символы, вплоть до последнего встреченного пробела, и затем вывести остаток.&amp;quot;&lt;br /&gt;
# Сделать это можно более простым способом:&lt;br /&gt;
#                        sed -e 's/.* //;q'&lt;br /&gt;
# Где, заданы два &amp;lt;диапазона&amp;gt;&amp;lt;действия&amp;gt; (можно записать и по другому&lt;br /&gt;
# sed -e 's/.* //' -e q):&lt;br /&gt;
# диапазон                       действие&lt;br /&gt;
# ничего (для совпадающих строк) s/.* //&lt;br /&gt;
# ничего (для совпадающих строк) q (quit)&lt;br /&gt;
# Здесь sed считывает только первую строку.&lt;br /&gt;
# Выполняет оба действия, и выводит строку перед завершением&lt;br /&gt;
# (действие &amp;quot;q&amp;quot;), поскольку ключ &amp;quot;-n&amp;quot; опущен.&lt;br /&gt;
# =================================================================== #&lt;br /&gt;
# Простая альтернатива:&lt;br /&gt;
#                        head -c4 /dev/urandom| od -An -tu4&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tail'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит последние строки из файла на ''stdout'' (по-умолчанию — 10 строк). Обычно используется для мониторинга системных журналов. Ключ ''-f'', позволяет вести непрерывное наблюдение за добавляемыми строками в файл.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Мониторинг системного журнала с помощью tail.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
filename=sys.log&lt;br /&gt;
cat /dev/null &amp;gt; $filename; echo &amp;quot;Создание / очистка временного файла.&amp;quot;&lt;br /&gt;
# Если файл отсутствует, то он создаётся,&lt;br /&gt;
# и очищается, если существует.&lt;br /&gt;
# : &amp;gt; filename и &amp;gt; filename дают тот же эффект.&lt;br /&gt;
tail /var/log/messages &amp;gt; $filename&lt;br /&gt;
# Файл /var/log/messages должен быть доступен для чтения.&lt;br /&gt;
echo &amp;quot;В файл $filename записаны последние строки из /var/log/messages.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''grep'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Многоцелевая поисковая утилита, использующая регулярные выражения. Изначально это была команда в древнем строчном редакторе ''ed'', g/re/p, что означает — ''global-regular expression-print''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
grep pattern [file...]&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Поиск участков текста в файле(ах), соответствующих шаблону ''pattern'', где ''pattern'' может быть как обычной строкой, так и регулярным выражением.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep '[rst]ystem.$' osinfo.txt&lt;br /&gt;
The GPL governs the distribution of the Linux operating system.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если файл(ы) для поиска не задан, то команда [[grep]] работает как фильтр для устройства ''stdout'', например в конвейере.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ps ax | grep clock&lt;br /&gt;
765 tty1 S 0:00 xclock&lt;br /&gt;
901 pts/1 S 0:00 grep clock&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''-i''''' — выполняется поиск без учёта регистра символов.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''-w''''' — поиск совпадений целого слова.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''-l''''' — вывод только имён файлов, в которых найдены участки, совпадающие с заданным образцом/шаблоном, без вывода совпадающих строк.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''-r''''' — (рекурсивный поиск) поиск выполняется в текущем каталоге и всех вложенных подкаталогах.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''-n''''' — отображает соответствующие строки вместе с номерами строк.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep -n Linux osinfo.txt&lt;br /&gt;
2:This is a file containing information about Linux.&lt;br /&gt;
6:The GPL governs the distribution of the Linux operating system.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 '''''-v (или --invert-match)''''' — выводит только строки, не содержащие совпадений.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
grep pattern1 *.txt | grep -v pattern2&lt;br /&gt;
# Выводятся строки из &amp;quot;*.txt&amp;quot;, совпадающие с &amp;quot;pattern1&amp;quot;,&lt;br /&gt;
# но ***не*** совпадающие с &amp;quot;pattern2&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
 '''''-c (--count)''''' — выводит количество совпадений без вывода самих совпадений.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
grep -c txt *.sgml # (количество совпадений с &amp;quot;txt&amp;quot; в &amp;quot;*.sgml&amp;quot; файлах)&lt;br /&gt;
# grep -cz .&lt;br /&gt;
#          ^ точка&lt;br /&gt;
# означает подсчет (-c) непустых (&amp;quot;.&amp;quot; -- содержащих хотя бы один символ) элементов,&lt;br /&gt;
# разделённых нулевыми байтами (-z)&lt;br /&gt;
#&lt;br /&gt;
printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz . # 4&lt;br /&gt;
printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '$' # 5&lt;br /&gt;
printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -cz '^' # 5&lt;br /&gt;
#&lt;br /&gt;
printf 'a b\nc d\n\n\n\n\n\000\n\000e\000\000\nf' | grep -c '$' # 9&lt;br /&gt;
# По-умолчанию, в качестве разделителя, принимается символ перевода строки (\n).&lt;br /&gt;
# Обратите внимание: ключ -z характерен для GNU-версии &amp;quot;grep&amp;quot;.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если [[grep]] вызывается для поиска по группе файлов, то вывод будет содержать указание на имена файлов, в которых найдены совпадения.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep Linux osinfo.txt misc.txt &lt;br /&gt;
osinfo.txt:This is a file containing information about Linux.&lt;br /&gt;
osinfo.txt:The GPL governs the distribution of the Linux operating system.&lt;br /&gt;
misc.txt:The Linux operating system is steadily gaining in popularity.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для того, чтобы заставить [[grep]] выводить имя файла, когда поиск производится по одному-единственному файлу, достаточно указать устройство ''/dev/null'' в качестве второго файла.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep Linux osinfo.txt /dev/null&lt;br /&gt;
osinfo.txt:This is a file containing information about Linux.&lt;br /&gt;
osinfo.txt:The GPL governs the distribution of the Linux operating system.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если совпадение было найдено, то [[grep]] возвращает код завершения — 0, это может оказаться полезным при выполнении поиска в условных операторах ( в таких случаях особый интерес может представлять ключ ''-q'', который подавляет вывод).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SUCCESS=0 # если найдено совпадение&lt;br /&gt;
word=Linux&lt;br /&gt;
filename=data.file&lt;br /&gt;
grep -q &amp;quot;$word&amp;quot; &amp;quot;$filename&amp;quot; # &amp;quot;-q&amp;quot; — подавляет вывод на stdout.&lt;br /&gt;
if [ $? -eq $SUCCESS ]&lt;br /&gt;
# if grep -q &amp;quot;$word&amp;quot; &amp;quot;$filename&amp;quot; эта комбинация может заменить строки 5 - 7.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Образец $word найден в $filename&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Образец $word в файле $filename не найден&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий-эмулятор &amp;quot;grep&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# grp.sh: Очень &amp;quot;грубая&amp;quot; реализация 'grep'.&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ] # Проверка наличия аргументов.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` pattern&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
for file in * # Обход всех файлов в $PWD.&lt;br /&gt;
do&lt;br /&gt;
 output=$(sed -n /&amp;quot;$1&amp;quot;/p $file) # Подстановка команд.&lt;br /&gt;
 if [ ! -z &amp;quot;$output&amp;quot; ] # Что произойдет, если кавычки вокруг &amp;quot;$output&amp;quot; убрать?&lt;br /&gt;
 then&lt;br /&gt;
  echo -n &amp;quot;$file: &amp;quot;&lt;br /&gt;
  echo $output&lt;br /&gt;
 fi # эквивалент: sed -ne &amp;quot;/$1/s|^|${file}: |p&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ---------&lt;br /&gt;
# 1) Добавьте вывод символов перевода строки, если найдено более одного совпадения в любом из файлов.&lt;br /&gt;
# 2) Добавьте обработку различных ключей.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''egrep''''' — то же самое, что и '''''grep -E'''''. Эта команда использует несколько отличающийся, расширенный набор регулярных выражений, что позволяет выполнять поиск более гибко.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''fgrep''''' — то же самое, что и '''''grep -F'''''. Эта команда выполняет поиск строк символов (не регулярных выражений), что несколько увеличивает скорость поиска.&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита '''''agrep''''' имеет более широкие возможности поиска приблизительных совпадений. Образец поиска может отличаться от найденой строки на указанное число символов.&amp;lt;br&amp;gt;&lt;br /&gt;
Для поиска по сжатым файлам следует использовать утилиты '''''zgrep''''', '''''zegrep''''' или '''''zfgrep'''''. Они с успехом могут использоваться и для не сжатых файлов, но в этом случае они уступают в скорости обычным '''''grep''''', '''''egrep''''' и '''''fgrep'''''. Они очень удобны при выполнении поиска по смешенному набору файлов — когда одни файлы сжаты, а другие нет.&amp;lt;br /&amp;gt; Для поиска по bzip-файлам используйте '''''bzgrep'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''look'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''look''''' очень похожа на [[grep]], и предназначена для поиска по &amp;quot;словарям&amp;quot; — отсортированным файлам. По-умолчанию, поиск выполняется в файле /usr/dict/words, но может быть указан и другой словарь.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Поиск слов в словаре.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# lookup: Выполняется поиск каждого слова из файла в словаре.&lt;br /&gt;
file=words.data # Файл с искомыми словами.&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$word&amp;quot; != end ] # Последнее слово в файле.&lt;br /&gt;
do&lt;br /&gt;
 read word # Из файла, потому, что выполнено перенаправление в конце цикла.&lt;br /&gt;
 look $word &amp;gt; /dev/null # Подавление вывода строк из словаря.&lt;br /&gt;
 lookup=$? # Код возврата команды 'look'.&lt;br /&gt;
 if [ &amp;quot;$lookup&amp;quot; -eq 0 ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Слово \&amp;quot;$word\&amp;quot; найдено.&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
  echo &amp;quot;Слово \&amp;quot;$word\&amp;quot; не найдено.&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done &amp;lt;&amp;quot;$file&amp;quot; # Перенаправление ввода из файла $file, так что &amp;quot;чтение&amp;quot; производится оттуда.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
# ----------------------------------------------------------------&lt;br /&gt;
# Строки, расположенные ниже не будут исполнены, поскольку выше стоит команда &amp;quot;exit&amp;quot;.&lt;br /&gt;
# Stephane Chazelas предложил более короткий вариант:&lt;br /&gt;
while read word &amp;amp;&amp;amp; [[ $word != end ]]&lt;br /&gt;
do if look &amp;quot;$word&amp;quot; &amp;gt; /dev/null&lt;br /&gt;
 then echo &amp;quot;Слово \&amp;quot;$word\&amp;quot; найдено.&amp;quot;&lt;br /&gt;
 else echo &amp;quot;Слово \&amp;quot;$word\&amp;quot; не найдено.&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done &amp;lt;&amp;quot;$file&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sed,awk'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Скриптовые языки, специально разработанные для анализа текстовых данных.&lt;br /&gt;
[[sed]] — Неинтерактивный &amp;quot;потоковый редактор&amp;quot;. Широко используется в сценариях на языке командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
[[awk]] — Утилита контекстного поиска и преобразования текста, замечательный инструмент для извлечения и/или обработки полей (колонок) в структурированных текстовых файлах. Синтаксис awk напоминает язык C.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''wc'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''wc''''' — &amp;quot;word count&amp;quot;, счётчик слов в файле или в потоке:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash $ wc /usr/doc/sed-3.02/README&lt;br /&gt;
20 127 838 /usr/doc/sed-3.02/README&lt;br /&gt;
[20 строк 127 слов 838 символов]&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''wc -w''''' — подсчитывает только слова.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''wc -l''''' — подсчитывает только строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''wc -c''''' — подсчитывает только символы.&amp;lt;br /&amp;gt;&lt;br /&gt;
 '''''wc -L''''' — возвращает длину наибольшей строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
Подсчёт количества .txt-файлов в текущем каталоге с помощью '''''wc''''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ ls *.txt | wc -l&lt;br /&gt;
# Эта команда будет работать, если ни в одном из имен файлов &amp;quot;*.txt&amp;quot; нет символа перевода строки.&lt;br /&gt;
# Альтернативный вариант:&lt;br /&gt;
# find . -maxdepth 1 -name \*.txt -print0 | grep -cz .&lt;br /&gt;
# (shopt -s nullglob; set -- *.txt; echo $#)&lt;br /&gt;
&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подсчёт общего размера файлов, чьи имена начинаются с символов, в диапазоне ''d—h''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ wc [d-h]* | grep total | awk '{print $3}'&lt;br /&gt;
71832&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
От переводчика: в случае, если у вас локаль отлична от &amp;quot;C&amp;quot;, то вышеприведённая команда может не дать результата, поскольку '''''wc''''' вернёт не слово &amp;quot;total&amp;quot;, в конце вывода, а &amp;quot;итого&amp;quot;. Тогда можно попробовать несколько изменённый вариант:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ wc [d-h]* | grep итого | awk '{print $3}'&lt;br /&gt;
71832&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование '''''wc''''' для подсчёта количества вхождений слова &amp;quot;Linux&amp;quot; в основной исходный файл с текстом этого руководства.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep Linux abs-book.sgml | wc -l&lt;br /&gt;
50&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Отдельные команды располагают функциональностью '''''wc''''' в виде своих ключей.&lt;br /&gt;
Часто встречающаяся конструкция, которая может быть сокращена:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;... | grep foo | wc -l&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''-c'' (''--count'') команды [[grep]]. Спасибо S.C.:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;... | grep -c foo &amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tr'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Замена одних символов на другие. В отдельных случаях символы необходимо заключать в кавычки и/или квадратные скобки. Кавычки предотвращают интерпретацию специальных символов командной оболочкой. Квадратные скобки должны заключаться в кавычки.&lt;br /&gt;
Команда '''''tr &amp;quot;A-Z&amp;quot; &amp;quot;*&amp;quot; &amp;lt; filename''''' или '''''tr A-Z \* &amp;lt; filename''''' заменяет все символы верхнего регистра в ''filename'' на звёздочки (вывод производится на ''stdout''). В некоторых системах этот вариант может оказаться неработоспособным, тогда попробуйте ''''' tr A-Z '[**]' '''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''-d'' удаляет символы из заданного диапазона.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;abcdef&amp;quot; # abcdef&lt;br /&gt;
echo &amp;quot;abcdef&amp;quot; | tr -d b-d # aef&lt;br /&gt;
&lt;br /&gt;
tr -d 0-9 &amp;lt;filename # Удалит все цифровые символы из файла &amp;quot;filename&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''--squeeze-repeats'' (''-s'') удалит все повторяющиеся последовательности символов. Может использоваться для удаления лишних пробельных символов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo &amp;quot;XXXXX&amp;quot; | tr --squeeze-repeats 'X'&lt;br /&gt;
X&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''-c'' &amp;quot;complement&amp;quot; заменит символы в соответствии с шаблоном. Этот ключ воздействует только на те символы, которые НЕ соответствуют заданному шаблону.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo &amp;quot;acfdeb123&amp;quot; | tr -c b-d +&lt;br /&gt;
+c+d+b++++&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание: команда '''''tr''''' корректно распознает символьные классы POSIX.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo &amp;quot;abcd2ef1&amp;quot; | tr '[:alpha:]' -&lt;br /&gt;
----2--1&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''toupper: Преобразование символов в верхний регистр.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Преобразование символов в верхний регистр.&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ] # Стандартная проверка командной строки.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
tr a-z A-Z &amp;lt;&amp;quot;$1&amp;quot;&lt;br /&gt;
# Тот же эффект можно получить при использовании символьных классов POSIX:&lt;br /&gt;
# tr '[:lower:]' '[:upper:]' &amp;lt;&amp;quot;$1&amp;quot;&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''lowercase: Изменение имен всех файлов в текущем каталоге в нижний регистр.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
#&lt;br /&gt;
# Изменит все имена файлов в текущем каталоге в нижний регистр.&lt;br /&gt;
#&lt;br /&gt;
for filename in * # Обход всех файлов в каталоге.&lt;br /&gt;
do&lt;br /&gt;
 fname=`basename $filename`&lt;br /&gt;
 n=`echo $fname | tr A-Z a-z` # Перевести символы в нижний регистр.&lt;br /&gt;
 if [ &amp;quot;$fname&amp;quot; != &amp;quot;$n&amp;quot; ] # Переименовать только те файлы, имена которых изменились.&lt;br /&gt;
 then&lt;br /&gt;
  mv $fname $n&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
# Строки приведённые ниже не будут исполняться, поскольку выше стоит команда &amp;quot;exit&amp;quot;.&lt;br /&gt;
#--------------------------------------------------------#&lt;br /&gt;
# Запустите эту часть сценария, удалив строки , стоящие выше.&lt;br /&gt;
# Сценарий, приведенный выше, не работает с именами файлов, содержащими пробелы или символы перевода строки.&lt;br /&gt;
# В связи с этим, Stephane Chazelas предложил следующий вариант:&lt;br /&gt;
for filename in * # Нет необходимости использовать basename,&lt;br /&gt;
                  # поскольку &amp;quot;*&amp;quot; возвращает имена, не содержащие &amp;quot;/&amp;quot;.&lt;br /&gt;
do n=`echo &amp;quot;$filename/&amp;quot; | tr '[:upper:]' '[:lower:]'`&lt;br /&gt;
# символьные классы POSIX.&lt;br /&gt;
# Завершающий слэш добавлен для того, чтобы символ перевода строки&lt;br /&gt;
# не был удален при подстановке команды.&lt;br /&gt;
# Подстановка переменной:&lt;br /&gt;
n=${n%/} # Удаление завершающего слэша, добавленного выше.&lt;br /&gt;
[[ $filename == $n ]] || mv &amp;quot;$filename&amp;quot; &amp;quot;$n&amp;quot;&lt;br /&gt;
# Проверка — действительно ли изменилось имя файла.&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''du: Преобразование текстового файла из формата DOS в формат Unix.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# du.sh: Преобразование текстового файла из формата DOS в формат UNIX.&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename-to-convert&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
NEWFILENAME=$1.unxCR='\015' # Возврат каретки.&lt;br /&gt;
                            # 015 — это символ CR в восьмеричном формате&lt;br /&gt;
# Строки в текстовых файлах DOS завершаются комбинацией символов CR-LF.&lt;br /&gt;
tr -d $CR &amp;lt; $1 &amp;gt; $NEWFILENAME&lt;br /&gt;
# Удалить символы CR и записать в новый файл.&lt;br /&gt;
echo &amp;quot;Исходный текстовый файл: \&amp;quot;$1\&amp;quot;.&amp;quot;&lt;br /&gt;
echo &amp;quot;Преобразованный файл: \&amp;quot;$NEWFILENAME\&amp;quot;.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Измените этот сценарий таким образом, чтобы он преобразовывал файлы из&lt;br /&gt;
# формата UNIX в формат DOS.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''rot13: Сверхслабое шифрование по алгоритму rot13.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# rot13.sh: Классический алгоритм шифрования rot13,&lt;br /&gt;
# который способен &amp;quot;расколоть&amp;quot; даже 3-х летний ребенок.&lt;br /&gt;
# Порядок использования: ./rot13.sh filename&lt;br /&gt;
# или ./rot13.sh &amp;lt;filename&lt;br /&gt;
# или ./rot13.sh и ввести текст с клавиатуры (stdin)&lt;br /&gt;
cat &amp;quot;$@&amp;quot; | tr 'a-zA-Z' 'n-za-mN-ZA-M' # &amp;quot;a&amp;quot; заменяется на &amp;quot;n&amp;quot;, &amp;quot;b&amp;quot; на &amp;quot;o&amp;quot;, и т.д.&lt;br /&gt;
# Конструкция 'cat &amp;quot;$@&amp;quot;'&lt;br /&gt;
# позволяет вводить данные как со stdin, так и из файла.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Более &amp;quot;сложный&amp;quot; шифр'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# crypto-quote.sh: Ограниченное шифрование&lt;br /&gt;
# Шифрование ограничивается простой заменой одних алфавитных символов другими.&lt;br /&gt;
# Результат очень похож на шифры-загадки&lt;br /&gt;
key=ETAOINSHRDLUBCFGJMQPVWZYXK&lt;br /&gt;
# Здесь, &amp;quot;key&amp;quot; — ни что иное, как &amp;quot;перемешанный&amp;quot; алфавит.&lt;br /&gt;
# Изменение ключа &amp;quot;key&amp;quot; приведет к изменению шифра.&lt;br /&gt;
# Конструкция 'cat &amp;quot;$@&amp;quot;' позволяет вводить данные как со stdin, так и из файла.&lt;br /&gt;
# Если используется stdin, то ввод должен завершаться комбинацией Control-D.&lt;br /&gt;
# Иначе, в командной строке, сценарию должно быть передано имя файла.&lt;br /&gt;
cat &amp;quot;$@&amp;quot; | tr &amp;quot;a-z&amp;quot; &amp;quot;A-Z&amp;quot; | tr &amp;quot;A-Z&amp;quot; &amp;quot;$key&amp;quot;&lt;br /&gt;
#        |в верхний регистр| шифрование&lt;br /&gt;
# Такой прием позволяет шифровать как символы в верхнем регистре, так и в нижнем.&lt;br /&gt;
# Неалфавитные символы остаются без изменений.&lt;br /&gt;
&lt;br /&gt;
# Попробуйте зашифровать какой либо текст, например&lt;br /&gt;
# &amp;quot;Nothing so needs reforming as other people's habits.&amp;quot; — Mark Twain&lt;br /&gt;
#&lt;br /&gt;
# Результат будет:&lt;br /&gt;
# &amp;quot;CFPHRCS QF CIIOQ MINFMBRCS EQ FPHIM GIFGUI'Q HETRPQ.&amp;quot; — BEML PZERC&lt;br /&gt;
# Для дешифрации можно использовать следующую комбинацию:&lt;br /&gt;
# cat &amp;quot;$@&amp;quot; | tr &amp;quot;$key&amp;quot; &amp;quot;A-Z&amp;quot;&lt;br /&gt;
# Этот нехитрый шифр может быть &amp;quot;взломан&amp;quot; 12-ти летним ребёнком&lt;br /&gt;
# с помощью карандаша и бумаги.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Различные версии tr&lt;br /&gt;
|-&lt;br /&gt;
| Утилита '''''tr''''' имеет две, исторически сложившиеся, версии. BSD-версия не использует квадратные скобки (tr a-z A-Z), в то время как SysV-версия использует их (tr '[a-z]' '[A-Z]'). GNU-версия утилиты '''''tr''''' напоминает версию BSD, но диапазоны символов обязательно должны заключаться в квадратные скобки.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fold'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выравнивает текст по ширине, разрывая, если это необходимо, слова. Особый интерес представляет ключ ''-s'', который производит перенос строк по пробелам, стараясь не разрывать слова.&amp;lt;br /&amp;gt; &lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fmt'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Очень простая утилита форматирования текста, чаще всего используемая как фильтр в конвейерах для того, чтобы выполнить &amp;quot;перенос&amp;quot; длинных строк текста.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Отформатированный список файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
WIDTH=40 # 40 символов в строке.&lt;br /&gt;
b=`ls /usr/local/bin` # Получить список файлов...&lt;br /&gt;
echo $b | fmt -w $WIDTH&lt;br /&gt;
# То же самое можно выполнить командой&lt;br /&gt;
# echo $b | fold - -s -w $WIDTH&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Очень мощной альтернативой утилите '''''fmt''''', является утилита '''''par''''' (автор Kamil Toman), которую вы сможете найти на http://www.cs.berkeley.edu/~amc/Par/.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''col'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита с обманчивым названием удаляет из входного потока символы обратной подачи бумаги (код ESC 7). Она так же пытается заменить пробелы на табуляции. Основная область применения утилиты '''''col''''' — фильтрация вывода отдельных утилит обработки текста, таких как '''''groff''''' и '''''tbl'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''col'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Форматирование по столбцам. Эта утилита преобразует текст, например какой либо список, в табличное, более &amp;quot;удобочитаемое&amp;quot;, представление, вставляя символы табуляции по мере необходимости.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример форматирования списка файлов в каталоге.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# За основу сценария взят пример &amp;quot;man column&amp;quot;.&lt;br /&gt;
(printf &amp;quot;PERMISSIONS LINKS OWNER GROUP SIZE DATE TIME PROG-NAME\n&amp;quot; \&lt;br /&gt;
; ls -l | sed 1d) | column -t   # Команда &amp;quot;sed 1d&amp;quot; удаляет первую строку, выводимую командой ls,&lt;br /&gt;
                                # (для локали &amp;quot;С&amp;quot; это строка: &amp;quot;total N&amp;quot;, где &amp;quot;N&amp;quot; — общее количество файлов.&lt;br /&gt;
# Ключ -t, команды &amp;quot;column&amp;quot;, означает &amp;quot;табличное&amp;quot; представление.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''colrm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита удаления колонок. Удаляет колонки (столбцы) символов из файла и выводит результат на ''stdout''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''colrm 2 4 &amp;lt; filename''''' — удалит символы со 2-го по 4-й включительно, в каждой строке в файле filename.&amp;lt;br /&amp;gt;&lt;br /&gt;
Если файл содержит символы табуляции или непечатаемые символы, то результат может получиться самым неожиданным. В таких случаях, как правило, утилиту '''''colrm''''', в конвейере, окружают командами '''''expand''''' и '''''unexpand'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''nl'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Нумерует строки в файле. '''''nl filename''''' — выведет файл ''filename'' на ''stdout'', и в начале каждой строки вставит её порядковый номер, счёт начинается с первой непустой строки. Если файл не указывается, то принимается ввод со ''stdin''. Вывод команды '''''nl''''' очень напоминает '''''cat -n''''', однако, по-умолчанию '''''nl''''' не нумерует пустые строки.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Самонумерующийся сценарий.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Сценарий выводит себя сам на stdout дважды, нумеруя строки сценария.&lt;br /&gt;
# 'nl' вставит для этой строки номер 3, поскольку она не нумерует пустые строки.&lt;br /&gt;
# 'cat -n' вставит для этой строки номер 5.&lt;br /&gt;
nl `basename $0`&lt;br /&gt;
echo; echo # А теперь попробуем вывести текст сценария с помощью 'cat -n'cat -n `basename $0`&lt;br /&gt;
# Различия состоят в том, что 'cat -n' нумерует все строки.&lt;br /&gt;
# Обратите внимание: 'nl -ba' — сделает то же самое.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''pr'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подготовка файла к печати. Утилита производит разбивку файла на страницы, приводя его в вид пригодный для печати или для вывода на экран. Разнообразные ключи позволяют выполнять различные манипуляции над строками и колонками, соединять строки, устанавливать поля, нумеровать строки, добавлять колонтитулы и многое, многое другое. Утилита '''''pr''''' соединяет в себе функциональность таких команд, как '''''nl''''', '''''paste''''', '''''fold''''', '''''column''''' и '''''expand'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Следующая команда выдаст хорошо оформленное и разбитое на страницы содержимое файла fileZZZ:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;pr -o 5 --width=65 fileZZZ | more &amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Хочу особо отметить ключ ''-d'', который выводит строки с двойным интервалом (тот же эффект,что и ''sed -G'').&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''gettext'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
GNU утилита, предназначена для нужд локализации и перевода сообщений программ, выводимых на экран, на язык пользователя. Не смотря на то, что это актуально, прежде всего,для программ на языке C, тем не менее '''''gettext''''' с успехом может использоваться в сценариях командной оболочки для тех же целей.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''msgfmt'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита предназначена для создания двоичных файлов с переводом сообщений, выводимых перед пользователем. Используется для нужд локализации.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''iconv'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита преобразования текста из одной кодировки в другую. В основном используется для нужд локализации.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''recode'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Может рассматриваться как разновидность утилиты '''''iconv''''', описанной выше. Универсальная утилита для преобразования текстовой информации в различные кодировки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''TeX,gs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''TeX''''' и '''''Postscript''''' — языки разметки текста, используемые для подготовки текста к печати или выводу на экран.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''TeX''''' — это сложная система подготовки к печати, разработанная Дональдом Кнутом (Donald Knuth). Эту утилиту удобнее использовать внутри сценария, чем в командной строке, поскольку в сценарии проще один раз записать все необходимые параметры, передаваемые утилите, для получения необходимого результата.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Ghostscript''''' (gs) — это GPL-версия интерпретатора Postscript.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''groff,tbl,eqn'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''groff''''' — это ещё один язык разметки текста и форматированного вывода. Является расширенной GNU-версией пакета '''''roff'''''/'''''troff''''' в Unix-системах.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''tbl''''' — утилита обработки таблиц, должна рассматриваться как составная часть '''''groff''''', так как её задачей является преобразование таблиц в команды '''''groff'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''eqn''''' — утилита преобразования математических выражений в команды '''''groff'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lex,yacc'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''lex''''' — утилита лексического разбора текста. В Linux-системах заменена на свободно распространяемую утилиту '''''flex'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''yacc''''' — утилита для создания синтаксических анализаторов, на основе набора грамматик, задаваемых разработчиком. В Linux-системах, эта утилита заменена на свободнораспространяемую утилиту '''''bison'''''.&lt;br /&gt;
&lt;br /&gt;
=== Команды для работы с файлами и архивами ===&lt;br /&gt;
'''Архивация'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tar'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Стандартная, для Unix, утилита архивирования. Первоначально — это была программа ''TapeARchiving'', которая впоследствии переросла в универсальный пакет, который может работать с любыми типами устройств. В GNU-версию [[tar]] была добавлена возможность одновременно производить сжатие tar-архива, например команда '''''tar czvf archive_name.tar.gz*''''' создаёт tar-архив дерева подкаталогов и вызывает [[gzip]] для выполнения сжатия, исключение составляют скрытые файлы в текущем каталоге (&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;&amp;lt;big&amp;gt;$PWD&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;).&amp;lt;br /&amp;gt;&lt;br /&gt;
Некоторые, часто используемые, ключи команды [[tar]]:&amp;lt;br /&amp;gt;&lt;br /&gt;
# '''''-c''''' — создать (''create'') новый архив&lt;br /&gt;
# '''''-x''''' — извлечь (''extract'') файлы из архива&lt;br /&gt;
# '''''--delete''''' — удалить (''delete'') файлы из архива. Этот ключ игнорируется для накопителей на магнитной ленте.&lt;br /&gt;
# '''''-r''''' — добавить (''append'') файлы в существующий архив&lt;br /&gt;
# '''''-A''''' — добавить (''append'') tar-файлы в существующий архив&lt;br /&gt;
# '''''-t''''' — список файлов в архиве (содержимое архива)&lt;br /&gt;
# '''''-u''''' — обновить (''update'') архив&lt;br /&gt;
# '''''-d''''' — операция сравнения архива с заданной файловой системой&lt;br /&gt;
# '''''-z''''' — обработка архива с помощью [[gzip]]. Сжатие или разжатие, в зависимости от комбинации сопутствующих ключей ''-c'' или ''-x''&lt;br /&gt;
# '''''-j''''' — обработка архива с помощью [[bzip2]]&amp;lt;br /&amp;gt;&lt;br /&gt;
При восстановлении &amp;quot;битых&amp;quot; tar.gz архивов могут возникнуть определённые сложности, поэтому делайте несколько резервных копий.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''shar'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита создания shell-архива. Архивируемые файлы объединяются в единый файл без выполнения сжатия, в результате получается архив — по сути полноценный сценарий на языке командной оболочки, начинающийся со строки '''''#!/bin/sh''''', который содержит полный набор команд, необходимый для разархивирования. Такого рода архивы до сих пор можно найти в некоторых телеконференциях в Internet, но в последнее время они активно вытесняются связкой [[tar]]/[[gzip]]. Для распаковки shar-архивов предназначена команда unshar.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ar'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита создания и обслуживания архивов, главным образом применяется к двоичным файлам библиотек.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rpm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Red Hat Package Manager, или [[rpm]] — набор утилит, предназначенных для построения и обслуживания пакетов программного обеспечения как в исходном коде, так и в собранном(откомпилированном) виде. Среди всего прочего, включает в себя утилиты, производящие установку ПО, проверку зависимостей пакетов и проверку их целостности.&amp;lt;br /&amp;gt;&lt;br /&gt;
Самый простой вариант установки ПО из [[rpm]] — выполнить команду '''''rpm -ipackage_name.rpm'''''. Команда '''''rpm -qa''''' выдаст полный список всех установленных rpm-пакетов в данной системе. Команда '''''rpm -qa package_name''''' выведет только пакет(ы) с именем, содержащим комбинацию символов ''package_name''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ rpm -qa&lt;br /&gt;
redhat-logos-1.1.3-1&lt;br /&gt;
glibc-2.2.4-13 &lt;br /&gt;
cracklib-2.7-12&lt;br /&gt;
dosfstools-2.7-1&lt;br /&gt;
gdbm-1.8.0-10&lt;br /&gt;
ksymoops-2.4.1-1 &lt;br /&gt;
mktemp-1.5-11 &lt;br /&gt;
perl-5.6.0-17&lt;br /&gt;
reiserfs-utils-3.x.0j-2&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ rpm -qa docbook-utils&lt;br /&gt;
docbook-utils-0.6.9-2&lt;br /&gt;
bash$ rpm -qa docbook | grep docbook&lt;br /&gt;
docbook-dtd31-sgml-1.0-10&lt;br /&gt;
docbook-style-dsssl-1.64-3&lt;br /&gt;
docbook-dtd30-sgml-1.0-10&lt;br /&gt;
docbook-dtd40-sgml-1.0-11&lt;br /&gt;
docbook-utils-pdf-0.6.9-2&lt;br /&gt;
docbook-dtd41-sgml-1.0-10&lt;br /&gt;
docbook-utils-0.6.9-2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cpio'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Специализированная утилита архивации и копирования (''copy input and output''). Используется всё реже и реже, поскольку вытесняется более мощным архиватором [[tar]]/[[gzip]]. Наиболее употребительна для таких операций, как перемещение дерева каталогов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример перемещения дерева каталогов с помощью cpio.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Копирование дерева каталогов с помощью cpio.&lt;br /&gt;
ARGS=2&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` source destination&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
source=$1&lt;br /&gt;
destination=$2&lt;br /&gt;
find &amp;quot;$source&amp;quot; -depth | cpio -admvp &amp;quot;$destination&amp;quot;&lt;br /&gt;
# Информацию по ключам утилиты cpio вы найдете в страницах руководства &amp;quot;man cpio&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rpm2cpio'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита конвертирует rpm-пакет в архив cpio.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Распаковка архива rpm.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# de-rpm.sh: Распаковка архива 'rpm'&lt;br /&gt;
: ${1?&amp;quot;Порядок использования: `basename $0` target-file&amp;quot;}&lt;br /&gt;
# Сценарию должно быть передано имя архива 'rpm'.&lt;br /&gt;
TEMPFILE=$$.cpio          # Временный файл с &amp;quot;уникальным&amp;quot; именем.&lt;br /&gt;
                          # $$ — PID процесса сценария.&lt;br /&gt;
rpm2cpio &amp;lt; $1 &amp;gt; $TEMPFILE # Конверсия из rpm в cpio.&lt;br /&gt;
cpio --make-directories -F $TEMPFILE -i # Распаковка cpio-архива.&lt;br /&gt;
rm -f $TEMPFILE           # Удаление cpio-архива.&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# Добавьте проверку на: &lt;br /&gt;
# 1) Существование &amp;quot;target-file&amp;quot;&lt;br /&gt;
# 2) Действительно ли &amp;quot;target-file&amp;quot; является rpm-архивом.&lt;br /&gt;
# Подсказка: используйте команду 'file'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''Сжатие'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''gzip'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Стандартная GNU/Unix утилита сжатия, заменившая более слабую, и к тому же проприетарную, утилиту ''compress''. Соответствующая утилита декомпрессии (разжатия) — gunzip, которая является эквивалентом команды ''[[gzip]] -d''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Для работы со сжатыми файлами в конвейере используется фильтр ''zcat'', который выводит результат своей работы на ''stdout'', допускает перенаправление вывода. Фактически это та же команда [[cat]], только приспособленная для работы со сжатыми файлами (включая файлы, сжатые утилитой ''compress''). Эквивалент команды ''zcat'' — ''[[gzip]] -dc''.&amp;lt;br /&amp;gt;&lt;br /&gt;
В некоторых коммерческих версиях Unix, команда ''zcat'' является синонимом команды ''uncompress -c'', и не может работать с файлами, сжатыми с помощью [[gzip]].&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''bzip2'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Альтернативная утилита сжатия, обычно даёт более высокую степень сжатия (но при этом работает медленнее), чем [[gzip]], особенно это проявляется на больших файлах. Соответствующая утилита декомпрессии — ''bunzip2''. В современные версии [[tar]] добавлена поддержка [[bzip2]].&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''compress,uncompress'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Устаревшие проприетарные утилиты для работы с архивами, входящие в состав некоторых коммерческих дистрибутивов Unix. В последнее время вытесняются более мощной утилитой [[gzip]]. Linux-дистрибутивы, как правило, включают в свой состав эти утилиты для обратной совместимости, однако ''gunzip'' корректно разархивирует файлы, обработанные с помощью compress.&amp;lt;br /&amp;gt; Утилита ''znew'' предназначена для преобразования compress-архивов в gzip-архивы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sq'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё одна утилита-фильтр сжатия, которая обслуживает только отсортированные списки слов. Использует стандартный, для фильтров, синтаксис вызова — '''''sq &amp;lt; input-file &amp;gt; output-file'''''. Быстрая, но не такая эффективная как [[gzip]]. Соответствующая ей утилита декомпрессии называется ''unsq'', синтаксис вызова аналогичен утилите ''sq''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Вывод от ''sq'' может быть передан по конвейеру утилите [[gzip]], для дальнейшего сжатия.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''zip,unzip'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Кроссплатформенная утилита архивирования и сжатия, совместимая, по формату архивного файла, с утилитой DOS — ''pkzip.exe''. &amp;quot;Zip&amp;quot;-архивы, по-моему, более приемлемый вариант для обмена данными через Internet, чем &amp;quot;tarballs&amp;quot; (тарболлы, или tar-архивы).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''unarc,unarj,unrar'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Этот набор утилит предназначен для распаковки архивов, созданных с помощью DOS-архиваторов — ''arc.exe'', ''arj.exe'' и ''rar.exe''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Получение сведений о файлах'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''file'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита идентификации файлов. Команда '''''file''''' ''filename'' вернёт тип файла ''filename'', например, ''ascii'', ''text'' или ''data''. Для этого она анализирует сигнатуру, или магическое число и сопоставляет её со списком известных сигнатур из ''/usr/share/magic'', ''/etc/magic'' или ''/usr/lib/magic'' (в зависимости от дистрибутива Linux/Unix).&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''-f''''' — ключ пакетного режима работы утилиты ''file'', в этом случае утилита принимает список анализируемых имён файлов из заданного файла. Ключ '''''-z''''' используется для анализа файлов в архиве.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ file test.tar.gz&lt;br /&gt;
test.tar.gz: gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os:&lt;br /&gt;
Unix&lt;br /&gt;
bash file -z test.tar.gz&lt;br /&gt;
test.tar.gz: GNU tar archive (gzip compressed data, deflated, last modified: Sun Sep 16 13:34:51 2001, os: Unix)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Удаление комментариев из файла с текстом программы на языке C.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# strip-comment.sh: Удаление комментариев (/* COMMENT */) из исходных текстов программ на языке C.&lt;br /&gt;
E_NOARGS=65&lt;br /&gt;
E_ARGERROR=66&lt;br /&gt;
E_WRONG_FILE_TYPE=67&lt;br /&gt;
if [ $# -eq &amp;quot;$E_NOARGS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` C-program-file&amp;quot; &amp;gt;&amp;amp;2 # Вывод сообщения на stderr.&lt;br /&gt;
exit $E_ARGERROR&lt;br /&gt;
fi&lt;br /&gt;
# Проверка типа файла.&lt;br /&gt;
type=`eval file $1 | awk '{ print $2, $3, $4, $5 }'`&lt;br /&gt;
# &amp;quot;file $1&amp;quot; — выводит тип файла...&lt;br /&gt;
# затем awk удаляет первое поле — имя файла...&lt;br /&gt;
# после этого результат записывается в переменную &amp;quot;type&amp;quot;.&lt;br /&gt;
correct_type=&amp;quot;ASCII C program text&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$type&amp;quot; != &amp;quot;$correct_type&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Этот сценарий работает только с исходными текстами программ на языке C.&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
 exit $E_WRONG_FILE_TYPE&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Довольно замысловатый сценарий sed :&lt;br /&gt;
#--------&lt;br /&gt;
sed '&lt;br /&gt;
/^\/\*/d&lt;br /&gt;
/.*\/\*/d&lt;br /&gt;
' $1&lt;br /&gt;
#--------&lt;br /&gt;
# Если вы потратите несколько часов на изучение основ sed, то он станет немного понятнее.&lt;br /&gt;
# Следовало бы добавить ещё обработку&lt;br /&gt;
# комментариев, расположенных в одной строке с кодом.&lt;br /&gt;
# Оставляю это вам, в качестве упражнения.&lt;br /&gt;
# Кроме того, этот сценарий удалит все строки, которые содержат комбинации символов &amp;quot;*/&amp;quot; или &amp;quot;/*&amp;quot;,&lt;br /&gt;
# не всегда желаемый результат.&lt;br /&gt;
exit 0&lt;br /&gt;
# ----------------------------------------------------------------&lt;br /&gt;
# Строки, расположенные ниже не будут исполнены из-за стоящей выше команды 'exit 0'.&lt;br /&gt;
# Stephane Chazelas предложил другой, альтернативный вариант:&lt;br /&gt;
usage() {&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` C-program-file&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
 exit 1&lt;br /&gt;
}&lt;br /&gt;
WEIRD=`echo -n -e '\377'` # или WEIRD=$'\377'&lt;br /&gt;
[[ $# -eq 1 ]] || usage&lt;br /&gt;
case `file &amp;quot;$1&amp;quot;` in&lt;br /&gt;
 *&amp;quot;C program text&amp;quot;*) sed -e &amp;quot;s%/\*%${WEIRD}%g;s%\*/%${WEIRD}%g&amp;quot; &amp;quot;$1&amp;quot; \&lt;br /&gt;
 | tr '\377\n' '\n\377' \&lt;br /&gt;
 | sed -ne 'p;n' \&lt;br /&gt;
 | tr -d '\n' | tr '\377' '\n';;&lt;br /&gt;
 *) usage;;&lt;br /&gt;
esac&lt;br /&gt;
# Этот вариант, все ещё некорректно обрабатывает такие строки как:&lt;br /&gt;
# printf(&amp;quot;/*&amp;quot;);&lt;br /&gt;
# или&lt;br /&gt;
# /* /* ошибочный вложенный комментарий */&lt;br /&gt;
#&lt;br /&gt;
# Для обработки специальных случаев (\&amp;quot;, \\&amp;quot; ...) придется написать синтаксический анализатор&lt;br /&gt;
# (может быть с помощью lex или yacc?).&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''which'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''which command-xxx''''' вернёт полный путь к ''command-xx''. Очень полезна для того,чтобы узнать — установлена ли та или иная утилита в системе.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$bash which rm&lt;br /&gt;
/usr/bin/rm&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''whereis'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Очень похожа на ''which'', упоминавшуюся выше. Команда ''whereis'' command-xxx вернёт полный путь к &amp;quot;command-xxx&amp;quot;, но кроме того, ещё и путь к manpage — файлу, странице справочника по заданной утилите.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$bash whereis rm&lt;br /&gt;
rm: /bin/rm /usr/share/man/man1/rm.1.bz2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''whatis'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита '''''whatis filexxx''''' отыщет &amp;quot;filexxx&amp;quot; в своей базе данных. Может рассматриваться как упрощённый вариант команды ''man''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$bash whatis whatis&lt;br /&gt;
whatis (1) - search the whatis database for complete words&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Исследование каталога /usr/X11R6/bin.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Что находится в каталоге /usr/X11R6/bin?&lt;br /&gt;
DIRECTORY=&amp;quot;/usr/X11R6/bin&amp;quot;&lt;br /&gt;
# Попробуйте также &amp;quot;/bin&amp;quot;, &amp;quot;/usr/bin&amp;quot;, &amp;quot;/usr/local/bin&amp;quot;, и т.д.&lt;br /&gt;
for file in $DIRECTORY/*&lt;br /&gt;
do&lt;br /&gt;
 whatis `basename $file` # Вывод информации о файле.&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
# Вывод этого сценария можно перенаправить в файл:&lt;br /&gt;
# ./what.sh &amp;gt;&amp;gt;whatis.db&lt;br /&gt;
# или включить постраничный просмотр на экране,&lt;br /&gt;
# ./what.sh | less&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''vdir'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Вывод списка файлов в каталоге. Тот же эффект имеет команда ''[[ls]] -l''&amp;lt;br /&amp;gt;&lt;br /&gt;
Это одна из утилит GNU fileutils.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ vdir&lt;br /&gt;
total 10&lt;br /&gt;
-rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 data1.xrolo&lt;br /&gt;
-rw-r--r-- 1 bozo bozo 4602 May 25 13:58 data1.xrolo.bak&lt;br /&gt;
-rw-r--r-- 1 bozo bozo 877 Dec 17 2000 employment.xrolo&lt;br /&gt;
bash ls -l&lt;br /&gt;
total 10&lt;br /&gt;
-rw-r--r-- 1 bozo bozo 4034 Jul 18 22:04 data1.xrolo&lt;br /&gt;
-rw-r--r-- 1 bozo bozo 4602 May 25 13:58 data1.xrolo.bak&lt;br /&gt;
-rw-r--r-- 1 bozo bozo 877 Dec 17 2000 employment.xrolo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''locate,slocate'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда ''locate'' определяет местонахождение файла, используя свою базу данных, создаваемую специально для этих целей. Команда ''slocate'' — это защищенная версия ''locate'' (которая может оказаться простым псевдонимом команды ''slocate'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$bash locate hickson&lt;br /&gt;
/usr/lib/xephem/catalogs/hickson.edb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''readlink'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Возвращает имя файла, на который указывает символическая ссылка.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ readlink /usr/bin/awk&lt;br /&gt;
../../bin/gawk&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''strings'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''strings''''' используется для поиска печатаемых строк в двоичных файлах. Она выводит последовательности печатаемых символов, обнаруженных в заданном файле. Может использоваться для прикидочного анализа дамп-файлов (core dump) или для отыскания информации о типе файла, например для графических файлов неизвестного формата(например, '''''strings image-file | more''''' может вывести такую строчку: JFIF, что говорит о том, что мы имеем дело с графическим файлом в формате jpeg). В сценариях, вероятнее всего, вам придётся использовать эту команду в связке с [[grep]] или [[sed]].&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;quot;Расширенная&amp;quot; команда strings.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# wstrings.sh: &amp;quot;word-strings&amp;quot; (расширенная команда &amp;quot;strings&amp;quot;)&lt;br /&gt;
#&lt;br /&gt;
# Этот сценарий фильтрует вывод команды &amp;quot;strings&amp;quot; путем проверки на соответствие&lt;br /&gt;
# выводимых слов по файлу словаря.&lt;br /&gt;
# Таким способом эффективно &amp;quot;отсекается&amp;quot; весь &amp;quot;мусор&amp;quot;,&lt;br /&gt;
# и выводятся только распознанные слова.&lt;br /&gt;
# =================================================================&lt;br /&gt;
# Стандартная проверка входных аргументов&lt;br /&gt;
ARGS=1&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
E_NOFILE=66&lt;br /&gt;
if [ $# -ne $ARGS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
if [ ! -f &amp;quot;$1&amp;quot; ] # Проверка наличия файла.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$1\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOFILE&lt;br /&gt;
fi&lt;br /&gt;
# =================================================================&lt;br /&gt;
MINSTRLEN=3                             # Минимальная длина строки.&lt;br /&gt;
WORDFILE=/usr/share/dict/linux.words    # Файл словаря.&lt;br /&gt;
                                        # Можно указать иной&lt;br /&gt;
                                        # файл словаря&lt;br /&gt;
                                        # в формате — &amp;quot;одно слово на строке&amp;quot;.&lt;br /&gt;
wlist=`strings &amp;quot;$1&amp;quot; | tr A-Z a-z | tr '[:space:]' Z | \&lt;br /&gt;
tr -cs '[:alpha:]' Z | tr -s '\173-\377' Z | tr Z ' '`&lt;br /&gt;
# Трансляция вывода от 'strings' с помощью нескольких 'tr'.&lt;br /&gt;
# &amp;quot;tr A-Z a-z&amp;quot; — перевод в нижний регистр.&lt;br /&gt;
# &amp;quot;tr '[:space:]'&amp;quot; — конвертирует пробелы в символы Z.&lt;br /&gt;
# &amp;quot;tr -cs '[:alpha:]' Z&amp;quot; — конвертирует неалфавитные символы в символы Z,&lt;br /&gt;
# и удаляет повторяющиеся символы Z.&lt;br /&gt;
# &amp;quot;tr -s '\173-\377' Z&amp;quot; — Конвертирует все символы, с кодами выше 'z' в Z&lt;br /&gt;
# и удаляет повторяющиеся символы Z,&lt;br /&gt;
# эта команда удалит все символы, которые не были распознаны предыдущими&lt;br /&gt;
# командами трансляции (tr).&lt;br /&gt;
# Наконец, &amp;quot;tr Z ' '&amp;quot; — преобразует все символы Z в пробелы,&lt;br /&gt;
# которые будут рассматриваться в качестве разделителя слов в цикле, приведенном ниже.&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание на технику многоуровневой обработки с помощью 'tr',&lt;br /&gt;
# каждый раз эта команда вызывается с различным набором аргументов.&lt;br /&gt;
for word in $wlist                   # Важно:&lt;br /&gt;
                                     # переменная $wlist не должна заключаться в кавычки.&lt;br /&gt;
                                     # &amp;quot;$wlist&amp;quot; — не сработает.&lt;br /&gt;
                                     # Почему?&lt;br /&gt;
do&lt;br /&gt;
 strlen=${#word}                   # Дина строки.&lt;br /&gt;
 if [ &amp;quot;$strlen&amp;quot; -lt &amp;quot;$MINSTRLEN&amp;quot; ] # Не рассматривать короткие строки.&lt;br /&gt;
 then&lt;br /&gt;
  continue&lt;br /&gt;
 fi&lt;br /&gt;
 grep -Fw $word &amp;quot;$WORDFILE&amp;quot;        # Проверка слова по словарю.&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Сравнение'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''diff,patch'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''diff''''': очень гибкая утилита сравнения файлов. Она выполняет построчное сравнение файлов. В отдельных случаях, таких как поиск по словарю, может оказаться полезной фильтрация файлов с помощью '''''sort''''' и '''''uniq''''' перед тем как отдать поток данных через конвейер утилите '''''diff'''''. '''''diff file-1 file-2''''' — выведет строки, имеющие отличия, указывая — какому файлу, какая строка принадлежит.&amp;lt;br /&amp;gt;&lt;br /&gt;
С ключом ''--side-by-side'', команда '''''diff''''' выведет сравниваемые файлы в две колонки, с указанием несовпадающих строк. Ключи ''-c'' и ''-u'' так же служат для облегчения интерпретации результатов работы '''''diff'''''. Существует ряд интерфейсных оболочек для утилиты '''''diff''''', среди них можно назвать: '''''spiff''''', '''''wdiff''''','''''xdiff ''''' и '''''mgdiff'''''. Команда '''''diff''''' возвращает код завершения 0, если сравниваемые файлы идентичны и 1, если они отличаются. Это позволяет использовать '''''diff''''' в условных операторах внутри сценариев на языке командной оболочки (см.ниже).&amp;lt;br /&amp;gt;&lt;br /&gt;
В общем случае, '''''diff''''' используется для генерации файла различий, который используется как аргумент команды '''''patch'''''. Ключ ''-e'' отвечает за вывод файла различий в формате, пригодном для использования с '''''ed''''' или '''''ex'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''patch''''': гибкая утилита для &amp;quot;наложения заплат&amp;quot;. С помощью файла различий, сгенерированного утилитой '''''diff''''', утилита '''''patch''''' может использоваться для обновления устаревших версий файлов. Это позволяет распространять относительно небольшие &amp;quot;diff&amp;quot;-файлы вместо целых пакетов. Распространение &amp;quot;заплат&amp;quot; к ядру стало наиболее предпочтительным методом распространения более новых версий ядра Linux.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
patch -p1 &amp;lt; patch-file &lt;br /&gt;
# Применит все изменения из 'patch-file'&lt;br /&gt;
# к файлам, описанным там же.&lt;br /&gt;
# Так выполняется обновление пакетов до более высоких версий.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Наложение &amp;quot;заплат&amp;quot; на ядро:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cd /usr/src&lt;br /&gt;
gzip -cd patchXX.gz | patch -p0&lt;br /&gt;
# Обновление исходных текстов ядра с помощью 'patch'.&lt;br /&gt;
# Пример взят из файла &amp;quot;README&amp;quot;,&lt;br /&gt;
# автор не известен (Alan Cox?).&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Кроме того, утилита '''''diff''''' в состоянии выполнять рекурсивный обход каталогов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ diff -r ~/notes1 ~/notes2&lt;br /&gt;
Only in /home/bozo/notes1: file02&lt;br /&gt;
Only in /home/bozo/notes1: file03&lt;br /&gt;
Only in /home/bozo/notes2: file04&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Утилита '''''zdiff''''' сравнивает сжатые, с помощью [[gzip]], файлы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''diff3'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Расширенная версия '''''diff''''', которая сравнивает сразу 3 файла. В случае успеха возвращает 0, но,к сожалению, не даёт никакой информации о результатах сравнения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ diff3 file-1 file-2 file-3&lt;br /&gt;
====&lt;br /&gt;
1:1c&lt;br /&gt;
 This is line 1 of &amp;quot;file-1&amp;quot;.&lt;br /&gt;
2:1c&lt;br /&gt;
 This is line 1 of &amp;quot;file-2&amp;quot;.&lt;br /&gt;
3:1c&lt;br /&gt;
 This is line 1 of &amp;quot;file-3&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sdiff'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сравнение и/или редактирование двух файлов перед объединением их в один файл. Это интерактивная утилита, по своей природе, и из-за этого она довольно редко используется в сценариях.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cmp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита '''''cmp''''' — это упрощенная версия '''''diff'''''. В то время, как '''''diff''''' выводит подробную информацию об имеющихся различиях, утилита '''''cmp''''' лишь показывает номер строки и позицию в строке, где было встречено различие. Подобно команде '''''diff''''', команда '''''cmp''''' возвращает код завершения 0, если файлы идентичны и 1, если они различны. Это позволяет использовать команду '''''cmp''''' в условных операторах.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример сравнения двух файлов с помощью cmp.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
ARGS=2 # Ожидаются два аргумента командной строки.&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
E_UNREADABLE=66&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` file1 file2&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
if [[ ! -r &amp;quot;$1&amp;quot; || ! -r &amp;quot;$2&amp;quot; ]]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Оба файла должны существовать и должны быть доступны для чтения.&amp;quot;&lt;br /&gt;
 exit $E_UNREADABLE&lt;br /&gt;
fi&lt;br /&gt;
cmp $1 $2 &amp;amp;&amp;gt; /dev/null # /dev/null — &amp;quot;похоронит&amp;quot; вывод от команды &amp;quot;cmp&amp;quot;.&lt;br /&gt;
# cmp -s $1 $2 даст тот же результат (&amp;quot;-s&amp;quot; — флаг &amp;quot;тишины&amp;quot; для &amp;quot;cmp&amp;quot;)&lt;br /&gt;
# Спасибо Anders Gustavsson за замечание.&lt;br /&gt;
#&lt;br /&gt;
# Также применимо к 'diff', т.е., diff $1 $2 &amp;amp;&amp;gt; /dev/null&lt;br /&gt;
if [ $? -eq 0 ] # Проверка кода возврата команды &amp;quot;cmp&amp;quot;.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$1\&amp;quot; идентичен файлу \&amp;quot;$2\&amp;quot;.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$1\&amp;quot; отличается от файла \&amp;quot;$2\&amp;quot;.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для работы с [[gzip]] файлами используется утилита '''''zcmp'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''comm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Универсальная утилита сравнения. Работает с отсортированными файлами.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;comm -options first-file second-file&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;comm file-1 file-2&amp;lt;/source&amp;gt;&lt;br /&gt;
вывод в три колонки:&lt;br /&gt;
* колонка 1 = уникальные строки для file-1&lt;br /&gt;
* колонка 2 = уникальные строки для file-2&lt;br /&gt;
* колонка 3 = одинаковые строки.&lt;br /&gt;
Ключи, подавляющие вывод в одной или более колонках:&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''''-1''''' — подавление вывода в колонку 1&lt;br /&gt;
* '''''-2''''' — подавление вывода в колонку 2&lt;br /&gt;
* '''''-3''''' — подавление вывода в колонку 3&lt;br /&gt;
* '''''-12''''' — подавление вывода в колонки 1 и 2, и т.д.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Утилиты'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''basename'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит только название файла, без каталога размещения. Конструкция '''''basename $0''''' — позволяет сценарию узнать свое имя, то есть имя файла, который был запущен. Это имя может быть использовано для вывода сообщений, например:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;echo &amp;quot;Порядок использования: `basename $0` arg1 arg2 ... argn&amp;quot;&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dirname'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Отсекает '''''basename''''' от полного имени файла и выводит только путь к файлу.&lt;br /&gt;
Утилитам '''''basename''''' и '''''dirname''''' может быть передана любая строка, в качестве аргумента. Этот аргумент необязательно должен быть именем существующего файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Утилиты basename и dirname.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
a=/home/bozo/daily-journal.txt&lt;br /&gt;
echo &amp;quot;Basename для /home/bozo/daily-journal.txt = `basename $a`&amp;quot;&lt;br /&gt;
echo &amp;quot;Dirname для /home/bozo/daily-journal.txt = `dirname $a`&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Мой домашний каталог `basename ~/`.&amp;quot; # Можно указать просто ~.&lt;br /&gt;
echo &amp;quot;Каталог моего домашнего каталога `dirname ~/`.&amp;quot; # Можно указать просто ~.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''split'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита разбивает файл на несколько частей. Обычно используется для разбиения больших файлов, чтобы их можно было записать на дискеты или передать по электронной почте по частям.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sum,cksum,md5sum'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эти утилиты предназначены для вычисления контрольных сумм. Контрольная сумма — это некоторое число, вычисляемое исходя из содержимого файла, и служит для контроля целостности информации в файле. Сценарий может выполнять проверку контрольных сумм для того, чтобы убедиться, что файл не был изменен или повреждён. Для большей безопасности, рекомендуется использовать 128-битную сумму, генерируемую утилитой '''''md5sum''''' (''messagedigest checksum'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cksum /boot/vmlinuz&lt;br /&gt;
1670054224 804083 /boot/vmlinuz&lt;br /&gt;
bash$ md5sum /boot/vmlinuz&lt;br /&gt;
0f43eccea8f09e0a0b2b5cf1dcf333ba /boot/vmlinuz&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Обратите внимание: утилита '''''cksum''''' выводит контрольную сумму и размер файла в байтах.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка целостности файла.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# file-integrity.sh: Проверка целостности файлов в заданном каталоге&lt;br /&gt;
E_DIR_NOMATCH=70&lt;br /&gt;
E_BAD_DBFILE=71&lt;br /&gt;
dbfile=File_record.md5&lt;br /&gt;
# Файл для хранения контрольных сумм.&lt;br /&gt;
set_up_database ()&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;&amp;quot;$directory&amp;quot;&amp;quot; &amp;gt; &amp;quot;$dbfile&amp;quot;&lt;br /&gt;
 # Записать название каталога в первую строку файла.&lt;br /&gt;
 md5sum &amp;quot;$directory&amp;quot;/* &amp;gt;&amp;gt; &amp;quot;$dbfile&amp;quot;&lt;br /&gt;
 # Записать контрольные суммы md5 и имена файлов.&lt;br /&gt;
}&lt;br /&gt;
check_database ()&lt;br /&gt;
{&lt;br /&gt;
 local n=0&lt;br /&gt;
 local filename&lt;br /&gt;
 local checksum&lt;br /&gt;
 # ------------------------------------------- #&lt;br /&gt;
 # Возможно эта проверка и не нужна,&lt;br /&gt;
 # но лучше перестраховаться сейчас, чем жалеть об этом потом.&lt;br /&gt;
 if [ ! -r &amp;quot;$dbfile&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Не могу прочитать файл с контрольными суммами!&amp;quot;&lt;br /&gt;
  exit $E_BAD_DBFILE&lt;br /&gt;
 fi&lt;br /&gt;
 # ------------------------------------------- #&lt;br /&gt;
 while read record[n]&lt;br /&gt;
 do&lt;br /&gt;
  directory_checked=&amp;quot;${record[0]}&amp;quot;&lt;br /&gt;
  if [ &amp;quot;$directory_checked&amp;quot; != &amp;quot;$directory&amp;quot; ]&lt;br /&gt;
  then&lt;br /&gt;
   echo &amp;quot;Имя каталога не совпадает с записаным в файле!&amp;quot;&lt;br /&gt;
   # Попытка использовать файл контрольных сумм для другого каталога.&lt;br /&gt;
   exit $E_DIR_NOMATCH&lt;br /&gt;
  fi&lt;br /&gt;
  if [ &amp;quot;$n&amp;quot; -gt 0 ] # Не имя каталога.&lt;br /&gt;
  then&lt;br /&gt;
   filename[n]=$( echo ${record[$n]} | awk '{ print $2 }' )&lt;br /&gt;
   # md5sum записывает в обратном порядке,&lt;br /&gt;
   # сначала контрольную сумму, затем имя файла.&lt;br /&gt;
   checksum[n]=$( md5sum &amp;quot;${filename[n]}&amp;quot; )&lt;br /&gt;
   if [ &amp;quot;${record[n]}&amp;quot; = &amp;quot;${checksum[n]}&amp;quot; ]&lt;br /&gt;
   then&lt;br /&gt;
    echo &amp;quot;Файл ${filename[n]} не был изменен.&amp;quot;&lt;br /&gt;
   else&lt;br /&gt;
    echo &amp;quot;ОШИБКА КОНТРОЛЬНОЙ СУММЫ для файла ${filename[n]}!&amp;quot;&lt;br /&gt;
    # Файл был изменен со времени последней проверки.&lt;br /&gt;
   fi&lt;br /&gt;
  fi&lt;br /&gt;
  let &amp;quot;n+=1&amp;quot;&lt;br /&gt;
done &amp;lt;&amp;quot;$dbfile&amp;quot; # Чтение контрольных сумм из файла.&lt;br /&gt;
}&lt;br /&gt;
# =================================================== #&lt;br /&gt;
# main ()&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 directory=&amp;quot;$PWD&amp;quot; # Если каталог не задан,&lt;br /&gt;
else              # то используется текущий каталог.&lt;br /&gt;
 directory=&amp;quot;$1&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
clear&lt;br /&gt;
# Очистка экрана.&lt;br /&gt;
# ------------------------------------------------------------------ #&lt;br /&gt;
if [ ! -r &amp;quot;$dbfile&amp;quot; ] # Необходимо создать файл с контрольными суммами?&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Создание файла с контрольными суммами, \&amp;quot;&amp;quot;$directory&amp;quot;/&amp;quot;$dbfile&amp;quot;\&amp;quot;.&amp;quot;; echo&lt;br /&gt;
 set_up_database&lt;br /&gt;
fi&lt;br /&gt;
# ------------------------------------------------------------------ #&lt;br /&gt;
check_database # Выполнить проверку.&lt;br /&gt;
echo&lt;br /&gt;
# Вывод этого сценария можно перенаправить в файл,&lt;br /&gt;
# это особенно полезно при проверке большого количества файлов.&lt;br /&gt;
# Более строгая проверка целостности файлов,&lt;br /&gt;
# может быть выполнена с помощью пакета &amp;quot;Tripwire&amp;quot;,&lt;br /&gt;
# http://sourceforge.net/projects/tripwire/.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''shred'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Надёжное, с точки зрения безопасности, стирание файла, посредством предварительной, многократной записи в файл случайной информации, перед тем как удалить его. Является составной частью пакета ''GNU fileutils''. Имеется ряд технологий, с помощью которых всё-таки возможно восстановить файлы, удаленные утилитой '''''shred'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Кодирование и шифрование'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''uuencode'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита используется для кодирования двоичных файлов в символы ASCII, после такого кодирования файлы могут, с достаточной степенью безопасности, передаваться по сети, вкладываться в электронные письма и т.п..&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''uudecode'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита декодирования файлов, прошедших обработку утилитой '''''uuencode'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Декодирование файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
lines=35 # 35 строк для заголовка (более чем достаточно).&lt;br /&gt;
for File in * # Обход всех файлов в текущем каталоге...&lt;br /&gt;
do&lt;br /&gt;
 search1=`head -$lines $File | grep begin | wc -w`&lt;br /&gt;
 search2=`tail -$lines $File | grep end | wc -w`&lt;br /&gt;
 # Закодированные файлы начинаются со слова &amp;quot;begin&amp;quot;,&lt;br /&gt;
 # и заканчиваются словом &amp;quot;end&amp;quot;.&lt;br /&gt;
 if [ &amp;quot;$search1&amp;quot; -gt 0 ]&lt;br /&gt;
 then&lt;br /&gt;
  if [ &amp;quot;$search2&amp;quot; -gt 0 ]&lt;br /&gt;
  then&lt;br /&gt;
   echo &amp;quot;декодируется файл - $File -&amp;quot;&lt;br /&gt;
   uudecode $File&lt;br /&gt;
  fi&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
# Обратите внимание: если передать сценарию самого себя, для декодирования,&lt;br /&gt;
# то это введёт его в заблуждение поскольку в тексте сценария встречаются слова &amp;quot;begin&amp;quot; и &amp;quot;end&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При декодировании и выводе длинных текстовых сообщений из новостных групп ''Usenet'', очень нелишним будет передать текст, по конвейеру, команде '''''fold -s'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mimencode,mmencode'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилиты '''''mimencode''''' и '''''mmencode''''' предназначены для обработки закодированных мультимедийных вложений в электронные письма. Хотя почтовые программы (такие как pine или kmail) имеют возможность автоматической обработки таких вложений, тем не менее эти утилиты позволяют обрабатывать вложения вручную, из командной строки или в пакетном режиме, из сценария на языке командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''crypt'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Одно время, это была стандартная, для Unix, утилита шифрования файлов. Политически мотивированные, правительственные постановления ряда стран, напрямую запрещают экспорт программного обеспечения для шифрования, что, в результате, привело практически к полному исчезновению '''''crypt''''' из большинства Unix-систем (в том числе и Linux). К счастью,программистами было разработано множество вполне приличных альтернатив, и среди них '''''cruft'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Прочее'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mktemp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создаёт временный файл с &amp;quot;уникальным&amp;quot; именем.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
PREFIX=filename&lt;br /&gt;
tempfile=`mktemp $PREFIX.XXXXXX`&lt;br /&gt;
#                        ^^^^^^ Необходимо по меньшей мере 6 заполнителейecho &amp;quot;имя временного файла = $tempfile&amp;quot;&lt;br /&gt;
echo &amp;quot;имя временного файла = $tempfile&amp;quot;&lt;br /&gt;
# имя временного файла = filename.QA2ZpY или нечто подобное...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''make'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита для компиляции и сборки программ. Но может использоваться для выполнения любых других операций, основанных на анализе наличия изменений в исходных файлах. Команда '''''make''''' использует в своей работе Makefile, который содержит перечень зависимостей и операций, которые необходимо выполнить для удовлетворения этих зависимостей.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''install'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Своего рода — утилита копирования файлов, похожа на ''cp'', но дополнительно позволяет изменять права доступа и атрибуты копируемых файлов. Напрямую эта команда практически не используется, чаще всего она встречается в Makefile (в разделе ''make install'' :). Она может использоваться в сценариях установки ПО.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dos2unix'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Автор утилиты — Benjamin Lin со-товарищи. Предназначена для преобразования текстовых файлов из формата DOS (в котором строки завершаются комбинацией символов CR-LF) в формат Unix (в котором строки завершаются одним символом LF) и обратно.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ptx'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''ptx [targetfile]''''' выводит a упорядоченный предметный указатель для ''targetfile'', который можно обработать, по мере необходимости, какой-либо утилитой форматирования, в конвейере.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''more,less'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команды постраничного просмотра текстовых файлов или потоков на ''stdout''. Могут использоваться в сценариях в качестве фильтров.&lt;br /&gt;
&lt;br /&gt;
=== Команды для работы с сетью ===&lt;br /&gt;
Команды, описываемые в этом разделе, могут найти применение при исследовании и анализе процессов передачи данных по сети, а также могут использоваться в борьбе со спамерами.&lt;br /&gt;
'''Информация и статистика'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''host'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Возвращает информацию об узле Интернета, по заданному имени или IP адресу, выполняя поиск с помощью службы DNS.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ host surfacemail.com&lt;br /&gt;
surfacemail.com. has address 202.92.42.236&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ipcalc'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит информацию о заданном узле сети. С ключом ''-h'', '''''ipcalc''''' выполняет поиск имени хоста в DNS, по заданному IP адресу.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ipcalc -h 202.92.42.236&lt;br /&gt;
HOSTNAME=surfacemail.com&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''nslookup'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выполняет &amp;quot;поиск имени узла&amp;quot; Интернета по заданному IP адресу. По сути, эквивалентна командам '''''ipcalc -h''''' и '''''dig -x'''''. Команда может исполняться как в интерактивном, так и в неинтерактивном режиме, т.е. в пределах сценария.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ nslookup -sil 66.97.104.180&lt;br /&gt;
nslookup kuhleersparnis.ch&lt;br /&gt;
Server: 135.116.137.2&lt;br /&gt;
Address: 135.116.137.2#53&lt;br /&gt;
Non-authoritative answer:&lt;br /&gt;
Name: kuhleersparnis.ch&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dig'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подобно команде '''''nslookup''''', выполняет &amp;quot;поиск имени узла&amp;quot; в Интернете.&lt;br /&gt;
Сравните вывод команды '''''dig -x''''' с выводом команд '''''ipcalc -h''''' и '''''nslookup'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ dig -x 81.9.6.2&lt;br /&gt;
;; Got answer:&lt;br /&gt;
;; -&amp;gt;&amp;gt;HEADER&amp;lt;&amp;lt;- opcode: QUERY, status: NXDOMAIN, id: 11649&lt;br /&gt;
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 0&lt;br /&gt;
;; QUESTION SECTION:&lt;br /&gt;
;2.6.9.81.in-addr.arpa.             IN            PTR&lt;br /&gt;
&lt;br /&gt;
;; AUTHORITY SECTION:&lt;br /&gt;
6.9.81.in-addr.arpa.         3600   IN            SOA ns.eltel.net. noc.eltel.net.&lt;br /&gt;
2002031705        900    600   86400 3600&lt;br /&gt;
&lt;br /&gt;
;; Query time: 537 msec&lt;br /&gt;
;; SERVER: 135.116.137.2#53(135.116.137.2)&lt;br /&gt;
;; WHEN: Wed Jun 26 08:35:24 2002&lt;br /&gt;
;; MSG SIZE rcvd: 91&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''traceroute'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита предназначена для исследования топологии сети посредством передачи ICMP пакетов удалённому узлу. Эта программа может работать в LAN, WAN и в Интернет. Удаленный узел может быть указан как по имени, так и по IP адресу. Вывод команды '''''traceroute''''' может быть передан по конвейеру утилитам [[grep]] или [[sed]], для дальнейшего анализа.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ traceroute 81.9.6.2&lt;br /&gt;
traceroute to 81.9.6.2 (81.9.6.2), 30 hops max, 38 byte packets&lt;br /&gt;
1 tc43.xjbnnbrb.com (136.30.178.8) 191.303 ms 179.400 ms 179.767 ms&lt;br /&gt;
2 or0.xjbnnbrb.com (136.30.178.1) 179.536 ms 179.534 ms 169.685 ms&lt;br /&gt;
3 192.168.11.101 (192.168.11.101) 189.471 ms 189.556 ms *&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ping'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выполняет передачу пакета &amp;quot;ICMP ECHO_REQUEST&amp;quot; другой системе в сети. Чаще всего служит в качестве инструмента диагностики соединений, должна использоваться с большой осторожностью.&lt;br /&gt;
В случае успеха, '''''ping''''' возвращает код завершения 0, поэтому команда '''''ping''''' может использоваться в условных операторах.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ping localhost&lt;br /&gt;
PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.&lt;br /&gt;
Warning: time of day goes back, taking countermeasures.&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=709 usec&lt;br /&gt;
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=1 ttl=255 time=286 usec&lt;br /&gt;
--- localhost.localdomain ping statistics ---&lt;br /&gt;
2 packets transmitted, 2 packets received, 0% packet loss&lt;br /&gt;
round-trip min/avg/max/mdev = 0.286/0.497/0.709/0.212 ms&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''whois'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выполняет поиск в DNS (Domain Name System). Ключом ''-h'' можно указать какой из ''whois'' серверов будет запрошен.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''finger'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Возвращает информацию о пользователях в сети. По желанию, эта команда может выводить содержимое файлов ''~/.plan'', ''~/.project'' и ''~/.forward'', указанного пользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ finger&lt;br /&gt;
Login Name Tty Idle Login Time Office Office Phone&lt;br /&gt;
bozo Bozo Bozeman tty1 8 Jun 25 16:59&lt;br /&gt;
bozo Bozo Bozeman ttyp0 Jun 25 16:59&lt;br /&gt;
bozo Bozo Bozeman ttyp1 Jun 25 17:07&lt;br /&gt;
&lt;br /&gt;
bash$ finger bozo&lt;br /&gt;
Login: bozo Name: Bozo Bozeman&lt;br /&gt;
Directory: /home/bozo Shell: /bin/bash&lt;br /&gt;
Office: 2355 Clown St., 543-1234&lt;br /&gt;
On since Fri Aug 31 20:13 (MST) on tty1 1 hour 38 minutes idle&lt;br /&gt;
On since Fri Aug 31 20:13 (MST) on pts/0 12 seconds idle&lt;br /&gt;
On since Fri Aug 31 20:13 (MST) on pts/1&lt;br /&gt;
On since Fri Aug 31 20:31 (MST) on pts/2 1 hour 16 minutes idle&lt;br /&gt;
No mail.&lt;br /&gt;
No Plan.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
По соображениям безопасности, в большинстве сетей служба '''''finger''''', и соответствующий демон,отключена.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''chfn'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Изменяет некоторые сведения о пользователе, такие как: полное имя, номер кабинета, телефон рабочий и домашний. Которые обычно выводятся командой '''''finger'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''vrfy'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Проверка адреса электронной почты.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Доступ к удалённым системам'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sx,rx'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команды '''''sx''''' и '''''rx''''' служат для приёма/передачи файлов на/из удалённый узел в сети, по протоколу ''xmodem''. Входят в состав пакета ''minicom''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sz,rz'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команды '''''sz''''' и '''''rz''''' служат для приёма/передачи файлов на/из удаленный узел в сети, по протоколу ''zmodem''. Протокол ''zmodem'' имеет некоторые преимущества перед протоколом ''xmodem'', в качестве такого преимущества можно назвать более высокую скорость передачи и возможность возобновления передачи, в случае её разрыва. Входят в состав пакета ''minicom''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ftp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Под этим именем подразумевается утилита и протокол передачи файлов. Сеансы '''''ftp''''' могут устанавливаться из сценариев.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''uucp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Unix to Unix copy''. Это коммуникационный пакет для передачи файлов между Unix серверами. Сценарий на языке командной оболочки — один из самых эффективных способов автоматизации такого обмена. Похоже, что с появлением Интернет и электронной почты, '''''uucp''''' постепенно уходит в небытие, однако, она с успехом может использоваться в изолированных, не имеющих выхода в Интернет, сетях.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cu'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Call Up'' — выполняет соединение с удалённой системой, как простой терминал. Эта команда является частью пакета '''''uucp''''' и, своего рода, упрощенным вариантом команды '''''telnet'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''telnet'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита и протокол для подключения к удалённой системе. Протокол '''''telnet''''' небезопасен по своей природе, поэтому следует воздерживаться от его использования.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''wget'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[wget]] — неинтерактивная утилита для скачивания файлов с Web или ftp сайтов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
wget -p http://www.xyz23.com/file01.html&lt;br /&gt;
wget -r ftp://ftp.xyz24.net/~bozo/project_files/ -o $SAVEFILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lynx'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''lynx''''' — Web-браузер, внутри сценариев (с ключом ''-dump'') может использоваться для скачивания файлов с Web или ftp сайтов, в неинтерактивном режиме.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
lynx -dump http://www.xyz23.com/file01.html &amp;gt;$SAVEFILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rlogin'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Remote login'' — инициирует сессию с удалённой системой. Эта команда небезопасна, вместо неё лучше использовать '''''ssh'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rsh'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Remote shell'' — исполняет команду на удалённой системе. Эта команда небезопасна, вместо неё лучше использовать '''''ssh'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rcp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Remote copy'' — копирование файлов между двумя машинами через сеть. Подобно прочим r*утилитам, команда '''''rcp''''' небезопасна и потому, использовать её в сценариях нежелательно. В качестве замены можно порекомендовать '''''ssh''''' или '''''expect'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ssh'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Secure shell'' — устанавливает сеанс связи и выполняет команды на удалённой системе. Выступает в качестве защищённой замены для '''''telnet''''', '''''rlogin''''', '''''rcp''''' и '''''rsh'''''. Использует идентификацию, аутентификацию и шифрование информации, передаваемой через сеть. Подробности вы найдете в ''man ssh''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Локальная сеть'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''write'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита позволяет передать текст сообщения на другой терминал (console или xterm). Разрешить или запретить доступ к терминалу можно с помощью команды '''''mesg'''''.&lt;br /&gt;
Поскольку команда '''''write''''' работает в интерактивном режиме, то, как правило, она не употребляется в сценариях.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''MAIL'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mail'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Чтение или передача электронной почты. Этот почтовый клиент командной строки с успехом может использоваться в сценариях.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий, отправляющий себя самого по электронной почте.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# self-mailer.sh: Сценарий отправляет себя самого по электронной почте&lt;br /&gt;
adr=${1:-`whoami`} # Если пользователь не указан, то — себе самому.&lt;br /&gt;
# Вызов 'self-mailer.sh wiseguy@superdupergenius.com'&lt;br /&gt;
# приведёт к передаче электронного письма по указанному адресу.&lt;br /&gt;
# Вызов 'self-mailer.sh' (без аргументов) — отправит письмо&lt;br /&gt;
# пользователю, запустившему сценарий, например, bozo@localhost.localdomain.&lt;br /&gt;
#&lt;br /&gt;
# Дополнительно о конструкции ${parameter:-default},&lt;br /&gt;
# см. раздел &amp;quot;Подстановка параметров&amp;quot;&lt;br /&gt;
# в главе &amp;quot;К вопросу о переменных&amp;quot;.&lt;br /&gt;
# ============================================================================&lt;br /&gt;
cat $0 | mail -s &amp;quot;Сценарий \&amp;quot;`basename $0`\&amp;quot; отправил себя сам.&amp;quot; &amp;quot;$adr&amp;quot;&lt;br /&gt;
# ============================================================================&lt;br /&gt;
# --------------------------------------------&lt;br /&gt;
# Поздравляю!&lt;br /&gt;
# Этот сценарий запустила какая-то &amp;quot;редиска&amp;quot;,&lt;br /&gt;
# и заставила отправить этот текст к Вам.&lt;br /&gt;
# Очевидно кто-то не знает куда девать свое время.&lt;br /&gt;
# --------------------------------------------&lt;br /&gt;
echo &amp;quot;`date`, сценарий \&amp;quot;`basename $0`\&amp;quot; отправлен &amp;quot;$adr&amp;quot;.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mailto'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''mailto''''', похожа на '''''mail''''', она также отправляет сообщения по электронной почте. Однако, кроме этого, '''''mailto''''' позволяет отправлять MIME (multimedia) сообщения.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''vacation'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита предназначена для автоматической передачи ответов на электронные письма, например для того, чтобы уведомить отправителя о том, что получатель временно отсутствует. Работает совместно с '''''sendmail''''' и не может использоваться для передачи сообщений через коммутируемые линии (по модему).&lt;br /&gt;
&lt;br /&gt;
=== Команды управления терминалом ===&lt;br /&gt;
'''Команды, имеющие отношение к консоли или терминалу'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tput'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Инициализация терминала или выполнение запроса к базе данных терминалов '''''terminfo'''''. С помощью '''''tput''''' можно выполнять различные операции. '''''tput clear''''' — эквивалентно команде '''''clear'''''. '''''tput reset''''' — эквивалентно команде '''''reset'''''. '''''tput sgr0''''' — так же сбрасывает настройки терминал, но без очистки экрана.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ tput longname&lt;br /&gt;
xterm terminal emulator (XFree86 4.0 Window System)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''tput cup X Y''''' перемещает курсор в координаты (X,Y). Обычно этой команде предшествует '''''clear''''', очищающая экран.&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание: '''''stty''''' предлагает более широкий диапазон возможностей.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''infocmp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Cравнение или печать информации о характеристиках терминалов, хранящейся в базе данных '''''terminfo'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ infocmp&lt;br /&gt;
# Reconstructed via infocmp from file:&lt;br /&gt;
/usr/share/terminfo/r/rxvt&lt;br /&gt;
rxvt|rxvt terminal emulator (X Window System),&lt;br /&gt;
am, bce, eo, km, mir, msgr, xenl, xon,&lt;br /&gt;
colors#8, cols#80, it#8, lines#24, pairs#64,&lt;br /&gt;
acsc=``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~,&lt;br /&gt;
bel=^G, blink=\E[5m, bold=\E[1m,&lt;br /&gt;
civis=\E[?25l,&lt;br /&gt;
clear=\E[H\E[2J, cnorm=\E[?25h, cr=^M,&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''reset'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сбрасывает настройки терминала и очищает экран. Как и в случае команды '''''clear''''', курсор и приглашение к вводу (''prompt'') выводятся в верхнем левом углу терминала.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''clear'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''clear''''' просто очищает экран терминала или окно ''xterm''. Курсор и приглашение к вводу (''prompt'') выводятся в верхнем левом углу терминала. Эта команда может запускаться как из командной строки, так и из сценария.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''script'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита позволяет сохранять в файле все символы, введённые пользователем c клавиатуры(вывод тоже). Получая, фактически, подробнейший синхронный протокол сессии.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Команды выполнения математических операций ===&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''factor'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Разложение целого числа на простые множители.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ factor 27417&lt;br /&gt;
27417: 3 13 19 37&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''bc'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash не в состоянии выполнять действия над числами с плавающей запятой и не содержит многих важных математических функций. К счастью существует '''''bc'''''.&lt;br /&gt;
Универсальная, выполняющая вычисления с произвольной точностью, утилита '''''bc''''' обладает некоторыми возможностями, характерными для языков программирования.&lt;br /&gt;
Синтаксис '''''bc''''' немного напоминает язык ''C''. Поскольку это утилита Unix, то она может достаточно широко использоваться в сценариях на языке командной оболочки, в том числе и в конвейерной обработке данных. Ниже приводится простой шаблон работы с утилитой '''''bc''''' в сценарии. Здесь используется приём подстановки команд.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable=$(echo &amp;quot;OPTIONS; OPERATIONS&amp;quot; | bc)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ежемесячные выплаты по займу.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# monthlypmt.sh: Расчёт ежемесячных выплат по займу.&lt;br /&gt;
# Это измененный вариант пакета &amp;quot;mcalc&amp;quot; (mortgage calculator),&lt;br /&gt;
# написанного Jeff Schmidt и Mendel Cooper (ваш покорный слуга).&lt;br /&gt;
# http://www.ibiblio.org/pub/Linux/apps/financial/mcalc-1.6.tar.gz&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Введите сумму займа, процентную ставку и срок займа,&amp;quot;&lt;br /&gt;
echo &amp;quot;для расчета суммы ежемесячных выплат.&amp;quot;&lt;br /&gt;
bottom=1.0&lt;br /&gt;
echo&lt;br /&gt;
echo -n &amp;quot;Сумма займа (без запятых — с точностью до доллара) &amp;quot;&lt;br /&gt;
read principal&lt;br /&gt;
echo -n &amp;quot;Процентная ставка (процент) &amp;quot; # Если 12%, то нужно вводить &amp;quot;12&amp;quot;, а не &amp;quot;.12&amp;quot;.&lt;br /&gt;
read interest_r&lt;br /&gt;
echo -n &amp;quot;Срок займа (месяцев) &amp;quot;&lt;br /&gt;
read term&lt;br /&gt;
interest_r=$(echo &amp;quot;scale=9; $interest_r/100.0&amp;quot; | bc) # Здесь &amp;quot;scale&amp;quot; — точность вычислений.&lt;br /&gt;
interest_rate=$(echo &amp;quot;scale=9; $interest_r/12 + 1.0&amp;quot; | bc)&lt;br /&gt;
top=$(echo &amp;quot;scale=9; $principal*$interest_rate^$term&amp;quot; | bc)&lt;br /&gt;
echo; echo &amp;quot;Прошу подождать. Вычисления потребуют некоторого времени.&amp;quot;&lt;br /&gt;
let &amp;quot;months = $term - 1&amp;quot;&lt;br /&gt;
# ====================================================================&lt;br /&gt;
for ((x=$months; x &amp;gt; 0; x--))&lt;br /&gt;
do&lt;br /&gt;
 bot=$(echo &amp;quot;scale=9; $interest_rate^$x&amp;quot; | bc)&lt;br /&gt;
 bottom=$(echo &amp;quot;scale=9; $bottom+$bot&amp;quot; | bc)&lt;br /&gt;
# bottom = $(($bottom + $bot&amp;quot;))&lt;br /&gt;
done&lt;br /&gt;
# --------------------------------------------------------------------&lt;br /&gt;
# Rick Boivie предложил более эффективную реализацию&lt;br /&gt;
# цикла вычислений, который дает выигрыш по времени на 2/3.&lt;br /&gt;
# for ((x=1; x &amp;lt;= $months; x++))&lt;br /&gt;
# do&lt;br /&gt;
#  bottom=$(echo &amp;quot;scale=9; $bottom * $interest_rate + 1&amp;quot; | bc)&lt;br /&gt;
# done&lt;br /&gt;
# А затем нашёл ещё более эффективную альтернативу,&lt;br /&gt;
# которая выполняется в 20 раз быстрее !!!&lt;br /&gt;
# bottom=`{&lt;br /&gt;
# echo &amp;quot;scale=9; bottom=$bottom; interest_rate=$interest_rate&amp;quot;&lt;br /&gt;
# for ((x=1; x &amp;lt;= $months; x++))&lt;br /&gt;
# do&lt;br /&gt;
#  echo 'bottom = bottom * interest_rate + 1'&lt;br /&gt;
# done&lt;br /&gt;
# echo 'bottom'&lt;br /&gt;
# } | bc` # Внедрить цикл 'for' в конструкцию подстановки команд.&lt;br /&gt;
# ====================================================================&lt;br /&gt;
# let &amp;quot;payment = $top/$bottom&amp;quot;&lt;br /&gt;
payment=$(echo &amp;quot;scale=2; $top/$bottom&amp;quot; | bc)&lt;br /&gt;
# Два знака после запятой, чтобы показать доллары и центы.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;ежемесячные выплаты = \$$payment&amp;quot; # Вывести знак &amp;quot;доллара&amp;quot; перед числом.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# 1) Добавьте возможность ввода суммы с точностью до цента.&lt;br /&gt;
# 2) Добавьте возможность ввода процентной ставки как в виде процентов, так и в виде десятичного числа — доли целого.&lt;br /&gt;
# 3) Если вы действительно честолюбивы, добавьте в сценарий вывод полной таблицы помесячных выплат.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перевод чисел из одной системы счисления в другую.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
##########################################################################&lt;br /&gt;
# Shellscript: base.sh - вывод чисел в разных системах счисления (Bourne Shell)&lt;br /&gt;
# Author : Heiner Steven (heiner.steven@odn.de)&lt;br /&gt;
# Date : 07-03-95&lt;br /&gt;
# Category : Desktop&lt;br /&gt;
# $Id: base.sh,v 1.2 2000/02/06 19:55:35 heiner Exp $&lt;br /&gt;
##########################################################################&lt;br /&gt;
# Description&lt;br /&gt;
#&lt;br /&gt;
# Changes&lt;br /&gt;
# 21-03-95 stv исправлена ошибка, возникающая при вводе числа 0xb (0.2)&lt;br /&gt;
##########################################################################&lt;br /&gt;
# ==&amp;gt; Используется в данном документе с разрешения автора.&lt;br /&gt;
# ==&amp;gt; Комментарии добавлены автором документа.&lt;br /&gt;
NOARGS=65&lt;br /&gt;
PN=`basename &amp;quot;$0&amp;quot;` # Имя программы&lt;br /&gt;
VER=`echo '$Revision: 1.2 $' | cut -d' ' -f2` # ==&amp;gt; VER=1.2&lt;br /&gt;
Usage () {&lt;br /&gt;
 echo &amp;quot;$PN - вывод чисел в различных системах счисления, $VER (stv '95)&lt;br /&gt;
Порядок использования: $PN [number ...]&lt;br /&gt;
Если число не задано, то производится ввод со stdin.&lt;br /&gt;
Число может быть:&lt;br /&gt;
двоичное — должно начинаться с комбинации символов 0b (например 0b1100)&lt;br /&gt;
восьмеричное — должно начинаться с 0 (например 014)&lt;br /&gt;
шестнадцатиричное — должно начинаться с комбинации символов 0x (например 0xc)&lt;br /&gt;
десятичное — в любом другом случае (например 12)&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
exit $NOARGS&lt;br /&gt;
} # ==&amp;gt; Функция вывода сообщения о порядке использования.&lt;br /&gt;
Msg () {&lt;br /&gt;
for i # ==&amp;gt; [список] параметров опущен.&lt;br /&gt;
do &lt;br /&gt;
 echo &amp;quot;$PN: $i&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
done&lt;br /&gt;
}&lt;br /&gt;
Fatal () { Msg &amp;quot;$@&amp;quot;; exit 66; }&lt;br /&gt;
PrintBases () {&lt;br /&gt;
# Определение системы счисления&lt;br /&gt;
for i # ==&amp;gt; [список] параметров опущен...&lt;br /&gt;
do # ==&amp;gt; поэтому работает с аргументами командной строки.&lt;br /&gt;
 case &amp;quot;$i&amp;quot; in&lt;br /&gt;
  0b*) ibase=2;; # двоичная&lt;br /&gt;
  0x*|[a-f]*|[A-F]*) ibase=16;;    # шестнадцатиричная&lt;br /&gt;
  0*) ibase=8;;                    # восьмеричная&lt;br /&gt;
  [1-9]*) ibase=10;;               # десятичная&lt;br /&gt;
  *)&lt;br /&gt;
  Msg &amp;quot;Ошибка в числе $i - число проигнорировано&amp;quot;&lt;br /&gt;
  continue;;&lt;br /&gt;
 esac&lt;br /&gt;
# Удалить префикс и преобразовать шестнадцатиричные цифры в верхний регистр (этого требует bc)&lt;br /&gt;
  number=`echo &amp;quot;$i&amp;quot; | sed -e 's:^0[bBxX]::' | tr '[a-f]' '[A-F]'`&lt;br /&gt;
# ==&amp;gt; вместо &amp;quot;/&amp;quot;, здесь используется символ &amp;quot;:&amp;quot; как разделитель для sed.&lt;br /&gt;
# Преобразование в десятичную систему счисления &lt;br /&gt;
 dec=`echo &amp;quot;ibase=$ibase; $number&amp;quot; | bc` # ==&amp;gt; 'bc' используется как калькулятор.&lt;br /&gt;
 case &amp;quot;$dec&amp;quot; in&lt;br /&gt;
  [0-9]*) ;;                 # всё в порядке&lt;br /&gt;
  *) continue;;              # ошибка: игнорировать&lt;br /&gt;
 esac&lt;br /&gt;
# Напечатать все преобразования в одну строку.&lt;br /&gt;
# ==&amp;gt; 'вложенный документ' — список команд для 'bc'.&lt;br /&gt;
 echo `bc &amp;lt;&amp;lt;!&lt;br /&gt;
 obase=16; &amp;quot;hex=&amp;quot;; $dec&lt;br /&gt;
 obase=10; &amp;quot;dec=&amp;quot;; $dec&lt;br /&gt;
 obase=8; &amp;quot;oct=&amp;quot;; $dec&lt;br /&gt;
 obase=2; &amp;quot;bin=&amp;quot;; $dec&lt;br /&gt;
!&lt;br /&gt;
` | sed -e 's: : :g'&lt;br /&gt;
done&lt;br /&gt;
}&lt;br /&gt;
while [ $# -gt 0 ]&lt;br /&gt;
do&lt;br /&gt;
 case &amp;quot;$1&amp;quot; in&lt;br /&gt;
  --) shift; break;;&lt;br /&gt;
  -h) Usage;; # ==&amp;gt; Вывод справочного сообщения.&lt;br /&gt;
  -*) Usage;;&lt;br /&gt;
  *) break;; # первое число&lt;br /&gt;
 esac # ==&amp;gt; Хорошо бы расширить анализ вводимых символов.&lt;br /&gt;
 shift&lt;br /&gt;
done&lt;br /&gt;
if [ $# -gt 0 ]&lt;br /&gt;
then&lt;br /&gt;
PrintBases &amp;quot;$@&amp;quot;&lt;br /&gt;
else # чтение со stdin&lt;br /&gt;
 while read line&lt;br /&gt;
 do&lt;br /&gt;
  PrintBases $line&lt;br /&gt;
 done&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Один из вариантов вызова bc — использование вложенного документа, внедряемого в блок с подстановкой команд. Это особенно актуально, когда сценарий должен передать '''''bc''''' значительный по объему список команд и аргументов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable=`bc &amp;lt;&amp;lt; LIMIT_STRING&lt;br /&gt;
options&lt;br /&gt;
statements&lt;br /&gt;
operations&lt;br /&gt;
LIMIT_STRING`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
...или...&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable=$(bc &amp;lt;&amp;lt; LIMIT_STRING&lt;br /&gt;
options&lt;br /&gt;
statements&lt;br /&gt;
operations&lt;br /&gt;
LIMIT_STRING)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример взаимодействия bc со &amp;quot;встроенным документом&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Комбинирование 'bc' с&lt;br /&gt;
# 'вложенным документом'.&lt;br /&gt;
var1=`bc &amp;lt;&amp;lt; EOF&lt;br /&gt;
18.33 * 19.78&lt;br /&gt;
EOF`&lt;br /&gt;
&lt;br /&gt;
echo $var1 # 362.56&lt;br /&gt;
# запись $( ... ) тоже работает.&lt;br /&gt;
v1=23.53&lt;br /&gt;
v2=17.881&lt;br /&gt;
v3=83.501&lt;br /&gt;
v4=171.63&lt;br /&gt;
&lt;br /&gt;
var2=$(bc &amp;lt;&amp;lt; EOF&lt;br /&gt;
scale = 4&lt;br /&gt;
a = ( $v1 + $v2 )&lt;br /&gt;
b = ( $v3 * $v4 )&lt;br /&gt;
a * b + 15.35&lt;br /&gt;
EOF&lt;br /&gt;
)&lt;br /&gt;
echo $var2 # 593487.8452&lt;br /&gt;
var3=$(bc -l &amp;lt;&amp;lt; EOF&lt;br /&gt;
scale = 9&lt;br /&gt;
s ( 1.7 )&lt;br /&gt;
EOF&lt;br /&gt;
)&lt;br /&gt;
# Возвращается значение синуса от 1.7 радиана.&lt;br /&gt;
# Ключом &amp;quot;-l&amp;quot; вызывается математическая библиотека 'bc'.&lt;br /&gt;
echo $var3 # .991664810&lt;br /&gt;
# Попробуем функции...&lt;br /&gt;
hyp= # Объявление глобальной переменной.&lt;br /&gt;
hypotenuse () # Расчёт гипотенузы прямоугольного треугольника.&lt;br /&gt;
{&lt;br /&gt;
hyp=$(bc -l &amp;lt;&amp;lt; EOF&lt;br /&gt;
scale = 9&lt;br /&gt;
sqrt ( $1 * $1 + $2 * $2 )&lt;br /&gt;
EOF&lt;br /&gt;
)&lt;br /&gt;
# К сожалению, функции Bash не могут возвращать числа с плавающей запятой.&lt;br /&gt;
}&lt;br /&gt;
hypotenuse 3.68 7.31&lt;br /&gt;
echo &amp;quot;гипотенуза = $hyp&amp;quot; # 8.184039344&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вычисление числа &amp;quot;пи&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# cannon.sh: Аппроксимация числа &amp;quot;пи&amp;quot;.&lt;br /&gt;
# Это очень простой вариант реализации метода &amp;quot;Monte Carlo&amp;quot;,&lt;br /&gt;
# математическое моделирование событий реальной жизни,&lt;br /&gt;
# для эмуляции случайного события используются псевдослучайные числа.&lt;br /&gt;
&lt;br /&gt;
# Допустим, что мы располагаем картой квадратного участка поверхности со стороной квадрата 10000 единиц.&lt;br /&gt;
# На этом участке, в центре, находится совершенно круглое озеро, с диаметром в 10000 единиц.&lt;br /&gt;
# Т.е. озеро покрывает почти всю карту, кроме её углов.&lt;br /&gt;
# (Фактически — это квадрат со вписанным кругом.)&lt;br /&gt;
#&lt;br /&gt;
# Пусть по этому участку ведется стрельба железными ядрами из древней пушки&lt;br /&gt;
# Все ядра падают где-то в пределах данного участка, т.е. либо в озеро, либо на сушу, по углам участка.&lt;br /&gt;
# Поскольку озеро покрывает большую часть участка, то большинство ядер будет падать в воду.&lt;br /&gt;
# Незначительная часть ядер будет падать на твердую почву.&lt;br /&gt;
#&lt;br /&gt;
# Если произвести достаточно большое число неприцельных выстрелов по данному участку,&lt;br /&gt;
# то отношение попаданий в воду к общему числу выстрелов будет примерно равно#+ значению PI/4.&lt;br /&gt;
#&lt;br /&gt;
# По той простой причине, что стрельба фактически ведётся только по правому верхнему квадранту карты.&lt;br /&gt;
# (Предыдущее описание было несколько упрощено.)&lt;br /&gt;
#&lt;br /&gt;
# Теоретически, чем больше будет произведено выстрелов, тем точнее будет результат.&lt;br /&gt;
# Однако, сценарий на языке командной оболочки, в отличие от других языков программирования,&lt;br /&gt;
# в которых доступны операции с плавающей запятой, имеет некоторые ограничения.&lt;br /&gt;
# К сожалению, это делает вычисления менее точными.&lt;br /&gt;
&lt;br /&gt;
DIMENSION=10000 # Длина стороны квадратного участка поверхности.&lt;br /&gt;
                # Он же — верхний предел для генератора случайных чисел.&lt;br /&gt;
MAXSHOTS=1000   # Количество выстрелов.&lt;br /&gt;
                # 10000 выстрелов (или больше) даст лучший результат, но потребует значительного количества времени.&lt;br /&gt;
PMULTIPLIER=4.0 # Масштабирующий коэффициент.&lt;br /&gt;
&lt;br /&gt;
get_random ()&lt;br /&gt;
{&lt;br /&gt;
SEED=$(head -1 /dev/urandom | od -N 1 | awk '{ print $2 }')&lt;br /&gt;
RANDOM=$SEED    # Из примера &amp;quot;seeding-random.sh&amp;quot;&lt;br /&gt;
let &amp;quot;rnum = $RANDOM % $DIMENSION&amp;quot; # Число не более чем 10000.&lt;br /&gt;
echo $rnum&lt;br /&gt;
}&lt;br /&gt;
distance= # Объявление глобальной переменной.&lt;br /&gt;
hypotenuse () # Расчет гипотенузы прямоугольного треугольника.&lt;br /&gt;
{ # Из примера &amp;quot;alt-bc.sh&amp;quot;.&lt;br /&gt;
distance=$(bc -l &amp;lt;&amp;lt; EOF&lt;br /&gt;
scale = 0&lt;br /&gt;
sqrt ( $1 * $1 + $2 * $2 )&lt;br /&gt;
EOF&lt;br /&gt;
)&lt;br /&gt;
# Установка &amp;quot;scale&amp;quot; в ноль приводит к округлению результата &amp;quot;вниз&amp;quot;,&lt;br /&gt;
# это и есть то самое ограничение, накладываемое командной оболочкой.&lt;br /&gt;
# Что, к сожалению, снижает точность аппроксимации.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# main() {&lt;br /&gt;
# Инициализация переменных.&lt;br /&gt;
shots=0&lt;br /&gt;
splashes=0&lt;br /&gt;
thuds=0&lt;br /&gt;
Pi=0&lt;br /&gt;
while [ &amp;quot;$shots&amp;quot; -lt &amp;quot;$MAXSHOTS&amp;quot; ] # Главный цикл.&lt;br /&gt;
do&lt;br /&gt;
 xCoord=$(get_random) # Получить случайные координаты X и Y.&lt;br /&gt;
 yCoord=$(get_random)&lt;br /&gt;
 hypotenuse $xCoord $yCoord # Гипотенуза = расстоянию.&lt;br /&gt;
 ((shots++))&lt;br /&gt;
 &lt;br /&gt;
 printf &amp;quot;#%4d &amp;quot; $shots&lt;br /&gt;
 printf &amp;quot;Xc = %4d &amp;quot; $xCoord&lt;br /&gt;
 printf &amp;quot;Yc = %4d &amp;quot; $yCoord&lt;br /&gt;
 printf &amp;quot;Distance = %5d &amp;quot; $distance # Расстояние от центра озера, с координатами (0,0).&lt;br /&gt;
 &lt;br /&gt;
 if [ &amp;quot;$distance&amp;quot; -le &amp;quot;$DIMENSION&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  echo -n &amp;quot;ШЛЁП! &amp;quot; # попадание в озеро&lt;br /&gt;
  ((splashes++))&lt;br /&gt;
 else&lt;br /&gt;
  echo -n &amp;quot;БУХ! &amp;quot; # попадание на твердую почву&lt;br /&gt;
  ((thuds++))&lt;br /&gt;
 fi&lt;br /&gt;
 Pi=$(echo &amp;quot;scale=9; $PMULTIPLIER*$splashes/$shots&amp;quot; | bc)&lt;br /&gt;
 # Умножение на коэффициент 4.0.&lt;br /&gt;
 echo -n &amp;quot;PI ~ $Pi&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;После $shots выстрела, примерное значение числа \&amp;quot;пи\&amp;quot; равно $Pi.&amp;quot;&lt;br /&gt;
# Имеет тенденцию к завышению...&lt;br /&gt;
# Вероятно из-за ошибок округления и несовершенства генератора случайных чисел.&lt;br /&gt;
echo&lt;br /&gt;
# &lt;br /&gt;
}&lt;br /&gt;
exit 0&lt;br /&gt;
# Самое время задуматься над тем, является ли сценарий удобным средством&lt;br /&gt;
# для выполнения большого количества столь сложных вычислений.&lt;br /&gt;
#&lt;br /&gt;
# Тем не менее, этот пример может расцениваться как&lt;br /&gt;
# 1) Доказательство возможностей языка командной оболочки.&lt;br /&gt;
# 2) Прототип для &amp;quot;обкатки&amp;quot; алгоритма перед тем как перенести&lt;br /&gt;
# его на высокоуровневые языки программирования компилирующего типа.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dc'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита '''''dc''''' (''desk calculator'') — это калькулятор, использующий &amp;quot;Обратную Польскую Нотацию&amp;quot;, и ориентированный на работу со стеком. Многие стараются избегать использования '''''dc''''', из-за непривычной формы записи операндов и операций. Однако, '''''dc''''' имеет и своих сторонников.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Преобразование чисел из десятичной в шестнадцатиричную систему счисления.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# hexconvert.sh: Преобразование чисел из десятичной в шестнадцатиричную систему счисления.&lt;br /&gt;
BASE=16 # Шестнадцатиричная.&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: $0 number&amp;quot;&lt;br /&gt;
 exit $E_NOARGS&lt;br /&gt;
 # Необходим аргумент командной строки.&lt;br /&gt;
fi&lt;br /&gt;
# Упражнение: добавьте проверку корректности аргумента.&lt;br /&gt;
hexcvt ()&lt;br /&gt;
{&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
echo 0&lt;br /&gt;
return # &amp;quot;Return&amp;quot; 0, если функции не был передан аргумент.&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;&amp;quot;$1&amp;quot; &amp;quot;$BASE&amp;quot; o p&amp;quot; | dc&lt;br /&gt;
# &amp;quot;o&amp;quot; устанавливает основание системы счисления для вывода.&lt;br /&gt;
# &amp;quot;p&amp;quot; выводит число, находящееся на вершине стека.&lt;br /&gt;
# См. 'man dc'.&lt;br /&gt;
return&lt;br /&gt;
}&lt;br /&gt;
hexcvt &amp;quot;$1&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Изучение страниц ''info dc'' позволит детальнее разобраться с утилитой. Однако, отряд &amp;quot;гуру&amp;quot;, которые могут похвастать своим знанием этой мощной, но весьма запутанной утилиты, весьма немногочислен.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Разложение числа на простые множители.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# factr.sh: Разложение числа на простые множители&lt;br /&gt;
MIN=2 # Не работает с числами меньше 2.&lt;br /&gt;
E_NOARGS=65&lt;br /&gt;
E_TOOSMALL=66&lt;br /&gt;
&lt;br /&gt;
if [ -z $1 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: $0 number&amp;quot;&lt;br /&gt;
 exit $E_NOARGS&lt;br /&gt;
fi&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -lt &amp;quot;$MIN&amp;quot; ]&lt;br /&gt;
then &lt;br /&gt;
 echo &amp;quot;Исходное число должно быть больше или равно $MIN.&amp;quot;&lt;br /&gt;
exit $E_TOOSMALL&lt;br /&gt;
fi&lt;br /&gt;
# Упражнение: Добавьте проверку типа числа (не целые числа должны отвергаться).&lt;br /&gt;
echo &amp;quot;Простые множители для числа $1:&amp;quot;&lt;br /&gt;
# ---------------------------------------------------------------------------------&lt;br /&gt;
echo &amp;quot;$1[p]s2[lip/dli%0=1dvsr]s12sid2%0=13sidvsr[dli%0=1lrli2+dsi!&amp;gt;.]ds.xd1&amp;lt;2&amp;quot; | dc&lt;br /&gt;
# ---------------------------------------------------------------------------------&lt;br /&gt;
# Автор вышеприведенной строки: Michel Charpentier &amp;lt;charpov@cs.unh.edu&amp;gt;.&lt;br /&gt;
# Используется с его разрешения (спасибо).&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''awk'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё один способ выполнения математических операций, над числами с плавающей запятой, состоит в создании сценария-обёртки, использующего математические функции [[awk]].&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Расчёт гипотенузы прямоугольного треугольника.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# hypotenuse.sh: Возвращает &amp;quot;гипотенузу&amp;quot; прямоугольного треугольника.&lt;br /&gt;
# ( корень квадратный от суммы квадратов катетов)&lt;br /&gt;
&lt;br /&gt;
ARGS=2 # В сценарий необходимо передать два катета.&lt;br /&gt;
E_BADARGS=65 # Ошибка в аргументах.&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ] # Проверка количества аргументов.&lt;br /&gt;
then&lt;br /&gt;
 echo -e &amp;quot;\e[32mПорядок использования\e[0m: \e[31m`basename $0`\e[0m \e[34mкатет_1\e[0m \e[33mкатет_2\e[0m&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
AWKSCRIPT=' { printf( &amp;quot;%3.7f\n&amp;quot;, sqrt($1*$1 + $2*$2) ) } '&lt;br /&gt;
# команды и параметры, передаваемые в awk&lt;br /&gt;
echo -n &amp;quot;Гипотенуза прямоугольного треугольника, с катетами $1 и $2 = &amp;quot;&lt;br /&gt;
echo $1 $2 | awk &amp;quot;$AWKSCRIPT&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Прочие команды ===&lt;br /&gt;
'''Команды, которые нельзя отнести ни к одной из вышеперечисленных категорий'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''jot,seq'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эти утилиты выводят последовательность целых чисел с шагом, заданным пользователем.&lt;br /&gt;
По-умолчанию, выводимые числа отделяются друг от друга символом перевода строки, однако,с помощью ключа ''-s'' может быть задан другой разделитель.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ seq 5&lt;br /&gt;
1&lt;br /&gt;
2&lt;br /&gt;
3&lt;br /&gt;
4&lt;br /&gt;
5&lt;br /&gt;
bash$ seq -s : 5&lt;br /&gt;
1:2:3:4:5&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Обе утилиты, и '''''jot''''', и '''''seq''''', очень удобно использовать для генерации списка аргументов в цикле ''for''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование seq для генерации списка аргументов цикла for.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Утилита &amp;quot;seq&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
for a in `seq 80` # или так: for a in $( seq 80 )&lt;br /&gt;
# То же самое, что и for a in 1 2 3 4 5 ... 80 (но как экономит время и силы!).&lt;br /&gt;
# Можно использовать и 'jot' (если эта утилита имеется в системе).&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done # 1 2 3 4 5 ... 80&lt;br /&gt;
# Пример использования вывода команды для генерации&lt;br /&gt;
# [списка] аргументов цикла &amp;quot;for&amp;quot;.&lt;br /&gt;
echo; echo&lt;br /&gt;
COUNT=80 # Да, 'seq' допускает указание переменных в качестве параметра.&lt;br /&gt;
for a in `seq $COUNT` # или так: for a in $( seq $COUNT )&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done # 1 2 3 4 5 ... 80&lt;br /&gt;
echo; echo&lt;br /&gt;
BEGIN=75&lt;br /&gt;
END=80&lt;br /&gt;
for a in `seq $BEGIN $END`&lt;br /&gt;
# Если &amp;quot;seq&amp;quot; передаются два аргумента, то первый означает начальное число последовательности, второй — последнее,&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done # 75 76 77 78 79 80&lt;br /&gt;
echo; echo&lt;br /&gt;
BEGIN=45&lt;br /&gt;
INTERVAL=5&lt;br /&gt;
END=80&lt;br /&gt;
for a in `seq $BEGIN $INTERVAL $END`&lt;br /&gt;
# Если &amp;quot;seq&amp;quot; передаётся три аргумента, то первый аргумент — начальное число в последовательности,&lt;br /&gt;
# второй — шаг последовательности, и третий — последнее число в последовательности.&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$a &amp;quot;&lt;br /&gt;
done # 45 50 55 60 65 70 75 80&lt;br /&gt;
echo; echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''getopt'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''getopt''''' служит для разбора командной строки, выделяя из неё ключи — символы, с предшествующим символом дефиса. В этой утилите имеется, встроенный в Bash, аналог — '''''getopts''''', более мощная и универсальная команда. Тем не менее, команда '''''getopt''''', с ключом ''-l'', позволяет производить разбор &amp;quot;длинных&amp;quot; ключей и допускает переупорядочивание ключей.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование getopt для разбора аргументов командной строки.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ex33a.sh&lt;br /&gt;
&lt;br /&gt;
# Попробуйте следующие варианты вызова этого сценария.&lt;br /&gt;
# sh ex33a -a&lt;br /&gt;
# sh ex33a -abc&lt;br /&gt;
# sh ex33a -a -b -c&lt;br /&gt;
# sh ex33a -d&lt;br /&gt;
# sh ex33a -dXYZ&lt;br /&gt;
# sh ex33a -d XYZ&lt;br /&gt;
# sh ex33a -abcd&lt;br /&gt;
# sh ex33a -abcdZ&lt;br /&gt;
# sh ex33a -z&lt;br /&gt;
# sh ex33a a&lt;br /&gt;
# Объясните полученные результаты.&lt;br /&gt;
E_OPTERR=65&lt;br /&gt;
if [ &amp;quot;$#&amp;quot; -eq 0 ]&lt;br /&gt;
then # Необходим по меньшей мере один аргумент.&lt;br /&gt;
 echo &amp;quot;Порядок использования: $0 -[options a,b,c]&amp;quot;&lt;br /&gt;
 exit $E_OPTERR&lt;br /&gt;
fi&lt;br /&gt;
set -- `getopt &amp;quot;abcd:&amp;quot; &amp;quot;$@&amp;quot;`&lt;br /&gt;
# Запись аргументов командной строки в позиционные параметры.&lt;br /&gt;
# Что произойдёт, если вместо &amp;quot;$@&amp;quot; указать &amp;quot;$*&amp;quot;?&lt;br /&gt;
while [ ! -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 case &amp;quot;$1&amp;quot; in&lt;br /&gt;
  -a) echo &amp;quot;Опция \&amp;quot;a\&amp;quot;&amp;quot;;;&lt;br /&gt;
  -b) echo &amp;quot;Опция \&amp;quot;b\&amp;quot;&amp;quot;;;&lt;br /&gt;
  -c) echo &amp;quot;Опция \&amp;quot;c\&amp;quot;&amp;quot;;;&lt;br /&gt;
  -d) echo &amp;quot;Опция \&amp;quot;d\&amp;quot; $2&amp;quot;;;&lt;br /&gt;
  *) break;;&lt;br /&gt;
 esac&lt;br /&gt;
 shift&lt;br /&gt;
done &lt;br /&gt;
# Вместо 'getopt' лучше использовать встроенную команду 'getopts',&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''run-parts'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда run-parts запускает на исполнение все сценарии, в порядке возрастания имён файлов-сценариев, в заданном каталоге. Естественно, файлы сценариев должны иметь права на исполнение. Демон ''cron'' вызывает '''''run-parts''''' для запуска сценариев из каталогов ''/etc/cron.*''.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''yes'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
По-умолчанию, команда '''''yes''''' выводит на ''stdout'' непрерывную последовательность символов ''y'', разделённых символами перевода строки. Исполнение команды можно прервать комбинацией клавиш ''Ctrl-c''. Команду '''''yes''''' можно заставить выводить иную последовательность символов. Теперь самое время задаться вопросом о практической пользе этой команды. Основное применение этой команды состоит в том, что вывод от неё может быть передан, через конвейер, другой команде, ожидающей реакции пользователя. В результате получается, своего рода, слабенькая версия команды ''expect''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Запускает '''''fsck''''' в неинтерактивном режиме (&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''будьте осторожны!'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;):&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
yes | fsck /dev/hda1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Имеет тот же эффект, что и '''''rm -rf dirname''''' (&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''будьте осторожны!'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;):&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
yes | rm -r dirname &lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''Внимание!'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;Передача вывода команды '''''yes''''' по конвейеру потенциально опасным командам, таким как '''''fsck''''' или '''''fdisk''''' может дать нежелательные побочные эффекты.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''banner'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Печатает на ''stdout'' заданную строку символов (не более 10), рисуя каждый символ строки при помощи символа '#'. Вывод от команды может быть перенаправлен на принтер.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''printenv'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит все переменные окружения текущего пользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ printenv | grep HOME&lt;br /&gt;
HOME=/home/bozo&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команды '''''lp''''' и '''''lpr''''' отправляют файлы в очередь печати для вывода на принтер. Названия этих команд произошли от ''&amp;quot;line printers&amp;quot;''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ lp file1.txt или bash lp &amp;lt;file1.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Очень часто используются в комбинации с командой форматированного вывода '''''pr'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ pr -options file1.txt | lp&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Программы подготовки текста к печати, такие как '''''groff''''' и ''Ghostscript'', так же могут напрямую взаимодействовать с '''''lp'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ groff -Tascii file.tr | lp&lt;br /&gt;
bash$ gs -options | lp file.ps&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''lpq''''' предназначена для просмотра очереди заданий печати, а '''''lprm''''' — для удаления заданий из очереди.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tee'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[Unix заимствовал эту идею из водопроводного дела.]&lt;br /&gt;
Это оператор перенаправления, но с некоторыми особенностями. Подобно водопроводным трубам, '''''tee''''' позволяет &amp;quot;направить поток&amp;quot; данных в несколько файлов и на ''stdout'' одновременно, никак не влияя на сами данные. Эта команда может оказаться очень полезной при отладке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
           tee |------&amp;gt; в файл&lt;br /&gt;
               |&lt;br /&gt;
===============|===============&lt;br /&gt;
command---&amp;gt;----|-operator--&amp;gt;---&amp;gt; результат работы команд(ы)&lt;br /&gt;
==================&lt;br /&gt;
cat listfile* | sort | tee check.file | uniq &amp;gt; result.file&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
(Здесь, в файл check.file будут записаны данные из всех &amp;quot;listfile*&amp;quot;, в отсортированном виде до того, как повторяющиеся строки будут удалены командой '''''uniq'''''.)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mkfifo'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта, редко встречающаяся, команда создаёт именованный канал — очередь, через который производится обмен данными между процессами. Как правило, один процесс записывает данные в очередь (FIFO), а другой читает данные из очереди.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''pathchk'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Производит проверку полного имени файла — проверяет, доступны ли на чтение, каталоги в пути к файлу, и не превышает ли длина полного имени файла 255 символов. При несоблюдении одного из условий — возвращает сообщение об ошибке. К сожалению, '''''pathchk''''' не возвращает соответствующего кода ошибки, и потому, в общем-то, бесполезна в сценариях. Вместо неё лучше использовать операторы проверки файлов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dd'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта немного непонятная и &amp;quot;страшная&amp;quot; команда (&amp;quot;data duplicator&amp;quot;) изначально использовалась для переноса данных на магнитной ленте между микрокомпьютерами с ОС Unix и майнфреймами IBM. Команда [[dd]] просто создаёт копию файла (или ''stdin/stdout''), выполняя по пути некоторые преобразования. Один из вариантов: преобразование из ASCII в EBCDIC, '''''[[dd|dd --help]]''''' выведет список возможных вариантов преобразований и опций этой мощной утилиты.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Изучаем 'dd'.&lt;br /&gt;
n=3&lt;br /&gt;
p=5&lt;br /&gt;
input_file=project.txt&lt;br /&gt;
output_file=log.txt&lt;br /&gt;
dd if=$input_file of=$output_file bs=1 skip=$((n-1)) count=$((p-n+1)) 2&amp;gt; /dev/null       # Извлечёт из $input_file символы с n-го по p-й.&lt;br /&gt;
echo -n &amp;quot;hello world&amp;quot; | dd cbs=1 conv=unblock 2&amp;gt; /dev/null&lt;br /&gt;
# Выведет &amp;quot;hello world&amp;quot; вертикально.&lt;br /&gt;
# Спасибо, S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для демонстрации возможностей [[dd]], попробуем перехватить нажатия на клавиши.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Захват нажатых клавиш.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Захват нажатых клавиш.&lt;br /&gt;
keypresses=4                 # Количество фиксируемых нажатий.&lt;br /&gt;
old_tty_setting=$(stty -g)   # Сохранить настройки терминала.&lt;br /&gt;
echo &amp;quot;Нажмите $keypresses клавиши.&amp;quot;&lt;br /&gt;
stty -icanon -echo           # Запретить канонический режим.&lt;br /&gt;
                             # Запретить эхо-вывод.&lt;br /&gt;
keys=$(dd bs=1 count=$keypresses 2&amp;gt; /dev/null)&lt;br /&gt;
# 'dd' использует stdin, если &amp;quot;if&amp;quot; не задан.&lt;br /&gt;
stty &amp;quot;$old_tty_setting&amp;quot;      # Восстановить настройки терминала.&lt;br /&gt;
echo &amp;quot;Вы нажали клавиши \&amp;quot;$keys\&amp;quot;.&amp;quot;&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда [[dd]] имеет возможность произвольного доступа к данным в потоке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo -n . | dd bs=1 seek=4 of=file conv=notrunc&lt;br /&gt;
# Здесь, опция &amp;quot;conv=notrunc&amp;quot; означает, что выходной файл не будет усечен.&lt;br /&gt;
# Спасибо, S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда [[dd]] может использоваться для создания образов дисков, считывая данные прямо с устройств, таких как дискеты, компакт-диски, магнитные ленты. Обычно она используется для создания загрузочных дискет.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dd if=kernel-image of=/dev/fd0H1440&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Точно так же, [[dd]] может скопировать всё содержимое дискеты, даже с неизвестной файловой системой, на жёсткий диск в виде файла-образа.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dd if=/dev/fd0 of=/home/bozo/projects/floppy.img&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё одно применение [[dd]] — создание временного swap-файла и ram-дисков. Она может создавать даже образы целых разделов жёсткого диска, хотя и не рекомендуется делать это без особой на то необходимости. Многие (которые, вероятно, не знают чем себя занять) постоянно придумывают всё новые и новые области применения команды [[dd]].&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Надёжное удаление файла.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# blotout.sh: Надежно удаляет файл.&lt;br /&gt;
# Этот сценарий записывает случайные данные в заданный файл, затем записывает туда нули и наконец удаляет файл.&lt;br /&gt;
# После такого удаления даже анализ дисковых секторов не даст ровным счётом ничего.&lt;br /&gt;
PASSES=7 # Количество проходов по файлу.&lt;br /&gt;
BLOCKSIZE=1 # операции ввода/вывода в/из /dev/urandom требуют указания размера блока, иначе вы не получите желаемого результата.&lt;br /&gt;
E_BADARGS=70&lt;br /&gt;
E_NOT_FOUND=71&lt;br /&gt;
E_CHANGED_MIND=72&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ] # Имя файла не указано.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
file=$1&lt;br /&gt;
if [ ! -e &amp;quot;$file&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$file\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOT_FOUND&lt;br /&gt;
fi&lt;br /&gt;
echo; echo -n &amp;quot;Вы совершенно уверены в том, что желаете уничтожить \&amp;quot;$file\&amp;quot; (y/n)? &amp;quot;&lt;br /&gt;
read answer&lt;br /&gt;
case &amp;quot;$answer&amp;quot; in&lt;br /&gt;
 [nN]) echo &amp;quot;Передумали? Операция отменена.&amp;quot;&lt;br /&gt;
       exit $E_CHANGED_MIND&lt;br /&gt;
       ;;&lt;br /&gt;
 *) echo &amp;quot;Уничтожается файл \&amp;quot;$file\&amp;quot;.&amp;quot;;;&lt;br /&gt;
esac&lt;br /&gt;
flength=$(ls -l &amp;quot;$file&amp;quot; | awk '{print $5}') # Поле с номером 5 — это длина файла.&lt;br /&gt;
pass_count=1&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$pass_count&amp;quot; -le &amp;quot;$PASSES&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Проход #$pass_count&amp;quot;&lt;br /&gt;
 sync # Вытолкнуть буферы.&lt;br /&gt;
 dd if=/dev/urandom of=$file bs=$BLOCKSIZE count=$flength # Заполнить файл случайными данными.&lt;br /&gt;
 sync # Снова вытолкнуть буферы.&lt;br /&gt;
 dd if=/dev/zero of=$file bs=$BLOCKSIZE count=$flength # Заполнить файл нулями.&lt;br /&gt;
 sync # Снова вытолкнуть буферы.&lt;br /&gt;
 let &amp;quot;pass_count += 1&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
rm -f $file # Наконец удалить изрядно &amp;quot;подпорченный&amp;quot; файл.&lt;br /&gt;
sync # Вытолкнуть буферы в последний раз.&lt;br /&gt;
echo &amp;quot;Файл \&amp;quot;$file\&amp;quot; уничтожен.&amp;quot;; echo&lt;br /&gt;
&lt;br /&gt;
# Это довольно надёжный, хотя и достаточно медленный способ уничтожения файлов.&lt;br /&gt;
# Более эффективно это делает команда &amp;quot;shred&amp;quot;, входящая в состав пакета GNU &amp;quot;fileutils&amp;quot;.&lt;br /&gt;
# Уничтоженный таким образом файл, не сможет быть восстановлен обычными методами.&lt;br /&gt;
# Однако...&lt;br /&gt;
# эта метода вероятно НЕ сможет противостоять аналитическим службам из СООТВЕТСТВУЮЩИХ ОРГАНОВ.&lt;br /&gt;
# Tom Vier разработал пакет &amp;quot;wipe&amp;quot;, который более надежно стирает файлы, чем этот простой сценарий.&lt;br /&gt;
# http://www.ibiblio.org/pub/Linux/utils/file/wipe-2.0.0.tar.bz2&lt;br /&gt;
# Для более глубоко изучения проблемы надёжного удаления файлов, рекомендую обратиться к cnfnmt Peter Gutmann,&lt;br /&gt;
# &amp;quot;Secure Deletion of Data From Magnetic and Solid-State Memory&amp;quot;.&lt;br /&gt;
# http://www.cs.auckland.ac.nz/~pgut001/pubs/secure_del.html&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''od'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''od''''' (''octal dump'') производит преобразование ввода (или файла) в один или несколько форматов, в соответствии с указанными опциями. При отсутствии опций используется восьмеричный формат (опция ''-o''). Эта команда полезна при просмотре или обработке файлов с двоичными данными, например ''/dev/urandom''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''hexdump'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит дамп двоичных данных из файла в восьмеричном, шестнадцатиричном, десятичном виде или в виде ASCII. Эту команду, с массой оговорок, можно назвать эквивалентом команды '''''od'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''objdump'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Отображает сведения об исполняемом или объектном файле либо в шестнадцатиричной форме, либо в виде дизассемблерного листинга (с ключом ''-d'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ objdump -d /bin/ls&lt;br /&gt;
/bin/ls: file format elf32-i386&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .init:&lt;br /&gt;
080490bc &amp;lt;.init&amp;gt;:&lt;br /&gt;
80490bc: 55 push %ebp&lt;br /&gt;
80490bd: 89 e5 mov %esp,%ebp&lt;br /&gt;
. . .&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mcookie'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда создает псевдослучайные шестнадцатиричные 128-битные числа, так называемые &amp;quot;magic cookie&amp;quot;, обычно используется X-сервером в качестве &amp;quot;сигнатуры&amp;quot; авторизации. В сценариях может использоваться как малоэффективный генератор случайных чисел.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
random000=$(mcookie)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конечно, для тех же целей, сценарий может использовать ''md5''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Сценарий вычисляет контрольную сумму для самого себя.&lt;br /&gt;
random001=`md5sum $0 | awk '{print $1}'`&lt;br /&gt;
# 'awk' удаляет имя файла.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
С помощью '''''mcookie''''' можно создавать &amp;quot;уникальные&amp;quot; имена файлов.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Генератор имён файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# tempfile-name.sh: Генератор имен временных файлов&lt;br /&gt;
BASE_STR=`mcookie`                 # 32-символьный (128 бит) magic cookie.&lt;br /&gt;
POS=11                             # Произвольная позиция в строке magic cookie.&lt;br /&gt;
LEN=5                              # $LEN последовательных символов.&lt;br /&gt;
prefix=temp                        # В конце концов это временный (&amp;quot;temp&amp;quot;) файл.&lt;br /&gt;
suffix=${BASE_STR:POS:LEN}&lt;br /&gt;
                                   # Извлечь строку, длиной в 5 символов, начиная с позиции 11.&lt;br /&gt;
temp_filename=$prefix.$suffix&lt;br /&gt;
                                   # Сборка имени файла.&lt;br /&gt;
echo &amp;quot;Имя временного файла = \&amp;quot;$temp_filename\&amp;quot;&amp;quot;&lt;br /&gt;
# sh tempfile-name.sh&lt;br /&gt;
# Имя временного файла = temp.e19ea&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''units'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита производит преобразование величин из одних единиц измерения в другие. Как правило вызывается в интерактивном режиме, ниже приводится пример использования '''''units''''' в сценарии.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Преобразование метров в мили.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# unit-conversion.sh&lt;br /&gt;
convert_units () # Принимает в качестве входных параметров единицы измерения.&lt;br /&gt;
{&lt;br /&gt;
cf=$(units &amp;quot;$1&amp;quot; &amp;quot;$2&amp;quot; | sed --silent -e '1p' | awk '{print $2}')&lt;br /&gt;
# Удаляет все кроме коэффициентов преобразования.&lt;br /&gt;
echo &amp;quot;$cf&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
Unit1=miles&lt;br /&gt;
Unit2=meters&lt;br /&gt;
cfactor=`convert_units $Unit1 $Unit2`&lt;br /&gt;
quantity=3.73&lt;br /&gt;
result=$(echo $quantity*$cfactor | bc)&lt;br /&gt;
echo &amp;quot;В $quantity милях $result метров.&amp;quot;&lt;br /&gt;
# Что произойдет, если в функцию передать несовместимые единицы измерения, например &amp;quot;acres&amp;quot; (акры) and &amp;quot;miles&amp;quot; (мили)?&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''m4'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Не команда, а клад, '''''m4''''' — это мощный фильтр обработки макроопределений, фактически — целый язык программирования. Изначально создававшаяся как препроцессор для RatFor, '''''m4''''' оказалась очень полезной и как самостоятельная утилита. Фактически, '''''m4''''' сочетает в себе функциональные возможности '''''eval''''', '''''tr''''', '''''awk''''', и дополнительно предоставляет обширные возможности по созданию новых макроопределений. В апрельском выпуске, за 2002 год, журнала ''Linux Journal'' вы найдёте замечательную статью, описывающую возможности утилиты '''''m4'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Работа с m4.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# m4.sh: Демонстрация некоторых возможностей макропроцессора m4&lt;br /&gt;
# Строки&lt;br /&gt;
string=abcdA01&lt;br /&gt;
echo &amp;quot;len($string)&amp;quot; | m4                   # 7&lt;br /&gt;
echo &amp;quot;substr($string,4)&amp;quot; | m4              # A01&lt;br /&gt;
echo &amp;quot;regexp($string,[0-1][0-1],\&amp;amp;Z)&amp;quot; | m4 # 01Z&lt;br /&gt;
# Арифметика&lt;br /&gt;
echo &amp;quot;incr(22)&amp;quot; | m4                       # 23&lt;br /&gt;
echo &amp;quot;eval(99 / 3)&amp;quot; | m4                   # 33&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''doexec'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''doexec''''' предоставляет возможность передачи произвольного списка аргументов внешней программе. В частности, передавая ''argv[0]'' (для сценариев соответствует специальной переменной ''$0''), можно вызвать программу под другим именем, определяя тем самым, её реакцию. Например, пусть в каталоге ''/usr/local/bin'' имеется программа с именем &amp;quot;aaa&amp;quot;, которая при вызове '''''doexec /usr/local/bin/aaa list''''' выведет список всех файлов в текущем каталоге, имена которых начинаются с символа &amp;quot;a&amp;quot;, а при вызове той же самой программы как '''''doexec/usr/local/bin/aaa delete''''', она удалит эти файлы. Естественно, реакция программы на своё собственное имя должна быть реализована в коде программы, для сценария на языке командной оболочки это может выглядеть примерно так:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
case `basename $0` in&lt;br /&gt;
 &amp;quot;name1&amp;quot; ) реакция на вызов под именем name1;;&lt;br /&gt;
 &amp;quot;name2&amp;quot; ) реакция на вызов под именем name2;;&lt;br /&gt;
 &amp;quot;name3&amp;quot; ) реакция на вызов под именем name3;;&lt;br /&gt;
 * ) действия по-умолчанию;;&lt;br /&gt;
esac&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dialog'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита '''''dialog''''' предоставляет в распоряжение программиста целый набор инструментов для построения интерактивного интерфейса в сценариях. Более совершенные разновидности команды '''''dialog''''' — '''''gdialog''''', '''''Xdialog''''' и '''''kdialog''''' — которые используют в своей работе графические элементы управления X-Windows.&lt;br /&gt;
&lt;br /&gt;
== Команды системного администрирования ==&lt;br /&gt;
Примеры использования большинства этих команд вы найдёте в сценариях начальной загрузки и остановки системы, в каталогах ''/etc/rc.d''. Они, обычно, вызываются пользователем ''root'' и используются для администрирования системы или восстановления файловой системы. Эти команды должны использоваться с большой осторожностью, так как некоторые из них могут разрушить систему, при неправильном использовании.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Пользователи и группы'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''users'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выведет список всех зарегистрировавшихся пользователей. Она, до некоторой степени,является эквивалентом команды '''''who -q'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''groups'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список групп, в состав которых входит текущий пользователь. Эта команда соответствует внутренней переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$GROUPS'''&amp;lt;/span&amp;gt;, но выводит названия групп, а не их числовые идентификаторы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ groups&lt;br /&gt;
bozita cdrom cdwriter audio xgrpbash&lt;br /&gt;
$ echo $GROUPS&lt;br /&gt;
501&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''chown,chgrp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда [[Chown_—_Команда_назначения_владельца_файлов_и/или_каталога|chown]] изменяет владельца файла или файлов. Эта команда полезна в случаях, когда '''''root''''' хочет передать монопольное право на файл от одного пользователя другому. Обычный пользователь не в состоянии изменить владельца файла, за исключением своих собственных файлов.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;root# chown bozo *.txt&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда [[Chgrp_—_Команда_изменяющая_группу_владельца_файла|chgrp]] изменяет группу, которой принадлежит файл или файлы. Чтобы изменить группу, вы должны быть владельцем файла (при этом должны входить в состав указываемой группы) или ''привилегированным пользователем''(''root'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
chgrp --recursive dunderheads *.data&lt;br /&gt;
# Группа &amp;quot;dunderheads&amp;quot; станет владельцем всех файлов &amp;quot;*.data&amp;quot;&lt;br /&gt;
# во всех подкаталогах текущей директории ($PWD) (благодаря ключу &amp;quot;--recursive&amp;quot;).&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''useradd,userdel'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда [[useradd]] добавляет учетную запись нового пользователя в систему и создаёт домашний каталог для данного пользователя. Противоположная, по смыслу, команда '''''userdel''''' удаляет учетную запись пользователя из системы, и, соответствующие файлы. Команда '''''adduser''''' является синонимом для [[useradd]] и, как правило, является обычной символической ссылкой на [[useradd]].&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''usermod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Модификация (изменение) характеристик пользовательского аккаунта. Может изменить пароль пользователя, членство в группах срок действия аккаунта и другие характеристики. С помощью этой команды можно заблокировать пользовательский пароль, что равносильно блокировке аккаунта.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''groupmod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Модификация (изменение) характеристик группы. С помощью этой команды можно изменить имя группы и/или ID группы.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''id'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда id выводит идентификатор пользователя (реальный и эффективный) иидентификаторы групп, в состав которых входит пользователь. По сути — выводит содержимое переменных &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$UID'''&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$EUID'''&amp;lt;/span&amp;gt; и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$GROUPS'''&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ id&lt;br /&gt;
uid=501(bozo) gid=501(bozo) groups=501(bozo),22(cdrom),80(cdwriter),81(audio)&lt;br /&gt;
bash$ echo $UID&lt;br /&gt;
501&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''id''''' выводит эффективный идентификатор только тогда, когда он отличается от реального.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''who'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список пользователей, работающих в настоящий момент в системе.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ who&lt;br /&gt;
bozo tty1 Apr 27 17:45&lt;br /&gt;
bozo pts/0 Apr 27 17:46&lt;br /&gt;
bozo pts/1 Apr 27 17:47&lt;br /&gt;
bozo pts/2 Apr 27 17:49&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
С ключом ''-m'' — выводит информацию только о текущем пользователе. Если число аргументов, передаваемых команде, равно двум, то это эквивалентно вызову '''''who -m''''', например ''who am i'' или ''who The Man''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ who -m&lt;br /&gt;
localhost.localdomain!bozo pts/2 Apr 27 17:49&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''whoami''''' — похожа на '''''who -m''''', но выводит только имя пользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ whoami&lt;br /&gt;
bozo&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''w'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит информацию о системе, список пользователей, подключенных к системе и процессы, связанные с пользователями. Это расширенная версия команды '''''who'''''. Вывод от команды '''''w''''' может быть передан по конвейеру команде [[grep]], с целью поиска требуемого пользователя и/или процесса.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ w | grep startx&lt;br /&gt;
bozo tty1 - 4:22pm 6:41 4.47s 0.45s startx&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''logname'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит имя текущего пользователя (из файла ''/var/run/utmp''). Это довольно близкий эквивалент команды '''''whoami'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ logname&lt;br /&gt;
bozo&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''logname''''' выводит имя пользователя, зарегистрировавшегося в системе(залогировавшегося), в то время как '''''whoami''''' — даёт имя пользователя, под которым исполняется текущий процесс. Как я уже упоминал — это не всегда одно и то же.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ whoami&lt;br /&gt;
bozo&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Однако...&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ su&lt;br /&gt;
Password: ......&lt;br /&gt;
bash# whoami&lt;br /&gt;
root&lt;br /&gt;
bash# logname&lt;br /&gt;
bozo&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''su'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда предназначена для запуска программы или сценария от имени другого пользователя. '''''su rjones''''' — запускает командную оболочку от имени пользователя ''rjones''. Запуск команды '''''su''''' без параметров означает запуск командной оболочки от имени привилегированного пользователя ''root''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sudo'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Исполняет заданную команду от имени пользователя ''root'' (или другого пользователя).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Доступ к &amp;quot;секретным&amp;quot; файлам.&lt;br /&gt;
sudo cp /root/secretfile /home/bozo/secret&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Имена пользователей, которым разрешено использовать команду '''''sudo''''', хранятся в файле ''/etc/sudoers''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''passwd'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Устанавливает или изменяет пароль пользователя. Команда '''''passwd''''' может использоваться в сценариях, но это плохая практика.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Установка нового пароля.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# setnew-password.sh: Не очень хорошая идея.&lt;br /&gt;
# Этот сценарий должен запускаться с правами root, а ещё лучше — вообще не запускать его.&lt;br /&gt;
ROOT_UID=0 # Root имеет $UID равный 0.&lt;br /&gt;
E_WRONG_USER=65 # Не root?&lt;br /&gt;
E_NOSUCHUSER=70&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo; echo &amp;quot;Только root может запускать этот сценарий.&amp;quot;; echo&lt;br /&gt;
 exit $E_WRONG_USER&lt;br /&gt;
else&lt;br /&gt;
 echo; echo &amp;quot;Вам не следовало бы запускать этот сценарий.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
username=bozo&lt;br /&gt;
NEWPASSWORD=security_violation &lt;br /&gt;
# Проверить — есть ли такой пользователь.&lt;br /&gt;
cat /etc/passwd | grep -q &amp;quot;$username&amp;quot;&lt;br /&gt;
if [ $? -ne $SUCCESS ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Пользователь $username не найден.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Пароль не был изменен.&amp;quot;&lt;br /&gt;
 exit $E_NOSUCHUSER&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;$NEWPASSWORD&amp;quot; | passwd --stdin &amp;quot;$username&amp;quot;&lt;br /&gt;
# Ключ '--stdin' указывает 'passwd'&lt;br /&gt;
# получить новый пароль с stdin (или из конвейера).&lt;br /&gt;
echo; echo &amp;quot;Пароль пользователя $username изменен!&amp;quot;&lt;br /&gt;
# Использование команды 'passwd' в сценариях крайне опасно.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''passwd''''' с ключами ''-l'', ''-u'' и ''-d'' выполняет блокировку, разблокировку и удаление пароля пользователя. Только ''root'' может вызывать команду '''''passwd''''' с этими ключами.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ac'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит время работы пользователей, основываясь на записях в файле ''/var/log/wtmp''. Это одна из утилит пакета ''GNU acct''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ac&lt;br /&gt;
total 68.08&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''last'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит информацию о последних входах/выходах пользователей в сиcтему, основываясь на записях в файле ''/var/log/wtmp''. Эта команда может отображать информацию об удаленных (в смысле — с удалённого терминала) соединениях.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''newgrp'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Позволяет сменить активную группу пользователя. Пользователь остается в системе и текущий каталог не изменяется, но права доступа к файлам вычисляются в соответствии с новыми реальным и эффективным идентификаторами группы. Эта команда используется довольно редко, так как пользователь, обычно, является членом нескольких групп.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Терминалы'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tty'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит имя терминала текущего пользователя. Обратите внимание: каждое отдельное окно xterm считается отдельным терминалом.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ tty&lt;br /&gt;
/dev/pts/1&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''stty'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит и/или изменяет настройки терминала. Эта сложная команда используется в сценариях для управления поведением терминала.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Установка символа &amp;quot;забоя&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# erase.sh: Использование команды &amp;quot;stty&amp;quot; для смены клавиши &amp;quot;забоя&amp;quot; при чтении ввода.&lt;br /&gt;
echo -n &amp;quot;Как Вас зовут? &amp;quot;&lt;br /&gt;
read name                    # Попробуйте стереть последние символы при вводе.&lt;br /&gt;
                             # Всё работает.&lt;br /&gt;
echo &amp;quot;Вас зовут $name.&amp;quot;&lt;br /&gt;
stty erase '#'               # Теперь, чтобы стереть символ нужно использовать клавишу&lt;br /&gt;
&amp;quot;#&amp;quot;.&lt;br /&gt;
echo -n &amp;quot;Как Вас зовут? &amp;quot;&lt;br /&gt;
read name                    # Попробуйте стереть последние символы при вводе с помощью&lt;br /&gt;
&amp;quot;#&amp;quot;.&lt;br /&gt;
echo &amp;quot;Вас зовут $name.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Невидимый пароль: Отключение эхо-вывода на терминал.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo&lt;br /&gt;
echo -n &amp;quot;Введите пароль &amp;quot;&lt;br /&gt;
read passwd&lt;br /&gt;
echo &amp;quot;Вы ввели пароль: $passwd&amp;quot;&lt;br /&gt;
echo -n &amp;quot;Если кто-нибудь в это время заглядывал Вам через плечо, &amp;quot;&lt;br /&gt;
echo &amp;quot;то теперь он знает Ваш пароль.&amp;quot;&lt;br /&gt;
echo &amp;amp;&amp;amp; echo # Две пустых строки через &amp;quot;and list&amp;quot;.&lt;br /&gt;
stty -echo # Отключить эхо-вывод.&lt;br /&gt;
echo -n &amp;quot;Введите пароль еще раз &amp;quot;&lt;br /&gt;
read passwd&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Вы ввели пароль: $passwd&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
stty echo # Восстановить эхо-вывод.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перехват нажатия на клавиши с помощью stty.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# keypress.sh: Определение нажатых клавиш.&lt;br /&gt;
echo&lt;br /&gt;
old_tty_settings=$(stty -g) # Сохранить прежние настройки.&lt;br /&gt;
stty -icanon&lt;br /&gt;
Keypress=$(head -c1) # или $(dd bs=1 count=1 2&amp;gt; /dev/null)&lt;br /&gt;
                     # для других, не GNU, систем&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Была нажата клавиша \&amp;quot;&amp;quot;$Keypress&amp;quot;\&amp;quot;.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
stty &amp;quot;$old_tty_settings&amp;quot; # Восстановить прежние настройки.&lt;br /&gt;
# Спасибо, Stephane Chazelas(S.C.).&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Терминалы и их режимы работы&lt;br /&gt;
|-&lt;br /&gt;
| Как правило, терминалы работают в каноническом режиме. Когда пользователь нажимает какую-либо клавишу, то соответствующий ей символ не сразу передаётся программе, исполняемой в окне терминала. Этот символ поступает сначала в локальный буфер терминала. Когда пользователь нажимает клавишу ''ENTER'', то тогда всё содержимое буфера передаётся программе.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ stty -a &lt;br /&gt;
speed 9600 baud; rows 36; columns 96; line = 0;&lt;br /&gt;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = &amp;lt;undef&amp;gt;; eol2 = &amp;lt;undef&amp;gt;;&lt;br /&gt;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O;&lt;br /&gt;
...&lt;br /&gt;
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В каноническом режиме можно использовать символы редактирования во время ввода.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat &amp;gt; filexxx&lt;br /&gt;
wha&amp;lt;ctl-W&amp;gt;I&amp;lt;ctl-H&amp;gt;foo bar&amp;lt;ctl-U&amp;gt;hello world&amp;lt;ENTER&amp;gt;&lt;br /&gt;
&amp;lt;ctl-D&amp;gt;&lt;br /&gt;
bash$ cat filexxx&lt;br /&gt;
hello world&lt;br /&gt;
bash$ bash$ wc -c &amp;lt; file13&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Процесс в терминале получит только 13 символов (12 алфавитных символов и символ перевода строки), хотя пользователь нажал 26 клавиш.&amp;lt;br /&amp;gt;&lt;br /&gt;
В неканоническом (&amp;quot;сыром&amp;quot;) режиме, каждая нажатая клавиша (включая специальные символы редактирования, такие как ''Ctl-H'') сразу же передается исполняющемуся в терминале процессу.&lt;br /&gt;
Под управлением Bash, базовый терминальный редактор заменяется более сложным терминальным редактором Bash. Например, если вы нажмете комбинацию клавиш ''Ctl-A'' в командной строке Bash, то вы не увидите символов ''^A'', которые выводит терминал, вместо этого Bash получит символ ''\1'', проанализирует его и переместит курсор в начало строки. &amp;lt;br /&amp;gt;©''Stephane Chazelas''&lt;br /&gt;
|}&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tset'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит или изменяет настройки терминала. Это более слабая версия '''''stty'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ tset -r&lt;br /&gt;
Terminal type is xterm-xfree86.&lt;br /&gt;
Kill is control-U (^U).&lt;br /&gt;
Interrupt is control-C (^C).&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''setserial'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Настройка параметров последовательного порта. Эта команда должна запускаться пользователем, обладающим привилегиями ''root''. Эту команду можно встретить в сценариях настройки системы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Взято из /etc/pcmcia/serial :&lt;br /&gt;
IRQ=`setserial /dev/$DEVICE | sed -e 's/.*IRQ: //'`&lt;br /&gt;
setserial /dev/$DEVICE irq 0 ; setserial /dev/$DEVICE irq $IRQ&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''getty,agetty'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Программа '''''getty''''' или '''''agetty''''' запускается процессом ''init'' и обслуживает процедуру входа пользователя в систему. Эти команды не используются в сценариях.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mesg'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Разрешает или запрещает доступ к терминалу текущего пользователя командой '''''write'''''. Наверное это очень неприятно, когда, во время работы над текстовым файлом, в окне терминала, прямо среди текста, вдруг появляется предложение заказать пиццу. Поэтому, при работе в многопользовательской системе, вам наверняка захочется отключить доступ к своему терминалу.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''wall'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Имя этой команды — аббревиатура от &amp;quot;write all&amp;quot;, т.е., передать сообщение всем пользователям на все терминалы в сети. Это, в первую очередь, инструмент администратора, который можно использовать, например, для оповещения всех пользователей о предстоящей, в ближайшее время, перезагрузке системы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ wall System going down for maintenance in 5 minutes!&lt;br /&gt;
Broadcast message from bozo (pts/1) Sun Jul 8 13:53:27 2001...&lt;br /&gt;
System going down for maintenance in 5 minutes!&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если доступ к терминалу был закрыт командой '''''mesg''''', то сообщение на этом терминале выводиться не будет.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dmesg'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит все сообщения, выдаваемые системой во время загрузки на ''stdout''. Очень полезная утилита для отладочных целей. Вывод '''''dmesg''''' может анализироваться с помощью [[grep]], [[sed]] или [[awk]] внутри сценария.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ dmesg | grep hda&lt;br /&gt;
Kernel command line: ro root=/dev/hda2&lt;br /&gt;
hda: IBM-DLGA-23080, ATA DISK drive&lt;br /&gt;
hda: 6015744 sectors (3080 MB) w/96KiB Cache, CHS=746/128/63&lt;br /&gt;
hda: hda1 hda2 hda3 &amp;lt; hda5 hda6 hda7 &amp;gt; hda4&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Информационные и статистические утилиты'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''uname'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит на ''stdout'' имя системы. С ключом ''-a'', выводит подробную информацию, содержащую имя системы, имя узла (то есть имя, под которым система известна в сети), версию операционной системы, наименование модификации операционной системы, аппаратную архитектуру.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ uname -a&lt;br /&gt;
Linux localhost.localdomain 2.2.15-2.5.0 #1 Sat Feb 5 00:13:43 EST 2000 i686 unknown&lt;br /&gt;
bash$ uname -s&lt;br /&gt;
Linux&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''arch'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит тип аппаратной платформы компьютера. Эквивалентна команде '''''uname -m'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ arch&lt;br /&gt;
i686&lt;br /&gt;
bash$ uname -m&lt;br /&gt;
i686&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lastcomm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит информацию, о ранее выполненных командах, из файла ''/var/account/pacct''. Дополнительно могут указываться команда и пользователь. Это одна из утилит пакета ''GNU acct''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lastlog'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список всех пользователей, с указанием времени последнего входа в систему. Данные берутся из файла ''/var/log/lastlog''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ lastlog&lt;br /&gt;
root tty1 Fri Dec 7 18:43:21 -0700 2001&lt;br /&gt;
bin **Never logged in**&lt;br /&gt;
daemon **Never logged in**&lt;br /&gt;
...&lt;br /&gt;
bozo tty1 Sat Dec 8 21:14:29 -0700 2001&lt;br /&gt;
&lt;br /&gt;
bash$ lastlog | grep root&lt;br /&gt;
root tty1 Fri Dec 7 18:43:21 -0700 2001&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Исполнение этой команды будет завершаться неудачей, если пользователь, вызвавший утилиту, не имеет прав на чтение файла ''/var/log/lastlog''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lsof'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит детальный список открытых, в настоящий момент времени, файлов в виде таблицы. В таблице указаны — владелец файла, размер файла, тип файла, процесс, открывший файл, и многое другое. Само собой разумеется, что вывод команды '''''lsof''''' может быть обработан, в конвейере, с помощью утилит [[grep]] и/или [[awk]].&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ lsof&lt;br /&gt;
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME&lt;br /&gt;
init 1 root mem REG 3,5 30748 30303 /sbin/init&lt;br /&gt;
init 1 root mem REG 3,5 73120 8069 /lib/ld-2.1.3.so&lt;br /&gt;
init 1 root mem REG 3,5 931668 8075 /lib/libc-2.1.3.so&lt;br /&gt;
cardmgr 213 root mem REG 3,5 36956 30357 /sbin/cardmgr&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''strace'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Диагностическая и отладочная утилита, предназначенная для трассировки системных вызовов и сигналов. В простейшем случае, запускается как: '''''strace''''' ''COMMAND''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ strace df&lt;br /&gt;
execve(&amp;quot;/bin/df&amp;quot;, [&amp;quot;df&amp;quot;], [/* 45 vars */]) = 0&lt;br /&gt;
uname({sys=&amp;quot;Linux&amp;quot;, node=&amp;quot;bozo.localdomain&amp;quot;, ...}) = 0&lt;br /&gt;
brk(0) = 0x804f5e4&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эквивалентна команде '''''truss'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''nmap'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сканер сетевых портов. Эта утилита сканирует сервер в поисках открытых портов и сервисов. Это очень важный инструмент, используемый для поиска уязвимостей при настройке системы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
SERVER=$HOST # localhost.localdomain (127.0.0.1).&lt;br /&gt;
PORT_NUMBER=25 # порт службы SMTP.&lt;br /&gt;
nmap $SERVER | grep -w &amp;quot;$PORT_NUMBER&amp;quot; # Проверить — открыт ли данный порт?&lt;br /&gt;
# grep -w — поиск только целых слов,&lt;br /&gt;
# так, например, порт 1025 будет пропущен.&lt;br /&gt;
exit 0&lt;br /&gt;
# 25/tcp open smtp&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''free'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Показывает информацию об использовании памяти, в табличной форме. Вывод команды может быть проанализирован с помощью [[grep]], [[awk]] или ''Perl''. Команда '''''procinfo''''' тоже выводит эту информацию, среди всего прочего.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ free&lt;br /&gt;
           total   used    free   shared   buffers   cached&lt;br /&gt;
Mem:       30504   28624   1880   15820    1608      16376&lt;br /&gt;
-/+ buffers/cache: 10640   19864&lt;br /&gt;
Swap:      68540   3128    65412&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Показать размер неиспользуемой памяти RAM:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ free | grep Mem | awk '{ print $4 }'&lt;br /&gt;
bash$ free -h | grep Mem | awk '{ print $4 }'&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''procinfo'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Извлекает и выводит информацию из файловой системы ''/proc''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ procinfo | grep Bootup&lt;br /&gt;
Bootup: Wed Mar 21 15:15:50 2001 Load average: 0.04 0.21 0.34 3/47 6829&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lsdev'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Список аппаратных устройств в системе.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ lsdev&lt;br /&gt;
Device DMA IRQ I/O Ports&lt;br /&gt;
------------------------------------------------&lt;br /&gt;
cascade 4 2&lt;br /&gt;
dma 0080-008f&lt;br /&gt;
dma1 0000-001f&lt;br /&gt;
dma2 00c0-00df&lt;br /&gt;
fpu 00f0-00ff&lt;br /&gt;
ide0 14 01f0-01f7 03f6-03f6&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''du'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит сведения о занимаемом дисковом пространстве в каталоге и вложенных подкаталогах. Если каталог не указан, то по-умолчанию выводятся сведения о текущем каталоге.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ du -ach&lt;br /&gt;
1.0k ./wi.sh&lt;br /&gt;
1.0k ./tst.sh&lt;br /&gt;
1.0k ./random.file&lt;br /&gt;
6.0k .&lt;br /&gt;
6.0k total&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''df'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит в табличной форме сведения о смонтированных файловых системах.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ df&lt;br /&gt;
Filesystem 1k-blocks  Used  Available Use% Mounted on&lt;br /&gt;
/dev/hda5  273262     92607  166547   36%     /&lt;br /&gt;
/dev/hda8  222525     123951 87085    59%     /home&lt;br /&gt;
/dev/hda7  1408796    1075744 261488  80%     /usr&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''stat'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Даёт подробную информацию о заданном файле (каталоге или файле устройства) или наборе файлов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ stat test.cru&lt;br /&gt;
File: &amp;quot;test.cru&amp;quot;&lt;br /&gt;
Size: 49970 Allocated Blocks: 100 Filetype: Regular File&lt;br /&gt;
Mode: (0664/-rw-rw-r--) Uid: ( 501/ bozo) Gid: ( 501/ bozo)&lt;br /&gt;
Device: 3,8 Inode: 18185 Links: 1&lt;br /&gt;
Access: Sat Jun 2 16:40:24 2001&lt;br /&gt;
Modify: Sat Jun 2 16:40:24 2001&lt;br /&gt;
Change: Sat Jun 2 16:40:24 2001&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если заданный файл отсутствует, то '''''stat''''' вернёт сообщение об ошибке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ stat nonexistent-file&lt;br /&gt;
nonexistent-file: No such file or directory&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''vmstat'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит информацию о виртуальной памяти.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ vmstat&lt;br /&gt;
procs memory swap io system cpu&lt;br /&gt;
r b w swpd free buff cache si so bi bo in cs us sy id&lt;br /&gt;
0 0 0 0 11040 2636 38952 0 0 33 7 271 88 8 3 89&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''netstat'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Показывает сведения о сетевой подсистеме, такие как: таблицы маршрутизации и активные соединения. Эта утилита получает сведения из ''/proc/net''. '''''netstat -r''''' — эквивалентна команде '''''route'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''uptime'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Показывает количество времени, прошедшего с момента последней перезагрузки системы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ uptime&lt;br /&gt;
10:28pm up 1:57, 3 users, load average: 0.17, 0.34, 0.27&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''hostname'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит имя узла (сетевое имя системы). С помощью этой команды устанавливается сетевое имя системы в сценарии ''/etc/rc.d/rc.sysinit''. Эквивалентна команде '''''uname -n''''' и внутренней переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$HOSTNAME&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ hostname&lt;br /&gt;
localhost.localdomain&lt;br /&gt;
bash$ echo $HOSTNAME&lt;br /&gt;
localhost.localdomain&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''hostid'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит 32-битный шестнадцатиричный идентификатор системы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ hostid&lt;br /&gt;
7f0100&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда генерирует &amp;quot;уникальный&amp;quot; числовой идентификатор системы. Некоторые программные продукты используют этот идентификатор в процедуре регистрации. К сожалению, при генерации идентификатора, '''''hostid''''' использует только IP адрес системы, переводя его в шестнадцатиричное представление и переставляя местами пары байт.&lt;br /&gt;
Обычно, IP адрес системы можно найти в файле ''/etc/hosts''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat /etc/hosts&lt;br /&gt;
127.0.0.1 localhost.localdomain localhost&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Переставив местами байты, попарно, в начальном адресе 127.0.0.1, мы получим 0.127.1.0, в шестнадцатиричном представлении это будет 007f0100, что вточности совпадает с приведённым выше результатом выполнения '''''hostid'''''. Наверняка можно найти несколько миллионов компьютеров с таким же &amp;quot;уникальным&amp;quot; идентификатором.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sar'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''sar''''' (System Activity Reporter) выводит очень подробную статистику о функционировании операционной системы. В июне 1999 года, компания Santa Cruz Operation(SCO) опубликовала исходные тексты утилиты. Она, как правило, не входит в базовый комплект пакетов Linux-систем. Но её можно получить в составе пакета ''sysstat utilities'', автор: ''Sebastien Godard''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ sar&lt;br /&gt;
Linux 2.4.9 (brooks.seringas.fr)  09/26/03&lt;br /&gt;
10:30:00    CPU      %user    %nice    %system    %iowait   %idle&lt;br /&gt;
10:40:00    all      2.21     10.90    65.48      0.00      21.41&lt;br /&gt;
10:50:00    all      3.36     0.00     72.36      0.00      24.28&lt;br /&gt;
11:00:00    all      1.12     0.00     80.77      0.00      18.11&lt;br /&gt;
Average:    all      2.23     3.63     72.87      0.00      21.27&lt;br /&gt;
&lt;br /&gt;
14:32:30 LINUX RESTART&lt;br /&gt;
&lt;br /&gt;
15:00:00    CPU      %user    %nice    %system    %iowait   %idle&lt;br /&gt;
15:10:00    all      8.59     2.40     17.47      0.00      71.54&lt;br /&gt;
15:20:00    all      4.07     1.00     11.95      0.00      82.98&lt;br /&gt;
15:30:00    all      0.79     2.94     7.56       0.00      88.71&lt;br /&gt;
Average:    all      6.33     1.70     14.71      0.00      77.26&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''readelf'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Показывает сведения о заданном бинарном файле формата ''elf''. Входит в состав пакета ''binutils''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ readelf -h /bin/bash&lt;br /&gt;
ELF Header:&lt;br /&gt;
    Magic:    7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00&lt;br /&gt;
    Class:                               ELF32&lt;br /&gt;
    Data:                                2`s complement, little endian&lt;br /&gt;
    Version:                             1 (current)&lt;br /&gt;
    OS/ABI:                              Unix - System V&lt;br /&gt;
    ABI Version:                         0&lt;br /&gt;
    Type:                                EXEC (Executable file)&lt;br /&gt;
    . . .&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''size'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''size [/path/to/binary]''''' выведет информацию о размерах различных сегментов в исполняемых или библиотечных файлах. В основном используется программистами.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ size /bin/bash&lt;br /&gt;
text    data    bss    dec    hex    filename&lt;br /&gt;
495971  22496   17392  535859 82d33  /bin/bash&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Системный журнал'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''logger'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Добавляет в системный журнал (''/var/log/messages'') сообщение от пользователя. Для добавления сообщения пользователь не должен обладать привилегиями суперпользователя.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ logger Experiencing instability in network connection at 23:10, 05/21.&lt;br /&gt;
# Теперь попробуйте дать команду 'tail /var/log/messages'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Встраивая вызов '''''logger''''' в сценарии, вы получаете возможность заносить отладочную информацию в системный журнал ''/var/log/messages''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ logger -t $0 -i Logging at line &amp;quot;$LINENO&amp;quot;.&lt;br /&gt;
# Ключ &amp;quot;-t&amp;quot; задаёт тэг записи в журнале.&lt;br /&gt;
# Ключ &amp;quot;-i&amp;quot; — записывает ID процесса.&lt;br /&gt;
&lt;br /&gt;
# tail /var/log/message&lt;br /&gt;
# ...&lt;br /&gt;
# Jul 7 20:48:58 localhost ./test.sh[1712]: Logging at line 3.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''logrotate'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита производит манипуляции над системным журналом: ротация, сжатие, удаление и/или отправляет его по электронной почте, по мере необходимости. Как правило, утилита '''''logrotate''''' вызывается демоном '''''cron''''' ежедневно. Добавляя соответствующие строки в ''/etc/logrotate.conf'', можно заставить '''''logrotate''''' обрабатывать не только системный журнал, но и ваш личный.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Управление заданиями'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ps'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''P'''''rocess '''''S'''''tatistics: Список исполняющихся в данный момент процессов. Обычно вызывается с ключами ''ax'', вывод команды может быть обработан командами [[grep]] или [[sed]], с целью поиска требуемого процесса.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ps ax | grep sendmail&lt;br /&gt;
295  ?   S   0:00  sendmail: accepting connections on port 25&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''pstree'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Список исполняющихся процессов в виде &amp;quot;дерева&amp;quot;. С ключом -p — вместе с именами процессов отображает их ''PID''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''top'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список наиболее активных процессов. С ключом ''-b'' — отображение ведется в обычном текстовом режиме, что даёт возможность анализа вывода от команды внутри сценария.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ top -b&lt;br /&gt;
8:30pm up 3 min, 3 users, load average: 0.49, 0.32, 0.13&lt;br /&gt;
45 processes: 44 sleeping, 1 running, 0 zombie, 0 stopped&lt;br /&gt;
CPU states: 13.6% user, 7.3% system, 0.0% nice, 78.9% idle&lt;br /&gt;
Mem: 78396K av, 65468K used, 12928K free, 0K shrd, 2352K buff&lt;br /&gt;
Swap: 157208K av, 0K used, 157208K free 37244K cached&lt;br /&gt;
&lt;br /&gt;
PID   USER   PRI   NI   SIZE   RSS   SHARE   STAT   %CPU   %MEM   TIME   COMMAND&lt;br /&gt;
848   bozo   17    0    996    996   800     R      5.6    1.2    0:00   top&lt;br /&gt;
1     root   8     0    512    512   444     S      0.0    0.6    0:04   init&lt;br /&gt;
2     root   9     0    0      0     0       SW     0.0    0.0    0:00   keventd&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''nice'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Запускает фоновый процесс с заданным приоритетом. Приоритеты могут задаваться числом из диапазона от '''''19''''' (''низший приоритет'') до '''''-20''''' (''высший приоритет''). Но только '''''root''''' может указать значение приоритета меньше нуля (отрицательные значения). См. так же команды '''''renice''''', '''''snice''''' и '''''skill'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''nohup'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Запуск команд в режиме игнорирования сигналов прерывания и завершения, что предотвращает завершение работы команды даже если пользователь, запустивший её, вышел из системы. Если после команды не указан символ '''''&amp;amp;''''', то она будет исполняться как процесс &amp;quot;переднего плана&amp;quot;. Если вы собираетесь использовать '''''nohup''''' в сценариях, то вам потребуется использовать его в связке с командой '''''wait''''', чтобы не породить процесс &amp;quot;зомби&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''pidof'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Возвращает идентификатор процесса (''pid'') по его имени. Поскольку многие команды управления процессами, такие как '''''kill''''' и '''''renice''''', требуют указать ''pid'' процесса, а не его имя, то '''''pidof''''' может сослужить неплохую службу при идентификации процесса по его имени. Эта команда может рассматриваться как приблизительный эквивалент внутренней переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$PPID&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ pidof xclock&lt;br /&gt;
880&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование команды pidof при остановке процесса.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# kill-process.sh&lt;br /&gt;
NOPROCESS=2&lt;br /&gt;
process=xxxyyyzzz # Несуществующий процесс.&lt;br /&gt;
# Только в демонстрационных целях...&lt;br /&gt;
# ... чтобы не уничтожить этим сценарием какой-нибудь процесс.&lt;br /&gt;
#&lt;br /&gt;
# Если с помощью этого сценария вы задумаете разрывать связь с Internet, то process=pppd &lt;br /&gt;
t=`pidof $process`    # Поиск pid (process id) процесса $process.&lt;br /&gt;
# pid требует команда 'kill' (невозможно остановить процесс, указав его имя).&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$t&amp;quot; ] # Если процесс с таким именем не найден, то 'pidof' вернет null.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Процесс $process не найден.&amp;quot;&lt;br /&gt;
 exit $NOPROCESS&lt;br /&gt;
fi&lt;br /&gt;
kill $t        # В некоторых случаях может потребоваться 'kill -9'.&lt;br /&gt;
# Здесь нужно проверить — был ли уничтожен процесс.&lt;br /&gt;
# Возможно так: &amp;quot; t=`pidof $process` &amp;quot;.&lt;br /&gt;
# Этот сценарий мог бы быть заменён командой&lt;br /&gt;
# kill $(pidof -x process_name)&lt;br /&gt;
# но это было бы не так поучительно.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fuser'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Возвращает идентификаторы процессов, использующих указанный файл(ы) или каталог. С ключом ''-k'', завершает найденные процессы. Может с успехом использоваться для защиты системы, особенно в сценариях разграничения доступа к системным службам.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''cron'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Планировщик заданий. С его помощью выполняются такие задачи, как очистка и удаление устаревших файлов системных журналов, обновление базы данных ''slocate''. Это суперпользовательская версия команды '''''at''''' (хотя любой пользователь может создать собственную таблицу ''crontab''). Эта утилита запускается как фоновый процесс-daemon и выполняет задания, находящиеся в файле ''/etc/crontab''. В некоторых дистрибутивах Linux, в качестве ''crond'' используется версия '''''cron''''' от ''Matthew Dillon''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Управление процессами и загрузкой'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''init'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
init — предок (родитель) всех процессов в системе. Вызывается на последнем этапе загрузки системы и определяет уровень загрузки (''runlevel'') из файла ''/etc/inittab''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''telinit'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Символическая ссылка на '''''init''''' — инструмент для смены уровня загрузки (''runlevel''), как правило используется при обслуживании системы или восстановлении файловой системы. Может быть вызвана только суперпользователем. Эта команда может быть очень опасна, при неумелом обращении — прежде чем использовать её, убедитесь в том, что вы совершенно точно понимаете что делаете!&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''runlevel'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит предыдущий и текущий уровни загрузки (''runlevel''). Уровень загрузки может иметь одно из 6 значений: '''''0''''' — остановка системы, '''''1''''' — однопользовательский режим, '''''2''''' или '''''3''''' — многопользовательский режим, '''''5''''' — многопользовательский режим и запуск X Window, '''''6''''' — перезагрузка. Уровни загрузки определяются из файла ''/var/run/utmp''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''halt,shutdown,reboot'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Набор команд для остановки системы, обычно перед выключением питания.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Команды для работы с сетью'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ifconfig'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита конфигурирования и запуска сетевых интерфейсов. Чаще всего используется в сценариях начальной загрузки системы, для настройки и запуска сетевых интерфейсов или для их остановки перед остановкой или перезагрузкой.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Фрагменты кода из /etc/rc.d/init.d/network&lt;br /&gt;
# ...&lt;br /&gt;
# Проверка сетевой полсистемы.&lt;br /&gt;
[ ${NETWORKING} = &amp;quot;no&amp;quot; ] &amp;amp;&amp;amp; exit 0&lt;br /&gt;
[ -x /sbin/ifconfig ] || exit 0&lt;br /&gt;
# ...&lt;br /&gt;
for i in $interfaces ; do&lt;br /&gt;
if ifconfig $i 2&amp;gt;/dev/null | grep -q &amp;quot;UP&amp;quot; &amp;gt;/dev/null 2&amp;gt;&amp;amp;1 ; then&lt;br /&gt;
 action &amp;quot;Останавливается $i: &amp;quot; ./ifdown $i boot&lt;br /&gt;
fi &lt;br /&gt;
# Ключ &amp;quot;-q&amp;quot;, характерный для GNU-версии &amp;quot;grep&amp;quot;, означает &amp;quot;quiet&amp;quot; (&amp;quot;молча&amp;quot;), т.е. подавляет вывод.&lt;br /&gt;
# Поэтому нет необходимости переадресовывать вывод на /dev/null.&lt;br /&gt;
# ...&lt;br /&gt;
echo &amp;quot;В настоящее время активны устройства:&amp;quot;&lt;br /&gt;
echo `/sbin/ifconfig | grep ^[a-z] | awk '{print $1}'`&lt;br /&gt;
#                            ^^^^^ скобки необходимы для предотвращения подстановки имён файлов (globbing).&lt;br /&gt;
# Следующий код делает то же самое.&lt;br /&gt;
# echo $(/sbin/ifconfig | awk '/^[a-z]/ { print $1 })'&lt;br /&gt;
# echo $(/sbin/ifconfig | sed -e 's/ .*//')&lt;br /&gt;
# Спасибо S.C. за комментарии.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''iwconfig'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда используется для настройки беспроводной (wireless) сети. Представляет собой эквивалент команды '''''ifconfig''''', описанной выше.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''route'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит сведения о таблице маршрутизации ядра или вносит туда изменения.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ route&lt;br /&gt;
Destination       Gateway          Genmask           Flags     MSS      Window     irtt    Iface&lt;br /&gt;
pm3-67.bozosisp   *                255.255.255.255   UH        40       0          0       ppp0&lt;br /&gt;
127.0.0.0         *                255.0.0.0         U         40       0          0       lo&lt;br /&gt;
default           pm3-67.bozosisp  0.0.0.0           UG        40       0          0       ppp0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''chkconfig'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Проверка сетевой конфигурации. Обслуживает список, запускаемых на этапе загрузки, сетевых сервисов, список сервисов хранится в каталогах /etc/rc?.d (строго говоря, chkconfig работает не только с сетевыми сервисами, а с сервисами вообще, не зависимо от того сетевые это службы или нет — прим. перев.). Изначально эта утилита была перенесена в ''Red Hat Linux'' из ОС ''IRIX'', '''''chkconfig''''' входит в состав далеко не всех дистрибутивов Linux.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ chkconfig --list&lt;br /&gt;
atd    0:off 1:off 2:off 3:on  4:on  5:on  6:off&lt;br /&gt;
rwhod  0:off 1:off 2:off 3:off 4:off 5:off 6:off&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tcpdump'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;quot;Сниффер&amp;quot; (&amp;quot;sniffer&amp;quot;) сетевых пакетов. Инструмент для перехвата и анализа сетевого трафика по определенным критериям. Дамп трафика ip-пакетов между двумя узлами сети — ''bozoville'' и ''caduceus'':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ tcpdump ip host bozoville and caduceus&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конечно же, вывод команды '''''tcpdump''''' может быть проанализирован с помощью команд обработки текста, обсуждавшихся выше.&lt;br /&gt;
'''Команды для работы с файловыми системами'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mount'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выполняет монтирование файловой системы, обычно на устройстве со сменными носителями, такими как дискеты или CDROM. Файл ''/etc/fstab'' содержит перечень доступных для монтирования файловых систем, разделов и устройств, включая опции монтирования, благодаря этому файлу, монтирование может производиться автоматически или вручную. Файл ''/etc/mtab'' содержит список смонтированных файловых систем и разделов (включая виртуальные, такие как ''/proc'').&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''mount -a''''' — монтирует все (all) файловые системы и разделы, перечисленные в ''/etc/fstab'', за исключением тех, которые имеют флаг ''noauto''. Эту команду можно встретить в сценариях начальной загрузки системы из ''/etc/rc.d'' (''rc.sysinit'' или нечто похожее).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mount -t iso9660 /dev/cdrom /mnt/cdrom&lt;br /&gt;
# Монтирование CDROM&lt;br /&gt;
mount /mnt/cdrom&lt;br /&gt;
# Более короткий и удобный вариант, если точка монтирования /mnt/cdrom описана в /etc/fstab&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда может даже смонтировать обычный файл как блочное устройство. Достигается это за счёт связывания файла с loopback-устройством. Эту возможность можно использовать для проверки ''ISO9660'' образа компакт-диска перед его записью на болванку.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка образа CD.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# С правами root...&lt;br /&gt;
mkdir /mnt/cdtest                                    # Подготовка точки монтирования.&lt;br /&gt;
mount -r -t iso9660 -o loop cd-image.iso /mnt/cdtest # Монтирование образа диска.&lt;br /&gt;
# ключ &amp;quot;-o loop&amp;quot; эквивалентен &amp;quot;losetup /dev/loop0&amp;quot;&lt;br /&gt;
cd /mnt/cdtest                                       # Теперь проверим образ диска.&lt;br /&gt;
ls -alR                                              # Вывод списка файлов&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''umount'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Отмонтирует смонтированную файловую систему. Перед тем как физически вынуть компакт-диск или дискету из устройства, это устройство должно быть отмонтировано командой '''''umount''''', иначе файловая система может оказаться поврежденной (особенно это относится к накопителям на гибких магнитных дисках, прим. перев.).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
umount /mnt/cdrom          # Теперь вы можете извлечь диск из привода.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита '''''automount''''', если она установлена, может выполнять автоматическое монтирование/размонтирование устройств со сменными носителями, такие как дискеты и компакт-диски. На ноутбуках со сменными устройствами FDD и CD-ROM, такой подход может привести к возникновению определённых проблем.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''sync'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Принудительный сброс содержимого буферов на жесткий диск (синхронизация содержимого буферов ввода-вывода и устройства-носителя). Несмотря на то, что нет такой уж острой необходимости в этой утилите, тем не менее '''''sync''''' придаёт уверенности системным администраторам или пользователям в том, что их данные будут сохранены на жёстком диске, и не будут потеряны в случае какого-либо сбоя. В былые дни, команда '''''sync; sync''''' (дважды — для абсолютной уверенности) была упреждающей мерой перед перезагрузкой системы. Иногда возникает необходимость принудительной синхронизации буферов ввода-вывода с содержимым на магнитном носителе, как, например, при надежном удалении файла или когда наблюдаются скачки напряжения в сети электроснабжения.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''losetup'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Устанавливает и конфигурирует &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;loopback-устройства&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание файловой системы в обычном файле.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
SIZE=1048576                        # 1 Мб&lt;br /&gt;
head -c $SIZE &amp;lt; /dev/zero &amp;gt; file    # Создаётся файл нужного размера.&lt;br /&gt;
losetup /dev/loop0 file             # Файл назначается как loopback-устройство.&lt;br /&gt;
mke2fs /dev/loop0                   # Создание файловой системы.&lt;br /&gt;
mount -o loop /dev/loop0 /mnt       # Монтирование только что созданной файловой системы.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mkswap'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создание swap-раздела или swap-файла. Созданный swap-раздел (файл) нужно затем подключить командой '''''swapon'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''swapon,swapoff'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Разрешает/запрещает использование swap-раздела (файла). Эта команда обычно используется во время загрузки системы или во время остановки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mke2fs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создает файловую систему ''ext2''. Должна вызываться с правами суперпользователя.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Добавление нового жёсткого диска.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash         # Добавление в систему второго жёсткого диска.&lt;br /&gt;
# Программное конфигурирование. Предполагается, что устройство уже подключено к аппаратуре компьютера.&lt;br /&gt;
# Взято из статьи автора документа.&lt;br /&gt;
# &amp;quot;Linux Gazette&amp;quot;, выпуск #38, http://www.linuxgazette.com.&lt;br /&gt;
&lt;br /&gt;
ROOT_UID=0          # Этот сценарий должен запускать только root.&lt;br /&gt;
E_NOTROOT=67        # Код ошибки, если сценарий запущен простым пользователем.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Для запуска этого сценария вы должны обладать правами root.&amp;quot;&lt;br /&gt;
 exit $E_NOTROOT&lt;br /&gt;
fi                  # Будьте крайне осторожны!&lt;br /&gt;
# Если что-то пойдёт не так, то вы можете потерять текущую файловую систему.&lt;br /&gt;
&lt;br /&gt;
NEWDISK=/dev/hdb    # Предполагается, что /dev/hdb — это новое устройство. Проверьте!&lt;br /&gt;
MOUNTPOINT=/mnt/newdisk # Или выберите иное устройство для монтирования.&lt;br /&gt;
fdisk $NEWDISK&lt;br /&gt;
mke2fs -cv $NEWDISK1 # Проверка на &amp;quot;плохие&amp;quot; блоки (bad blocks) и подробный вывод.&lt;br /&gt;
# Обратите внимание: /dev/hdb1, *не* то же самое, что /dev/hdb!&lt;br /&gt;
mkdir $MOUNTPOINT&lt;br /&gt;
chmod 777 $MOUNTPOINT # Сделать новое устройство доступным для всех пользователей.&lt;br /&gt;
# Теперь проверим...&lt;br /&gt;
# mount -t ext2 /dev/hdb1 /mnt/newdisk  &lt;br /&gt;
# Попробуйте создать каталог.&lt;br /&gt;
# Если получилось — отмонтируйте устройство и продолжим.&lt;br /&gt;
# Последний штрих:&lt;br /&gt;
# Добавьте следующую строку в /etc/fstab.&lt;br /&gt;
# /dev/hdb1 /mnt/newdisk ext2 defaults 1 1&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tune2fs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Настройка отдельных параметров файловой системы ''ext2'', например счётчик максимального количества монтирований без проверки. Должна вызываться с привилегиями пользователя ''root''.&lt;br /&gt;
Очень опасная утилита~ Вы можете использовать её только на свой страх и риск,поскольку, по неосторожности, вы запросто можете разрушить файловую систему.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dumpe2fs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит на ''stdout'' очень подробную информацию о файловой системе. Должна вызываться с привилегиями пользователя ''root''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root# dumpe2fs /dev/hda7 | grep 'ount count'&lt;br /&gt;
dumpe2fs 1.19, 13-Jul-2000 for EXT2 FS 0.5b, 95/08/09&lt;br /&gt;
Mount count: 6 &lt;br /&gt;
Maximum mount count: 20&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''hdparm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит или изменяет параметры настройки жёсткого диска. Должна вызываться с привилегиями пользователя ''root''. Потенциально опасна при неправильном использовании.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fdisk'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создание или изменение таблицы разделов на устройствах хранения информации, обычно — жёстких дисках. Должна вызываться с привилегиями пользователя ''root''. Пользуйтесь этой утилитой с особой осторожностью, т.к. при неправильном использовании можно легко разрушить существующую файловую систему!&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fsck,e2fsck,debugfs'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Набор команд для проверки, восстановления и отладки файловой системы.&lt;br /&gt;
'''''fsck''''': интерфейсная утилита для проверки файловых систем в Unix (может вызывать другие утилиты проверки).&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''e2fsck''''': проверка файловой системы ''ext2''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''debugfs''''': отладчик файловой системы ''ext2''. Одно из применений этой универсальной (и опасной!) утилиты — это восстановление удалённых файлов. Только для опытных пользователей!&amp;lt;br /&amp;gt;&lt;br /&gt;
Все эти утилиты должны вызываться с привилегиями пользователя ''root''. При неправильном использовании, любая из них может разрушить файловую систему!&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''badblocks'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выполняет поиск плохих блоков (физические повреждения носителей) на устройствах хранения информации. Эта команда может использоваться для поиска плохих блоков при форматировании вновь устанавливаемых жёстких дисков или для проверки устройств резервного копирования.Например, '''''badblocks /dev/fd0''''', проверит дискету на наличие&lt;br /&gt;
повреждённых блоков. Утилита '''''badblocks''''' может быть вызвана в деструктивном (проверка осуществляется путём записи некоторого шаблона в каждый блок, а затем производится попытка чтения этого блока) или в недеструктивном (неразрушающем — только чтение) режиме.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lsusb,usbmodules'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''lsusb''''' выводит сведения о имеющихся в системе шинах USB (Universal Serial Bus) и подключенных к ним устройствах.&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''usbmodules''''' выводит информацию о модулях драйверов присоединенных USB-устройств.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root# lsusb&lt;br /&gt;
Bus 001 Device 001: ID 0000:0000&lt;br /&gt;
Device Descriptor:&lt;br /&gt;
bLength            18&lt;br /&gt;
bDescriptorType    1&lt;br /&gt;
bcdUSB             1.00&lt;br /&gt;
bDeviceClass       9 Hub&lt;br /&gt;
bDeviceSubClass    0&lt;br /&gt;
bDeviceProtocol    0&lt;br /&gt;
bMaxPacketSize0    8&lt;br /&gt;
idVendor           0x0000&lt;br /&gt;
idProduct          0x0000&lt;br /&gt;
. . .&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mkbootdisk'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создание загрузочной дискеты, которая может быть использована для загрузки системы, если, например, была повреждена MBR (''master boot record'' — главная загрузочная запись). Команда '''''mkbootdisk''''' — это сценарий на языке командной оболочки Bash, автор: ''Erik Troan'', располагается в каталоге ''/sbin''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''chroot'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''CH'''''ange '''''ROOT''''' — смена корневого каталога. Обычно, команды и утилиты ориентируются в файловой системе посредством переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$PATH&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;, относительно корневого каталога / . Команда '''''chroot''''' изменяет корневой каталог по-умолчанию на другой (рабочий каталог также изменяется). Эта утилита, как правило, используется с целью защиты системы, например, с её помощью можно ограничить доступ к разделам файловой системы для пользователей, подключающихся к системе с помощью '''''telnet''''' (это называется — &amp;quot;поместить пользователя в chroot окружение&amp;quot;). Обратите внимание: после выполнения команды '''''chroot''''' изменяется путь к исполняемым файлам системы.&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''chroot /opt''''' приведёт к тому, что все обращения к каталогу ''/usr/bin'' будут переводиться на каталог ''/opt/usr/bin''. Аналогично, '''''chroot /aaa/bbb /bin/ls''''' будет пытаться вызвать команду [[ls]] из каталога ''/aaa/bbb/bin'', при этом, корневым каталогом для [[ls]] станет каталог ''/aaa/bbb''. Поместив строчку ''alias XX 'chroot /aaa/bbb ls' '' в пользовательский ''~/.bashrc'', можно эффективно ограничить доступ команде &amp;quot;XX&amp;quot;, запускаемой пользователем, к разделам файловой системы. При изменении корневого каталога, вам наверняка потребуется скопировать системные утилиты и разделяемые библиотеки в новый корневой каталог, поскольку после смены корневого каталога, директории с системными утилитами могут оказаться за пределами нового корневого каталога.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lockfile'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта утилита входит в состав пакета ''procmail'' (www.procmail.org). Она создаёт ''lock file'', файл-семафор (или, если угодно, файл блокировки), который управляет доступом к заданному файлу, устройству или ресурсу. ''Lock file'' служит признаком того, что данный файл, устройство или ресурс &amp;quot;занят&amp;quot; некоторым процессом, и ограничивает (или вообще запрещает) доступ к ресурсу другим процессам.&amp;lt;br /&amp;gt;&lt;br /&gt;
Файлы блокировок широко применяются для защиты системных почтовых каталогов от одновременной записи несколькими пользователями, для индикации занятости порта модема, и т.п. Сценарии могут использовать файлы блокировок для того, чтобы выяснить — запущен ли тот или иной процесс. Обратите внимание: если в сценарии будет предпринята попытка создать файл блокировки, когда он уже существует, то такой сценарий скорее всего зависнет. Как правило, файлы блокировки создаются в каталоге ''/var/lock''. Проверка наличия файла блокировки может быть проверена примерно таким образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
appname=xyzip&lt;br /&gt;
# Приложение &amp;quot;xyzip&amp;quot; создает файл блокировки &amp;quot;/var/lock/xyzip.lock&amp;quot;.&lt;br /&gt;
if [ -e &amp;quot;/var/lock/$appname.lock ]&lt;br /&gt;
then&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''mknod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создаёт специальный файл для блочного или символьного устройства (может потребоваться при установке новых устройств в компьютер). В системе имеется более удобная в обращении утилита '''''MAKEDEV''''', которая обладает всей функциональностью команды '''''mknod'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''tmpwatch'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Автоматически удаляет файлы, к которым не было обращений в течение заданного периода времени. Обычно вызывается демоном '''''cron''''' для удаления устаревших файлов системного журнала.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''MAKEDEV'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита предназначена для создания файлов-устройств. Должна запускаться с привилегиями пользователя ''root'', в каталоге ''/dev''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
root# ./MAKEDEV&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Это своего рода расширенная версия утилиты '''''mknod'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Команды резервного копирования'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''dump,restore'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''dump''''' создаёт резервные копии целых файловых систем, обычно используется в крупных системах и сетях. Она считывает дисковые разделы и сохраняет их в файле, в двоичном формате. Созданные таким образом файлы, могут быть сохранены на каком-либо носителе — на жёстком диске или магнитной ленте. Команда '''''restore''''' — &amp;quot;разворачивает&amp;quot; файлы, созданные утилитой '''''dump'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''fdformat'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выполняет низкоуровневое форматирование дискет.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Команды управления системными ресурсами'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ulimit'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Устанавливает верхний предел для системных ресурсов. Как правило вызывается с ключом ''-f'', что означает наложение ограничений на размер файлов ('''''ulimit -f 1000''''' ограничит размер вновь создаваемых файлов одним мегабайтом). Ключ ''-c'' ограничивает размер файлов ''coredump'' ('''''ulimit -c 0''''' запретит создание coredump-файлов). Обычно, все ограничения прописываются в файле ''/etc/profile'' и/или ''~/.bash_profile''. Грамотное использование '''''ulimit''''' поможет избежать нападений, целью которых является исчерпание системных ресурсов, известных под названием ''fork bomb''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Этот сценарий служит исключительно демонстрационным целям!&lt;br /&gt;
# Запускайте его на свой страх и риск — он ПОДВЕСИТ вашу систему!&lt;br /&gt;
while true # Бесконечный цикл.&lt;br /&gt;
do&lt;br /&gt;
 $0 &amp;amp; # Этот сценарий вызывает сам себя . . .&lt;br /&gt;
      # порождая дочерние процессы бесконечное число раз . . .&lt;br /&gt;
      # точнее — до тех пор, пока не иссякнут системные ресурсы.&lt;br /&gt;
done # Это печально известный сценарий &amp;quot;sorcerer's appentice&amp;quot;.&lt;br /&gt;
exit 0 # Сценарий никогда не завершит свою работу.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''ulimit -Hu XX''''' (где ''XX'' — это верхний предел количества процессов, которые может запустить пользователь одновременно) в ''/etc/profile'' вызовет аварийное завершение этого сценария, когда количество процессов превысит установленный предел.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''setquota'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда управления дисковыми квотами для пользователей и групп.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''umask'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Установка маски режима создания файлов. Накладывает ограничения на атрибуты по-умолчанию для создаваемых файлов. Маска представляет собой восьмеричное значение и определяет запрещённые атрибуты файла. Например, '''''umask 022''''' удаляет права на запись для группы и прочих пользователей (у файлов, создававшихся с режимом ''777'', он оказывается равным ''755'', а режим ''666'' преобразуется в ''644'', т.е. ''777 NAND 022 = 755'', ''666 NAND 022 = 644''). Конечно же, в последствие, пользователь может откорректировать права доступа к своему файлу с помощью команды [[chmod]]. Как правило, значение '''''umask''''' устанавливается в файле ''/etc/profile'' и/или ''~/.bash_profile''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rdev'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит или изменяет корневое устройство, размер RAM-диска или видео режим.Функциональные возможности утилиты '''''rdev''''' вообще повторяются загрузчиком ''lilo'', но '''''rdev''''' по прежнему остаётся востребованной, например, при установке электронного диска (RAM-диск).Это потенциально опасная, при неумелом использовании, утилита.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Команды для работы с модулями ядра'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''lsmod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список загруженных модулей.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ lsmod&lt;br /&gt;
Module    Size   Used by&lt;br /&gt;
autofs    9456   2 (autoclean)&lt;br /&gt;
opl3      11376  0&lt;br /&gt;
serial_cs 5456   0 (unused)&lt;br /&gt;
sb        34752  0&lt;br /&gt;
uart401   6384   0 [sb]&lt;br /&gt;
sound     58368  0 [opl3 sb uart401]&lt;br /&gt;
soundlow  464    0 [sound]&lt;br /&gt;
soundcore 2800   6 [sb sound]&lt;br /&gt;
ds        6448   2 [serial_cs]&lt;br /&gt;
i82365    22928  2&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''cat /proc/modules''''' выведет на экран эту же информацию.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''insmod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Принудительная загрузка модуля ядра (старайтесь вместо '''''insmod''''' использовать команду '''''modprobe'''''). Должна вызываться с привилегиями пользователя ''root''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rmmod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выгружает модуль ядра. Должна вызываться с привилегиями пользователя ''root''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''modprobe'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Загрузчик модулей, который обычно вызывается из сценариев начальной загрузки системы. Должна вызываться с привилегиями пользователя ''root''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''depmod'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Создаёт файл зависимостей между модулями, обычно вызывается из сценариев начальной загрузки системы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''modinfo'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит сведения о загруженных модулях ядра.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ modinfo hid&lt;br /&gt;
filename: /lib/modules/2.4.20-6/kernel/drivers/usb/hid.o&lt;br /&gt;
description: &amp;quot;USB HID support drivers&amp;quot;&lt;br /&gt;
author: &amp;quot;Andreas Gal, Vojtech Pavlik &amp;lt;vojtech@suse.cz&amp;gt;&amp;quot;&lt;br /&gt;
license: &amp;quot;GPL&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Прочие команды'''&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''env'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Запускает указанную программу или сценарий с модифицированными переменными окружения(не изменяя среду системы в целом, изменения касаются только окружения запускаемой программы/сценария). Посредством [varname=xxx], устанавливает значение &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;переменной окружения&amp;lt;/span&amp;gt; varname, которая будет доступна из запускаемой программы/сценария. Без параметров — просто выводит список переменных окружения с их значениями. В Bash, и других производных от Bourne shell, имеется возможность установки переменных окружения и запуска программы (или сценария) одной командной строкой.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
var1=value1 var2=value2 commandXXX&lt;br /&gt;
# $var1 и $var2 — будут определены только в окружении для 'commandXXX'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В первой строке сценария (&amp;quot;sha-bang&amp;quot;) можно указать команду env, если путь к командному интерпретатору не известен.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /usr/bin/env perl&lt;br /&gt;
print &amp;quot;Этот сценарий, на языке программирования Perl, будет запущен,\n&amp;quot;;&lt;br /&gt;
print &amp;quot;даже если я не знаю где в системе находится Perl.\n&amp;quot;;&lt;br /&gt;
# Прекрасно подходит для написания кросс-платформенных сценариев,&lt;br /&gt;
# когда Perl может находиться совсем не там, где вы ожидаете.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''ldd'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список разделяемых библиотек, необходимых для исполняемого файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ldd /bin/ls&lt;br /&gt;
libc.so.6 =&amp;gt; /lib/libc.so.6 (0x4000c000)&lt;br /&gt;
/lib/ld-linux.so.2 =&amp;gt; /lib/ld-linux.so.2 (0x80000000)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''watch'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Периодически запускает указанную программу с заданным интервалом времени. По-умолчанию интервал между запусками принимается равным 2 секундам, но может быть изменён ключом ''-n''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
watch -n 5 tail /var/log/messages&lt;br /&gt;
# Выводит последние 10 строк из системного журнала, /var/log/messages, каждые пять секунд.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''strip'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Удаляет отладочную информацию из исполняемого файла. Это значительно уменьшает размер исполняемого файла, но при этом делает отладку программы невозможной. Эту команду часто можно встретить в Makefile-ах, и редко — в сценариях на языке командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''nm'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Выводит список символов (используемых в целях отладки), содержащихся в откомпилированном двоичном файле.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''rdist'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Позволяет на заданных машинах хранить идентичные копии файлов. По умолчанию, '''''rdist''''' просматривает только те файлы, версия которых на удалённых машинах более старая, чем на локальной машине. Это делается сравнением последнего времени модификации и размера файла на локальной машине и на удалённых. А теперь, используя полученные нами знания, попробуем разобраться с одним из системных сценариев. Один из самых коротких и простых — это '''''killall''''', который вызывается для остановки процессов при перезагрузке или выключении компьютера.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий killall, из каталога /etc/rc.d/init.d .'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/sh&lt;br /&gt;
# --&amp;gt; Комментарии, начинающиеся с &amp;quot;# --&amp;gt;&amp;quot;, добавлены автором документа.&lt;br /&gt;
# --&amp;gt; Этот сценарий является частью пакета 'rc'-сценариев&lt;br /&gt;
# --&amp;gt; Автор: Miquel van Smoorenburg, &amp;lt;miquels@drinkel.nl.mugnet.org&amp;gt;&lt;br /&gt;
# --&amp;gt; Этот сценарий характерен для дистрибутива Red Hat&lt;br /&gt;
# --&amp;gt; (в других дистрибутивах может отсутствовать).&lt;br /&gt;
# Остановить все ненужные сервисы которые еще работают (собственно, их уже не должно быть, это лишь формальная проверка, на всякий случай)&lt;br /&gt;
&lt;br /&gt;
for i in /var/lock/subsys/*; do&lt;br /&gt;
 # --&amp;gt; Стандартный заголовок цикла for/in, но, поскольку &amp;quot;do&amp;quot;&lt;br /&gt;
 # --&amp;gt; находится в той же самой строке, что и for,&lt;br /&gt;
 # --&amp;gt; необходимо разделить их символом &amp;quot;;&amp;quot;.&lt;br /&gt;
 # Проверяется наличие сценария.&lt;br /&gt;
 [ ! -f $i ] &amp;amp;&amp;amp; continue&lt;br /&gt;
 # --&amp;gt; Очень интересное использование &amp;quot;И-списка&amp;quot;, эквивалентно:&lt;br /&gt;
 # --&amp;gt; if [ ! -f &amp;quot;$i&amp;quot; ]; then continue&lt;br /&gt;
&lt;br /&gt;
 # Получить имя подсистемы.&lt;br /&gt;
 subsys=${i#/var/lock/subsys/}&lt;br /&gt;
 # --&amp;gt; В данном случае совпадает с именем файла.&lt;br /&gt;
 # --&amp;gt; Это точный эквивалент subsys=`basename $i`.&lt;br /&gt;
 # --&amp;gt; Таким образом получается имя файла блокировки (если он присутствует,&lt;br /&gt;
 # --&amp;gt; то это означает, что процесс запущен).&lt;br /&gt;
 # --&amp;gt; См. описание команды &amp;quot;lockfile&amp;quot; выше.&lt;br /&gt;
 &lt;br /&gt;
 # Остановить службу.&lt;br /&gt;
 if [ -f /etc/rc.d/init.d/$subsys.init ]; then&lt;br /&gt;
  /etc/rc.d/init.d/$subsys.init stop&lt;br /&gt;
 else&lt;br /&gt;
  /etc/rc.d/init.d/$subsys stop&lt;br /&gt;
 # --&amp;gt; Останавливает задачу или демона&lt;br /&gt;
 # --&amp;gt; посредством встроенной команды 'stop'.&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В общем всё довольно понятно. Кроме хитрого манипулирования с переменными, при определении имени подсистемы(службы), здесь нет ничего нового.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Упражнение 1'''. Просмотрите сценарий '''halt''' в каталоге ''/etc/rc.d/init.d''. Он по размеру немного больше, чем '''''killall''''', но придерживается той же концепции. Создайте копию этого сценария в своём домашнем каталоге и поэкспериментируйте с ним (НЕ запускайте его с привилегиями суперпользователя!). Попробуйте запустить его с ключами ''-vn'' ('''''sh -vn scriptname'''''). Добавьте свои комментарии. Замените действующие команды на &amp;quot;echo&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Упражнение 2'''. Просмотрите другие, более сложные сценарии из ''/etc/rc.d/init.d''. Попробуйте разобраться в их работе. Проверьте их работу, следуя рекомендациям, приведённым выше. За дополнительной информацией вы можете обратиться к документу ''sysvinitfiles'' в каталоге ''/usr/share/doc/initscripts-?.??'', который входит в пакет документации к &amp;quot;initscripts&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Подстановка команд ==&lt;br /&gt;
Подстановка команд — это подстановка результатов выполнения команды или даже серии команд; буквально, эта операция позволяет вызвать команду в другом окружении. Классический пример подстановки команд — использование обратных одиночных кавычек (`...`). Команды внутри этих кавычек представляют собой текст командной строки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
script_name=`basename $0`&lt;br /&gt;
echo &amp;quot;Имя этого файла-сценария: $script_name.&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Вывод от команд может использоваться: как аргумент другой команды, для установки значения переменной и даже для генерации списка аргументов цикла for.'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rm `cat filename` # здесь &amp;quot;filename&amp;quot; содержит список удаляемых файлов.&lt;br /&gt;
#&lt;br /&gt;
# S. C. предупреждает, что в данном случае может возникнуть ошибка &amp;quot;arg list too long&amp;quot;.&lt;br /&gt;
# Такой вариант будет лучше: xargs rm -- &amp;lt; filename&lt;br /&gt;
# ( -- подходит для случая, когда &amp;quot;filename&amp;quot; начинается с символа &amp;quot;-&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
textfile_listing=`ls *.txt`&lt;br /&gt;
# Переменная содержит имена всех файлов *.txt в текущем каталоге.&lt;br /&gt;
echo $textfile_listing&lt;br /&gt;
&lt;br /&gt;
textfile_listing2=$(ls *.txt) # Альтернативный вариант.&lt;br /&gt;
echo $textfile_listing2&lt;br /&gt;
# Результат будет тем же самым.&lt;br /&gt;
&lt;br /&gt;
# Проблема записи списка файлов в строковую переменную состоит в том,&lt;br /&gt;
# что символы перевода строки заменяются на пробел.&lt;br /&gt;
#&lt;br /&gt;
# Как вариант решения проблемы -- записывать список файлов в массив.&lt;br /&gt;
# shopt -s nullglob # При несоответствии, имя файла игнорируется.&lt;br /&gt;
# textfile_listing=( *.txt )&lt;br /&gt;
#&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подставляемая команда выполняется в подоболочке. Подставляемая команда может получиться разбитой на отдельные слова.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
COMMAND `echo a b` # 2 аргумента: a и b&lt;br /&gt;
COMMAND &amp;quot;`echo a b`&amp;quot; # 1 аргумент: &amp;quot;a b&amp;quot;&lt;br /&gt;
COMMAND `echo` # без аргументов &lt;br /&gt;
COMMAND &amp;quot;`echo`&amp;quot; # один пустой аргумент&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Даже когда не происходит разбиения на слова, операция подстановки команд может удалять завершающие символы перевода строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# cd &amp;quot;`pwd`&amp;quot; # Должна выполняться всегда.&lt;br /&gt;
# Однако...&lt;br /&gt;
mkdir 'dir with trailing newline&lt;br /&gt;
'&lt;br /&gt;
cd 'dir with trailing newline&lt;br /&gt;
'&lt;br /&gt;
cd &amp;quot;`pwd`&amp;quot; # Ошибка:&lt;br /&gt;
# bash: cd: /tmp/dir with trailing newline: No such file or directory&lt;br /&gt;
cd &amp;quot;$PWD&amp;quot; # Выполняется без ошибки.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
old_tty_setting=$(stty -g) # Сохранить настройки терминала.&lt;br /&gt;
echo &amp;quot;Нажмите клавишу &amp;quot;&lt;br /&gt;
stty -icanon -echo # Запретить &amp;quot;канонический&amp;quot; режим терминала.&lt;br /&gt;
                   # Также запрещает эхо-вывод.&lt;br /&gt;
key=$(dd bs=1 count=1 2&amp;gt; /dev/null) # Поймать нажатие на клавишу.&lt;br /&gt;
stty &amp;quot;$old_tty_setting&amp;quot; # Восстановить настройки терминала.&lt;br /&gt;
echo &amp;quot;Количество нажатых клавиш = ${#key}.&amp;quot; # ${#variable} = количество символов в переменной $variable&lt;br /&gt;
#&lt;br /&gt;
# Нажмите любую клавишу, кроме RETURN, на экране появится &amp;quot;Количество нажатых клавиш = 1.&amp;quot;&lt;br /&gt;
# Нажмите RETURN, и получите: &amp;quot;Количество нажатых клавиш = 0.&amp;quot;&lt;br /&gt;
# Символ перевода строки будет &amp;quot;съеден&amp;quot; операцией подстановки команды.&lt;br /&gt;
Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
При выводе значений переменных, полученных в результате подстановки команд, командой '''''echo''''', без кавычек, символы перевода строки будут удалены. Это может оказаться неприятным сюрпризом.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
dir_listing=`ls -l`&lt;br /&gt;
echo $dir_listing # без кавычек&lt;br /&gt;
# Вы наверно ожидали увидеть удобочитаемый список каталогов.&lt;br /&gt;
&lt;br /&gt;
# Однако, вы получите:&lt;br /&gt;
# total 3 -rw-rw-r-- 1 bozo bozo 30 May 13 17:15 1.txt -rw-rw-r-- 1 bozo&lt;br /&gt;
# bozo 51 May 15 20:57 t2.sh -rwxr-xr-x 1 bozo bozo 217 Mar 5 21:13 wi.sh&lt;br /&gt;
# Символы перевода строки были заменены пробелами.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;$dir_listing&amp;quot; # в кавычках&lt;br /&gt;
# -rw-rw-r-- 1 bozo 30 May 13 17:15 1.txt&lt;br /&gt;
# -rw-rw-r-- 1 bozo 51 May 15 20:57 t2.sh&lt;br /&gt;
# -rwxr-xr-x 1 bozo 217 Mar 5 21:13 wi.sh&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подстановка команд позволяет даже записывать в переменные содержимое целых файлов, с помощью перенаправления или команды [[cat]].&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable1=`&amp;lt;file1`    # Записать в переменную &amp;quot;variable1&amp;quot; содержимое файла &amp;quot;file1&amp;quot;.&lt;br /&gt;
variable2=`cat file2` # Записать в переменную &amp;quot;variable2&amp;quot; содержимое файла &amp;quot;file2&amp;quot;.&lt;br /&gt;
                      # Однако, эта команда порождает дочерний процесс,&lt;br /&gt;
                      # поэтому эта строка выполняется медленнее, чем предыдущая.&lt;br /&gt;
# Замечание:&lt;br /&gt;
# В переменные можно записать даже управляющие символы.&lt;br /&gt;
&lt;br /&gt;
# Выдержки из системного файла /etc/rc.d/rc.sysinit (Red Hat Linux)&lt;br /&gt;
&lt;br /&gt;
if [ -f /fsckoptions ]; then&lt;br /&gt;
 fsckoptions=`cat /fsckoptions`&lt;br /&gt;
...&lt;br /&gt;
fi&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
if [ -e &amp;quot;/proc/ide/${disk[$device]}/media&amp;quot; ] ; then&lt;br /&gt;
 hdmedia=`cat /proc/ide/${disk[$device]}/media`&lt;br /&gt;
...&lt;br /&gt;
fi&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
if [ ! -n &amp;quot;`uname -r | grep -- &amp;quot;-&amp;quot;`&amp;quot; ]; then&lt;br /&gt;
ktag=&amp;quot;`cat /proc/version`&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
fi&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
if [ $usb = &amp;quot;1&amp;quot; ]; then&lt;br /&gt;
 sleep 5&lt;br /&gt;
 mouseoutput=`cat /proc/bus/usb/devices 2&amp;gt;/dev/null|grep -E &amp;quot;^I.*Cls=03.*Prot=02&amp;quot;`&lt;br /&gt;
 kbdoutput=`cat /proc/bus/usb/devices 2&amp;gt;/dev/null|grep -E &amp;quot;^I.*Cls=03.*Prot=01&amp;quot;`&lt;br /&gt;
...&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Не используйте переменные для хранения содержимого текстовых файлов большого объёма, без веских на то оснований. Не записывайте в переменные содержимое бинарных файлов, даже шутки ради.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Глупая выходка.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# stupid-script-tricks.sh: Люди! Будьте благоразумны!&lt;br /&gt;
# Из &amp;quot;Глупые выходки&amp;quot;, том I.&lt;br /&gt;
dangerous_variable=`cat /boot/vmlinuz` # Сжатое ядро Linux.&lt;br /&gt;
echo &amp;quot;длина строки \$dangerous_variable = ${#dangerous_variable}&amp;quot;&lt;br /&gt;
# длина строки $dangerous_variable = 794151&lt;br /&gt;
# ('wc -c /boot/vmlinuz' даст другой результат.)&lt;br /&gt;
# echo &amp;quot;$dangerous_variable&amp;quot;&lt;br /&gt;
# Даже не пробуйте раскомментировать эту строку! Это приведёт к зависанию сценария.&lt;br /&gt;
# Автор этого документа не знает, где можно было бы использовать запись содержимого двоичных файлов в переменные.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание: в данной ситуации не возникает ошибки переполнения буфера. Этот пример показывает превосходство защищённости интерпретирующих языков, таких как Bash, от ошибок программиста, над компилирующими языками программирования. Подстановка команд, позволяет записать в переменную результаты выполнения цикла. Ключевым моментом здесь является команда '''''echo''''', в теле цикла.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Запись результатов выполнения цикла в переменную.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# csubloop.sh: Запись результатов выполнения цикла в переменную &lt;br /&gt;
variable1=`for i in 1 2 3 4 5&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$i&amp;quot; # Здесь 'echo' — это ключевой момент&lt;br /&gt;
done`&lt;br /&gt;
echo &amp;quot;variable1 = $variable1&amp;quot; # variable1 = 12345&lt;br /&gt;
i=0&lt;br /&gt;
variable2=`while [ &amp;quot;$i&amp;quot; -lt 10 ]&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$i&amp;quot; # Опять же, команда 'echo' просто необходима.&lt;br /&gt;
 let &amp;quot;i += 1&amp;quot; # Увеличение на 1.&lt;br /&gt;
done`&lt;br /&gt;
echo &amp;quot;variable2 = $variable2&amp;quot; # variable2 = 0123456789&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Подстановка команд позволяет существенно расширить набор инструментальных средств, которыми располагает Bash. Суть состоит в том, чтобы написать программу или сценарий, которая выводит результаты своей работы на ''stdout'' (как это делает подавляющее большинство утилит в Unix) и записать вывод от программы в переменную.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
/* Программа на C &amp;quot;Hello, world.&amp;quot; */&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
 printf( &amp;quot;Hello, world.&amp;quot; );&lt;br /&gt;
 return (0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ gcc -o hello hello.c&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# hello.sh&lt;br /&gt;
greeting=`./hello`&lt;br /&gt;
echo $greeting&lt;br /&gt;
bash$ sh hello.sh&lt;br /&gt;
Hello, world.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
|}&amp;lt;br /&amp;gt;&lt;br /&gt;
Альтернативой обратным одиночным кавычкам, используемым для подстановки команд, можно считать такую форму записи: '''''$(COMMAND)'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
output=$(sed -n /&amp;quot;$1&amp;quot;/p $file) # К примеру из &amp;quot;grp.sh&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Запись в переменную содержимого текстового файла.&lt;br /&gt;
File_contents1=$(cat $file1)&lt;br /&gt;
File_contents2=$(&amp;lt;$file2) # Bash допускает и такую запись.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Следует упомянуть, что в конструкции '''''$(...)''''' два идущих подряд обратных слэша интерпретируются несколько иначе, чем в конструкции '''''`...`'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo `echo \\`&lt;br /&gt;
&lt;br /&gt;
bash$ echo $(echo \\)&lt;br /&gt;
\&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Арифметические подстановки ==&lt;br /&gt;
Арифметические подстановки — это мощный инструмент, предназначенный для выполнения арифметических операций в сценариях. Перевод строки в числовое выражение производится с помощью обратных одиночных кавычек, двойных круглых скобок или предложения '''''let'''''.&lt;br /&gt;
'''Вариации'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Арифметические подстановки в обратных одиночных кавычках(часто используются совместно с командой '''''expr''''').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
z=`expr $z + 3` # Команда 'expr' вычисляет значение выражения.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Арифметические подстановки в двойных круглых скобках и предложение '''''let'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
В арифметических подстановках, обратные одиночные кавычки могут быть заменены на двойные круглые скобки — '''''$((...))''''' и '''''$((...))''''' или очень удобной конструкцией, с применением предложения '''''let'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
z=$(($z+3))&lt;br /&gt;
z=$((z+3) # Тоже верно.&lt;br /&gt;
# Внутри двойных круглых скобок, переменные разыменовываются автоматически.&lt;br /&gt;
# $((EXPRESSION)) — это подстановка арифметического выражения!&lt;br /&gt;
# Не путайте с подстановкой команд!&lt;br /&gt;
# Внутри двойных круглых скобок допускается выполнение арифметических&lt;br /&gt;
# действий без использования оператора присваивания&lt;br /&gt;
n=0&lt;br /&gt;
echo &amp;quot;n = $n&amp;quot; # n = 0&lt;br /&gt;
(( n += 1 )) # Инкремент.&lt;br /&gt;
# (( $n += 1 )) это неверно!&lt;br /&gt;
echo &amp;quot;n = $n&amp;quot; # n = 1&lt;br /&gt;
let z=z+3&lt;br /&gt;
let &amp;quot;z += 3&amp;quot; # Кавычки позволяют вставлять пробелы&lt;br /&gt;
             # Оператор 'let' вычисляет арифметическое выражение,&lt;br /&gt;
             # это не подстановка арифметического выражения.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Перенаправление ввода/вывода ==&lt;br /&gt;
В системе по-умолчанию всегда открыты три &amp;quot;файла&amp;quot; — ''stdin'' (клавиатура), ''stdout'' (экран) и ''stderr''(вывод сообщений об ошибках на экран). Эти, и любые другие открытые файлы, могут быть перенаправлены. В данном случае, термин &amp;quot;''перенаправление''&amp;quot; означает получить вывод из файла, команды, программы, сценария или даже отдельного блока в сценарии и передать его на вход в другой файл, команду, программу или сценарий.&amp;lt;br /&amp;gt;&lt;br /&gt;
С каждым открытым файлом связан дескриптор файла. Дескрипторы файлов ''stdin'', ''stdout'' и ''stderr'' — 0, 1 и 2, соответственно. При открытии дополнительных файлов, дескрипторы с 3 по 9 остаются незанятыми. Иногда дополнительные дескрипторы могут сослужить неплохую службу, временно сохраняя в себе ссылку на ''stdin'', ''stdout'' или ''stderr''. Это упрощает возврат дескрипторов в нормальное состояние после сложных манипуляций с перенаправлением и перестановками.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
COMMAND_OUTPUT &amp;gt; &lt;br /&gt;
  # Перенаправление stdout (вывода) в файл. &lt;br /&gt;
  # Если файл отсутствовал, то он создаётся, иначе — перезаписывается. &lt;br /&gt;
&lt;br /&gt;
  ls -lR &amp;gt; dir-tree.list&lt;br /&gt;
  # Создаёт файл, содержащий список дерева каталогов.&lt;br /&gt;
: &amp;gt; filename&lt;br /&gt;
  # Операция &amp;gt; усекает файл &amp;quot;filename&amp;quot; до нулевой длины.&lt;br /&gt;
  # Если до выполнения операции файла не существовало,&lt;br /&gt;
  # то создаётся новый файл с нулевой длиной (тот же эффект дает команда 'touch').&lt;br /&gt;
  # Символ : выступает здесь в роли местозаполнителя, не выводя ничего.&lt;br /&gt;
&amp;gt; filename&lt;br /&gt;
  # Операция &amp;gt; усекает файл &amp;quot;filename&amp;quot; до нулевой длины.&lt;br /&gt;
  # Если до выполнения операции файла не существовало,&lt;br /&gt;
  # то создается новый файл с нулевой длиной (тот же эффект дает команда 'touch').&lt;br /&gt;
  # (тот же результат, что и выше — &amp;quot;: &amp;gt;&amp;quot;, но этот вариант неработоспособен&lt;br /&gt;
  # в некоторых командных оболочках.)&lt;br /&gt;
COMMAND_OUTPUT &amp;gt;&amp;gt;&lt;br /&gt;
  # Перенаправление stdout (вывода) в файл.&lt;br /&gt;
  # Создаёт новый файл, если он отсутствовал, иначе — дописывает в конец файла.&lt;br /&gt;
 &lt;br /&gt;
  # Однострочные команды перенаправления&lt;br /&gt;
  # (затрагивают только ту строку, в которой они встречаются):&lt;br /&gt;
  # --------------------------------------------------------------------&lt;br /&gt;
1&amp;gt;filename&lt;br /&gt;
  # Перенаправление вывода (stdout) в файл &amp;quot;filename&amp;quot;.&lt;br /&gt;
1&amp;gt;&amp;gt;filename&lt;br /&gt;
  # Перенаправление вывода (stdout) в файл &amp;quot;filename&amp;quot;, файл открывается в режиме добавления.&lt;br /&gt;
2&amp;gt;filename&lt;br /&gt;
  # Перенаправление stderr в файл &amp;quot;filename&amp;quot;.&lt;br /&gt;
2&amp;gt;&amp;gt;filename&lt;br /&gt;
  # Перенаправление stderr в файл &amp;quot;filename&amp;quot;, файл открывается в режиме добавления.&lt;br /&gt;
&amp;amp;&amp;gt;filename&lt;br /&gt;
  # Перенаправление stdout и stderr в файл &amp;quot;filename&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
  #==============================================================================&lt;br /&gt;
  # Перенаправление stdout, только для одной строки.&lt;br /&gt;
  LOGFILE=script.log&lt;br /&gt;
  &lt;br /&gt;
  echo &amp;quot;Эта строка будет записана в файл \&amp;quot;$LOGFILE\&amp;quot;.&amp;quot; 1&amp;gt;$LOGFILE&lt;br /&gt;
  echo &amp;quot;Эта строка будет добавлена в конец файла \&amp;quot;$LOGFILE\&amp;quot;.&amp;quot; 1&amp;gt;&amp;gt;$LOGFILE&lt;br /&gt;
  echo &amp;quot;Эта строка тоже будет добавлена в конец файла \&amp;quot;$LOGFILE\&amp;quot;.&amp;quot; 1&amp;gt;&amp;gt;$LOGFILE&lt;br /&gt;
  echo &amp;quot;Эта строка будет выведена на экран и не попадет в файл \&amp;quot;$LOGFILE\&amp;quot;.&amp;quot;&lt;br /&gt;
  # После каждой строки, сделанное перенаправление автоматически &amp;quot;сбрасывается&amp;quot;.&lt;br /&gt;
  &lt;br /&gt;
  # Перенаправление stderr, только для одной строки.&lt;br /&gt;
  ERRORFILE=script.errors&lt;br /&gt;
&lt;br /&gt;
  bad_command1 2&amp;gt;$ERRORFILE # Сообщение об ошибке запишется в $ERRORFILE.&lt;br /&gt;
  bad_command2 2&amp;gt;&amp;gt;$ERRORFILE # Сообщение об ошибке добавится в конец $ERRORFILE.&lt;br /&gt;
  bad_command3 # Сообщение об ошибке будет выведено на stderr, и не попадет в $ERRORFILE.&lt;br /&gt;
  # После каждой строки, сделанное перенаправление также автоматически &amp;quot;сбрасывается&amp;quot;.&lt;br /&gt;
  #==============================================================================&lt;br /&gt;
&lt;br /&gt;
2&amp;gt;&amp;amp;1&lt;br /&gt;
  # Перенаправляется stderr на stdout.&lt;br /&gt;
  # Сообщения об ошибках передаются туда же, куда и стандартный вывод.&lt;br /&gt;
&lt;br /&gt;
i&amp;gt;&amp;amp;j&lt;br /&gt;
  # Перенаправляется файл с дескриптором i в j.&lt;br /&gt;
  # Вывод в файл с дескриптором i передаётся в файл с дескриптором j.&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;amp;j&lt;br /&gt;
  # Перенаправляется файл с дескриптором 1 (stdout) в файл с дескриптором j.&lt;br /&gt;
  # Вывод на stdout передаётся в файл с дескриптором j.&lt;br /&gt;
&lt;br /&gt;
0&amp;lt; FILENAME&lt;br /&gt;
 &amp;lt; FILENAME&lt;br /&gt;
  # Ввод из файла.&lt;br /&gt;
  # Парная команде &amp;quot;&amp;gt;&amp;quot;, часто встречается в комбинации с ней.&lt;br /&gt;
  #&lt;br /&gt;
  # grep search-word &amp;lt;filename&lt;br /&gt;
&lt;br /&gt;
[j]&amp;lt;&amp;gt;filename&lt;br /&gt;
  # Файл &amp;quot;filename&amp;quot; открывается на чтение и запись, и связывается с дескриптором &amp;quot;j&amp;quot;. 249&lt;br /&gt;
  # Если &amp;quot;filename&amp;quot; отсутствует, то он создаётся.&lt;br /&gt;
  # Если дескриптор &amp;quot;j&amp;quot; не указан, то, по-умолчанию, берётся дескриптор 0, stdin.&lt;br /&gt;
  #&lt;br /&gt;
  # Как одно из применений этого — запись в конкретную позицию в файле.&lt;br /&gt;
  echo 1234567890 &amp;gt; File # Записать строку в файл &amp;quot;File&amp;quot;.&lt;br /&gt;
  exec 3&amp;lt;&amp;gt; File # Открыть &amp;quot;File&amp;quot; и связать с дескриптором 3.&lt;br /&gt;
  read -n 4 &amp;lt;&amp;amp;3 # Прочитать 4 символа.&lt;br /&gt;
  echo -n . &amp;gt;&amp;amp;3 # Записать символ точки.&lt;br /&gt;
  exec 3&amp;gt;&amp;amp;- # Закрыть дескриптор 3.&lt;br /&gt;
  cat File # ==&amp;gt; 1234.67890&lt;br /&gt;
  # Произвольный доступ, да и только!&lt;br /&gt;
&lt;br /&gt;
|&lt;br /&gt;
  # Конвейер (канал).&lt;br /&gt;
  # Универсальное средство для объединения команд в одну цепочку.&lt;br /&gt;
  # Похоже на &amp;quot;&amp;gt;&amp;quot;, но на самом деле — более обширная.&lt;br /&gt;
  # Используется для объединения команд, сценариев, файлов и программ в одну цепочку (конвейер).&lt;br /&gt;
  cat *.txt | sort | uniq &amp;gt; result-file&lt;br /&gt;
  # Содержимое всех файлов .txt сортируется, удаляются повторяющиеся строки,&lt;br /&gt;
  # результат сохраняется в файле &amp;quot;result-file&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Операции перенаправления и/или конвейеры могут комбинироваться в одной командной строке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
command &amp;lt; input-file &amp;gt; output-file&lt;br /&gt;
command1 | command2 | command3 &amp;gt; output-file&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Допускается перенаправление нескольких потоков в один файл.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -yz &amp;gt;&amp;gt; command.log 2&amp;gt;&amp;amp;1&lt;br /&gt;
# Сообщение о неверной опции &amp;quot;yz&amp;quot; в команде &amp;quot;ls&amp;quot; будет записано в файл &amp;quot;command.log&amp;quot;.&lt;br /&gt;
# Поскольку stderr перенаправлен в файл.&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание: следующая строка даст иной результат.&lt;br /&gt;
ls -yz 2&amp;gt;&amp;amp;1 &amp;gt;&amp;gt; command.log&lt;br /&gt;
# Сообщение об ошибке не попадет в файл.&lt;br /&gt;
# Если производится перенаправление обоих устройств, stdout и stderr, то порядок действий изменяется.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Закрытие дескрипторов файлов'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''n&amp;lt;&amp;amp;-'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Закрыть дескриптор входного файла n.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''0&amp;lt;&amp;amp;-,&amp;lt;&amp;amp;-'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Закрыть ''stdin''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''n&amp;gt;&amp;amp;-'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Закрыть дескриптор выходного файла n.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;&amp;lt;big&amp;gt;'''1&amp;gt;&amp;amp;-,&amp;gt;&amp;amp;-'''&amp;lt;/big&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Закрыть ''stdout''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Дочерние процессы наследуют дескрипторы открытых файлов. По этой причине и работают конвейеры. Чтобы предотвратить наследование дескрипторов — закройте их перед запуском дочернего процесса.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# В конвейер передается только stderr.&lt;br /&gt;
exec 3&amp;gt;&amp;amp;1 # Сохранить текущее &amp;quot;состояние&amp;quot; stdout.&lt;br /&gt;
ls -l 2&amp;gt;&amp;amp;1 &amp;gt;&amp;amp;3 3&amp;gt;&amp;amp;- | grep bad 3&amp;gt;&amp;amp;- # Закрыть дескр. 3 для 'grep' (но не для 'ls').&lt;br /&gt;
#              ^^^^   ^^^^&lt;br /&gt;
exec 3&amp;gt;&amp;amp;- # Теперь закрыть его для оставшейся части сценария.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== С помощью команды exec ===&lt;br /&gt;
Команда '''''exec &amp;lt;filename''''' перенаправляет ввод со ''stdin'' на файл. С этого момента весь ввод, вместо ''stdin'' (обычно это клавиатура), будет производиться из этого файла. Это даёт возможность читать содержимое файла, строку за строкой, и анализировать каждую введённую строку с помощью [[sed]] и/или [[awk]].&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление stdin с помощью exec.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Перенаправление stdin с помощью 'exec'.&lt;br /&gt;
exec 6&amp;lt;&amp;amp;0          # Связать дескр. #6 со стандартным вводом (stdin).&lt;br /&gt;
                   # Сохраняя stdin.&lt;br /&gt;
&lt;br /&gt;
exec &amp;lt; data-file   # stdin заменяется файлом &amp;quot;data-file&amp;quot;&lt;br /&gt;
&lt;br /&gt;
read a1            # Читается первая строка из &amp;quot;data-file&amp;quot;.&lt;br /&gt;
read a2            # Читается вторая строка из &amp;quot;data-file.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Следующие строки были прочитаны из файла.&amp;quot;&lt;br /&gt;
echo &amp;quot;-----------------------------------------&amp;quot;&lt;br /&gt;
echo $a1&lt;br /&gt;
echo $a2&lt;br /&gt;
&lt;br /&gt;
echo; echo; echo&lt;br /&gt;
&lt;br /&gt;
exec 0&amp;lt;&amp;amp;6 6&amp;lt;&amp;amp;-&lt;br /&gt;
# Восстанавливается stdin из дескр. #6, где он был предварительно сохранен,&lt;br /&gt;
# и дескр. #6 закрывается ( 6&amp;lt;&amp;amp;- ) освобождая его для других процессов.&lt;br /&gt;
#&lt;br /&gt;
#&amp;lt;&amp;amp;6 6&amp;lt;&amp;amp;- даёт тот же результат.&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Введите строку &amp;quot;&lt;br /&gt;
read b1 # Теперь функция &amp;quot;read&amp;quot;, как и следовало ожидать, принимает данные с обычного stdin.&lt;br /&gt;
echo &amp;quot;Строка, принятая со stdin.&amp;quot;&lt;br /&gt;
echo &amp;quot;--------------------------&amp;quot;&lt;br /&gt;
echo &amp;quot;b1 = $b1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Аналогично, конструкция '''''exec &amp;gt;filename''''' перенаправляет вывод на ''stdout'' в заданный файл. После этого, весь вывод от команд, который обычно направляется на ''stdout'', теперь выводится в этот файл.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление stdout с помощью exec.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# reassign-stdout.sh&lt;br /&gt;
LOGFILE=logfile.txt&lt;br /&gt;
exec 6&amp;gt;&amp;amp;1       # Связать дескр. #6 со stdout.&lt;br /&gt;
                # Сохраняя stdout.&lt;br /&gt;
&lt;br /&gt;
exec &amp;gt; $LOGFILE # stdout замещается файлом &amp;quot;logfile.txt&amp;quot;.&lt;br /&gt;
# ----------------------------------------------------------- #&lt;br /&gt;
# Весь вывод от команд, в данном блоке, записывается в файл $LOGFILE.&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;Logfile: &amp;quot;&lt;br /&gt;
date&lt;br /&gt;
echo &amp;quot;-------------------------------------&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Вывод команды \&amp;quot;ls -al\&amp;quot;&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
ls -al&lt;br /&gt;
echo; echo&lt;br /&gt;
echo &amp;quot;Вывод команды \&amp;quot;df\&amp;quot;&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
df&lt;br /&gt;
# ----------------------------------------------------------- #&lt;br /&gt;
exec 1&amp;gt;&amp;amp;6 6&amp;gt;&amp;amp;- # Восстановить stdout и закрыть дескр. #6.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;== stdout восстановлено в значение по-умолчанию == &amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
ls -al&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Одновременное перенаправление устройств, stdin и stdout, с помощью команды exec.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# upperconv.sh&lt;br /&gt;
# Преобразование символов во входном файле в верхний регистр.&lt;br /&gt;
E_FILE_ACCESS=70&lt;br /&gt;
E_WRONG_ARGS=71&lt;br /&gt;
if [ ! -r &amp;quot;$1&amp;quot; ] # Файл доступен для чтения?&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Невозможно прочитать из заданного файла!&amp;quot;&lt;br /&gt;
 echo &amp;quot;Порядок использования: $0 input-file output-file&amp;quot;&lt;br /&gt;
 exit $E_FILE_ACCESS&lt;br /&gt;
fi # В случае, если входной файл ($1) не задан код завершения будет этим же.&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$2&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Необходимо задать выходной файл.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Порядок использования: $0 input-file output-file&amp;quot;&lt;br /&gt;
exit $E_WRONG_ARGS&lt;br /&gt;
fi&lt;br /&gt;
exec 4&amp;lt;&amp;amp;0&lt;br /&gt;
exec &amp;lt; $1 # Назначить ввод из входного файла.&lt;br /&gt;
exec 7&amp;gt;&amp;amp;1&lt;br /&gt;
exec &amp;gt; $2 # Назначить вывод в выходной файл.&lt;br /&gt;
          # Предполагается, что выходной файл доступен для записи (добавить проверку?).&lt;br /&gt;
&lt;br /&gt;
# -----------------------------------------------&lt;br /&gt;
  cat - | tr a-z A-Z # Перевод в верхний регистр&lt;br /&gt;
# ^^^^^              # Чтение со stdin.&lt;br /&gt;
#         ^^^^^^^^^^ # Запись в stdout.&lt;br /&gt;
# Однако, и stdin и stdout были перенаправлены.&lt;br /&gt;
# -----------------------------------------------&lt;br /&gt;
exec 1&amp;gt;&amp;amp;7 7&amp;gt;&amp;amp;- # Восстановить stdout.&lt;br /&gt;
exec 0&amp;lt;&amp;amp;4 4&amp;lt;&amp;amp;- # Восстановить stdin.&lt;br /&gt;
&lt;br /&gt;
# После восстановления, следующая строка выводится на stdout, чего и следовало ожидать.&lt;br /&gt;
echo &amp;quot;Символы из \&amp;quot;$1\&amp;quot; преобразованы в верхний регистр, результат записан в \&amp;quot;$2\&amp;quot;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== Перенаправление для блоков кода ===&lt;br /&gt;
Блоки кода, такие как циклы ''while'', ''until'' и ''for'', условный оператор ''if/then'', так же могут смешиваться с перенаправлением ''stdin''. Даже функции могут использовать эту форму перенаправления. Оператор перенаправления '''''&amp;lt;''''', в таких случаях, ставится в конце блока.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление в цикл while.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 Filename=names.data # По-умолчанию, если имя файла не задано.&lt;br /&gt;
else&lt;br /&gt;
 Filename=$1&lt;br /&gt;
fi&lt;br /&gt;
# Конструкцию проверки выше, можно заменить следующей строкой (подстановка параметров):&lt;br /&gt;
# Filename=${1:-names.data}&lt;br /&gt;
&lt;br /&gt;
count=0&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$name&amp;quot; != Smith ] # Почему переменная $name взята в кавычки?&lt;br /&gt;
do&lt;br /&gt;
read name # Чтение из $Filename, не со stdin.&lt;br /&gt;
echo $name&lt;br /&gt;
let &amp;quot;count += 1&amp;quot;&lt;br /&gt;
done &amp;lt;&amp;quot;$Filename&amp;quot; # Перенаправление на ввод из файла $Filename.&lt;br /&gt;
#    ^^^^^^^^^^^^&lt;br /&gt;
&lt;br /&gt;
echo; echo &amp;quot;Имён прочитано: $count&amp;quot;; echo&lt;br /&gt;
# Обратите внимание: в некоторых старых командных интерпретаторах,&lt;br /&gt;
# перенаправление в циклы приводит к запуску цикла в субоболочке (subshell).&lt;br /&gt;
# Таким образом, переменная $count, по окончании цикла, будет содержать 0,&lt;br /&gt;
# значение, записанное в неё до входа в цикл.&lt;br /&gt;
# Bash и ksh стремятся избежать запуска субоболочки (subshell), если это возможно,&lt;br /&gt;
# так что этот сценарий, в этих оболочках, работает корректно.&lt;br /&gt;
#&lt;br /&gt;
# Спасибо Heiner Steven за это примечание.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Альтернативная форма перенаправления в цикле while.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Это альтернативный вариант предыдущего сценария.&lt;br /&gt;
# Предложил: by Heiner Steven&lt;br /&gt;
# для случаев, когда циклы с перенаправлением&lt;br /&gt;
# запускаются в субоболочке, из-за чего переменные, устанавливаемые в цикле,&lt;br /&gt;
# не сохраняют свои значения по завершении цикла.&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 Filename=names.data # По-умолчанию, если имя файла не задано.&lt;br /&gt;
else&lt;br /&gt;
 Filename=$1&lt;br /&gt;
fi&lt;br /&gt;
exec 3&amp;lt;&amp;amp;0 # Сохранить stdin в дескр. 3.&lt;br /&gt;
exec 0&amp;lt;&amp;quot;$Filename&amp;quot; # Перенаправить stdin.&lt;br /&gt;
&lt;br /&gt;
count=0&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$name&amp;quot; != Smith ]&lt;br /&gt;
do&lt;br /&gt;
 read name # Прочитать с перенаправленного stdin ($Filename).&lt;br /&gt;
 echo $name&lt;br /&gt;
 let &amp;quot;count += 1&amp;quot;&lt;br /&gt;
done &amp;lt;&amp;quot;$Filename&amp;quot; # Цикл читает из файла $Filename.&lt;br /&gt;
#    ^^^^^^^^^^^^&lt;br /&gt;
&lt;br /&gt;
exec 0&amp;lt;&amp;amp;3 # Восстановить stdin.&lt;br /&gt;
exec 3&amp;lt;&amp;amp;- # Закрыть временный дескриптор 3.&lt;br /&gt;
echo; echo &amp;quot;Имен прочитано: $count&amp;quot;; echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление в цикл until.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# То же самое, что и в предыдущем примере, только для цикла &amp;quot;until&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 Filename=names.data # По-умолчанию, если файл не задан.&lt;br /&gt;
else&lt;br /&gt;
 Filename=$1&lt;br /&gt;
fi&lt;br /&gt;
# while [ &amp;quot;$name&amp;quot; != Smith ]&lt;br /&gt;
until [ &amp;quot;$name&amp;quot; = Smith ] # Проверка != изменена на =.&lt;br /&gt;
do&lt;br /&gt;
 read name # Чтение из $Filename, не со stdin.&lt;br /&gt;
 echo $name&lt;br /&gt;
done &amp;lt;&amp;quot;$Filename&amp;quot; # Перенаправление на ввод из файла $Filename.&lt;br /&gt;
#    ^^^^^^^^^^^^&lt;br /&gt;
&lt;br /&gt;
# Результаты получаются теми же, что и в случае с циклом &amp;quot;while&amp;quot;, в предыдущем примере.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление в цикл for.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 Filename=names.data # По-умолчанию, если файл не задан.&lt;br /&gt;
else&lt;br /&gt;
 Filename=$1&lt;br /&gt;
fi&lt;br /&gt;
line_count=`wc $Filename | awk '{ print $1 }'`&lt;br /&gt;
#           Число строк в файле.&lt;br /&gt;
# Слишком запутано, тем не менее показывает&lt;br /&gt;
# возможность перенаправления stdin внутри цикла &amp;quot;for&amp;quot;...&lt;br /&gt;
# если вы достаточно умны.&lt;br /&gt;
# Более короткий вариант line_count=$(wc &amp;lt; &amp;quot;$Filename&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
for name in `seq $line_count` # &amp;quot;seq&amp;quot; выводит последовательность чисел.&lt;br /&gt;
# while [ &amp;quot;$name&amp;quot; != Smith ] — более запутанно, чем в случае с циклом &amp;quot;while&amp;quot; &lt;br /&gt;
do&lt;br /&gt;
 read name # Чтение из файла $Filename, не со stdin.&lt;br /&gt;
 echo $name&lt;br /&gt;
 if [ &amp;quot;$name&amp;quot; = Smith ]&lt;br /&gt;
 then&lt;br /&gt;
  break&lt;br /&gt;
 fi&lt;br /&gt;
done &amp;lt;&amp;quot;$Filename&amp;quot; # Перенаправление на ввод из файла $Filename.&lt;br /&gt;
#    ^^^^^^^^^^^^&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Предыдущий пример можно модифицировать так, чтобы перенаправить вывод из цикла.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление устройств (stdin и stdout) в цикле for.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 Filename=names.data # По-умолчанию, если файл не задан.&lt;br /&gt;
else&lt;br /&gt;
 Filename=$1&lt;br /&gt;
fi&lt;br /&gt;
Savefile=$Filename.new # Имя файла, в котором сохраняются результаты.&lt;br /&gt;
FinalName=Jonah # Имя, на котором завершается чтение.&lt;br /&gt;
&lt;br /&gt;
line_count=`wc $Filename | awk '{ print $1 }'` # Число строк в заданном файле.&lt;br /&gt;
&lt;br /&gt;
for name in `seq $line_count`&lt;br /&gt;
do&lt;br /&gt;
 read name&lt;br /&gt;
 echo &amp;quot;$name&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$name&amp;quot; = &amp;quot;$FinalName&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  break&lt;br /&gt;
 fi&lt;br /&gt;
done &amp;lt; &amp;quot;$Filename&amp;quot; &amp;gt; &amp;quot;$Savefile&amp;quot; # Перенаправление на ввод из файла $Filename,&lt;br /&gt;
#    ^^^^^^^^^^^^^^^^^^^^^^^^^^^ и сохранение результатов в файле.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Перенаправление в конструкции if/then.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 Filename=names.data # По-умолчанию, если файл не задан.&lt;br /&gt;
else&lt;br /&gt;
 Filename=$1&lt;br /&gt;
fi&lt;br /&gt;
TRUE=1&lt;br /&gt;
if [ &amp;quot;$TRUE&amp;quot; ] # конструкции &amp;quot;if true&amp;quot; и &amp;quot;if :&amp;quot; тоже вполне допустимы.&lt;br /&gt;
then&lt;br /&gt;
 read name&lt;br /&gt;
 echo $name&lt;br /&gt;
fi &amp;lt;&amp;quot;$Filename&amp;quot;&lt;br /&gt;
#  ^^^^^^^^^^^^&lt;br /&gt;
# Читает только первую строку из файла.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Файл с именами &amp;quot;names.data&amp;quot;, для примеров выше.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Aristotle&lt;br /&gt;
Belisarius&lt;br /&gt;
Capablanca&lt;br /&gt;
Euler&lt;br /&gt;
Goethe&lt;br /&gt;
Hamurabi&lt;br /&gt;
Jonah&lt;br /&gt;
Laplace&lt;br /&gt;
Maroczy&lt;br /&gt;
Purcell&lt;br /&gt;
Schmidt&lt;br /&gt;
Semmelweiss&lt;br /&gt;
Smith&lt;br /&gt;
Turing&lt;br /&gt;
Venn&lt;br /&gt;
Wilson&lt;br /&gt;
Znosko-Borowski&lt;br /&gt;
# Это файл с именами для примеров&lt;br /&gt;
# &amp;quot;redir2.sh&amp;quot;, &amp;quot;redir3.sh&amp;quot;, &amp;quot;redir4.sh&amp;quot;, &amp;quot;redir4a.sh&amp;quot;, &amp;quot;redir5.sh&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Перенаправление ''stdout'' для блока кода, может использоваться для сохранения результатов работы этого блока в файл.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Встроенный документ&amp;lt;/span&amp;gt; — это особая форма перенаправления для блоков кода.&lt;br /&gt;
=== Область применения ===&lt;br /&gt;
Как один из вариантов грамотного применения перенаправления ввода/вывода, можно назвать разбор и &amp;quot;сшивание&amp;quot; вывода от команд. Это позволяет создавать файлы отчетов и журналов регистрации событий.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Регистрация событий.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# logevents.sh, автор: Stephane Chazelas.&lt;br /&gt;
# Регистрация событий в файле.&lt;br /&gt;
# Сценарий должен запускаться с привилегиями root (что бы иметь право на запись в /var/log).&lt;br /&gt;
&lt;br /&gt;
ROOT_UID=0 # Привилегии root имеет только пользователь с $UID = 0.&lt;br /&gt;
E_NOTROOT=67 # Код завершения, если не root.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Сценарий должен запускаться с привилегиями root.&amp;quot;&lt;br /&gt;
 exit $E_NOTROOT&lt;br /&gt;
fi&lt;br /&gt;
FD_DEBUG1=3&lt;br /&gt;
FD_DEBUG2=4&lt;br /&gt;
FD_DEBUG3=5&lt;br /&gt;
&lt;br /&gt;
# Раскомментируйте одну из двух строк, ниже, для активизации сценария.&lt;br /&gt;
# LOG_EVENTS=1&lt;br /&gt;
# LOG_VARS=1log() # Запись даты и времени в файл.&lt;br /&gt;
&lt;br /&gt;
log() # Запись даты и времени в файл.&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;$(date) $*&amp;quot; &amp;gt;&amp;amp;7 # Добавляет в конец файла.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
case $LOG_LEVEL in&lt;br /&gt;
 1) exec 3&amp;gt;&amp;amp;2 4&amp;gt; /dev/null 5&amp;gt; /dev/null;;&lt;br /&gt;
 2) exec 3&amp;gt;&amp;amp;2 4&amp;gt;&amp;amp;2 5&amp;gt; /dev/null;;&lt;br /&gt;
 3) exec 3&amp;gt;&amp;amp;2 4&amp;gt;&amp;amp;2 5&amp;gt;&amp;amp;2;;&lt;br /&gt;
 *) exec 3&amp;gt; /dev/null 4&amp;gt; /dev/null 5&amp;gt; /dev/null;;&lt;br /&gt;
esac&lt;br /&gt;
FD_LOGVARS=6&lt;br /&gt;
if [[ $LOG_VARS ]]&lt;br /&gt;
then exec 6&amp;gt;&amp;gt; /var/log/vars.log&lt;br /&gt;
else exec 6&amp;gt; /dev/null # Подавить вывод.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
FD_LOGEVENTS=7&lt;br /&gt;
if [[ $LOG_EVENTS ]]&lt;br /&gt;
then&lt;br /&gt;
 # then exec 7 &amp;gt;(exec gawk '{print strftime(), $0}' &amp;gt;&amp;gt; /var/log/event.log)&lt;br /&gt;
 # Строка, выше, не работает в Bash, версии 2.04.&lt;br /&gt;
 exec 7&amp;gt;&amp;gt; /var/log/event.log # Добавление в конец &amp;quot;event.log&amp;quot;.&lt;br /&gt;
 log # Записать дату и время.&lt;br /&gt;
 else exec 7&amp;gt; /dev/null # Подавить вывод.&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;DEBUG3: beginning&amp;quot; &amp;gt;&amp;amp;${FD_DEBUG3}&lt;br /&gt;
ls -l &amp;gt;&amp;amp;5 2&amp;gt;&amp;amp;4 # command1 &amp;gt;&amp;amp;5 2&amp;gt;&amp;amp;4&lt;br /&gt;
echo &amp;quot;Done&amp;quot; # command2&lt;br /&gt;
echo &amp;quot;sending mail&amp;quot; &amp;gt;&amp;amp;${FD_LOGEVENTS} # Написать &amp;quot;sending mail&amp;quot; в дескр. #7.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Встроенные документы ==&lt;br /&gt;
''Встроенный документ'' (here document) является специальной формой перенаправления ввода/вывода, которая позволяет передать список команд интерактивной программе или команде, например '''''ftp''''', '''''telnet''''' или '''''ex'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
COMMAND &amp;lt;&amp;lt;InputComesFromHERE&lt;br /&gt;
...&lt;br /&gt;
InputComesFromHERE&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конец встроенного документа выделяется &amp;quot;строкой-ограничителем&amp;quot;, которая задается с помощью специальной последовательности символов &amp;lt;&amp;lt;. Эта последовательность — есть перенаправление вывода из файла на ''stdin'' программы или команды, что напоминает конструкцию '''''interactive-program&amp;lt; command-file''''', где ''command-file'' содержит строки:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
command #1&lt;br /&gt;
command #2&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сценарий, использующий &amp;quot;встроенный документ&amp;quot; для тех же целей, может выглядеть примерно так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
interactive-program &amp;lt;&amp;lt;LimitString&lt;br /&gt;
command #1&lt;br /&gt;
command #2&lt;br /&gt;
...&lt;br /&gt;
LimitString&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В качестве строки-ограничителя должна выбираться такая последовательность символов, которая не будет встречаться в теле &amp;quot;встроенного документа&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание: использование встроенных документов может иногда с успехом применяться и при работе с неинтерактивными командами и утилитами.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''dummyfile: Создание 2-х строчного файла-заготовки.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Неинтерактивное редактирование файла с помощью 'vi'.&lt;br /&gt;
# Эмуляция 'sed'.&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
TARGETFILE=$1&lt;br /&gt;
# Вставить 2 строки в файл и сохранить.&lt;br /&gt;
#--------Начало встроенного документа-----------#&lt;br /&gt;
vi $TARGETFILE &amp;lt;&amp;lt;x23LimitStringx23&lt;br /&gt;
i&lt;br /&gt;
Это строка 1.&lt;br /&gt;
Это строка 2.&lt;br /&gt;
^[&lt;br /&gt;
ZZ&lt;br /&gt;
x23LimitStringx23&lt;br /&gt;
#----------Конец встроенного документа-----------#&lt;br /&gt;
# Обратите внимание: ^[, выше — это escape-символ Control-V &amp;lt;Esc&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
# Bram Moolenaar указывает, что этот скрипт может не работать с 'vim',&lt;br /&gt;
# из-за возможных проблем взаимодействия с терминалом.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Этот сценарий, с тем же эффектом, мог бы быть реализован, основываясь не на '''''vi''''', а на '''''ex'''''. Встроенные документы, содержащие команды для '''''ex''''', стали настолько обычным делом, что их уже смело можно вынести в отдельную категорию — ''ex-сценарии''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''broadcast: Передача сообщения всем, работающим в системе,пользователям.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
wall &amp;lt;&amp;lt;zzz23EndOfMessagezzz23&lt;br /&gt;
Пошлите, по электронной почте, ваш заказ на пиццу, системному администратору.&lt;br /&gt;
(Добавьте дополнительный доллар, если вы желаете положить на пиццу анчоусы или грибы.)&lt;br /&gt;
# Внимание: строки комментария тоже будут переданы команде 'wall' как часть текста.&lt;br /&gt;
zzz23EndOfMessagezzz23&lt;br /&gt;
&lt;br /&gt;
# Возможно, более эффективно это может быть сделано так:&lt;br /&gt;
# wall &amp;lt;message-file&lt;br /&gt;
# Однако, встроенный документ помогает сэкономить ваши силы и время.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вывод многострочных сообщений с помощью cat.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Команда 'echo' прекрасно справляется с выводом однострочных сообщений,&lt;br /&gt;
# но иногда необходимо вывести несколько строк.&lt;br /&gt;
# Команда 'cat' и встроенный документ помогут вам в этом.&lt;br /&gt;
cat &amp;lt;&amp;lt;End-of-message&lt;br /&gt;
-------------------------------------&lt;br /&gt;
Это первая строка сообщения.&lt;br /&gt;
Это вторая строка сообщения.&lt;br /&gt;
Это третья строка сообщения.&lt;br /&gt;
Это четвертая строка сообщения.&lt;br /&gt;
Это последняя строка сообщения.&lt;br /&gt;
-------------------------------------&lt;br /&gt;
End-of-message&lt;br /&gt;
exit 0&lt;br /&gt;
#--------------------------------------------&lt;br /&gt;
# Команда &amp;quot;exit 0&amp;quot;, выше, не позволить исполнить нижележащие строки.&lt;br /&gt;
# S.C. отмечает, что следующий код работает точно так же.&lt;br /&gt;
echo &amp;quot;-------------------------------------&lt;br /&gt;
Это первая строка сообщения.&lt;br /&gt;
Это вторая строка сообщения.&lt;br /&gt;
Это третья строка сообщения.&lt;br /&gt;
Это четвертая строка сообщения.&lt;br /&gt;
Это последняя строка сообщения.&lt;br /&gt;
-------------------------------------&amp;quot;&lt;br /&gt;
# Однако, в этом случае, двойные кавычки в теле сообщения, должны экранироваться.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если строка-ограничитель встроенного документа начинается с символа '''-''' (&amp;lt;&amp;lt;-LimitString), то это приводит к подавлению вывода ведущих (начальных) символов табуляции (но не пробелов). Это может оказаться полезным при форматировании текста сценария для большей удобочитаемости.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вывод многострочных сообщений с подавлением символов табуляции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# То же, что и предыдущий сценарий, но...&lt;br /&gt;
# Символ &amp;quot;-&amp;quot;, начинающий строку-ограничитель встроенного документа: &amp;lt;&amp;lt;-&lt;br /&gt;
# подавляет вывод символов табуляции, которые могут встречаться в теле документа,&lt;br /&gt;
# но не пробелов.&lt;br /&gt;
&lt;br /&gt;
cat &amp;lt;&amp;lt;-ENDOFMESSAGE&lt;br /&gt;
        Это первая строка сообщения.&lt;br /&gt;
        Это вторая строка сообщения.&lt;br /&gt;
        Это третья строка сообщения.&lt;br /&gt;
        Это четвертая строка сообщения.&lt;br /&gt;
        Это последняя строка сообщения.&lt;br /&gt;
ENDOFMESSAGE&lt;br /&gt;
# Текст, выводимый сценарием, будет смещен влево.&lt;br /&gt;
# Ведущие символы табуляции не будут выводиться.&lt;br /&gt;
&lt;br /&gt;
# Вышеприведённые 5 строк текста &amp;quot;сообщения&amp;quot; начинаются с табуляции, а не с пробелов.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Встроенные документы поддерживают подстановку команд и параметров. Что позволяет передавать различные параметры в тело встроенного документа.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Встроенные документы и подстановка параметров.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Вывод встроенного документа командой 'cat', с использованием подстановки параметров.&lt;br /&gt;
# Попробуйте запустить сценарий без аргументов, ./scriptname&lt;br /&gt;
# Попробуйте запустить сценарий с одним аргументом, ./scriptname Mortimer&lt;br /&gt;
# Попробуйте запустить сценарий с одним аргументом, из двух слов, в кавычках,&lt;br /&gt;
#         ./scriptname &amp;quot;Mortimer Jones&amp;quot;&lt;br /&gt;
&lt;br /&gt;
CMDLINEPARAM=1 # Минимальное число аргументов командной строки.&lt;br /&gt;
&lt;br /&gt;
if [ $# -ge $CMDLINEPARAM ]&lt;br /&gt;
then&lt;br /&gt;
 NAME=$1 # Если аргументов больше одного,&lt;br /&gt;
         # то рассматривается только первый.&lt;br /&gt;
else&lt;br /&gt;
 NAME=&amp;quot;John Doe&amp;quot; # По-умолчанию, если сценарий запущен без аргументов.&lt;br /&gt;
fi&lt;br /&gt;
RESPONDENT=&amp;quot;автора этого сценария&amp;quot;&lt;br /&gt;
&lt;br /&gt;
cat &amp;lt;&amp;lt;Endofmessage&lt;br /&gt;
Привет, $NAME!&lt;br /&gt;
Примите поздравления от $RESPONDENT.&lt;br /&gt;
# Этот комментарий тоже выводится (почему?).&lt;br /&gt;
Endofmessage&lt;br /&gt;
# Обратите внимание на то, что пустые строки тоже выводятся.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё один пример сценария, содержащего встроенный документ и подстановку параметров в его теле.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача пары файлов во входящий каталог на &amp;quot;Sunsite&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# upload.sh&lt;br /&gt;
# Передача пары файлов (Filename.lsm, Filename.tar.gz)&lt;br /&gt;
# на Sunsite (ibiblio.org).&lt;br /&gt;
&lt;br /&gt;
E_ARGERROR=65&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` filename&amp;quot;&lt;br /&gt;
 exit $E_ARGERROR&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
Filename=`basename $1` # Отсечь имя файла от пути к нему.&lt;br /&gt;
Server=&amp;quot;ibiblio.org&amp;quot;&lt;br /&gt;
Directory=&amp;quot;/incoming/Linux&amp;quot;&lt;br /&gt;
# Вообще, эти строки должны бы не &amp;quot;зашиваться&amp;quot; жёстко в сценарий,&lt;br /&gt;
# а приниматься в виде аргумента из командной строки.&lt;br /&gt;
&lt;br /&gt;
Password=&amp;quot;your.e-mail.address&amp;quot; # Измените на свой.&lt;br /&gt;
ftp -n $Server &amp;lt;&amp;lt;End-Of-Session&lt;br /&gt;
# Ключ -n запрещает автоматическую регистрацию (auto-logon)&lt;br /&gt;
&lt;br /&gt;
user anonymous &amp;quot;$Password&amp;quot;&lt;br /&gt;
binary&lt;br /&gt;
bell # &amp;quot;Звякнуть&amp;quot; после передачи каждого файла&lt;br /&gt;
cd $Directory&lt;br /&gt;
put &amp;quot;$Filename.lsm&amp;quot;&lt;br /&gt;
put &amp;quot;$Filename.tar.gz&amp;quot;&lt;br /&gt;
bye&lt;br /&gt;
End-Of-Session&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Заключая строку-ограничитель в кавычки или экранируя её, можно запретить подстановку параметров в теле встроенного документа.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Отключение подстановки параметров.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Вывод встроенного документа командой 'cat', с запретом подстановки параметров.&lt;br /&gt;
&lt;br /&gt;
NAME=&amp;quot;John Doe&amp;quot;&lt;br /&gt;
RESPONDENT=&amp;quot;автора этого сценария&amp;quot;&lt;br /&gt;
&lt;br /&gt;
cat &amp;lt;&amp;lt;'Endofmessage'&lt;br /&gt;
&lt;br /&gt;
Привет, $NAME.&lt;br /&gt;
Примите поздравления от $RESPONDENT.&lt;br /&gt;
Endofmessage&lt;br /&gt;
# Подстановка параметров не производится, если строка ограничитель заключена в кавычки или экранирована.&lt;br /&gt;
# Тот же эффект дают:&lt;br /&gt;
# cat &amp;lt;&amp;lt;&amp;quot;Endofmessage&amp;quot;&lt;br /&gt;
# cat &amp;lt;&amp;lt;\Endofmessage&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Запрет на подстановку параметров позволяет выводить текст, как говорится, &amp;quot;один к одному&amp;quot;. Это обстоятельство может использоваться, например, для автоматической генерации сценариев или даже текстов программ на других языках программирования.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий, который создаёт другой сценарий.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# generate-script.sh&lt;br /&gt;
# Автор идеи: Albert Reiner.&lt;br /&gt;
OUTFILE=generated.sh # Имя нового сценария.&lt;br /&gt;
&lt;br /&gt;
# -----------------------------------------------------------&lt;br /&gt;
# 'Встроенный документ' содержит тело создаваемого сценария.&lt;br /&gt;
(&lt;br /&gt;
cat &amp;lt;&amp;lt;'EOF'&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Этот сценарий сгенерирован автоматически.&amp;quot;&lt;br /&gt;
# Обратите внимание: поскольку действия происходят в подоболочке,&lt;br /&gt;
# мы не можем получить доступ к переменным родительской оболочки.&lt;br /&gt;
# Удостоверимся в этом...&lt;br /&gt;
echo &amp;quot;Файл сценария был назван: $OUTFILE&amp;quot; # Не работает.&lt;br /&gt;
a=7&lt;br /&gt;
b=3&lt;br /&gt;
let &amp;quot;c = $a * $b&amp;quot;&lt;br /&gt;
echo &amp;quot;c = $c&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
EOF&lt;br /&gt;
) &amp;gt; $OUTFILE&lt;br /&gt;
# -----------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
# Заключение 'строки-ограничителя' предотвращает подстановку значений переменных в теле 'встроенного документа.'&lt;br /&gt;
# Что позволяет записать все строки в выходной файл &amp;quot;один к одному&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
if [ -f &amp;quot;$OUTFILE&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 chmod 755 $OUTFILE&lt;br /&gt;
 # Дать право на исполнение.&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Не могу создать файл: \&amp;quot;$OUTFILE\&amp;quot;&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Этот метод можно использовать для создания Makefile-ов, программ на языках C, Perl, Python и т.п.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Допускается запись тела встроенного документа в переменную.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
variable=$(cat &amp;lt;&amp;lt;SETVAR&lt;br /&gt;
Это многострочная переменная.&lt;br /&gt;
SETVAR)&lt;br /&gt;
echo &amp;quot;$variable&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Встроенные документы могут передаваться на вход функции, находящейся в том же сценарии.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Встроенные документы и функции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# here-function.sh&lt;br /&gt;
GetPersonalData ()&lt;br /&gt;
{&lt;br /&gt;
 read firstname&lt;br /&gt;
 read lastname&lt;br /&gt;
 read address&lt;br /&gt;
 read city&lt;br /&gt;
 read state&lt;br /&gt;
 read zipcode&lt;br /&gt;
} # Это немного напоминает интерактивную функцию, но...&lt;br /&gt;
&lt;br /&gt;
# Передать ввод в функцию.&lt;br /&gt;
GetPersonalData &amp;lt;&amp;lt;RECORD001&lt;br /&gt;
Bozo&lt;br /&gt;
Bozeman&lt;br /&gt;
2726 &lt;br /&gt;
Nondescript Dr.&lt;br /&gt;
Baltimore&lt;br /&gt;
MD&lt;br /&gt;
21226&lt;br /&gt;
RECORD001&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;$firstname $lastname&amp;quot;&lt;br /&gt;
echo &amp;quot;$address&amp;quot;&lt;br /&gt;
echo &amp;quot;$city, $state $zipcode&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Встроенный документ можно передать &amp;quot;пустой команде&amp;quot; :. Такая конструкция, фактически, создаёт &amp;quot;анонимный&amp;quot; встроенный документ.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;quot;Анонимный&amp;quot; встроенный документ.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
: &amp;lt;&amp;lt;TESTVARIABLES${HOSTNAME?}${USER?}${MAIL?} # Если одна из переменных не определена, то выводится сообщение об ошибке.&lt;br /&gt;
TESTVARIABLES&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подобную технику можно использовать для создания &amp;quot;блочных комментариев&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Блочный комментарий.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# commentblock.sh&lt;br /&gt;
: &amp;lt;&amp;lt; COMMENTBLOCK&lt;br /&gt;
echo &amp;quot;Эта строка не будет выведена.&amp;quot;&lt;br /&gt;
Эта строка комментария не начинается с символа &amp;quot;#&amp;quot;.&lt;br /&gt;
Это ещё одна строка комментария, которая начинается не с символа &amp;quot;#&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;*@!!++=&lt;br /&gt;
Эта строка не вызовет ошибки,&lt;br /&gt;
поскольку Bash проигнорирует её.&lt;br /&gt;
COMMENTBLOCK&lt;br /&gt;
echo &amp;quot;Код завершения \&amp;quot;COMMENTBLOCK\&amp;quot; = $?.&amp;quot; # 0&lt;br /&gt;
# Показывает, что ошибок не возникало.&lt;br /&gt;
&lt;br /&gt;
# Такая методика создания блочных комментариев может использоваться для комментирования блоков кода во время отладки.&lt;br /&gt;
# Это экономит силы и время, т.к. не нужно вставлять символ &amp;quot;#&amp;quot; в начале каждой строки, а затем удалять их.&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;&amp;lt; DEBUGXXX&lt;br /&gt;
for file in *&lt;br /&gt;
do&lt;br /&gt;
 cat &amp;quot;$file&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
DEBUGXXX&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё одно остроумное применение встроенных документов — встроенная справка к сценарию.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Встроенная справка к сценарию.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# self-document.sh: сценарий со встроенной справкой&lt;br /&gt;
# Модификация сценария &amp;quot;colm.sh&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
DOC_REQUEST=70&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; = &amp;quot;-h&amp;quot; -o &amp;quot;$1&amp;quot; = &amp;quot;--help&amp;quot; ] # Request help.&lt;br /&gt;
then&lt;br /&gt;
 echo; echo &amp;quot;Порядок использования: $0 [directory-name]&amp;quot;; echo&lt;br /&gt;
 sed --silent -e '/DOCUMENTATIONXX$/,/^DOCUMENTATION/p' &amp;quot;$0&amp;quot; |&lt;br /&gt;
 sed -e '/DOCUMENTATIONXX/d'; exit $DOC_REQUEST; fi&lt;br /&gt;
: &amp;lt;&amp;lt; DOCUMENTATIONXX&lt;br /&gt;
Сценарий выводит сведения о заданном каталоге в виде таблице.&lt;br /&gt;
-------------------------------------------------------------&lt;br /&gt;
Сценарию необходимо передать имя каталога. Если каталог неуказан или он недоступен для чтения, то выводятся сведения о текущем каталоге.&lt;br /&gt;
DOCUMENTATIONXX&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; -o ! -r &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 directory=.&lt;br /&gt;
else&lt;br /&gt;
 directory=&amp;quot;$1&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;Сведения о каталоге &amp;quot;$directory&amp;quot;:&amp;quot;; echo&lt;br /&gt;
(printf &amp;quot;PERMISSIONS LINKS OWNER GROUP SIZE MONTH DAY HH:MM PROG-NAME\n&amp;quot; \&lt;br /&gt;
; ls -l &amp;quot;$directory&amp;quot; | sed 1d) | column -t&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для встроенных документов, во время исполнения, создаются временные файлы, но эти файлыудаляются после открытия и недоступны для других процессов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ bash -c 'lsof -a -p $$ -d0' &amp;lt;&amp;lt; EOF&lt;br /&gt;
&amp;gt; EOF&lt;br /&gt;
lsof 1213 bozo 0r REG 3,5 0 30386 /tmp/t1213-0-sh (deleted)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Некоторые утилиты не могут работать внутри встроенных документов. Строка-ограничитель, закрывающая встроенный документ, должна начинаться с первого символа в строке. Перед ней не должно быть пробельных символов. Аналогично, пробельные символы, стоящие за строкой-ограничителем, могут дать нежелательные побочные эффекты.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo &amp;quot;----------------------------------------------------------------------&amp;quot;&lt;br /&gt;
cat &amp;lt;&amp;lt;LimitString&lt;br /&gt;
echo &amp;quot;Это первая строка сообщения во встроенном документе.&amp;quot;&lt;br /&gt;
echo &amp;quot;Это вторая строка сообщения во встроенном документе.&amp;quot;&lt;br /&gt;
echo &amp;quot;Это последняя строка сообщения во встроенном документе.&amp;quot;&lt;br /&gt;
     LimitString&lt;br /&gt;
#^^^^Отступ перед строкой-ограничителем. Ошибка!&lt;br /&gt;
#    Этот сценарий будет вести себя не так как вы ожидаете.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;----------------------------------------------------------------------&amp;quot;&lt;br /&gt;
# &amp;quot;Этот комментарий находится за пределами 'встроенного документа', и не должен выводиться.&lt;br /&gt;
echo &amp;quot;За пределами встроенного документа.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Держу пари, что эта строка не будет выведена.&amp;quot; # Стоит после команды 'exit'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если какая-либо задача не может быть решена с помощью &amp;quot;встроенного документа&amp;quot;, то вам следует попробовать язык сценариев '''''expect''''', который приспособлен для передачи параметров на вход интерактивных программ.&lt;br /&gt;
&lt;br /&gt;
= Часть четвёртая. Материал повышенной сложности =&lt;br /&gt;
Итак, мы вплотную подошли к изучению очень сложных и необычных аспектов написания сценариев. В этой части мы попытаемся &amp;quot;'''сбросить покров тайны'''&amp;quot; и заглянуть за пределы известного нам мира(представьте себе путешествие по территории, не отмеченной на карте).&lt;br /&gt;
== Регулярные выражения ==&lt;br /&gt;
Для того, чтобы полностью реализовать потенциал командной оболочки, вам придётся овладеть ''Регулярными Выражениями''. Многие команды и утилиты, обычно используемые в сценариях, такие как [[grep]], [[expr]], [[sed]] и [[awk]], используют ''Регулярные Выражения''.&lt;br /&gt;
=== Краткое введение в регулярные выражения ===&lt;br /&gt;
Выражение — это строка символов. Символы, которые имеют особое назначение, называются '''''метасимволами'''''. Так, например, кавычки могут выделять прямую речь, т.е. быть метасимволами для строки, заключенной в эти кавычки. '''''Регулярные выражения''''' — это набор символов и/или метасимволов, которые наделены особыми свойствами.&amp;lt;br /&amp;gt;&lt;br /&gt;
Основное назначение регулярных выражений — это поиск текста по шаблону и работа со строками.&amp;lt;br /&amp;gt;&lt;br /&gt;
* Звёздочка — &amp;lt;big&amp;gt;'''''*'''''&amp;lt;/big&amp;gt; — означает любое количество символов в строке, предшествующих &amp;quot;звёздочке&amp;quot;, в том числе и нулевое число символов. &lt;br /&gt;
:Выражение ''&amp;quot;113*&amp;quot;'' — означает ''11 + один или более символов &amp;quot;3&amp;quot; + любые другие символы: 113,1133, 113312'', и так далее.&lt;br /&gt;
* Точка —&amp;lt;big&amp;gt;''''' . '''''&amp;lt;/big&amp;gt; — означает не менее одного любого символа, за исключением символа перевода строки — '''\n'''. &lt;br /&gt;
:Выражение &amp;quot;''13.''&amp;quot; будет означать ''13 + по меньшей мере один любой символ (включая пробел): 1133,11333 и т.д.'', но не ''13'' (отсутствуют дополнительные символы).&lt;br /&gt;
* Символ —'''''&amp;lt;big&amp;gt; ^ &amp;lt;/big&amp;gt;'''''— означает начало строки, но иногда, в зависимости от контекста, означает отрицание в регулярных выражениях.&lt;br /&gt;
* Знак доллара —'''''&amp;lt;big&amp;gt; $ &amp;lt;/big&amp;gt;'''''— в конце регулярного выражения соответствует концу строки.&lt;br /&gt;
:Выражение &amp;quot;'''''^$'''''&amp;quot; соответствует пустой строке.&lt;br /&gt;
* Квадратные скобки —'''''&amp;lt;big&amp;gt; [...] &amp;lt;/big&amp;gt;''''' — предназначены для задания подмножества символов. Квадратные скобки, внутри регулярного выражения, считаются одним символом, который может принимать значения, перечисленные внутри этих скобок.&lt;br /&gt;
:Выражение &amp;quot;'''''[xyz]'''''&amp;quot; — соответствует одному из символов '''x''', '''y''' или '''z'''.&lt;br /&gt;
:Выражение &amp;quot;'''''[c-n]'''''&amp;quot; соответствует одному из символов в диапазоне от '''c''' до '''n''', включительно.&lt;br /&gt;
:Выражение &amp;quot;'''''[B-Pk-y]'''''&amp;quot; соответствует одному из символов в диапазоне от '''B''' до '''P''' или в диапазоне от '''k''' до '''y''', включительно.&lt;br /&gt;
:Выражение &amp;quot;'''''[a-z0-9]'''''&amp;quot; соответствует одному из символов латиницы в нижнем регистре или цифре.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Выражение &amp;quot;'''''[^b-d]'''''&amp;quot; соответствует любому символу, кроме символов из диапазона от '''b''' до '''d''', включительно. В данном случае, метасимвол '''^''' означает отрицание.&lt;br /&gt;
Объединяя квадратные скобки в одну последовательность, можно задать шаблон искомого слова. &lt;br /&gt;
:Так, выражение &amp;quot;'''''[Yy][Ee][Ss]'''''&amp;quot; соответствует словам '''yes''', '''Yes''', '''YES''', '''yEs''' и так далее. &lt;br /&gt;
:Выражение &amp;quot;'''''[0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9][0-9][0-9]'''''&amp;quot; определяет шаблон для поиска любого номера карточки социального страхования (для США).&lt;br /&gt;
* Обратный слэш —'''''&amp;lt;big&amp;gt; \ &amp;lt;/big&amp;gt;''''' — служит для экранирования специальных символов, это означает, что экранированные символы должны интерпретироваться буквально, т.е. как простые символы.&lt;br /&gt;
:Комбинация &amp;quot;'''''\$'''''&amp;quot; указывает на то, что символ &amp;quot;'''$'''&amp;quot; трактуется как обычный символ, а не как признак конца строки в регулярных выражениях. Аналогично, комбинация &amp;quot;'''''\\'''''&amp;quot; соответствует простому символу &amp;quot;'''\'''&amp;quot;.&lt;br /&gt;
* Экранированные &amp;quot;угловые скобки&amp;quot; —'''''&amp;lt;big&amp;gt; \&amp;lt;...\&amp;gt; &amp;lt;/big&amp;gt;''''' — отмечают границы слова.&lt;br /&gt;
:Угловые скобки должны экранироваться, иначе они будут интерпретироваться как простые символы.&lt;br /&gt;
:Выражение &amp;quot;'''''\&amp;lt;the\&amp;gt;'''''&amp;quot; соответствует слову &amp;quot;'''the'''&amp;quot;, и не соответствует словам &amp;quot;'''them'''&amp;quot;, &amp;quot;'''there'''&amp;quot;, &amp;quot;'''other'''&amp;quot; и т.п.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat textfile&lt;br /&gt;
This is line 1, of which there is only one instance.&lt;br /&gt;
This is the only instance of line 2.&lt;br /&gt;
This is line 3, another line.&lt;br /&gt;
This is line 4.&lt;br /&gt;
&lt;br /&gt;
bash$ grep 'the' textfile&lt;br /&gt;
This is line 1, of which there is only one instance.&lt;br /&gt;
This is the only instance of line 2.&lt;br /&gt;
This is line 3, another line.&lt;br /&gt;
&lt;br /&gt;
bash$ grep '\&amp;lt;the\&amp;gt;' textfile&lt;br /&gt;
This is the only instance of line 2.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Дополнительные метасимволы'''. Использующиеся при работе с [[egrep]], [[awk]] и '''Perl'''&lt;br /&gt;
* Знак вопроса —'''''&amp;lt;big&amp;gt; ? &amp;lt;/big&amp;gt;''''' — означает, что предыдущий символ или регулярное выражение встречается 0 или 1 раз. В основном используется для поиска одиночных символов.&lt;br /&gt;
* Знак &amp;quot;плюс&amp;quot; —'''''&amp;lt;big&amp;gt; + &amp;lt;/big&amp;gt;''''' — указывает на то, что предыдущий символ или выражение встречается 1 или более раз. Играет ту же роль, что и символ &amp;quot;звёздочка&amp;quot; ('''*'''), за исключением случая нулевого количества вхождений.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# GNU версии sed и awk допускают использование &amp;quot;+&amp;quot;, но его необходимо экранировать.&lt;br /&gt;
&lt;br /&gt;
echo a111b | sed -ne '/a1\+b/p'&lt;br /&gt;
echo a111b | grep 'a1\+b'&lt;br /&gt;
echo a111b | gawk '/a1+b/'&lt;br /&gt;
# Все три варианта эквивалентны.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* Экранированные &amp;quot;фигурные скобки&amp;quot; —'''''&amp;lt;big&amp;gt; \{ \} &amp;lt;/big&amp;gt;''''' — задают число вхождений предыдущего выражения.&lt;br /&gt;
:Экранирование фигурных скобок — обязательное условие, иначе они будут интерпретироваться как простые символы. Такой порядок использования, технически, не является частью основного набора правил построения регулярных выражений.&lt;br /&gt;
:Выражение &amp;quot;'''''[0-9]\{5\}'''''&amp;quot; — в точности соответствует подстроке из пяти десятичных цифр(символов из диапазона от '''0''' до '''9''', включительно).&lt;br /&gt;
В &amp;quot;классической&amp;quot; (не совместимой с POSIX) версии [[awk]], фигурные скобки не могут быть использованы. Однако, в [[gawk]] предусмотрен ключ ''--re-interval'', который позволяет использовать (неэкранированные) фигурные скобки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo 2222 | gawk --re-interval '/2{3}/'&lt;br /&gt;
2222&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Язык программирования '''Perl''' и некоторые версии [[egrep]] не требуют экранирования фигурных скобок.&lt;br /&gt;
* Круглые скобки —'''''&amp;lt;big&amp;gt; ( ) &amp;lt;/big&amp;gt;''''' — предназначены для выделения групп регулярных выражений. Они полезны при использовании с оператором &amp;quot;'''|'''&amp;quot; и при извлечении подстроки с помощью команды '''''expr'''''.&lt;br /&gt;
* Вертикальная черта —'''''&amp;lt;big&amp;gt; | &amp;lt;/big&amp;gt;''''' — выполняет роль логического оператора &amp;quot;ИЛИ&amp;quot; в регулярных выражениях и служит для задания набора альтернатив.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ egrep 're(a|e)d' misc.txt&lt;br /&gt;
People who read seem to be better informed than those who do not.&lt;br /&gt;
The clarinet produces sound by the vibration of its reed.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Некоторые версии [[sed]], '''''ed''''' и '''''ex''''' поддерживают экранированные версии регулярных выражений, описанные выше.&lt;br /&gt;
&lt;br /&gt;
'''Классы символов POSIX'''. [:class:]&amp;lt;br /&amp;gt;&lt;br /&gt;
Это ''альтернативный способ'' указания диапазона символов.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:alnum:]&amp;lt;/big&amp;gt;''''' — соответствует алфавитным символам и цифрам. Эквивалентно выражению '''''A-Za-z0-9'''''.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:alpha:]&amp;lt;/big&amp;gt;''''' — соответствует символам алфавита. Эквивалентно выражению '''''A-Za-z'''''.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:blank:]&amp;lt;/big&amp;gt;''''' — соответствует символу пробела или символу табуляции.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:cntrl:]&amp;lt;/big&amp;gt;''''' — соответствует управляющим символам (control characters).&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:digit:]&amp;lt;/big&amp;gt;''''' — соответствует набору десятичных цифр. Эквивалентно выражению 0-9.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:graph:]&amp;lt;/big&amp;gt;''''' — (печатаемые и псевдографические символы) — соответствует набору символов из диапазона ''ASCII 33'' - 126. Это то же самое, что и класс '''''[:print:]''''', за исключением символа пробела.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:lower:]&amp;lt;/big&amp;gt;''''' — соответствует набору алфавитных символов в нижнем регистре.Эквивалентно выражению '''a-z'''.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:print:]&amp;lt;/big&amp;gt;''''' — (печатаемые символы) — соответствует набору символов из диапазона ''ASCII 32'' - 126. По своему составу этот класс идентичен классу '''''[:graph:]''''', описанному выше, за исключением того, что в этом классе дополнительно присутствует символ пробела.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:space:]&amp;lt;/big&amp;gt;''''' — соответствует пробельным символам (пробел и горизонтальная табуляция).&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:upper:]&amp;lt;/big&amp;gt;''''' — соответствует набору символов алфавита в верхнем регистре. Эквивалентно выражению '''A-Z'''.&lt;br /&gt;
* Класс '''''&amp;lt;big&amp;gt;[:xdigit:]&amp;lt;/big&amp;gt;''''' — соответствует набору шестнадцатиричных цифр. Эквивалентно выражению '''0-9A-Fa-f'''.&lt;br /&gt;
Вообще, символьные классы POSIX требуют заключения в кавычки или двойные квадратные скобки ('''''[[ ]]''''').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ grep [[:digit:]] test.file&lt;br /&gt;
abc=723&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эти символьные классы могут использоваться, с некоторыми ограничениями, даже в операциях подстановки имен файлов (''globbing'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ls -l ?[[:digit:]][[:digit:]]?&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 21 14:47 a33b&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
[[Sed]], [[awk]] и [[Perl]], используемые в сценариях в качестве фильтров, могут принимать регулярные выражения в качестве входных аргументов.&amp;lt;br /&amp;gt;&lt;br /&gt;
В качестве стандартного руководства по этой сложной теме можно порекомендовать &amp;quot;MasteringRegular Expressions&amp;quot;, автор Friedl. Книга &amp;quot;'''''Sed &amp;amp; Awk'''''&amp;quot; (авторы ''Dougherty и Robbins'') так же даёт полное и ясное описание регулярных выражений (см. раздел Библиография).&lt;br /&gt;
=== Globbing — Подстановка имён файлов ===&lt;br /&gt;
Bash, сам по себе, не распознаёт регулярные выражения. Но в сценариях можно использовать команды и утилиты, такие как [[sed]] и [[awk]], которые прекрасно справляются с обработкой регулярных выражений.&amp;lt;br /&amp;gt;&lt;br /&gt;
Фактически, Bash может выполнять подстановку имён файлов, этот процесс называется &amp;quot;''globbing''&amp;quot;, но при этом не используется стандартный набор регулярных выражений. Вместо этого, при выполнении подстановки имён файлов, производится распознавание и интерпретация шаблонных символов. В число интерпретируемых шаблонов входят символы '''*''' и '''?''', списки символов в квадратных скобках и некоторые специальные символы (например '''^''', используемый для выполнения операции отрицания). Применение шаблонных символов имеет ряд важных ограничений. Например, если имена файлов начинаются с точки (например так: '''''.bashrc'''''), то они не будут соответствовать шаблону, содержащему символ '''*'''. Аналогично, символ '''?''' в операции подстановки имён файлов имеет иной смысл, нежели в регулярных выражениях.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ls -l&lt;br /&gt;
total 2&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt&lt;br /&gt;
&lt;br /&gt;
bash$ ls -l t?.sh&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh&lt;br /&gt;
&lt;br /&gt;
bash$ ls -l [ab]*&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1&lt;br /&gt;
&lt;br /&gt;
bash$ ls -l [a-c]*&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 a.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1&lt;br /&gt;
&lt;br /&gt;
bash$ ls -l [^ab]*&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 466 Aug 6 17:48 t2.sh&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt&lt;br /&gt;
&lt;br /&gt;
bash$ ls -l {b*,c*,*est*}&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 b.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 0 Aug 6 18:42 c.1&lt;br /&gt;
-rw-rw-r-- 1 bozo bozo 758 Jul 30 09:02 test1.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash выполняет подстановку имён файлов при использовании аргументов командной строки без кавычек. Команда [[echo]] наглядно демонстрирует это.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo *&lt;br /&gt;
a.1 b.1 c.1 t2.sh test1.txt&lt;br /&gt;
&lt;br /&gt;
bash$ echo t*&lt;br /&gt;
t2.sh test1.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash предоставляет возможность изменить порядок интерпретации специальных символов вовремя подстановки имён файлов. Так команда '''''set -f''''' запрещает подстановку, а ключи ''nocaseglob'' и ''nullglob'' в '''''shopt''''' изменяют характер подстановки.&lt;br /&gt;
&lt;br /&gt;
== Подоболочки или Subshells ==&lt;br /&gt;
Запуск сценария приводит к запуску дочернего командного интерпретатора. Который выполняет интерпретацию и исполнение списка команд, содержащихся в файле сценария, точно так же, как если бы они были введены из командной строки. Любой сценарий запускается как дочерний процесс родительской командной оболочки, той самой, которая выводит перед вами строку приглашения к вводу на консоли или в окне '''''xterm'''''. Сценарий может, так же, запустить другой дочерний процесс, в своей подоболочке. Это позволяет сценариям распараллелить процесс обработки данных по нескольким задачам, исполняемым одновременно.&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Как правило, внешние команды в сценариях порождают дочерние процессы, в то время как встроенные команды Bash — нет. По этой причине, встроенные команды выполняются много быстрее своих &amp;quot;внешних&amp;quot; аналогов.&lt;br /&gt;
|}&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Список команд в круглых скобках'''&lt;br /&gt;
:( command1; command2; command3; ... )&lt;br /&gt;
Список команд, в круглых скобках, исполняется в подоболочке. Значения переменных, определённых в дочерней оболочке, не могут быть переданы родительской оболочке. Они недоступны родительскому процессу. Фактически, они ведут себя как ''локальные переменные''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Область видимости переменных.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# subshell.sh&lt;br /&gt;
echo&lt;br /&gt;
outer_variable=Outer&lt;br /&gt;
&lt;br /&gt;
(&lt;br /&gt;
inner_variable=Inner&lt;br /&gt;
echo &amp;quot;Дочерний процесс, \&amp;quot;inner_variable\&amp;quot; = $inner_variable&amp;quot;&lt;br /&gt;
echo &amp;quot;Дочерний процесс, \&amp;quot;outer\&amp;quot; = $outer_variable&amp;quot;&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$inner_variable&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Переменная inner_variable не определена в родительской оболочке&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Переменная inner_variable определена в родительской оболочке&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Родительский процесс, \&amp;quot;inner_variable\&amp;quot; = $inner_variable&amp;quot;&lt;br /&gt;
# Переменная $inner_variable не будет определена&lt;br /&gt;
# потому, что переменные, определенные в дочернем процессе,&lt;br /&gt;
# ведут себя как &amp;quot;локальные переменные&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
+&amp;lt;br /&amp;gt;&lt;br /&gt;
Смена текущего каталога в дочернем процессе (подоболочке) не влечёт за собой смену текущего каталога в родительской оболочке.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Личные настройки пользователей.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# allprofs.sh: вывод личных настроек (profiles) всех пользователей&lt;br /&gt;
# Автор: Heiner Steven&lt;br /&gt;
# С некоторыми изменениями, внесенными автором документа.&lt;br /&gt;
&lt;br /&gt;
FILE=.bashrc # Файл настроек пользователя,&lt;br /&gt;
             # в оригинальном сценарии называется &amp;quot;.profile&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
for home in `awk -F: '{print $6}' /etc/passwd`&lt;br /&gt;
do&lt;br /&gt;
 [ -d &amp;quot;$home&amp;quot; ] || continue # Перейти к следующей итерации, если нет домашнего каталога.&lt;br /&gt;
 [ -r &amp;quot;$home&amp;quot; ] || continue # Перейти к следующей итерации, если не доступен для чтения.&lt;br /&gt;
 (cd $home; [ -e $FILE ] &amp;amp;&amp;amp; less $FILE)&lt;br /&gt;
done&lt;br /&gt;
# По завершении сценария — нет необходимости выполнять команду 'cd', чтобы вернуться в первоначальный каталог, поскольку 'cd $home' выполняется в подоболочке.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подоболочка может использоваться для задания &amp;quot;специфического окружения&amp;quot; для группы команд.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
COMMAND1&lt;br /&gt;
COMMAND2&lt;br /&gt;
COMMAND3&lt;br /&gt;
(&lt;br /&gt;
 IFS=:&lt;br /&gt;
 PATH=/bin&lt;br /&gt;
 unset TERMINFO&lt;br /&gt;
 set -C&lt;br /&gt;
 shift 5&lt;br /&gt;
 COMMAND4&lt;br /&gt;
 COMMAND5&lt;br /&gt;
 exit 3 # Выход только из подоболочки.&lt;br /&gt;
)&lt;br /&gt;
# Изменение переменных окружения не коснется родительской оболочки.&lt;br /&gt;
COMMAND6&lt;br /&gt;
COMMAND7&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Как вариант использования подоболочки — проверка переменных.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if (set -u; : $variable) 2&amp;gt; /dev/null&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Переменная определена.&amp;quot;&lt;br /&gt;
fi # Переменная была инициализирована в данном сценарии&lt;br /&gt;
   # или это внутренняя переменная Bash&lt;br /&gt;
   # или это переменная окружения (была экспортирована в оболочку).&lt;br /&gt;
&lt;br /&gt;
# Можно сделать то же самое по другому: [[ ${variable-x} != x || ${variable-y} != y ]]&lt;br /&gt;
# или                                   [[ ${variable-x} != x$variable ]]&lt;br /&gt;
# или                                   [[ ${variable+x} = x ]])&lt;br /&gt;
# или                                   [[ ${variable-x} != x ]])&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё одно применение — проверка файлов блокировки:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if (set -C; : &amp;gt; lock_file) 2&amp;gt; /dev/null&lt;br /&gt;
then&lt;br /&gt;
 : # lock_file отсутствует: программа (сценарий) не запущена&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Этот сценарий уже запущен другим пользователем.&amp;quot;&lt;br /&gt;
 exit 65&lt;br /&gt;
fi&lt;br /&gt;
# Автор фрагмента Stephane Chazelas,&lt;br /&gt;
# небольшие дополнения сделаны Paulo Marcel Coelho Aragao.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Процессы в подоболочках могут исполняться параллельно. Это позволяет разбить сложную задачу на несколько простых подзадач, выполняющих параллельную обработку информации.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Запуск нескольких процессов в подоболочках.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
(cat list1 list2 list3 | sort | uniq &amp;gt; list123) &amp;amp;&lt;br /&gt;
(cat list4 list5 list6 | sort | uniq &amp;gt; list456) &amp;amp;&lt;br /&gt;
# Слияние и сортировка двух списков производится одновременно.&lt;br /&gt;
# Запуск в фоне гарантирует параллельное исполнение.&lt;br /&gt;
#&lt;br /&gt;
# Тот же эффект даёт&lt;br /&gt;
# cat list1 list2 list3 | sort | uniq &amp;gt; list123 &amp;amp;&lt;br /&gt;
# cat list4 list5 list6 | sort | uniq &amp;gt; list456 &amp;amp;&lt;br /&gt;
&lt;br /&gt;
wait # Ожидание завершения работы подоболочек.&lt;br /&gt;
&lt;br /&gt;
diff list123 list456&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Перенаправление ввода/вывода в/из подоболочки производится оператором построения конвейера &amp;quot;'''|'''&amp;quot;, например, '''''ls -al | (command)'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Блок команд, заключенный в фигурные скобки не приводит к запуску дочерней подоболочки.&lt;br /&gt;
''{ command1; command2; command3; ... }''&lt;br /&gt;
&lt;br /&gt;
== Ограниченный режим командной оболочки ==&lt;br /&gt;
'''Команды, запрещённые в ограниченном режиме командной оболочки'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Запуск сценария или его части в ограниченном режиме, приводит к наложению ограничений на использование некоторых команд. Эта мера предназначена для ограничения привилегий пользователя, запустившего сценарий, и минимизации возможного ущерба системе, который может нанести сценарий.&lt;br /&gt;
:'''''В ограниченном режиме запрещена команда [[cd]] — смена текущего каталога.'''''&lt;br /&gt;
:'''''Запрещено изменять переменные окружения &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$PATH&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$SHELL&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$BASH_ENV&amp;lt;/span&amp;gt; и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$ENV&amp;lt;/span&amp;gt;.'''''&lt;br /&gt;
:'''''Запрещён доступ к переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$SHELLOPTS&amp;lt;/span&amp;gt;.'''''&lt;br /&gt;
:'''''Запрещено перенаправление вывода.'''''&lt;br /&gt;
:'''''Запрещён вызов утилит, в названии которых присутствует хотя бы один символ &amp;quot;слэш&amp;quot; (''/'').'''''&lt;br /&gt;
:'''''Запрещён вызов команды '''''exec''''' для запуска другого процесса.'''''&lt;br /&gt;
:'''''Запрещён ряд других команд, которые могут использовать сценарий для выполнения непредусмотренных действий.'''''&lt;br /&gt;
:'''''Запрещён выход из ограниченного режима.'''''&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Запуск сценария в ограниченном режиме.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Если sha-bang задать в таком виде: &amp;quot;#!/bin/bash -r&amp;quot;&lt;br /&gt;
# то это приведёт к включению ограниченного режима с момента запуска скрипта.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Смена каталога.&amp;quot;&lt;br /&gt;
cd /usr/local&lt;br /&gt;
echo &amp;quot;Текущий каталог: `pwd`&amp;quot;&lt;br /&gt;
echo &amp;quot;Переход в домашний каталог.&amp;quot;&lt;br /&gt;
cd&lt;br /&gt;
echo &amp;quot;Текущий каталог: `pwd`&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
# До сих пор сценарий исполнялся в обычном, неограниченном режиме.&lt;br /&gt;
set -r&lt;br /&gt;
# set --restricted имеет тот же эффект.&lt;br /&gt;
echo &amp;quot;==&amp;gt; Переход в ограниченный режим. &amp;lt;==&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Попытка сменить текущий каталог в ограниченном режиме.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
cd ..&lt;br /&gt;
echo &amp;quot;Текущий каталог остался прежним: `pwd`&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;\$SHELL = $SHELL&amp;quot;&lt;br /&gt;
echo &amp;quot;Попытка смены командного интерпретатора в ограниченном режиме.&amp;quot;&lt;br /&gt;
SHELL=&amp;quot;/bin/ash&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;\$SHELL= $SHELL&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Попытка перенаправления вывода в ограниченном режиме.&amp;quot;&lt;br /&gt;
ls -l /usr/bin &amp;gt; bin.files&lt;br /&gt;
ls -l bin.files # Попробуем найти файл, который пытались создать.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Подстановка процессов ==&lt;br /&gt;
''Подстановка процессов'' — это аналог подстановки команд. Операция подстановки команд записывает в переменную результат выполнения некоторой команды, например, ''dir_contents=`ls -al`'' или ''xref=$(grep word datafile)''. Операция подстановки процессов передаёт вывод одного процесса на ввод другого (другими словами, передаёт результат выполнения одной команды — другой).&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Шаблон подстановки команды'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Внутри круглых скобок:&lt;br /&gt;
:&amp;lt;big&amp;gt;'''&amp;gt;(command)'''&amp;lt;/big&amp;gt;&lt;br /&gt;
:&amp;lt;big&amp;gt;'''&amp;lt;(command)'''&amp;lt;/big&amp;gt;&lt;br /&gt;
:Таким образом инициируется подстановка процессов. Здесь, для передачи результата работы процесса в круглых скобках, используются файлы ''/dev/fd/&amp;lt;n&amp;gt;''. Между круглой скобкой и символом &amp;quot;'''&amp;lt;'''&amp;quot; или &amp;quot;'''&amp;gt;'''&amp;quot;, не должно быть пробелов, в противном случае это вызовет сообщение об ошибке.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo &amp;gt;(true)&lt;br /&gt;
/dev/fd/63&lt;br /&gt;
&lt;br /&gt;
bash$ echo &amp;lt;(true)&lt;br /&gt;
/dev/fd/63&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash создаёт канал с двумя файловыми дескрипторами, ''--fIn'' и ''fOut--''. ''stdin'' команды ''true'' присоединяется к ''fOut'' (dup2(fOut, 0)), затем Bash передаёт ''/dev/fd/fIn'' в качестве аргумента команде [[echo]]. В системах, где отсутствуют файлы ''/dev/fd/&amp;lt;n&amp;gt;'', Bash может использовать временные файлы. (Спасибо S.C.)&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat &amp;lt;(ls -l)&lt;br /&gt;
# То же самое, что и ls -l | cat&lt;br /&gt;
&lt;br /&gt;
sort -k 9 &amp;lt;(ls -l /bin) &amp;lt;(ls -l /usr/bin) &amp;lt;(ls -l /usr/X11R6/bin)&lt;br /&gt;
# Список файлов в трёх основных каталогах 'bin', отсортированный по именам файлов.&lt;br /&gt;
# Обратите внимание: на вход 'sort' поданы три самостоятельные команды.&lt;br /&gt;
&lt;br /&gt;
diff &amp;lt;(command1) &amp;lt;(command2) # Выдаст различия в выводе команд.&lt;br /&gt;
&lt;br /&gt;
tar cf &amp;gt;(bzip2 -c &amp;gt; file.tar.bz2) $directory_name&lt;br /&gt;
# Вызовет &amp;quot;tar cf /dev/fd/?? $directory_name&amp;quot; и затем &amp;quot;bzip2 -c &amp;gt; file.tar.bz2&amp;quot;.&lt;br /&gt;
#&lt;br /&gt;
# Из-за особенностей, присущих некоторым системам, связанным с /dev/fd/&amp;lt;n&amp;gt;,&lt;br /&gt;
# канал между командами не обязательно должен быть именованным.&lt;br /&gt;
#&lt;br /&gt;
# Это можно сделать и так.&lt;br /&gt;
#&lt;br /&gt;
bzip2 -c &amp;lt; pipe &amp;gt; file.tar.bz2&amp;amp;&lt;br /&gt;
tar cf pipe $directory_name&lt;br /&gt;
rm pipe&lt;br /&gt;
# или&lt;br /&gt;
exec 3&amp;gt;&amp;amp;1tar cf /dev/fd/4 $directory_name 4&amp;gt;&amp;amp;1 &amp;gt;&amp;amp;3 3&amp;gt;&amp;amp;- | bzip2 -c &amp;gt; file.tar.bz2 3&amp;gt;&amp;amp;-&lt;br /&gt;
exec 3&amp;gt;&amp;amp;-&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ниже приводится ещё один очень интересный пример использования подстановки процессов.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Фрагмент сценария из дистрибутива SuSE:&lt;br /&gt;
while read des what mask iface; do&lt;br /&gt;
# Некоторые команды ...&lt;br /&gt;
done &amp;lt; &amp;lt;(route -n)&lt;br /&gt;
&lt;br /&gt;
# Чтобы проверить это, попробуем вставить команду, выполняющую какие-либо действия.&lt;br /&gt;
while read des what mask iface; do&lt;br /&gt;
 echo $des $what $mask $iface&lt;br /&gt;
done &amp;lt; &amp;lt;(route -n)&lt;br /&gt;
&lt;br /&gt;
# Вывод на экран:&lt;br /&gt;
# Kernel IP routing table&lt;br /&gt;
# Destination Gateway Genmask Flags Metric Ref Use Iface&lt;br /&gt;
# 127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo&lt;br /&gt;
# Как указывает S.C. — более простой для понимания эквивалент:&lt;br /&gt;
route -n |&lt;br /&gt;
 while read des what mask iface; do # Переменные берут значения с устройства вывода конвейера (канала).&lt;br /&gt;
  echo $des $what $mask $iface&lt;br /&gt;
 done # На экран выводится то же самое, что и выше.&lt;br /&gt;
      # Однако, Ulrich Gayer отметил, что ...&lt;br /&gt;
      # этот вариант запускает цикл while в подоболочке, этот вариант запускает цикл while в подоболочке,&lt;br /&gt;
      # и поэтому переменные не видны за пределами цикла, после закрытия канала.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Функции ==&lt;br /&gt;
Подобно &amp;quot;настоящим&amp;quot; языкам программирования, Bash тоже имеет функции, хотя и в несколько ограниченном варианте. Функция — это подпрограмма, блок кода который реализует набор операций, своего рода &amp;quot;чёрный ящик&amp;quot;, предназначенный для выполнения конкретной задачи. Функции могут использоваться везде, где имеются участки повторяющегося кода.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''function''' ''function_name'' {&amp;lt;br/&amp;gt;&lt;br /&gt;
''command...''&amp;lt;br/&amp;gt;&lt;br /&gt;
}&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
или&lt;br /&gt;
&lt;br /&gt;
''function_name'' () {command...}&amp;lt;br /&amp;gt;&lt;br /&gt;
Вторая форма записи ближе к сердцу C-программистам (она же более переносимая). Как и в языке C, скобка, открывающая тело функции, может помещаться на следующей строке.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''function_name ()'''&amp;lt;br /&amp;gt;&lt;br /&gt;
{&amp;lt;br /&amp;gt;&lt;br /&gt;
''command...''&amp;lt;br /&amp;gt;&lt;br /&gt;
}&amp;lt;br /&amp;gt;&lt;br /&gt;
Вызов функции осуществляется простым указанием её имени в тексте сценария.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простые функции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
JUST_A_SECOND=1&lt;br /&gt;
funky ()&lt;br /&gt;
{ # Это пример простейшей функции, которая выводит сообщение.&lt;br /&gt;
 echo &amp;quot;Это функция funky.&amp;quot;&lt;br /&gt;
} # Объявление функции должно предшествовать её вызову.&lt;br /&gt;
&lt;br /&gt;
fun ()&lt;br /&gt;
{ # Более сложная функция.&lt;br /&gt;
 i=0&lt;br /&gt;
 REPEATS=30&lt;br /&gt;
 &lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Теперь запускается функция fun.&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
&lt;br /&gt;
 sleep $JUST_A_SECOND # Эй! Погодите секундочку!&lt;br /&gt;
 while [ $i -lt $REPEATS ]&lt;br /&gt;
 do&lt;br /&gt;
  echo &amp;quot;------------------РАБОТА-------------------&amp;gt;&amp;quot;&lt;br /&gt;
  echo &amp;quot;&amp;lt;---------------С ФУНКЦИЯМИ----------------&amp;quot;&lt;br /&gt;
  echo &amp;quot;&amp;lt;------------ОЧЕНЬ УВЛЕКАТЕЛЬНА------------&amp;gt;&amp;quot;&lt;br /&gt;
  echo&lt;br /&gt;
  let &amp;quot;i+=1&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
# А теперь собственно вызов функций.&lt;br /&gt;
funky&lt;br /&gt;
fun&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Функция должна быть объявлена раньше, чем её можно будет использовать. К сожалению, в Bash нет возможности &amp;quot;опережающего объявления&amp;quot; функции, как например в C.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
f1&lt;br /&gt;
# Эта строка вызовет сообщение об ошибке, поскольку функция &amp;quot;f1&amp;quot; еще не определена.&lt;br /&gt;
&lt;br /&gt;
declare -f f1 # Это не поможет.&lt;br /&gt;
f1 # По прежнему — сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
# Однако...&lt;br /&gt;
&lt;br /&gt;
f1 ()&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;Вызов функции \&amp;quot;f2\&amp;quot; из функции \&amp;quot;f1\&amp;quot;.&amp;quot;&lt;br /&gt;
 f2&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
f2 ()&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;Функция \&amp;quot;f2\&amp;quot;.&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
f1 # Функция &amp;quot;f2&amp;quot;, фактически, не вызывается выше этой строки,&lt;br /&gt;
   # хотя ссылка на неё встречается выше, до её объявления.&lt;br /&gt;
   # Это допускается.&lt;br /&gt;
   # Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Допускается даже создание вложенных функций, хотя пользы от этого немного.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
f1 ()&lt;br /&gt;
{&lt;br /&gt;
 f2 () # вложенная&lt;br /&gt;
 {&lt;br /&gt;
  echo &amp;quot;Функция \&amp;quot;f2\&amp;quot;, вложенная в \&amp;quot;f1\&amp;quot;.&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
f2 # Вызывает сообщение об ошибке.&lt;br /&gt;
   # Даже &amp;quot;declare -f f2&amp;quot; не поможет.&lt;br /&gt;
echo&lt;br /&gt;
f1 # Ничего не происходит, простой вызов &amp;quot;f1&amp;quot;, не означает автоматический вызов &amp;quot;f2&amp;quot;.&lt;br /&gt;
f2 # Теперь всё нормально, вызов &amp;quot;f2&amp;quot; не приводит к появлению ошибки,&lt;br /&gt;
   # поскольку функция &amp;quot;f2&amp;quot; была определена в процессе вызова &amp;quot;f1&amp;quot;.&lt;br /&gt;
   # Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Объявление функции может размещаться в самых неожиданных местах.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls -l | foo() { echo &amp;quot;foo&amp;quot;; } # Допустимо, но бесполезно.&lt;br /&gt;
if [ &amp;quot;$USER&amp;quot; = bozo ]&lt;br /&gt;
then&lt;br /&gt;
 bozo_greet () # Объявление функции размещено в условном операторе.&lt;br /&gt;
 {&lt;br /&gt;
  echo &amp;quot;Привет, Bozo!&amp;quot;&lt;br /&gt;
 }&lt;br /&gt;
fi&lt;br /&gt;
bozo_greet # Работает только у пользователя bozo, другие получат сообщение об ошибке.&lt;br /&gt;
# Нечто подобное можно использовать с определённой пользой для себя.&lt;br /&gt;
NO_EXIT=1 # Will enable function definition below.&lt;br /&gt;
&lt;br /&gt;
[[ $NO_EXIT -eq 1 ]] &amp;amp;&amp;amp; exit() { true; } # Определение функции в последовательности &amp;quot;И-список&amp;quot;.&lt;br /&gt;
# Если $NO_EXIT равна 1, то объявляется &amp;quot;exit ()&amp;quot;.&lt;br /&gt;
# Тем самым, функция &amp;quot;exit&amp;quot; подменяет встроенную команду &amp;quot;exit&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
exit # Вызывается функция &amp;quot;exit ()&amp;quot;, а не встроенная команда &amp;quot;exit&amp;quot;.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== Сложные функции и сложности с функциями ===&lt;br /&gt;
Функции могут принимать входные аргументы и возвращать &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;код завершения&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;function_name $arg1 $arg2&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Доступ к входным аргументам, в функциях, производится посредством позиционных параметров, т.е. '''$1''', '''$2''' и так далее.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Функция с аргументами.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Функции и аргументы&lt;br /&gt;
&lt;br /&gt;
DEFAULT=default # Значение аргумента по-умолчанию.&lt;br /&gt;
&lt;br /&gt;
func2 () {&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; ] # Длина аргумента #1 равна нулю?&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;-Аргумент #1 имеет нулевую длину.-&amp;quot; # Или аргумент не был передан функции.&lt;br /&gt;
 else&lt;br /&gt;
  echo &amp;quot;-Аргумент #1: \&amp;quot;$1\&amp;quot;.-&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 variable=${1-$DEFAULT}        # Что делает&lt;br /&gt;
 echo &amp;quot;variable = $variable&amp;quot;   # показанная подстановка параметра?&lt;br /&gt;
                               # ---------------------------&lt;br /&gt;
                               # Она различает отсутствующий аргумент от &amp;quot;пустого&amp;quot; аргумента.&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$2&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;-Аргумент #2: \&amp;quot;$2\&amp;quot;.-&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 return 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Вызов функции без аргументов.&amp;quot;&lt;br /&gt;
func2&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Вызов функции с \&amp;quot;пустым\&amp;quot; аргументом.&amp;quot;&lt;br /&gt;
func2 &amp;quot;&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Вызов функции с неинициализированным аргументом.&amp;quot;&lt;br /&gt;
func2 &amp;quot;$uninitialized_param&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Вызов функции с одним аргументом.&amp;quot;&lt;br /&gt;
func2 first&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Вызов функции с двумя аргументами.&amp;quot;&lt;br /&gt;
func2 first second&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Вызов функции с аргументами \&amp;quot;\&amp;quot; \&amp;quot;second\&amp;quot;.&amp;quot;&lt;br /&gt;
func2 &amp;quot;&amp;quot; second # Первый параметр &amp;quot;пустой&amp;quot;&lt;br /&gt;
echo # и второй параметр — ASCII-строка.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''shift''''' вполне применима и к аргументам функций.&amp;lt;br /&amp;gt;&lt;br /&gt;
В отличие от других языков программирования, в сценариях на языке командной оболочки, аргументы в функции передаются по значению. Переменные (которые фактически являются указателями) при передаче в функции в виде параметров, интерпретируются как строковые литералы. Функции всегда интерпретируют свои аргументы буквально. Механизм &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;косвенных ссылок&amp;lt;/span&amp;gt; на переменные слишком неудобен для передачи аргументов по ссылке.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача косвенных ссылок в функцию.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ind-func.sh: Передача косвенных ссылок в функцию.&lt;br /&gt;
echo_var ()&lt;br /&gt;
{&lt;br /&gt;
echo &amp;quot;$1&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
message=Hello&lt;br /&gt;
Hello=Goodbye&lt;br /&gt;
&lt;br /&gt;
echo_var &amp;quot;$message&amp;quot; # Hello&lt;br /&gt;
# А теперь передадим функции косвенную ссылку.&lt;br /&gt;
&lt;br /&gt;
echo_var &amp;quot;${!message}&amp;quot; # Goodbyeecho &amp;quot;-------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;-------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Что произойдёт, если изменить содержимое переменной &amp;quot;Hello&amp;quot;?&lt;br /&gt;
Hello=&amp;quot;Hello, again!&amp;quot;&lt;br /&gt;
echo_var &amp;quot;$message&amp;quot; # Hello&lt;br /&gt;
echo_var &amp;quot;${!message}&amp;quot; # Hello, again!&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Тут же возникает вопрос: &amp;quot;Возможно ли изменить значение переменной, которая была передана по ссылке?&amp;quot;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Изменение значения переменной, переданной в функцию по ссылке.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# dereference.sh&lt;br /&gt;
# Изменение значения переменной, переданной в функцию по ссылке.&lt;br /&gt;
# Автор: Bruce W. Clare.&lt;br /&gt;
dereference ()&lt;br /&gt;
{&lt;br /&gt;
 y=\$&amp;quot;$1&amp;quot; # Имя переменной.&lt;br /&gt;
 echo $y # $Junk&lt;br /&gt;
&lt;br /&gt;
 x=`eval &amp;quot;expr \&amp;quot;$y\&amp;quot; &amp;quot;`&lt;br /&gt;
 echo $1=$x&lt;br /&gt;
 eval &amp;quot;$1=\&amp;quot;Некий другой текст \&amp;quot;&amp;quot; # Присвоить новое значение.&lt;br /&gt;
}&lt;br /&gt;
Junk=&amp;quot;Некий текст&amp;quot;&lt;br /&gt;
echo $Junk &amp;quot;до того как...&amp;quot; # Некий текст до того как...&lt;br /&gt;
&lt;br /&gt;
dereference Junk&lt;br /&gt;
echo $Junk &amp;quot;после того как...&amp;quot; # Некий другой текст после того как...&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ещё один пример разыменования параметров функции, передаваемых по ссылке.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
ITERATIONS=3 # Количество вводимых значений.&lt;br /&gt;
icount=1&lt;br /&gt;
&lt;br /&gt;
my_read () {&lt;br /&gt;
 # При вызове my_read varname,&lt;br /&gt;
 # выводит предыдущее значение в квадратных скобках,&lt;br /&gt;
 # затем просит ввести новое значение.&lt;br /&gt;
&lt;br /&gt;
 local local_var&lt;br /&gt;
&lt;br /&gt;
 echo -n &amp;quot;Введите говое значение переменной &amp;quot;&lt;br /&gt;
 eval 'echo -n &amp;quot;[$'$1'] &amp;quot;' # Прежнее значение.&lt;br /&gt;
 read local_var&lt;br /&gt;
 [ -n &amp;quot;$local_var&amp;quot; ] &amp;amp;&amp;amp; eval $1=\$local_var&lt;br /&gt;
 # Последовательность &amp;quot;And-list&amp;quot;: если &amp;quot;local_var&amp;quot; не пуста, то ее значение переписывается в &amp;quot;$1&amp;quot;.&lt;br /&gt;
}&lt;br /&gt;
echo&lt;br /&gt;
while [ &amp;quot;$icount&amp;quot; -le &amp;quot;$ITERATIONS&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 my_read var&lt;br /&gt;
 echo &amp;quot;Значение #$icount = $var&amp;quot;&lt;br /&gt;
 let &amp;quot;icount += 1&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
done&lt;br /&gt;
# Спасибо Stephane Chazelas за этот поучительный пример.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Exit and Return'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Код завершения'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Функции возвращают значение в виде кода завершения. Код завершения может быть задан явно, с помощью команды ''return'', в противном случае будет возвращен код завершения последней команды в функции ('''0''' — в случае '''успеха''', иначе — '''ненулевой код ошибки'''). Код завершения в сценарии может быть получен через переменную '''''$?'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''return'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Завершает исполнение функции. Команда ''return'' может иметь необязательный аргумент типа ''integer'', который возвращается в вызывающий сценарий как &amp;quot;код завершения&amp;quot; функции, это значение так же записывается в переменную '''''$?'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Наибольшее из двух чисел.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# max.sh: Наибольшее из двух целых чисел.&lt;br /&gt;
&lt;br /&gt;
E_PARAM_ERR=-198 # Если функции передано меньше двух параметров.&lt;br /&gt;
EQUAL=-199 # Возвращаемое значение, если числа равны.&lt;br /&gt;
&lt;br /&gt;
max2 () # Возвращает наибольшее из двух чисел.&lt;br /&gt;
{       # Внимание: сравниваемые числа должны быть меньше 257.&lt;br /&gt;
 if [ -z &amp;quot;$2&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return $E_PARAM_ERR&lt;br /&gt;
 fi&lt;br /&gt;
 if [ &amp;quot;$1&amp;quot; -eq &amp;quot;$2&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return $EQUAL&lt;br /&gt;
 else&lt;br /&gt;
  if [ &amp;quot;$1&amp;quot; -gt &amp;quot;$2&amp;quot; ]&lt;br /&gt;
  then&lt;br /&gt;
   return $1&lt;br /&gt;
  else&lt;br /&gt;
   return $2&lt;br /&gt;
  fi&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
max2 33 34&lt;br /&gt;
return_val=$?&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$return_val&amp;quot; -eq $E_PARAM_ERR ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Функции должно быть передано два аргумента.&amp;quot;&lt;br /&gt;
elif [ &amp;quot;$return_val&amp;quot; -eq $EQUAL ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Числа равны.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Наибольшее из двух чисел: $return_val.&amp;quot; &lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ---------------&lt;br /&gt;
# Сделайте этот сценарий интерактивным, &lt;br /&gt;
# т.е. заставьте сценарий запрашивать числа для сравнения у пользователя (два числа).&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для случаев, когда функция должна возвращать строку или массив, используйте специальные переменные.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
count_lines_in_etc_passwd()&lt;br /&gt;
{&lt;br /&gt;
 [[ -r /etc/passwd ]] &amp;amp;&amp;amp; REPLY=$(echo $(wc -l &amp;lt; /etc/passwd))&lt;br /&gt;
 # Если файл /etc/passwd доступен на чтение, то в переменную REPLY заносится число строк.&lt;br /&gt;
 # Возвращаются как количество строк, так и код завершения.&lt;br /&gt;
 # Команда 'echo' может показаться ненужной, но . . .&lt;br /&gt;
 # она предотвращает вывод лишних пробелов.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if count_lines_in_etc_passwd&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;В файле /etc/passwd найдено $REPLY строк.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Невозможно подсчитать число строк в файле /etc/passwd.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Преобразование чисел в римскую форму записи.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Преобразование чисел из арабской формы записи в римскую&lt;br /&gt;
# Диапазон: 0 - 200&lt;br /&gt;
&lt;br /&gt;
# Расширение диапазона представляемых чисел и улучшение сценария&lt;br /&gt;
# оставляю вам, в качестве упражнения.&lt;br /&gt;
&lt;br /&gt;
# Порядок использования: roman number-to-convert\&lt;br /&gt;
LIMIT=200&lt;br /&gt;
E_ARG_ERR=65&lt;br /&gt;
E_OUT_OF_RANGE=66&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` number-to-convert&amp;quot;&lt;br /&gt;
 exit $E_ARG_ERR&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
num=$1&lt;br /&gt;
if [ &amp;quot;$num&amp;quot; -gt $LIMIT ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Выход за границы диапазона!&amp;quot;&lt;br /&gt;
 exit $E_OUT_OF_RANGE&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
to_roman () # Функция должна быть объявлена до того как она будет вызвана.&lt;br /&gt;
{&lt;br /&gt;
 number=$1&lt;br /&gt;
 factor=$2&lt;br /&gt;
 rchar=$3&lt;br /&gt;
 let &amp;quot;remainder = number - factor&amp;quot;&lt;br /&gt;
 while [ &amp;quot;$remainder&amp;quot; -ge 0 ]&lt;br /&gt;
 do&lt;br /&gt;
  echo -n $rchar&lt;br /&gt;
  let &amp;quot;number -= factor&amp;quot;&lt;br /&gt;
  let &amp;quot;remainder = number - factor&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
 &lt;br /&gt;
 return $number&lt;br /&gt;
  # Упражнение:&lt;br /&gt;
  # --------&lt;br /&gt;
  # Объясните — как работает функция.&lt;br /&gt;
  # Подсказка: деление последовательным вычитанием.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
to_roman $num 100 Cnum=$?&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 90 LXXXX&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 50 L&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 40 X&lt;br /&gt;
Lnum=$?&lt;br /&gt;
to_roman $num 10 X&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 9 IX&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 5 V&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 4 IV&lt;br /&gt;
num=$?&lt;br /&gt;
to_roman $num 1 I&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Наибольшее положительное целое число, которое может вернуть функция — 255. Команда ''return'' очень тесно связана с понятием код завершения, что объясняет это специфическое ограничение. К счастью существуют различные способы преодоления этого ограничения.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка возможности возврата функциями больших значений.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# return-test.sh&lt;br /&gt;
# Наибольшее целое число, которое может вернуть функция, не может превышать 256.&lt;br /&gt;
&lt;br /&gt;
return_test () # Просто возвращает то, что ей передали.&lt;br /&gt;
{&lt;br /&gt;
 return $1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
return_test 27 # o.k.&lt;br /&gt;
echo $? # Возвращено число 27.&lt;br /&gt;
&lt;br /&gt;
return_test 255 # o.k.&lt;br /&gt;
echo $? # Возвращено число 255.&lt;br /&gt;
&lt;br /&gt;
return_test 257 # Ошибка!&lt;br /&gt;
echo $? # Возвращено число 1.&lt;br /&gt;
&lt;br /&gt;
return_test -151896 # Как бы то ни было, но для больших отрицательных чисел проходит!&lt;br /&gt;
echo $? # Возвращено число -151896.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Самый простой способ вернуть из функции большое положительное число — это присвоить &amp;quot;возвращаемое значение&amp;quot; глобальной переменной.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Return_Val= # Глобальная переменная, которая хранит значение, возвращаемое функцией.&lt;br /&gt;
alt_return_test ()&lt;br /&gt;
{&lt;br /&gt;
 fvar=$1&lt;br /&gt;
 Return_Val=$fvar&lt;br /&gt;
 return # Возвратить 0 (успешное завершение).&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
alt_return_test 1&lt;br /&gt;
echo $? # 0&lt;br /&gt;
echo &amp;quot;Функция вернула число $Return_Val&amp;quot; # 1&lt;br /&gt;
alt_return_test 255&lt;br /&gt;
echo &amp;quot;Функция вернула число $Return_Val&amp;quot; # 255&lt;br /&gt;
alt_return_test 257&lt;br /&gt;
echo &amp;quot;Функция вернула число $Return_Val&amp;quot; # 257&lt;br /&gt;
alt_return_test 25701&lt;br /&gt;
echo &amp;quot;Функция вернула число $Return_Val&amp;quot; #25701&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё более элегантный способ заключается в передаче возвращаемого значения команде [[echo]], для вывода на ''stdout'', которое затем снимается со стандартного вывода конструкцией подстановки команд.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сравнение двух больших целых чисел.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# max2.sh: Наибольшее из двух БОЛЬШИХ целых чисел.&lt;br /&gt;
&lt;br /&gt;
# Это модификация предыдущего примера &amp;quot;max.sh&amp;quot;,&lt;br /&gt;
# которая позволяет выполнять сравнение больших целых чисел.&lt;br /&gt;
&lt;br /&gt;
EQUAL=0 # Если числа равны.&lt;br /&gt;
MAXRETVAL=255 # Максимально возможное положительное число, которое может вернуть функция.&lt;br /&gt;
E_PARAM_ERR=-99999 # Код ошибки в параметрах.&lt;br /&gt;
E_NPARAM_ERR=99999 # &amp;quot;Нормализованный&amp;quot; код ошибки в параметрах.&lt;br /&gt;
&lt;br /&gt;
max2 () # Возвращает наибольшее из двух больших целых чисел.&lt;br /&gt;
{&lt;br /&gt;
 if [ -z &amp;quot;$2&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return $E_PARAM_ERR&lt;br /&gt;
 fi&lt;br /&gt;
 if [ &amp;quot;$1&amp;quot; -eq &amp;quot;$2&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return $EQUAL&lt;br /&gt;
 else&lt;br /&gt;
  if [ &amp;quot;$1&amp;quot; -gt &amp;quot;$2&amp;quot; ]&lt;br /&gt;
  then&lt;br /&gt;
   retval=$1&lt;br /&gt;
  else&lt;br /&gt;
   retval=$2&lt;br /&gt;
  fi&lt;br /&gt;
 fi&lt;br /&gt;
# -------------------------------------------------------------- #&lt;br /&gt;
# Следующие строки позволяют &amp;quot;обойти&amp;quot; ограничение&lt;br /&gt;
if [ &amp;quot;$retval&amp;quot; -gt &amp;quot;$MAXRETVAL&amp;quot; ] # Если больше предельного значения,&lt;br /&gt;
then                              # то&lt;br /&gt;
 let &amp;quot;retval = (( 0 - $retval ))&amp;quot; # изменение знака числа.&lt;br /&gt;
 # (( 0 - $VALUE )) изменяет знак числа.&lt;br /&gt;
fi&lt;br /&gt;
# Функции имеют возможность возвращать большие *отрицательные* числа.&lt;br /&gt;
# -------------------------------------------------------------- #&lt;br /&gt;
&lt;br /&gt;
return $retval&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
max2 33001 33997&lt;br /&gt;
return_val=$?&lt;br /&gt;
&lt;br /&gt;
# --------------------------------------------------------------------------&lt;br /&gt;
#&lt;br /&gt;
if [ &amp;quot;$return_val&amp;quot; -lt 0 ]                # Если число отрицательное,&lt;br /&gt;
then                                      # то&lt;br /&gt;
 let &amp;quot;return_val = (( 0 - $return_val ))&amp;quot; # опять изменить его знак.&lt;br /&gt;
fi                                        # &amp;quot;Абсолютное значение&amp;quot; переменной $return_val.&lt;br /&gt;
# --------------------------------------------------------------------------&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$return_val&amp;quot; -eq &amp;quot;$E_NPARAM_ERR&amp;quot; ]&lt;br /&gt;
then      # Признак ошибки в параметрах, при выходе из функции так же поменял знак.&lt;br /&gt;
 echo &amp;quot;Ошибка: Недостаточно аргументов.&amp;quot;&lt;br /&gt;
elif [ &amp;quot;$return_val&amp;quot; -eq &amp;quot;$EQUAL&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Числа равны.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Наибольшее число: $return_val.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Упражнение''''': Используя только что полученные знания, добавьте в предыдущий пример, преобразования чисел в римскую форму записи, возможность обрабатывать большие числа.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Перенаправление'''&amp;lt;br /&amp;gt;&lt;br /&gt;
''Перенаправление ввода для функций''&amp;lt;br /&amp;gt;&lt;br /&gt;
Функции — суть есть блок кода, а это означает, что устройство ''stdin'' для функций может быть переопределено (перенаправление ''stdin'').&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Настоящее имя пользователя.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# По имени пользователя получить его &amp;quot;настоящее имя&amp;quot; из /etc/passwd.&lt;br /&gt;
&lt;br /&gt;
ARGCOUNT=1 # Ожидается один аргумент.&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
file=/etc/passwd&lt;br /&gt;
pattern=$1&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGCOUNT&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` USERNAME&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
file_excerpt () # Производит поиск в файле по заданному шаблону, выводит требуемую часть строки.&lt;br /&gt;
{&lt;br /&gt;
 while read line&lt;br /&gt;
 do&lt;br /&gt;
  echo &amp;quot;$line&amp;quot; | grep $1 | awk -F&amp;quot;:&amp;quot; '{ print $5 }' # Указывает awk использовать &amp;quot;:&amp;quot; как разделитель полей.&lt;br /&gt;
 done&lt;br /&gt;
} &amp;lt;$file # Подменить stdin для функции.&lt;br /&gt;
&lt;br /&gt;
file_excerpt $pattern&lt;br /&gt;
# Да, этот сценарий можно уменьшить до&lt;br /&gt;
# grep PATTERN /etc/passwd | awk -F&amp;quot;:&amp;quot; '{ print $5 }'&lt;br /&gt;
# или&lt;br /&gt;
# awk -F: '/PATTERN/ {print $5}'&lt;br /&gt;
# или&lt;br /&gt;
# awk -F: '($1 == &amp;quot;username&amp;quot;) { print $5 }'&lt;br /&gt;
# Однако, это было бы не так поучительно.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ниже приводится альтернативный, и возможно менее запутанный, способ перенаправления ввода для функций. Он заключается в использовании перенаправления ввода для блока кода, заключенного в фигурные скобки, в пределах функции.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Вместо:&lt;br /&gt;
Function ()&lt;br /&gt;
{&lt;br /&gt;
 ...&lt;br /&gt;
} &amp;lt; file &lt;br /&gt;
&lt;br /&gt;
# Попробуйте так:&lt;br /&gt;
Function ()&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  ...&lt;br /&gt;
 } &amp;lt; file&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Похожий вариант,&lt;br /&gt;
Function () # Тоже работает.&lt;br /&gt;
{&lt;br /&gt;
 {&lt;br /&gt;
  echo $*&lt;br /&gt;
 } | tr a b&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Function () # Этот вариант не работает.&lt;br /&gt;
{&lt;br /&gt;
 echo $*&lt;br /&gt;
} | tr a b # Наличие вложенного блока кода — обязательное условие.&lt;br /&gt;
&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== Локальные переменные ===&lt;br /&gt;
'''Что такое &amp;quot;локальная&amp;quot; переменная?'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Локальные переменные&amp;lt;br /&amp;gt;&lt;br /&gt;
Переменные, объявленные как локальные, имеют ограниченную область видимости, и доступны только в пределах блока, в котором они были объявлены. Для функций это означает, что локальная переменная &amp;quot;видна&amp;quot; только в теле самой функции.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Область видимости локальных переменных.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
func ()&lt;br /&gt;
{&lt;br /&gt;
 local loc_var=23 # Объявление локальной переменной.&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;\&amp;quot;loc_var\&amp;quot; в функции = $loc_var&amp;quot;&lt;br /&gt;
 global_var=999 # Эта переменная не была объявлена локальной.&lt;br /&gt;
 echo &amp;quot;\&amp;quot;global_var\&amp;quot; в функции = $global_var&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
func&lt;br /&gt;
# Проверим, &amp;quot;видна&amp;quot; ли локальная переменная за пределами функции.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;\&amp;quot;loc_var\&amp;quot; за пределами функции = $loc_var&amp;quot;&lt;br /&gt;
                                         # &amp;quot;loc_var&amp;quot; за пределами функции =&lt;br /&gt;
                                         # Итак, $loc_var не видна в глобальном контексте.&lt;br /&gt;
echo &amp;quot;\&amp;quot;global_var\&amp;quot; за пределами функции = $global_var&amp;quot;&lt;br /&gt;
                                         # &amp;quot;global_var&amp;quot; за пределами функции = 999&lt;br /&gt;
                                         # $global_var имеет глобальную область видимости.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Переменные, объявляемые в теле функции, считаются необъявленными до тех пор, пока функция не будет вызвана. Это касается всех переменных.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
func ()&lt;br /&gt;
{&lt;br /&gt;
global_var=37 # Эта переменная будет считаться необъявленной&lt;br /&gt;
              # до тех пор, пока функция не будет вызвана.&lt;br /&gt;
              } # КОНЕЦ ФУНКЦИИ&lt;br /&gt;
echo &amp;quot;global_var = $global_var&amp;quot; # global_var =&lt;br /&gt;
                                # Функция &amp;quot;func&amp;quot; ещё не была вызвана,&lt;br /&gt;
                                # поэтому $global_var пока ещё не &amp;quot;видна&amp;quot; здесь.&lt;br /&gt;
&lt;br /&gt;
func&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;global_var = $global_var&amp;quot; # global_var = 37&lt;br /&gt;
                                # Переменная была инициализирована в функции.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
==== Локальные переменные делают возможной рекурсию. ====&lt;br /&gt;
Хотя локальные переменные и допускают рекурсию, но она сопряжена с большими накладными расходами и не рекомендуется для использования в сценариях.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Использование локальных переменных при рекурсии.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# факториал&lt;br /&gt;
# ---------&lt;br /&gt;
&lt;br /&gt;
# Действительно ли bash допускает рекурсию?&lt;br /&gt;
# Да! Но...&lt;br /&gt;
# Нужно быть действительно дубинноголовым, чтобы использовать её в сценариях&lt;br /&gt;
# на языке командной оболочки.&lt;br /&gt;
&lt;br /&gt;
MAX_ARG=5&lt;br /&gt;
E_WRONG_ARGS=65&lt;br /&gt;
E_RANGE_ERR=66&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` число&amp;quot;&lt;br /&gt;
 exit $E_WRONG_ARGS&lt;br /&gt;
fi&lt;br /&gt;
if [ &amp;quot;$1&amp;quot; -gt $MAX_ARG ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Выход за верхний предел (максимально возможное число -- 5).&amp;quot;&lt;br /&gt;
 # Вернитесь к реальности.&lt;br /&gt;
 # Если вам захочется поднять верхнюю границу,&lt;br /&gt;
 # то перепишите эту программу на настоящем языке программирования.&lt;br /&gt;
 exit $E_RANGE_ERR&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
fact ()&lt;br /&gt;
{&lt;br /&gt;
 local number=$1&lt;br /&gt;
 # Переменная &amp;quot;number&amp;quot; должна быть объявлена как локальная,&lt;br /&gt;
 # иначе результат будет неверный.&lt;br /&gt;
 if [ &amp;quot;$number&amp;quot; -eq 0 ]&lt;br /&gt;
 then&lt;br /&gt;
  factorial=1 # Факториал числа 0 = 1.&lt;br /&gt;
 else&lt;br /&gt;
  let &amp;quot;decrnum = number - 1&amp;quot;&lt;br /&gt;
  fact $decrnum # Рекурсивный вызов функции.&lt;br /&gt;
  let &amp;quot;factorial = $number * $?&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 return $factorial&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
fact $1&lt;br /&gt;
echo &amp;quot;Факториал числа $1 = $?.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Не забывайте, что рекурсия весьма ресурсоёмкое удовольствие, к тому же она выполняется слишком медленно, поэтому не следует использовать её в сценариях.&lt;br /&gt;
&lt;br /&gt;
=== Рекурсия без локальных переменных ===&lt;br /&gt;
Функции допускают выполнять рекурсивный вызов даже без использования локальных переменных.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ханойские Башни.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
#&lt;br /&gt;
# Ханойские Башни&lt;br /&gt;
# Bash script# Copyright (C) 2000 Amit Singh. All Rights Reserved.&lt;br /&gt;
# http://hanoi.kernelthread.com&lt;br /&gt;
#&lt;br /&gt;
# Тестировался под bash 2.05b.0(13)-release&lt;br /&gt;
#&lt;br /&gt;
# Используется в &amp;quot;Advanced Bash Scripting Guide&amp;quot;&lt;br /&gt;
# с разрешения автора.&lt;br /&gt;
# С небольшими изменениями, внесенными автором документа.&lt;br /&gt;
&lt;br /&gt;
#=================================================================#&lt;br /&gt;
# Ханойские Башни — это древняя математическая головоломка.&lt;br /&gt;
# Дается три вертикальных стержня.&lt;br /&gt;
# На первый нанизан набор колец.&lt;br /&gt;
# Эти кольца представляют собой плоские диски с дыркой по-середине,&lt;br /&gt;
# так что они могут свободно скользить по стержню.&lt;br /&gt;
# Кольца имеют различный диаметр, и изначально расположены на первом стержне&lt;br /&gt;
# в порядке убывания их диаметров.&lt;br /&gt;
# Наименьшее кольцо расположено сверху, наибольшее — внизу.&lt;br /&gt;
#&lt;br /&gt;
# Суть задачи заключается в том, чтобы перенести кольца с первого&lt;br /&gt;
# стержня на последний так, чтобы порядок следования колец не изменился.&lt;br /&gt;
# Кольца можно перемещать со стержня на стержень только по одному за раз.&lt;br /&gt;
# Можно помещать кольца обратно на тот же самый стержень.&lt;br /&gt;
# При перемещении нельзя класть больший диск на меньший.&lt;br /&gt;
#&lt;br /&gt;
# Для небольшого количества колец требуется некоторое количество перемещений.&lt;br /&gt;
# Каждое дополнительное кольцо&lt;br /&gt;
# увеличивает необходимое количество перемещений примерно в два раза,&lt;br /&gt;
# при этом &amp;quot;стратегия&amp;quot; перемещения усложняется все больше и больше.&lt;br /&gt;
#&lt;br /&gt;
# За дополнительной информацией обращайтесь на http://hanoi.kernelthread.com.&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
#        ...                ...                   ...&lt;br /&gt;
#        | |                | |                   | |&lt;br /&gt;
#       _|_|_               | |                   | |&lt;br /&gt;
#      |_____|              | |                   | |&lt;br /&gt;
#     |_______|             | |                   | |&lt;br /&gt;
#    |_________|            | |                   | |&lt;br /&gt;
#   |___________|           | |                   | |&lt;br /&gt;
#  |             |          | |                   | |&lt;br /&gt;
# .--------------------------------------------------------------.&lt;br /&gt;
# |**************************************************************|&lt;br /&gt;
#        #1                 #2                    #3#&lt;br /&gt;
#=================================================================#&lt;br /&gt;
&lt;br /&gt;
E_NOPARAM=66  # Сценарий запущен без параметров.&lt;br /&gt;
E_BADPARAM=67 # Неверное число колец.&lt;br /&gt;
Moves=        # Глобальная переменная, хранит число перемещений.&lt;br /&gt;
              # Добавлено в оригинальный сценарий.&lt;br /&gt;
&lt;br /&gt;
dohanoi() { # Рекурсивная функция.&lt;br /&gt;
 case $1 in&lt;br /&gt;
  0)&lt;br /&gt;
    ;;&lt;br /&gt;
  *)&lt;br /&gt;
    dohanoi &amp;quot;$(($1-1))&amp;quot; $2 $4 $3&lt;br /&gt;
    echo move $2 &amp;quot;--&amp;gt;&amp;quot; $3&lt;br /&gt;
     let &amp;quot;Moves += 1&amp;quot; # Добавлено в оригинальный сценарий.&lt;br /&gt;
    dohanoi &amp;quot;$(($1-1))&amp;quot; $4 $3 $2&lt;br /&gt;
    ;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
case $# in&lt;br /&gt;
 1)&lt;br /&gt;
   case $(($1&amp;gt;0)) in # Как минимум должен быть хотя бы один диск.&lt;br /&gt;
    1)&lt;br /&gt;
      dohanoi $1 1 3 2&lt;br /&gt;
      echo &amp;quot;Всего перемещений = $Moves&amp;quot;&lt;br /&gt;
      exit 0;&lt;br /&gt;
      ;;&lt;br /&gt;
    *)&lt;br /&gt;
      echo &amp;quot;$0: Неверное число колец&amp;quot;;&lt;br /&gt;
      exit $E_BADPARAM;&lt;br /&gt;
      ;;&lt;br /&gt;
    esac&lt;br /&gt;
    ;;&lt;br /&gt;
 *)&lt;br /&gt;
   echo &amp;quot;Порядок использования: $0 N&amp;quot;&lt;br /&gt;
   echo &amp;quot; Где \&amp;quot;N\&amp;quot; — это число колец.&amp;quot;&lt;br /&gt;
   exit $E_NOPARAM;&lt;br /&gt;
   ;;&lt;br /&gt;
esac&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ---------&lt;br /&gt;
# 1) Будут ли исполнены дополнительные команды, если разместить их ниже этой строки?&lt;br /&gt;
# Почему нет? (Это так просто!)&lt;br /&gt;
# 2) Объясните — как работает функция &amp;quot;dohanoi&amp;quot;.&lt;br /&gt;
# (А вот это уже сложнее)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Псевдонимы ==&lt;br /&gt;
''Псевдонимы'' в Bash — это ни что иное, как &amp;quot;горячие клавиши&amp;quot;, средство, позволяющее избежать набора длинных строк в командной строке. Если, к примеру, в файл&lt;br /&gt;
''~/.bashrc'' вставить строку '''''alias lm=&amp;quot;ls -l | more&amp;quot;''''', то потом вы сможете экономить свои силы и время, набирая команду '''lm'', вместо более длинной '''''ls -l | more'''''. Установив '''''alias rm=&amp;quot;rm -i&amp;quot;''''' (интерактивный режим удаления файлов), Вы сможете избежать многих неприятностей, потому что сократится вероятность удаления важных файлов по неосторожности.&amp;lt;br /&amp;gt;&lt;br /&gt;
Псевдонимы в сценариях могут иметь весьма ограниченную область применения. Было бы здорово, если бы псевдонимы имели функциональность, присущую макроопределениям в языке C, но, к сожалению, Bash не может &amp;quot;разворачивать&amp;quot; аргументы в теле псевдонима. Кроме того, попытка обратиться к псевдониму, созданному внутри &amp;quot;составных конструкций&amp;quot;, таких как ''if/then'', циклы и функции, будет приводить к появлению ошибок. Практически всегда, действия, возлагаемые на псевдоним, более эффективно могут быть выполнены с помощью функций.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Псевдонимы в сценарии.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
shopt -s expand_aliases&lt;br /&gt;
# Эта опция должна быть включена, иначе сценарий не сможет &amp;quot;разворачивать&amp;quot; псевдонимы.&lt;br /&gt;
&lt;br /&gt;
alias ll=&amp;quot;ls -l&amp;quot;&lt;br /&gt;
# В определении псевдонима можно использовать как одиночные ('), так и двойные (&amp;quot;) кавычки.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Попытка обращения к псевдониму \&amp;quot;ll\&amp;quot;:&amp;quot;&lt;br /&gt;
ll /usr/X11R6/bin/mk* #* Работает.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
directory=/usr/X11R6/bin/&lt;br /&gt;
prefix=mk* # Определить -- не будет ли проблем с шаблонами.&lt;br /&gt;
echo &amp;quot;Переменные \&amp;quot;directory\&amp;quot; + \&amp;quot;prefix\&amp;quot; = $directory$prefix&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
alias lll=&amp;quot;ls -l $directory$prefix&amp;quot;&lt;br /&gt;
echo &amp;quot;Попытка обращения к псевдониму \&amp;quot;lll\&amp;quot;:&amp;quot;&lt;br /&gt;
lll # Список всех файлов в /usr/X11R6/bin, чьи имена начинаются с mk.&lt;br /&gt;
# Псевдонимы могут работать с шаблонами.&lt;br /&gt;
TRUE=1&lt;br /&gt;
echo&lt;br /&gt;
if [ TRUE ]&lt;br /&gt;
then&lt;br /&gt;
 alias rr=&amp;quot;ls -l&amp;quot;&lt;br /&gt;
 echo &amp;quot;Попытка обращения к псевдониму \&amp;quot;rr\&amp;quot;, созданному внутри if/then:&amp;quot;&lt;br /&gt;
 rr /usr/X11R6/bin/mk* #* В результате -- сообщение об ошибке!&lt;br /&gt;
 # К псевдонимам, созданным внутри составных инструкций, нельзя обратиться.&lt;br /&gt;
 echo &amp;quot;Однако, ранее созданный псевдоним остается работоспособным:&amp;quot;&lt;br /&gt;
 ll /usr/X11R6/bin/mk*&lt;br /&gt;
fi&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
count=0&lt;br /&gt;
while [ $count -lt 3 ]&lt;br /&gt;
do&lt;br /&gt;
 alias rrr=&amp;quot;ls -l&amp;quot;&lt;br /&gt;
 echo &amp;quot;Попытка обращения к псевдониму \&amp;quot;rrr\&amp;quot;, созданному внутри цикла \&amp;quot;while\&amp;quot;:&amp;quot;&lt;br /&gt;
 rrr /usr/X11R6/bin/mk* #* Так же возникает ошибка.&lt;br /&gt;
                        # alias.sh: line 57: rrr: command not found&lt;br /&gt;
 let count+=1&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo; echo&lt;br /&gt;
&lt;br /&gt;
alias xyz='cat $0' # Сценарий печатает себя самого.&lt;br /&gt;
                   # Обратите внимание на &amp;quot;строгие&amp;quot; кавычки.&lt;br /&gt;
xyz&lt;br /&gt;
# Похоже работает,&lt;br /&gt;
# хотя документация Bash утверждает, что такой псевдоним не должен работать.&lt;br /&gt;
#&lt;br /&gt;
# Steve Jacobson отметил, что параметр &amp;quot;$0&amp;quot; интерпретируется непосредственно, во время объявления псевдонима.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''unalias''''' удаляет псевдоним, объявленный ранее.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''unalias: Объявление и удаление псевдонимов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
shopt -s expand_aliases # Разрешить &amp;quot;разворачивание&amp;quot; псевдонимов.&lt;br /&gt;
&lt;br /&gt;
alias llm='ls -al | more'&lt;br /&gt;
llm&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
unalias llm # Удалить псевдоним.&lt;br /&gt;
llm&lt;br /&gt;
# Сообщение об ошибке, т.к. команда 'llm' больше не распознается.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ./unalias.sh&lt;br /&gt;
total 6&lt;br /&gt;
drwxrwxr-x 2 bozo bozo 3072 Feb 6 14:04 .&lt;br /&gt;
drwxr-xr-x 40 bozo bozo 2048 Feb 6 14:04 ..&lt;br /&gt;
-rwxr-xr-x 1 bozo bozo 199 Feb 6 14:04 unalias.sh&lt;br /&gt;
./unalias.sh: llm: command not found&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Списки команд ==&lt;br /&gt;
Средством обработки последовательности из нескольких команд служат списки: &amp;quot;''И-списки''&amp;quot; и &amp;quot;''ИЛИ-списки''&amp;quot;. Они эффективно могут заменить сложную последовательность вложенных '''''if/then''''' или даже '''''case'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Объединение команд в цепочки'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''И-список''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''command-1 &amp;amp;&amp;amp; command-2 &amp;amp;&amp;amp; command-3 &amp;amp;&amp;amp; ... command-n''&amp;lt;br /&amp;gt;&lt;br /&gt;
Каждая последующая команда, в таком списке, выполняется только тогда, когда предыдущая команда вернула код завершения ''true''(ноль). Если какая-либо из команд возвращает ''false''(не ноль), то исполнение списка команд в этом месте завершается, т.е. следующие далее команды не выполняются.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка аргументов командной строки с помощью &amp;quot;И-списка&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# &amp;quot;И-список&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ ! -z &amp;quot;$1&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;Аргумент #1 = $1&amp;quot; &amp;amp;&amp;amp; [ ! -z &amp;quot;$2&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;Аргумент #2 = $2&amp;quot;&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Сценарию передано не менее 2 аргументов.&amp;quot;&lt;br /&gt;
 # Все команды в цепочке возвращают true.&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Сценарию передано менее 2 аргументов.&amp;quot;&lt;br /&gt;
 # Одна из команд в списке вернула false.&lt;br /&gt;
fi&lt;br /&gt;
# Обратите внимание: &amp;quot;if [ ! -z $1 ]&amp;quot; тоже работает, но, казалось бы эквивалентный вариант&lt;br /&gt;
# if [ -n $1 ] — нет. Однако, если добавить кавычки&lt;br /&gt;
# if [ -n &amp;quot;$1&amp;quot; ] то всё работает. Будьте внимательны!&lt;br /&gt;
# Проверяемые переменные лучше всегда заключать в кавычки.&lt;br /&gt;
&lt;br /&gt;
# То же самое, только без списка команд.&lt;br /&gt;
if [ ! -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Аргумент #1 = $1&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
if [ ! -z &amp;quot;$2&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Аргумент #2 = $2&amp;quot;&lt;br /&gt;
 echo &amp;quot;Сценарию передано не менее 2 аргументов.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Сценарию передано менее 2 аргументов.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# Получилось менее элегантно и длиннее, чем с использованием &amp;quot;И-списка&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ещё один пример проверки аргументов с помощью &amp;quot;И-списков&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
ARGS=1 # Ожидаемое число аргументов.&lt;br /&gt;
E_BADARGS=65 # Код завершения, если число аргументов меньше ожидаемого.&lt;br /&gt;
&lt;br /&gt;
test $# -ne $ARGS &amp;amp;&amp;amp; echo &amp;quot;Порядок использования: `basename $0` $ARGS аргумент(а)(ов)&amp;quot; &amp;amp;&amp;amp; exit $E_BADARGS&lt;br /&gt;
# Если проверка первого условия возвращает true (неверное число аргументов),&lt;br /&gt;
# то исполняется остальная часть строки, и сценарий завершается.&lt;br /&gt;
&lt;br /&gt;
# Строка ниже выполняется только тогда, когда проверка выше не проходит.&lt;br /&gt;
# обратите внимание на условие &amp;quot;-ne&amp;quot; — &amp;quot;не равно&amp;quot; (прим. перев.)&lt;br /&gt;
echo &amp;quot;Сценарию передано корректное число аргументов.&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
# Проверьте код завершения сценария командой &amp;quot;echo $?&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конечно же, с помощью ''И-списка'' можно присваивать переменным значения по-умолчанию.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
arg1=$@ # В $arg1 записать аргументы командной строки.&lt;br /&gt;
&lt;br /&gt;
[ -z &amp;quot;$arg1&amp;quot; ] &amp;amp;&amp;amp; arg1=DEFAULT&lt;br /&gt;
# Записать DEFAULT, если аргументы командной строки отсутствуют.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;''ИЛИ-список''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''command-1 || command-2 || command-3 || ... command-n''&amp;lt;br /&amp;gt;&lt;br /&gt;
Каждая последующая команда, в таком списке, выполняется только тогда, когда предыдущая команда вернула код завершения ''false''(не ноль). Если какая-либо из команд возвращает ''true''(ноль), то исполнение cписка команд в этом месте завершается, т.е. следующие далее команды не выполняются. Очевидно, что &amp;quot;''ИЛИ-списки''&amp;quot; имеют смысл обратный, по отношению к &amp;quot;''И-спискам''&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ещё один пример проверки аргументов с помощью &amp;quot;И-списков&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# delete.sh, утилита удаления файлов.&lt;br /&gt;
# Порядок использования: delete имя_файла&lt;br /&gt;
E_BADARGS=65if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя_файла&amp;quot;&lt;br /&gt;
 exit $E_BADARGS # Если не задано имя файла.&lt;br /&gt;
else&lt;br /&gt;
 file=$1 # Запомнить имя файла.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
[ ! -f &amp;quot;$file&amp;quot; ] &amp;amp;&amp;amp; echo &amp;quot;Файл \&amp;quot;$file\&amp;quot; не найден. \&lt;br /&gt;
Робкий отказ удаления несуществующего файла.&amp;quot;&lt;br /&gt;
# И-СПИСОК, выдать сообщение об ошибке, если файл не существует.&lt;br /&gt;
# Обратите внимание: выводимое сообщение продолжается во второй строке,&lt;br /&gt;
# благодаря экранированию символа перевода строки.&lt;br /&gt;
&lt;br /&gt;
[ ! -f &amp;quot;$file&amp;quot; ] || (rm -f $file; echo &amp;quot;Файл \&amp;quot;$file\&amp;quot; удален.&amp;quot;)&lt;br /&gt;
# ИЛИ-СПИСОК, удаляет существующий файл.&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание на логические условия.&lt;br /&gt;
# И-СПИСОК отрабатывает по true, ИЛИ-СПИСОК -- по false.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Списки возвращают код завершения последней выполненной команды'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Комбинируя &amp;quot;И&amp;quot; и &amp;quot;ИЛИ&amp;quot; списки, легко &amp;quot;перемудрить&amp;quot; с логическими условиями, поэтому, в таких случаях может потребоваться детальная отладка.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
false &amp;amp;&amp;amp; true || echo false # false&lt;br /&gt;
# Тот же результат даёт( false &amp;amp;&amp;amp; true ) || echo false # false&lt;br /&gt;
# Но не эта комбинация&lt;br /&gt;
false &amp;amp;&amp;amp; ( true || echo false ) # (нет вывода на экран)&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание на группировку и порядок вычисления условий — слева-направо,&lt;br /&gt;
# поскольку логические операции &amp;quot;&amp;amp;&amp;amp;&amp;quot; и &amp;quot;||&amp;quot; имеют равный приоритет.&lt;br /&gt;
# Если вы не уверены в своих действиях, то лучше избегать таких сложных конструкций.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Массивы ==&lt;br /&gt;
Новейшие версии Bash поддерживают одномерные массивы. Инициализация элементов массива может быть произведена в виде: ''variable[xx]''. Можно явно объявить массив в сценарии, с помощью директивы declare: '''''declare -a variable'''''. Обращаться к отдельным элементам массива можно с помощью фигурных скобок, т.е.: ''${variable[xx]}''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простой массив.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
area[11]=23&lt;br /&gt;
area[13]=37&lt;br /&gt;
area[51]=UFOs&lt;br /&gt;
&lt;br /&gt;
# Массивы не требуют, чтобы последовательность элементов в массиве была непрерывной.&lt;br /&gt;
# Некоторые элементы массива могут оставаться неинициализированными.&lt;br /&gt;
# &amp;quot;Дырки&amp;quot; в массиве не являются ошибкой.&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;area[11] = &amp;quot;&lt;br /&gt;
echo ${area[11]} # необходимы {фигурные скобки}&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;area[13] = &amp;quot;&lt;br /&gt;
echo ${area[13]}&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;содержимое area[51] = ${area[51]}.&amp;quot;&lt;br /&gt;
# Обращение к неинициализированным элементам дает пустую строку.&lt;br /&gt;
echo -n &amp;quot;area[43] = &amp;quot;&lt;br /&gt;
echo ${area[43]}&lt;br /&gt;
echo &amp;quot;(элемент area[43] — неинициализирован)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
# Сумма двух элементов массива, записанная в третий элемент&lt;br /&gt;
area[5]=`expr ${area[11]} + ${area[13]}`&lt;br /&gt;
echo &amp;quot;area[5] = area[11] + area[13]&amp;quot;&lt;br /&gt;
echo -n &amp;quot;area[5] = &amp;quot;&lt;br /&gt;
echo ${area[5]}&lt;br /&gt;
&lt;br /&gt;
area[6]=`expr ${area[11]} + ${area[51]}`&lt;br /&gt;
echo &amp;quot;area[6] = area[11] + area[51]&amp;quot;&lt;br /&gt;
echo -n &amp;quot;area[6] = &amp;quot;&lt;br /&gt;
echo ${area[6]}&lt;br /&gt;
# Эта попытка закончится неудачей, поскольку сложение целого числа со строкой не допускается.&lt;br /&gt;
&lt;br /&gt;
echo; echo; echo&lt;br /&gt;
&lt;br /&gt;
# -----------------------------------------------------------------&lt;br /&gt;
# Другой массив, &amp;quot;area2&amp;quot;.&lt;br /&gt;
# И другой способ инициализации массива...&lt;br /&gt;
# array_name=( XXX YYY ZZZ ... )&lt;br /&gt;
&lt;br /&gt;
area2=( ноль один два три четыре )&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;area2[0] = &amp;quot;&lt;br /&gt;
echo ${area2[0]}&lt;br /&gt;
# Ага, индексация начинается с нуля (первый элемент массива имеет индекс [0], а не [1]).&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;area2[1] = &amp;quot;&lt;br /&gt;
echo ${area2[1]} # [1] -- второй элемент массива.&lt;br /&gt;
# -----------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
echo; echo; echo&lt;br /&gt;
&lt;br /&gt;
# -----------------------------------------------&lt;br /&gt;
# Ещё один массив, &amp;quot;area3&amp;quot;.&lt;br /&gt;
# И ещё один способ инициализации...&lt;br /&gt;
# array_name=([xx]=XXX [yy]=YYY ...)&lt;br /&gt;
&lt;br /&gt;
area3=([17]=семнадцать [21]=двадцать_один)&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;area3[17] = &amp;quot;&lt;br /&gt;
echo ${area3[17]}&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;area3[21] = &amp;quot;&lt;br /&gt;
echo ${area3[21]}&lt;br /&gt;
# -----------------------------------------------&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash позволяет оперировать переменными, как массивами, даже если они не были явно объявлены таковыми.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
string=abcABC123ABCabc&lt;br /&gt;
echo ${string[@]} # abcABC123ABCabc&lt;br /&gt;
echo ${string[*]} # abcABC123ABCabc&lt;br /&gt;
echo ${string[0]} # abcABC123ABCabc&lt;br /&gt;
echo ${string[1]} # Ничего не выводится! Почему?&lt;br /&gt;
&lt;br /&gt;
echo ${#string[@]} # 1   Количество элементов в массиве.&lt;br /&gt;
# Спасибо Michael Zick за этот пример.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эти примеры ещё раз подтверждают &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;отсутствие контроля типов в Bash&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Форматирование стихотворения.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# poem.sh&lt;br /&gt;
# Строки из стихотворения (одна строфа).&lt;br /&gt;
&lt;br /&gt;
Line[1]=&amp;quot;Мой дядя самых честных правил,&amp;quot;&lt;br /&gt;
Line[2]=&amp;quot;Когда не в шутку занемог;&amp;quot;&lt;br /&gt;
Line[3]=&amp;quot;Он уважать себя заставил,&amp;quot;&lt;br /&gt;
Line[4]=&amp;quot;И лучше выдумать не мог.&amp;quot;&lt;br /&gt;
Line[5]=&amp;quot;Его пример другим наука...&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Атрибуты.&lt;br /&gt;
Attrib[1]=&amp;quot; А.С. Пушкин&amp;quot;&lt;br /&gt;
Attrib[2]=&amp;quot;\&amp;quot;Евгений Онегин\&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
for index in 1 2 3 4 5 # Пять строк.&lt;br /&gt;
do&lt;br /&gt;
 printf &amp;quot; %s\n&amp;quot; &amp;quot;${Line[index]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
for index in 1 2 # Две строки дополнительных атрибутов.&lt;br /&gt;
do&lt;br /&gt;
 printf &amp;quot; %s\n&amp;quot; &amp;quot;${Attrib[index]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
При работе с отдельными элементами массива можно использовать специфический синтаксис, даже стандартные команды и операторы Bash адаптированы для работы с массивами.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Различные операции над массивами.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# array-ops.sh: Операции над массивами.&lt;br /&gt;
&lt;br /&gt;
array=( ноль один два три четыре пять )&lt;br /&gt;
&lt;br /&gt;
echo ${array[0]} # ноль&lt;br /&gt;
echo ${array:0}  # ноль&lt;br /&gt;
                 # Подстановка параметра - первый элемент,&lt;br /&gt;
                 # начиная с позиции 0 (с 1-го символа).&lt;br /&gt;
echo ${array:1}  # ноль&lt;br /&gt;
                 # Подстановка параметра - первый элемент,&lt;br /&gt;
                 # начиная с позиции 1 (со 2-го символа).&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo ${#array[0]} # 4&lt;br /&gt;
                  # Длина первого элемента массива.&lt;br /&gt;
echo ${#array}    # 4&lt;br /&gt;
                  # Длина первого элемента массива.&lt;br /&gt;
                  # (Альтернативный вариант)&lt;br /&gt;
echo ${#array[1]} # 4&lt;br /&gt;
                  # Длина второго элемента массива.&lt;br /&gt;
                  # Индексация массивов в Bash начинается с нуля.&lt;br /&gt;
echo ${#array[*]} # 6&lt;br /&gt;
                  # Число элементов в массиве.&lt;br /&gt;
echo ${#array[@]} # 6&lt;br /&gt;
                  # Число элементов в массиве.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;--------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
array2=( [0]=&amp;quot;первый элемент&amp;quot; [1]=&amp;quot;второй элемент&amp;quot; [3]=&amp;quot;четвертый элемент&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
echo ${array2[0]} # первый элемент&lt;br /&gt;
echo ${array2[1]} # второй элемент&lt;br /&gt;
echo ${array2[2]} #&lt;br /&gt;
                  # Не был проинициализирован, поэтому null.&lt;br /&gt;
echo ${array2[3]} # четвёртый элемент&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Большинство стандартных операций над строками применимы к массивам.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Строковые операции и массивы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# array-strops.sh: Строковые операции и массивы.&lt;br /&gt;
# Автор: Michael Zick.&lt;br /&gt;
# Используется с его разрешения.&lt;br /&gt;
&lt;br /&gt;
# Как правило, строковые операции, в нотации ${name ... }&lt;br /&gt;
# могут использоваться для работы со строковыми элементами массивов&lt;br /&gt;
# в виде: ${name[@] ... } или ${name[*] ...} .&lt;br /&gt;
&lt;br /&gt;
arrayZ=( one two three four five five )&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
# Извлечение части строки&lt;br /&gt;
echo ${arrayZ[@]:0}   # one two three four five five&lt;br /&gt;
                      # Все элементы массива.&lt;br /&gt;
echo ${arrayZ[@]:1}   # two three four five five&lt;br /&gt;
                      # Все элементы массива, начиная со 2-го.&lt;br /&gt;
echo ${arrayZ[@]:1:2} # two three&lt;br /&gt;
                      # Два элемента массива, начиная со 2-го.&lt;br /&gt;
echo &amp;quot;-----------------------&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Удаление части строки&lt;br /&gt;
# Удаляет наименьшую из подстрок, найденных по шаблону (поиск ведётся с начала строки)&lt;br /&gt;
# где шаблон — это регулярное выражение.&lt;br /&gt;
&lt;br /&gt;
echo ${arrayZ[@]#f*r} # one two three five five&lt;br /&gt;
                      # Находит подстроку &amp;quot;four&amp;quot; и удаляет ее.&lt;br /&gt;
                      # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Удаляет наибольшую подстроку, из найденных по шаблону&lt;br /&gt;
echo ${arrayZ[@]##t*e} # one two four five five&lt;br /&gt;
                      # Находит подстроку &amp;quot;three&amp;quot; и удаляет её.&lt;br /&gt;
                      # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Удаляет наименьшую из подстрок, найденных по шаблону (поиск ведётся с конца строки)&lt;br /&gt;
echo ${arrayZ[@]%h*e} # one two t four five five&lt;br /&gt;
                      # Находит подстроку &amp;quot;hree&amp;quot; и удаляет её.&lt;br /&gt;
                      # Поиск ведется по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Удаляет наибольшую из подстрок, найденных по шаблону (поиск ведётся с конца строки)&lt;br /&gt;
echo ${arrayZ[@]%%t*e} # one two four five five&lt;br /&gt;
                       # Находит подстроку &amp;quot;three&amp;quot; и удаляет её.&lt;br /&gt;
                       # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;-----------------------&amp;quot;&lt;br /&gt;
# Замена части строки&lt;br /&gt;
&lt;br /&gt;
# Заменяет первую найденную подстроку заданной строкой&lt;br /&gt;
echo ${arrayZ[@]/fiv/XYZ} # one two three four XYZe XYZe&lt;br /&gt;
                          # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Заменяет все найденные подстроки&lt;br /&gt;
echo ${arrayZ[@]//iv/YY} # one two three four fYYe fYYe&lt;br /&gt;
                         # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Удаляет все найденные подстроки&lt;br /&gt;
# Если замещающая строка не задана, то это означает &amp;quot;удаление&amp;quot;&lt;br /&gt;
echo ${arrayZ[@]//fi/} # one two three four ve ve&lt;br /&gt;
                       # Поиск ведется по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Заменяет первую найденную подстроку (поиск ведётся с начала строки)&lt;br /&gt;
echo ${arrayZ[@]/#fi/XY} # one two three four XYve XYve&lt;br /&gt;
                         # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
# Заменяет первую найденную подстроку (поиск ведется с конца строки)&lt;br /&gt;
echo ${arrayZ[@]/%ve/ZZ} # one two three four fiZZ fiZZ&lt;br /&gt;
                         # Поиск ведётся по всем элементам массива&lt;br /&gt;
&lt;br /&gt;
echo ${arrayZ[@]/%o/XX} # one twXX three four five five&lt;br /&gt;
                        # Почему?&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;-----------------------&amp;quot;&lt;br /&gt;
# Before reaching for awk (or anything else)&lt;br /&gt;
# Вспомним:&lt;br /&gt;
# $( ... ) — вызов функции.&lt;br /&gt;
# Функция запускается как подпроцесс.&lt;br /&gt;
# Функции выводят на stdout.&lt;br /&gt;
# Присваивание производится со stdout функции.&lt;br /&gt;
# Запись name[@] — означает операцию &amp;quot;for-each&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
newstr() {&lt;br /&gt;
 echo -n &amp;quot;!!!&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo ${arrayZ[@]/%e/$(newstr)}&lt;br /&gt;
# on!!! two thre!!! four fiv!!! fiv!!!&lt;br /&gt;
# Q.E.D: Замена — суть есть &amp;quot;присваивание&amp;quot;.&lt;br /&gt;
# Доступ &amp;quot;For-Each&amp;quot; — ко всем элементам массива&lt;br /&gt;
echo ${arrayZ[@]//*/$(newstr optional_arguments)}&lt;br /&gt;
# Теперь, если бы Bash просто передал согласованную строку как $0&lt;br /&gt;
# к вызываемой функции...&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подстановка команд может создавать отдельные элементы массива.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Загрузка исходного текста сценария в массив.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# script-array.sh: Сценарий загружает себя в массив.&lt;br /&gt;
# Идею подал Chris Martin (спасибо!).&lt;br /&gt;
&lt;br /&gt;
script_contents=( $(cat &amp;quot;$0&amp;quot;) ) # Записать содержимое этого сценария ($0)&lt;br /&gt;
                                # в массив.&lt;br /&gt;
&lt;br /&gt;
for element in $(seq 0 $((${#script_contents[@]} - 1)))&lt;br /&gt;
do                          # ${#script_contents[@]}&lt;br /&gt;
                            # даёт число элементов массива.&lt;br /&gt;
                            #&lt;br /&gt;
                            # Вопрос:&lt;br /&gt;
                            # Для чего необходима команда seq 0 ?&lt;br /&gt;
                            # Попробуйте заменить её на seq 1.&lt;br /&gt;
 echo -n &amp;quot;${script_contents[$element]}&amp;quot;&lt;br /&gt;
                            # Вывести элементы массива в одну строку,&lt;br /&gt;
 echo -n &amp;quot; — &amp;quot;              # разделяя их комбинацией &amp;quot; — &amp;quot; .&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# --------&lt;br /&gt;
# Попробуйте изменить сценарий таким образом,&lt;br /&gt;
# чтобы он выводил себя на экран в первоначальном виде,&lt;br /&gt;
# со всеми пробелами, переводами строк и т.п.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
При работе с массивами, некоторые встроенные команды Bash имеют несколько иной смысл. Например, '''''unset''''' — удаляет отдельные элементы массива, или даже массив целиком.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Некоторые специфичные особенности массивов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
declare -a colors&lt;br /&gt;
# Допускается объявление массива без указания его размера.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Введите ваши любимые цвета (разделяя их пробелами).&amp;quot;&lt;br /&gt;
&lt;br /&gt;
read -a colors # Введите хотя бы 3 цвета для демонстрации некоторых свойств массивов.&lt;br /&gt;
# Специфический ключ команды 'read',&lt;br /&gt;
# позволяющий вводить несколько элементов массива.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
element_count=${#colors[@]}&lt;br /&gt;
&lt;br /&gt;
# Получение количества элементов в массиве.&lt;br /&gt;
# element_count=${#colors[*]} — даёт тот же результат.&lt;br /&gt;
#&lt;br /&gt;
# Переменная &amp;quot;@&amp;quot; позволяет &amp;quot;разбивать&amp;quot; строку в кавычках на отдельные слова&lt;br /&gt;
# (выделяются слова, разделенные пробелами).&lt;br /&gt;
&lt;br /&gt;
index=0&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$index&amp;quot; -lt &amp;quot;$element_count&amp;quot; ]&lt;br /&gt;
do # Список всех элементов в массиве.&lt;br /&gt;
 echo ${colors[$index]}&lt;br /&gt;
 let &amp;quot;index = $index + 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# Каждый элемент массива выводится в отдельной строке.&lt;br /&gt;
# Если этого не требуется, то используйте echo -n &amp;quot;${colors[$index]} &amp;quot;&lt;br /&gt;
#&lt;br /&gt;
# Эквивалентный цикл &amp;quot;for&amp;quot;:&lt;br /&gt;
# for i in &amp;quot;${colors[@]}&amp;quot;&lt;br /&gt;
# do&lt;br /&gt;
#  echo &amp;quot;$i&amp;quot;&lt;br /&gt;
# done&lt;br /&gt;
# (Спасибо S.C.)&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
# Ещё один, более элегантный, способ вывода списка всех элементов массива.&lt;br /&gt;
echo ${colors[@]}    # ${colors[*]} даёт тот же результат.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Команда &amp;quot;unset&amp;quot; удаляет элементы из массива, или даже массив целиком.&lt;br /&gt;
unset colors[1]   # Удаление 2-го элемента массива.&lt;br /&gt;
                  # Тот же эффект даёт команда colors[1]=&lt;br /&gt;
&lt;br /&gt;
echo ${colors[@]} # Список всех элементов массива — 2-й элемент отсутствует.&lt;br /&gt;
&lt;br /&gt;
unset colors      # Удаление всего массива.&lt;br /&gt;
                  # Тот же эффект имеют команды unset colors[*]&lt;br /&gt;
                  # и unset colors[@].&lt;br /&gt;
echo; echo -n &amp;quot;Массив цветов опустошен.&amp;quot;&lt;br /&gt;
echo ${colors[@]} # Список элементов массива пуст.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Как видно из предыдущего примера, обращение к '''''${array_name[@]}''''' или '''''${array_name[*]}''''' относится ко всем элементам массива. Чтобы получить количество элементов массива, можно обратиться к '''''${#array_name[@]}''''' или к '''''${#array_name[*]}'''''. '''''${#array_name}''''' — это длина(количество символов) первого элемента массива, т.е. '''''${array_name[0]}'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пустые массивы и пустые элементы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# empty-array.sh&lt;br /&gt;
# Выражаю свою благодарность Stephane Chazelas за этот пример,&lt;br /&gt;
# и Michael Zick за его доработку.&lt;br /&gt;
&lt;br /&gt;
# Пустой массив — это не то же самое, что массив с пустыми элементами.&lt;br /&gt;
array0=( первый второй третий )&lt;br /&gt;
array1=( '' ) # &amp;quot;array1&amp;quot; имеет один пустой элемент.&lt;br /&gt;
array2=( )    # Массив &amp;quot;array2&amp;quot; не имеет ни одного элемента, т.е. пуст.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
ListArray()&lt;br /&gt;
{&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array0: ${array0[@]}&amp;quot;&lt;br /&gt;
echo &amp;quot;Элементы массива array1: ${array1[@]}&amp;quot;&lt;br /&gt;
echo &amp;quot;Элементы массива array2: ${array2[@]}&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Длина первого элемента массива array0 = ${#array0}&amp;quot;&lt;br /&gt;
echo &amp;quot;Длина первого элемента массива array1 = ${#array1}&amp;quot;&lt;br /&gt;
echo &amp;quot;Длина первого элемента массива array2 = ${#array2}&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Число элементов в массиве array0 = ${#array0[*]}&amp;quot; # 3&lt;br /&gt;
echo &amp;quot;Число элементов в массиве array1 = ${#array1[*]}&amp;quot; # 1 (сюрприз!)&lt;br /&gt;
echo &amp;quot;Число элементов в массиве array2 = ${#array2[*]}&amp;quot; # 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# ===================================================================&lt;br /&gt;
ListArray&lt;br /&gt;
# Попробуем добавить новые элементы в массивы&lt;br /&gt;
&lt;br /&gt;
# Добавление новых элементов в массивы.&lt;br /&gt;
array0=( &amp;quot;${array0[@]}&amp;quot; &amp;quot;новый1&amp;quot; )&lt;br /&gt;
array1=( &amp;quot;${array1[@]}&amp;quot; &amp;quot;новый1&amp;quot; )&lt;br /&gt;
array2=( &amp;quot;${array2[@]}&amp;quot; &amp;quot;новый1&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
ListArray&lt;br /&gt;
&lt;br /&gt;
# или&lt;br /&gt;
array0[${#array0[*]}]=&amp;quot;новый2&amp;quot;&lt;br /&gt;
array1[${#array1[*]}]=&amp;quot;новый2&amp;quot;&lt;br /&gt;
array2[${#array2[*]}]=&amp;quot;новый2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ListArray&lt;br /&gt;
# Теперь представим каждый массив как 'стек' ('stack')&lt;br /&gt;
# Команды выше, можно считать командами 'push' — добавление нового значения на вершину стека&lt;br /&gt;
# 'Глубина' стека:&lt;br /&gt;
height=${#array2[@]}&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Глубина стека array2 = $height&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Команда 'pop' — выталкивание элемента стека, находящегося на вершине:&lt;br /&gt;
unset array2[${#array2[@]}-1] # Индексация массивов начинается с нуля&lt;br /&gt;
height=${#array2[@]}&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;POP&amp;quot;&lt;br /&gt;
echo &amp;quot;Глубина стека array2, после выталкивания = $height&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ListArray&lt;br /&gt;
# Вывести только 2-й и 3-й элементы массива array0&lt;br /&gt;
from=1 # Индексация массивов начинается с нуля&lt;br /&gt;
to=2   #&lt;br /&gt;
declare -a array3=( ${array0[@]:1:2} )&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array3: ${array3[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Замена элементов по шаблону&lt;br /&gt;
declare -a array4=( ${array0[@]/второй/2-й} )&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array4: ${array4[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Замена строк по шаблону&lt;br /&gt;
declare -a array5=( ${array0[@]//новый?/старый} )&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array5: ${array5[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Надо лишь привыкнуть к такой записи...&lt;br /&gt;
declare -a array6=( ${array0[@]#*новый} )&lt;br /&gt;
echo # Это может вас несколько удивить&lt;br /&gt;
echo &amp;quot;Элементы массива array6: ${array6[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
declare -a array7=( ${array0[@]#новый1} )&lt;br /&gt;
echo # Теперь это вас уже не должно удивлять&lt;br /&gt;
echo &amp;quot;Элементы массива array7: ${array7[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Выглядит очень похоже на предыдущий вариант...&lt;br /&gt;
declare -a array8=( ${array0[@]/новый1/} )&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array8: ${array8[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Итак, что вы можете сказать обо всем этом?&lt;br /&gt;
&lt;br /&gt;
# Строковые операции выполняются последовательно, над каждым элементом в массиве var[@].&lt;br /&gt;
# Таким образом, BASH поддерживает векторные операции&lt;br /&gt;
# Если в результате операции получается пустая строка, то элемент массива &amp;quot;исчезает&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Вопрос: это относится к строкам в &amp;quot;строгих&amp;quot; или &amp;quot;мягких&amp;quot; кавычках?&lt;br /&gt;
&lt;br /&gt;
zap='новый*'&lt;br /&gt;
declare -a array9=( ${array0[@]/$zap/} )&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array9: ${array9[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;...А с платформы говорят: &amp;quot;Это город Ленинград!&amp;quot;...&amp;quot;&lt;br /&gt;
declare -a array10=( ${array0[@]#$zap} )&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Элементы массива array10: ${array10[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Сравните массивы array7 и array10&lt;br /&gt;
# Сравните массивы array8 и array9&lt;br /&gt;
# Ответ: в &amp;quot;мягких&amp;quot; кавычках.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Разница между '''''${array_name[@]}''''' и '''''${array_name[*]}''''' такая же, как между &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$@&amp;lt;/span&amp;gt; и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$*&amp;lt;/span&amp;gt;. Эти свойства массивов широко применяются на практике.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Копирование массивов.&lt;br /&gt;
array2=( &amp;quot;${array1[@]}&amp;quot; )&lt;br /&gt;
# или&lt;br /&gt;
array2=&amp;quot;${array1[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Добавить элемент.&lt;br /&gt;
array=( &amp;quot;${array[@]}&amp;quot; &amp;quot;новый элемент&amp;quot; )&lt;br /&gt;
# или&lt;br /&gt;
array[${#array[*]}]=&amp;quot;новый элемент&amp;quot;&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Операция &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;подстановки команд&amp;lt;/span&amp;gt; — '''''array=( element1 element2 ... elementN )''''', позволяет загружать содержимое текстовых файлов в массивы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
filename=sample_file&lt;br /&gt;
#           cat sample_file&lt;br /&gt;
#&lt;br /&gt;
#           1 a b c&lt;br /&gt;
#           2 d e fg&lt;br /&gt;
&lt;br /&gt;
declare -a array1array1=( `cat &amp;quot;$filename&amp;quot;`) # Загрузка содержимого файла $filename в массив array1.&lt;br /&gt;
&lt;br /&gt;
# Вывод на stdout.&lt;br /&gt;
#&lt;br /&gt;
# array1=( `cat &amp;quot;$filename&amp;quot; | tr '\n' ' '`)&lt;br /&gt;
#                         с заменой символов перевода строки на пробелы.&lt;br /&gt;
# Впрочем, в этом нет необходимости, поскольку Bash&lt;br /&gt;
# выполняет разбивку по словам заменяя символы перевода строки&lt;br /&gt;
# на пробелы автоматически.&lt;br /&gt;
&lt;br /&gt;
echo ${array1[@]} # список элементов массива.&lt;br /&gt;
#           1 a b c 2 d e fg&lt;br /&gt;
#&lt;br /&gt;
# Каждое &amp;quot;слово&amp;quot;, в текстовом файле, отделяемое от других пробелами&lt;br /&gt;
# заносится в отдельный элемент массива.&lt;br /&gt;
&lt;br /&gt;
element_count=${#array1[*]}&lt;br /&gt;
echo $element_count # 8&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Инициализация массивов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
# array-assign.bash&lt;br /&gt;
# Поскольку здесь рассматриваются операции, специфичные для Bash,&lt;br /&gt;
# файл сценария имеет расширение &amp;quot;.bash&amp;quot;.&lt;br /&gt;
# Copyright (c) Michael S. Zick, 2003, All rights reserved.&lt;br /&gt;
# Лицензионное соглашение: Допускается использование сценария# в любом виде без каких либо ограничений.&lt;br /&gt;
# Версия: $ID$&lt;br /&gt;
&lt;br /&gt;
# Основан на примере, предоставленном Stephane Chazelas,&lt;br /&gt;
# который включен в состав книги: Advanced Bash Scripting Guide.&lt;br /&gt;
&lt;br /&gt;
# Формат вывода команды 'times':&lt;br /&gt;
# User CPU &amp;lt;space&amp;gt; System CPU&lt;br /&gt;
# User CPU of dead children &amp;lt;space&amp;gt; System CPU of dead children&lt;br /&gt;
&lt;br /&gt;
# Bash предоставляет два способа записи всех элементов&lt;br /&gt;
# одного массива в другой.&lt;br /&gt;
# В Bash, версий 2.04, 2.05a и 2.05b,&lt;br /&gt;
# оба они пропускают 'пустые' элементы&lt;br /&gt;
# В более новых версиях добавлена возможность присваивания&lt;br /&gt;
# в виде [индекс]=значение.&lt;br /&gt;
&lt;br /&gt;
declare -a bigOne=( /dev/* )&lt;br /&gt;
echo&lt;br /&gt;
echo 'Условия проверки: Отсутствие кавычек, IFS по-умолчанию, Все-Элементы'&lt;br /&gt;
echo &amp;quot;Количество элементов в массиве: ${#bigOne[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# set -vx&lt;br /&gt;
echo&lt;br /&gt;
echo '- - проверяется: =( ${array[@]} ) - -'&lt;br /&gt;
times&lt;br /&gt;
declare -a bigTwo=( ${bigOne[@]} )&lt;br /&gt;
#                 ^              ^&lt;br /&gt;
times&lt;br /&gt;
echo&lt;br /&gt;
echo '- - проверяется: =${array[@]} - -'&lt;br /&gt;
times&lt;br /&gt;
declare -a bigThree=${bigOne[@]}&lt;br /&gt;
# Обратите внимание: круглые скобки отсутствуют.&lt;br /&gt;
times&lt;br /&gt;
# Сравнение временных показателей свидетельствует о том, что вторая форма записи,&lt;br /&gt;
# как заметил Stephane Chazelas, работает в 3-4 раза быстрее.&lt;br /&gt;
# Тем не менее, в своих примерах, я буду продолжать использовать первую форму записи&lt;br /&gt;
# потому что, на мой взгляд, она более показательна.&lt;br /&gt;
&lt;br /&gt;
# Однако, в отдельных случаях, я буду использовать вторую форму записи,&lt;br /&gt;
# с целью увеличения скорости исполнения сценариев.&lt;br /&gt;
# MSZ: Прошу прощения, что не предупредил об этом заранее!&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Явное объявление массива с помощью конструкции '''''declare -a''''' может повысить скорость работы с этим массивом в последующих операциях.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Копирование и конкатенация массивов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
# CopyArray.sh&lt;br /&gt;
#&lt;br /&gt;
# Автор: Michael Zick.&lt;br /&gt;
# Используется с его разрешения.&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;Принять из массива с заданным именем записать в массив с заданным именем&amp;quot;&lt;br /&gt;
# или &amp;quot;собственный Оператор Присваивания&amp;quot;.&lt;br /&gt;
CpArray_Mac() {&lt;br /&gt;
# Оператор Присваивания&lt;br /&gt;
 echo -n 'eval '&lt;br /&gt;
 echo -n &amp;quot;$2&amp;quot; # Имя массива-результата&lt;br /&gt;
 echo -n '=( ${'&lt;br /&gt;
 echo -n &amp;quot;$1&amp;quot; # Имя исходного массива&lt;br /&gt;
 echo -n '[@]} )'&lt;br /&gt;
# Все это могло бы быть объединено в одну команду.&lt;br /&gt;
# Это лишь вопрос стиля.&lt;br /&gt;
}&lt;br /&gt;
declare -f CopyArray # &amp;quot;Указатель&amp;quot; на функцию&lt;br /&gt;
CopyArray=CpArray_Mac # Оператор Присваивания&lt;br /&gt;
&lt;br /&gt;
Hype()&lt;br /&gt;
{&lt;br /&gt;
# Исходный массив с именем в $1.&lt;br /&gt;
# (Слить с массивом, содержащим &amp;quot;-- Настоящий Рок-н-Ролл&amp;quot;.)&lt;br /&gt;
# Вернуть результат в массиве с именем $2.&lt;br /&gt;
 local -a TMP&lt;br /&gt;
 local -a hype=( -- Настоящий Рок-н-Ролл )&lt;br /&gt;
&lt;br /&gt;
 $($CopyArray $1 TMP)&lt;br /&gt;
 TMP=( ${TMP[@]} ${hype[@]} )&lt;br /&gt;
 $($CopyArray TMP $2)&lt;br /&gt;
}&lt;br /&gt;
declare -a before=( Advanced Bash Scripting )&lt;br /&gt;
declare -a after&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Массив before = ${before[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Hype before after&lt;br /&gt;
echo &amp;quot;Массив after = ${after[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Ещё?&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Что такое ${after[@]:4:2}?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
declare -a modest=( ${after[@]:2:1} ${after[@]:3:3} )&lt;br /&gt;
#                    ---- выделение подстроки ----&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Массив Modest = ${modest[@]}&amp;quot;&lt;br /&gt;
# А что в массиве 'before' ?&lt;br /&gt;
echo &amp;quot;Массив Before = ${before[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ещё пример на конкатенацию массивов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
# array-append.bash&lt;br /&gt;
# Copyright (c) Michael S. Zick, 2003, All rights reserved.&lt;br /&gt;
# Лицензионное соглашение: Допускается использование сценария&lt;br /&gt;
# в любом виде без каких-либо ограничений.&lt;br /&gt;
# Версия: $ID$&lt;br /&gt;
#&lt;br /&gt;
# С небольшими изменениями, внесёнными автором книги.&lt;br /&gt;
&lt;br /&gt;
# Действия над массивами являются специфичными для Bash.&lt;br /&gt;
# Эквиваленты в /bin/sh отсутствуют!&lt;br /&gt;
&lt;br /&gt;
# Чтобы избежать скроллинга выводимой информации за пределы терминала,&lt;br /&gt;
# передайте вывод от сценария, через конвейер, команде 'more'.&lt;br /&gt;
# Упакованный массив.&lt;br /&gt;
declare -a array1=( zero1 one1 two1 )&lt;br /&gt;
# Разреженный массив (элемент [1] -- не определен).&lt;br /&gt;
declare -a array2=( [0]=zero2 [2]=two2 [3]=three2 )&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Проверка того, что массив получился разреженным. -'&lt;br /&gt;
echo &amp;quot;Число элементов: 4&amp;quot; # Жёстко &amp;quot;зашито&amp;quot;, в демонстрационных целях.&lt;br /&gt;
for (( i = 0 ; i &amp;lt; 4 ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Элемент [$i]: ${array2[$i]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# См. так же пример basics-reviewed.bash.&lt;br /&gt;
&lt;br /&gt;
declare -a dest&lt;br /&gt;
# Конкатенация двух массивов.&lt;br /&gt;
echo&lt;br /&gt;
echo 'Условия: Отсутствие кавычек, IFS по-умолчанию, Все-Элементы'&lt;br /&gt;
echo '- Неопределённые элементы не передаются. -'&lt;br /&gt;
#&lt;br /&gt;
# На самом деле неопределенные элементы отсутствуют в массиве.&lt;br /&gt;
dest=( ${array1[@]} ${array2[@]} )&lt;br /&gt;
# dest=${array1[@]}${array2[@]} # Странный результат, возможно ошибка.&lt;br /&gt;
&lt;br /&gt;
# Теперь выведем результат.&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Проверка конкатенации массивов - -'&lt;br /&gt;
cnt=${#dest[@]}&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Число элементов: $cnt&amp;quot;&lt;br /&gt;
for (( i = 0 ; i &amp;lt; cnt ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Элемент [$i]: ${dest[$i]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# Записать массив в элемент другого массива (дважды).&lt;br /&gt;
dest[0]=${array1[@]}&lt;br /&gt;
dest[1]=${array2[@]}&lt;br /&gt;
&lt;br /&gt;
# Вывести результат.&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Проверка записи содержимого одного массива в элемент другого массива - -'&lt;br /&gt;
cnt=${#dest[@]}&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Число элементов: $cnt&amp;quot;&lt;br /&gt;
for (( i = 0 ; i &amp;lt; cnt ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Элемент [$i]: ${dest[$i]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# Рассмотрение содержимого второго элемента.&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Запись содержимого второго элемента и вывод результата - -'&lt;br /&gt;
&lt;br /&gt;
declare -a subArray=${dest[1]}&lt;br /&gt;
cnt=${#subArray[@]}&lt;br /&gt;
echo &amp;quot;Число элементов: $cnt&amp;quot;&lt;br /&gt;
for (( i = 0 ; i &amp;lt; cnt ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Элемент [$i]: ${subArray[$i]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# Запись содержимого целого массива в элемент другого массива,&lt;br /&gt;
# с помощью конструкции '=${ ... }',&lt;br /&gt;
# приводит к преобразованию содержимого первого массива в строку,&lt;br /&gt;
# в которой отдельные элементы первого массива разделены пробелом&lt;br /&gt;
# (первый символ из переменной IFS).&lt;br /&gt;
&lt;br /&gt;
# If the original elements didn't contain whitespace . . .&lt;br /&gt;
# If the original array isn't subscript sparse . . .&lt;br /&gt;
# Then we could get the original array structure back again.&lt;br /&gt;
&lt;br /&gt;
# Restore from the modified second element.&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Listing restored element - -'&lt;br /&gt;
&lt;br /&gt;
declare -a subArray=( ${dest[1]} )&lt;br /&gt;
cnt=${#subArray[@]}&lt;br /&gt;
echo &amp;quot;Number of elements: $cnt&amp;quot;&lt;br /&gt;
for (( i = 0 ; i &amp;lt; cnt ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Element [$i]: ${subArray[$i]}&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
echo '- - Не зависеть от этого поведения. - -'&lt;br /&gt;
echo '- - Такое поведение может быть изменено - -'&lt;br /&gt;
echo '- - в версиях Bash, более новых, чем версия 2.05b - -'&lt;br /&gt;
&lt;br /&gt;
# MSZ: Прошу прощения за любую раннюю путаницу, ребята.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Массивы допускают перенос хорошо известных алгоритмов в сценарии на языке командной оболочки. Хорошо ли это — решать вам. &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Старая, добрая: &amp;quot;Пузырьковая&amp;quot; сортировка.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# bubble.sh: &amp;quot;Пузырьковая&amp;quot; сортировка.&lt;br /&gt;
&lt;br /&gt;
# На каждом проходе по сортируемому массиву,&lt;br /&gt;
# сравниваются два смежных элемента, и, если необходимо, они меняются местами.&lt;br /&gt;
# В конце первого прохода, самый &amp;quot;тяжелый&amp;quot; элемент &amp;quot;опускается&amp;quot; в конец массива.&lt;br /&gt;
# В конце второго прохода, следующий по &amp;quot;тяжести&amp;quot; элемент занимает второе место снизу.&lt;br /&gt;
# И так далее.&lt;br /&gt;
# Каждый последующий проход требует на одно сравнение меньше предыдущего.&lt;br /&gt;
# Поэтому вы должны заметить ускорение работы сценария на последних проходах.&lt;br /&gt;
&lt;br /&gt;
exchange()&lt;br /&gt;
{&lt;br /&gt;
 # Поменять местами два элемента массива.&lt;br /&gt;
 local temp=${Countries[$1]} # Временная переменная&lt;br /&gt;
 Countries[$1]=${Countries[$2]}&lt;br /&gt;
 Countries[$2]=$temp&lt;br /&gt;
 &lt;br /&gt;
 return&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
declare -a Countries # Объявление массива,&lt;br /&gt;
                     # необязательно, поскольку он явно инициализируется ниже.&lt;br /&gt;
# Допустимо ли выполнять инициализацию массива в нескольких строках?&lt;br /&gt;
# ДА!&lt;br /&gt;
&lt;br /&gt;
Countries=(Нидерланды Украина Заир Турция Россия Йемен Сирия \&lt;br /&gt;
Бразилия Аргентина Никарагуа Япония Мексика Венесуэла Греция Англия \&lt;br /&gt;
Израиль Перу Канада Оман Дания Уэльс Франция Кения \&lt;br /&gt;
Занаду Катар Лихтенштейн Венгрия)&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;Занаду&amp;quot; — это мифическое государство, где, согласно Coleridge,&lt;br /&gt;
# Kubla Khan построил величественный дворец.&lt;br /&gt;
&lt;br /&gt;
clear # Очистка экрана.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;0: ${Countries[*]}&amp;quot; # Список элементов несортированного массива.&lt;br /&gt;
&lt;br /&gt;
number_of_elements=${#Countries[@]}&lt;br /&gt;
let &amp;quot;comparisons = $number_of_elements - 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
count=1 # Номер прохода.&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$comparisons&amp;quot; -gt 0 ] # Начало внешнего цикла&lt;br /&gt;
do&lt;br /&gt;
 index=0 # Сбросить индекс перед началом каждого прохода.&lt;br /&gt;
 while [ &amp;quot;$index&amp;quot; -lt &amp;quot;$comparisons&amp;quot; ] # Начало внутреннего цикла&lt;br /&gt;
 do&lt;br /&gt;
  if [ ${Countries[$index]} \&amp;gt; ${Countries[`expr $index + 1`]} ]&lt;br /&gt;
  # Если элементы стоят не по порядку...&lt;br /&gt;
  # Оператор \&amp;gt; выполняет сравнение ASCII-строк&lt;br /&gt;
  # внутри одиночных квадратных скобок.&lt;br /&gt;
&lt;br /&gt;
  # if [[ ${Countries[$index]} &amp;gt; ${Countries[`expr $index + 1`]} ]]&lt;br /&gt;
  # даёт тот же результат.&lt;br /&gt;
  then&lt;br /&gt;
   exchange $index `expr $index + 1` # Поменять местами.&lt;br /&gt;
  fi&lt;br /&gt;
  let &amp;quot;index += 1&amp;quot;&lt;br /&gt;
 done # Конец внутреннего цикла&lt;br /&gt;
 let &amp;quot;comparisons -= 1&amp;quot; # Поскольку самый &amp;quot;тяжелый&amp;quot; элемент уже &amp;quot;опустился&amp;quot; на дно,&lt;br /&gt;
                       # то на каждом последующем проходе нужно выполнять на одно сравнение меньше.&lt;br /&gt;
&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;$count: ${Countries[@]}&amp;quot; # Вывести содержимое массива после каждого прохода.&lt;br /&gt;
 echo&lt;br /&gt;
 let &amp;quot;count += 1&amp;quot; # Увеличить счетчик проходов.&lt;br /&gt;
done # Конец внешнего цикла&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Можно ли вложить один массив в другой?&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# &amp;quot;Вложенный&amp;quot; массив.&lt;br /&gt;
&lt;br /&gt;
# Автор: Michael Zick.&lt;br /&gt;
# незначительные изменения и комментарии добавил William Park.&lt;br /&gt;
&lt;br /&gt;
AnArray=( $(ls --inode --ignore-backups --almost-all \&lt;br /&gt;
 --directory --full-time --color=none --time=status \&lt;br /&gt;
 --sort=time -l ${PWD} ) ) # Команды и опции.&lt;br /&gt;
&lt;br /&gt;
# Пробелы важны . . .&lt;br /&gt;
&lt;br /&gt;
SubArray=( ${AnArray[@]:11:1} ${AnArray[@]:6:5} )&lt;br /&gt;
# Этот массив содержит шесть элементов:&lt;br /&gt;
# SubArray=( [0]=${AnArray[11]} [1]=${AnArray[6]} [2]=${AnArray[7]}&lt;br /&gt;
# [3]=${AnArray[8]} [4]=${AnArray[9]} [5]=${AnArray[10]} )&lt;br /&gt;
#&lt;br /&gt;
# Массивы в Bash оформляются в виде связанных (циклических) списков&lt;br /&gt;
# где каждый элемент списка имеет тип string (char *).&lt;br /&gt;
# Таким образом, вложенные массивы фактически таковыми не являются,&lt;br /&gt;
# хотя функционально очень похожи на них.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Текущий каталог и дата последнего изменения:&amp;quot;&lt;br /&gt;
echo &amp;quot;${SubArray[@]}&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Вложенные массивы, в комбинации с &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;косвенными ссылками&amp;lt;/span&amp;gt;, предоставляют в распоряжение программиста ряд замечательных возможностей.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вложенные массивы и косвенные ссылки.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# embedded-arrays.sh&lt;br /&gt;
# Вложенные массивы и косвенные ссылки.&lt;br /&gt;
&lt;br /&gt;
# Автор: Dennis Leeuw.&lt;br /&gt;
# Используется с его разрешения.&lt;br /&gt;
# Дополнен автором документа.&lt;br /&gt;
ARRAY1=(&lt;br /&gt;
        VAR1_1=value11&lt;br /&gt;
        VAR1_2=value12&lt;br /&gt;
        VAR1_3=value13&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
ARRAY2=(&lt;br /&gt;
        VARIABLE=&amp;quot;test&amp;quot;&lt;br /&gt;
        STRING=&amp;quot;VAR1=value1 VAR2=value2 VAR3=value3&amp;quot;&lt;br /&gt;
        ARRAY21=${ARRAY1[*]}&lt;br /&gt;
) # Вложение массива ARRAY1 в массив ARRAY2.&lt;br /&gt;
&lt;br /&gt;
function print () {&lt;br /&gt;
         OLD_IFS=&amp;quot;$IFS&amp;quot;&lt;br /&gt;
         IFS=$'\n' # Вывод каждого элемента массива в отдельной строке.&lt;br /&gt;
         TEST1=&amp;quot;ARRAY2[*]&amp;quot;&lt;br /&gt;
         local ${!TEST1} # Посмотрите, что произойдет, если убрать эту строку.&lt;br /&gt;
         # Косвенная ссылка.&lt;br /&gt;
         # Позволяет получить доступ к компонентам $TEST1 в этой функции.&lt;br /&gt;
&lt;br /&gt;
         # Посмотрим, что получилось.&lt;br /&gt;
         echo&lt;br /&gt;
         echo &amp;quot;\$TEST1 = $TEST1&amp;quot; # Просто имя переменной.&lt;br /&gt;
         echo; echo&lt;br /&gt;
         echo &amp;quot;{\$TEST1} = ${!TEST1}&amp;quot; # Вывод на экран содержимого переменной.&lt;br /&gt;
                                      # Это то, что даёт косвенная ссылка.&lt;br /&gt;
         echo&lt;br /&gt;
         echo &amp;quot;-------------------------------------------&amp;quot;; echo&lt;br /&gt;
         echo&lt;br /&gt;
&lt;br /&gt;
         # Вывод переменной&lt;br /&gt;
         echo &amp;quot;Переменная VARIABLE: $VARIABLE&amp;quot;&lt;br /&gt;
&lt;br /&gt;
         # Вывод элементов строки&lt;br /&gt;
         IFS=&amp;quot;$OLD_IFS&amp;quot;&lt;br /&gt;
         TEST2=&amp;quot;STRING[*]&amp;quot;&lt;br /&gt;
         local ${!TEST2} # Косвенная ссылка (то же, что и выше).&lt;br /&gt;
         echo &amp;quot;Элемент VAR2: $VAR2 из строки STRING&amp;quot;&lt;br /&gt;
&lt;br /&gt;
         # Вывод элемента массива&lt;br /&gt;
         TEST2=&amp;quot;ARRAY21[*]&amp;quot;&lt;br /&gt;
         local ${!TEST2} # Косвенная ссылка.&lt;br /&gt;
         echo &amp;quot;Элемент VAR1_1: $VAR1_1 из массива ARRAY21&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
print&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0     &lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
С помощью массивов, на языке командной оболочки, вполне возможно реализовать алгоритм ''Решета Эратосфена''. Конечно же — это очень ресурсоёмкая задача. В виде сценария она будет работать мучительно долго, так что лучше всего реализовать её на каком-либо другом, компилирующем, языке программирования, таком как C.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример реализации алгоритма Решето Эратосфена.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# sieve.sh&lt;br /&gt;
&lt;br /&gt;
# Решето Эратосфена&lt;br /&gt;
# Очень старый алгоритм поиска простых чисел.&lt;br /&gt;
&lt;br /&gt;
# Этот сценарий выполняется во много раз медленнее&lt;br /&gt;
# чем аналогичная программа на C.&lt;br /&gt;
&lt;br /&gt;
LOWER_LIMIT=1 # Начиная с 1.&lt;br /&gt;
UPPER_LIMIT=1000 # До 1000.&lt;br /&gt;
# (Вы можете установить верхний предел и выше... если вам есть чем себя занять.)&lt;br /&gt;
&lt;br /&gt;
PRIME=1&lt;br /&gt;
NON_PRIME=0&lt;br /&gt;
declare -a Primes # Primes[] — массив.&lt;br /&gt;
&lt;br /&gt;
initialize ()&lt;br /&gt;
{&lt;br /&gt;
# Инициализация массива.&lt;br /&gt;
i=$LOWER_LIMIT&lt;br /&gt;
until [ &amp;quot;$i&amp;quot; -gt &amp;quot;$UPPER_LIMIT&amp;quot; ]&lt;br /&gt;
 do&lt;br /&gt;
  Primes[i]=$PRIME&lt;br /&gt;
  let &amp;quot;i += 1&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
# Все числа в заданном диапазоне считать простыми,&lt;br /&gt;
# пока не доказано обратное.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
print_primes ()&lt;br /&gt;
{&lt;br /&gt;
# Вывод индексов элементов массива Primes[], которые признаны простыми.&lt;br /&gt;
i=$LOWER_LIMIT&lt;br /&gt;
until [ &amp;quot;$i&amp;quot; -gt &amp;quot;$UPPER_LIMIT&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 if [ &amp;quot;${Primes[i]}&amp;quot; -eq &amp;quot;$PRIME&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  printf &amp;quot;%8d&amp;quot; $i&lt;br /&gt;
  # 8 пробелов перед числом придают удобочитаемый табличный вывод на экран.&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;i += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
sift () # Отсеивание составных чисел.&lt;br /&gt;
{&lt;br /&gt;
let i=$LOWER_LIMIT+1&lt;br /&gt;
# Нам известно, что 1 — это простое число, поэтому начнем с 2.&lt;br /&gt;
 &lt;br /&gt;
until [ &amp;quot;$i&amp;quot; -gt &amp;quot;$UPPER_LIMIT&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 if [ &amp;quot;${Primes[i]}&amp;quot; -eq &amp;quot;$PRIME&amp;quot; ]&lt;br /&gt;
 # Не следует проверять вторично числа, которые уже признаны составными.&lt;br /&gt;
 then&lt;br /&gt;
  t=$i&lt;br /&gt;
&lt;br /&gt;
  while [ &amp;quot;$t&amp;quot; -le &amp;quot;$UPPER_LIMIT&amp;quot; ]&lt;br /&gt;
  do&lt;br /&gt;
   let &amp;quot;t += $i &amp;quot;&lt;br /&gt;
   Primes[t]=$NON_PRIME&lt;br /&gt;
   # Все числа, которые делятся на $t без остатка, пометить как составные.&lt;br /&gt;
  done&lt;br /&gt;
 fi&lt;br /&gt;
  let &amp;quot;i += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Вызов функций.&lt;br /&gt;
initialize&lt;br /&gt;
sift&lt;br /&gt;
printprimes&lt;br /&gt;
&lt;br /&gt;
# Это называется структурным программированием.&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
# ----------------------------------------------- #&lt;br /&gt;
# Код, приведенный ниже, не исполняется из-за команды exit, стоящей выше.&lt;br /&gt;
&lt;br /&gt;
# Улучшенная версия, предложенная Stephane Chazelas,&lt;br /&gt;
# работает несколько быстрее.&lt;br /&gt;
&lt;br /&gt;
# Должен вызываться с аргументом командной строки, определяющем верхний предел.&lt;br /&gt;
UPPER_LIMIT=$1 # Из командной строки.&lt;br /&gt;
let SPLIT=UPPER_LIMIT/2 # Рассматривать делители только до середины диапазона.&lt;br /&gt;
&lt;br /&gt;
Primes=( '' $(seq $UPPER_LIMIT) )&lt;br /&gt;
&lt;br /&gt;
i=1&lt;br /&gt;
until (( ( i += 1 ) &amp;gt; SPLIT )) # Числа из верхней половины диапазона могут не рассматриваться.&lt;br /&gt;
do&lt;br /&gt;
 if [[ -n $Primes[i] ]]&lt;br /&gt;
 then&lt;br /&gt;
  t=$i&lt;br /&gt;
  until (( ( t += i ) &amp;gt; UPPER_LIMIT ))&lt;br /&gt;
  do&lt;br /&gt;
   Primes[t]=&lt;br /&gt;
  done&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
echo ${Primes[*]}&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сравните этот сценарий с генератором простых чисел, не использующим массивов. Массивы позволяют эмулировать некоторые структуры данных, поддержка которых в Bash не предусмотрена.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Эмуляция структуры &amp;quot;СТЕК&amp;quot; (&amp;quot;первый вошёл — последний вышел&amp;quot;).'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# stack.sh: Эмуляция структуры &amp;quot;СТЕК&amp;quot; (&amp;quot;первый вошёл — последний вышел&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Подобно стеку процессора, этот &amp;quot;стек&amp;quot; сохраняет и возвращает данные по принципу&lt;br /&gt;
# &amp;quot;первый вошёл — последний вышел&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
BP=100          # Базовый указатель на массив-стек.&lt;br /&gt;
                # Дно стека — 100-й элемент.&lt;br /&gt;
&lt;br /&gt;
SP=$BP          # Указатель вершины стека.&lt;br /&gt;
                # Изначально — стек пуст.&lt;br /&gt;
&lt;br /&gt;
Data=           # Содержимое вершины стека.&lt;br /&gt;
                # Следует использовать дополнительную переменную,&lt;br /&gt;
                # из-за ограничений на диапазон возвращаемых функциями значений.&lt;br /&gt;
&lt;br /&gt;
declare -a stack&lt;br /&gt;
&lt;br /&gt;
push() # Поместить элемент на вершину стека.&lt;br /&gt;
{&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ] # А вообще, есть что помещать на стек?&lt;br /&gt;
then&lt;br /&gt;
 return&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;SP -= 1&amp;quot; # Переместить указатель стека.&lt;br /&gt;
stack[$SP]=$1&lt;br /&gt;
&lt;br /&gt;
return&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pop() # Снять элемент с вершины стека.&lt;br /&gt;
{&lt;br /&gt;
Data=                  # Очистить переменную.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$SP&amp;quot; -eq &amp;quot;$BP&amp;quot; ] # Стек пуст?&lt;br /&gt;
then&lt;br /&gt;
 return&lt;br /&gt;
fi                     # Это предохраняет от выхода SP за границу стека — 100,&lt;br /&gt;
&lt;br /&gt;
Data=${stack[$SP]}&lt;br /&gt;
let &amp;quot;SP += 1&amp;quot;          # Переместить указатель стека.&lt;br /&gt;
return&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
status_report()        # Вывод вспомогательной информации.&lt;br /&gt;
{&lt;br /&gt;
echo &amp;quot;-------------------------------------&amp;quot;&lt;br /&gt;
echo &amp;quot;ОТЧЁТ&amp;quot;&lt;br /&gt;
echo &amp;quot;Указатель стека SP = $SP&amp;quot;&lt;br /&gt;
echo &amp;quot;Со стека был снят элемент \&amp;quot;&amp;quot;$Data&amp;quot;\&amp;quot;&amp;quot;&lt;br /&gt;
echo &amp;quot;-------------------------------------&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# =======================================================&lt;br /&gt;
# А теперь позабавимся.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
# Попробуем вытолкнуть что-нибудь из пустого стека.&lt;br /&gt;
&lt;br /&gt;
pop&lt;br /&gt;
status_report&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
push garbage&lt;br /&gt;
pop&lt;br /&gt;
status_report # Втолкнуть garbage, вытолкнуть garbage.&lt;br /&gt;
&lt;br /&gt;
value1=23; push $value1&lt;br /&gt;
value2=skidoo; push $value2&lt;br /&gt;
value3=FINAL; push $value3&lt;br /&gt;
pop           # FINAL&lt;br /&gt;
status_report&lt;br /&gt;
pop           # skidoo&lt;br /&gt;
status_report&lt;br /&gt;
pop           # 23&lt;br /&gt;
status_report # Первый вошёл — последний вышел!&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание как изменяется указатель стека на каждом вызове функций push и pop.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
# =======================================================&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# -----------&lt;br /&gt;
&lt;br /&gt;
# 1) Измените функцию &amp;quot;push()&amp;quot; таким образом,&lt;br /&gt;
#  чтобы она позволяла помещать на стек несколько значений за один вызов.&lt;br /&gt;
&lt;br /&gt;
# 2) Измените функцию &amp;quot;pop()&amp;quot; таким образом,&lt;br /&gt;
#  чтобы она позволяла снимать со стека несколько значений за один вызов.&lt;br /&gt;
&lt;br /&gt;
# 3) Попробуйте написать простейший калькулятор, выполняющий 4 арифметических действия,&lt;br /&gt;
# используя этот пример.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Иногда, манипуляции с &amp;quot;индексами&amp;quot; массивов могут потребовать введения переменных для хранения промежуточных результатов. В таких случаях вам предоставляется лишний повод подумать о реализации проекта на более мощном языке программирования, например Perl или C.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Исследование математических последовательностей.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Пресловутая &amp;quot;Q-последовательность&amp;quot; Дугласа Хольфштадтера *Douglas Hofstadter):&lt;br /&gt;
&lt;br /&gt;
# Q(1) = Q(2) = 1&lt;br /&gt;
# Q(n) = Q(n - Q(n-1)) + Q(n - Q(n-2)), для n&amp;gt;2&lt;br /&gt;
# Это &amp;quot;хаотическая&amp;quot; последовательность целых чисел с непредсказуемым поведением.&lt;br /&gt;
# Первые 20 членов последовательности:&lt;br /&gt;
# 1 1 2 3 3 4 5 5 6 6 6 8 8 8 10 9 10 11 11 12&lt;br /&gt;
# См. книгу Дугласа Хольфштадтера, &amp;quot;Goedel, Escher, Bach: An Eternal Golden Braid&amp;quot;,&lt;br /&gt;
# p. 137, ff.&lt;br /&gt;
&lt;br /&gt;
LIMIT=100     # Найти первые 100 членов последовательности&lt;br /&gt;
LINEWIDTH=20  # Число членов последовательности, выводимых на экран в одной строке&lt;br /&gt;
Q[1]=1        # Первые два члена последовательности равны 1.&lt;br /&gt;
Q[2]=1&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Q-последовательность [первые $LIMIT членов]:&amp;quot;&lt;br /&gt;
echo -n &amp;quot;${Q[1]} &amp;quot; # Вывести первые два члена последовательности.&lt;br /&gt;
echo -n &amp;quot;${Q[2]} &amp;quot;&lt;br /&gt;
&lt;br /&gt;
for ((n=3; n &amp;lt;= $LIMIT; n++)) # C-подобное оформление цикла.&lt;br /&gt;
do # Q[n] = Q[n - Q[n-1]] + Q[n - Q[n-2]] для n&amp;gt;2&lt;br /&gt;
# Это выражение необходимо разбить на отдельные действия,&lt;br /&gt;
# поскольку Bash не очень хорошо поддерживает сложные арифметические действия над элементами массивов.&lt;br /&gt;
 let &amp;quot;n1 = $n - 1&amp;quot; # n-1&lt;br /&gt;
 let &amp;quot;n2 = $n - 2&amp;quot; # n-2&lt;br /&gt;
 &lt;br /&gt;
 t0=`expr $n - ${Q[n1]}` # n - Q[n-1]&lt;br /&gt;
 t1=`expr $n - ${Q[n2]}` # n - Q[n-2]&lt;br /&gt;
 &lt;br /&gt;
 T0=${Q[t0]} # Q[n - Q[n-1]]&lt;br /&gt;
 T1=${Q[t1]} # Q[n - Q[n-2]]&lt;br /&gt;
 Q[n]=`expr $T0 + $T1` # Q[n - Q[n-1]] + Q[n - Q[n-2]]&lt;br /&gt;
 echo -n &amp;quot;${Q[n]} &amp;quot;&lt;br /&gt;
&lt;br /&gt;
 if [ `expr $n % $LINEWIDTH` -eq 0 ] # Если выведено очередные 20 членов в строке.&lt;br /&gt;
 then # то&lt;br /&gt;
  echo # перейти на новую строку.&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
# Этот сценарий реализует итеративный алгоритм поиска членов Q-последовательности.&lt;br /&gt;
# Рекурсивную реализацию, как более интуитивно понятную, оставляю вам, в качестве упражнения.&lt;br /&gt;
# Внимание: рекурсивный поиск членов последовательности будет занимать *очень* продолжительное время.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash поддерживает только одномерные массивы, но, путем небольших ухищрений, можно эмулировать многомерные массивы.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Эмуляция массива с двумя измерениями.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Эмуляция двумерного массива.&lt;br /&gt;
&lt;br /&gt;
# Второе измерение представлено как последовательность строк.&lt;br /&gt;
Rows=5&lt;br /&gt;
Columns=5&lt;br /&gt;
&lt;br /&gt;
declare -a alpha    # char alpha [Rows] [Columns];&lt;br /&gt;
                    # Необязательное объявление массива.&lt;br /&gt;
&lt;br /&gt;
load_alpha ()&lt;br /&gt;
{&lt;br /&gt;
local rc=0&lt;br /&gt;
local index&lt;br /&gt;
&lt;br /&gt;
for i in A B C D E F G H I J K L M N O P Q R S T U V W X Y&lt;br /&gt;
do&lt;br /&gt;
 local row=`expr $rc / $Columns`&lt;br /&gt;
 local column=`expr $rc % $Rows`&lt;br /&gt;
 let &amp;quot;index = $row * $Rows + $column&amp;quot;&lt;br /&gt;
 alpha[$index]=$i # alpha[$row][$column]&lt;br /&gt;
 let &amp;quot;rc += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# Более простой вариант&lt;br /&gt;
# declare -a alpha=( A B C D E F G H I J K L M N O P Q R S T U V W X Y )&lt;br /&gt;
# но при таком объявлении второе измерение массива завуалировано.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
print_alpha ()&lt;br /&gt;
{&lt;br /&gt;
local row=0&lt;br /&gt;
local index&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$row&amp;quot; -lt &amp;quot;$Rows&amp;quot; ] # Вывод содержимого массива построчноdo&lt;br /&gt;
do&lt;br /&gt;
 local column=0&lt;br /&gt;
&lt;br /&gt;
 while [ &amp;quot;$column&amp;quot; -lt &amp;quot;$Columns&amp;quot; ]&lt;br /&gt;
 do&lt;br /&gt;
  let &amp;quot;index = $row * $Rows + $column&amp;quot;&lt;br /&gt;
  echo -n &amp;quot;${alpha[index]} &amp;quot; # alpha[$row][$column]&lt;br /&gt;
  let &amp;quot;column += 1&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;row += 1&amp;quot;&lt;br /&gt;
 echo&lt;br /&gt;
&lt;br /&gt;
done&lt;br /&gt;
# Более простой эквивалент:&lt;br /&gt;
# echo ${alpha[*]} | xargs -n $Columns&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
filter () # Отфильтровывание отрицательных индексов.&lt;br /&gt;
{&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot; &amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [[ &amp;quot;$1&amp;quot; -ge 0 &amp;amp;&amp;amp; &amp;quot;$1&amp;quot; -lt &amp;quot;$Rows&amp;quot; &amp;amp;&amp;amp; &amp;quot;$2&amp;quot; -ge 0 &amp;amp;&amp;amp; &amp;quot;$2&amp;quot; -lt &amp;quot;$Columns&amp;quot; ]]&lt;br /&gt;
then&lt;br /&gt;
 let &amp;quot;index = $1 * $Rows + $2&amp;quot;&lt;br /&gt;
 echo -n &amp;quot; ${alpha[index]}&amp;quot; # alpha[$row][$column]&lt;br /&gt;
fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
rotate () # Поворот массива на 45 градусов&lt;br /&gt;
{&lt;br /&gt;
local row&lt;br /&gt;
local column&lt;br /&gt;
&lt;br /&gt;
for (( row = Rows; row &amp;gt; -Rows; row-- )) # В обратном порядке.&lt;br /&gt;
do&lt;br /&gt;
 for (( column = 0; column &amp;lt; Columns; column++ ))&lt;br /&gt;
 do&lt;br /&gt;
  if [ &amp;quot;$row&amp;quot; -ge 0 ]&lt;br /&gt;
  then&lt;br /&gt;
   let &amp;quot;t1 = $column - $row&amp;quot;&lt;br /&gt;
   let &amp;quot;t2 = $column&amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
   let &amp;quot;t1 = $column&amp;quot;&lt;br /&gt;
   let &amp;quot;t2 = $column + $row&amp;quot;&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
  filter $t1 $t2 # Отфильтровать отрицательный индекс.&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
echo; echo&lt;br /&gt;
&lt;br /&gt;
done&lt;br /&gt;
# Поворот массива выполнен на основе примеров (стр. 143-146)&lt;br /&gt;
# из книги &amp;quot;Advanced C Programming on the IBM PC&amp;quot;, автор Herbert Mayer(см. библиографию).&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#----------------------------------------------------------------#&lt;br /&gt;
load_alpha    # Инициализация массива.&lt;br /&gt;
print_alpha   # Вывод на экран.&lt;br /&gt;
rotate        # Повернуть на 45 градусов против часовой стрелки.&lt;br /&gt;
#----------------------------------------------------------------#&lt;br /&gt;
&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# -----------&lt;br /&gt;
&lt;br /&gt;
# 1) Сделайте инициализацию и вывод массива на экран более простым и элегантным способом.&lt;br /&gt;
#&lt;br /&gt;
# 2) Объясните принцип работы функции rotate().&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
По существу, двумерный массив эквивалентен одномерному, с тем лишь различием, что для индексации отдельных элементов используются два ''индекса'' — &amp;quot;'''''строка'''''&amp;quot; и &amp;quot;'''''столбец'''''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Файлы ==&lt;br /&gt;
'''Сценарии начальной загрузки'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Эти файлы содержат объявления псевдонимов и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;переменных окружения&amp;lt;/span&amp;gt;, которые становятся доступны Bash после загрузки и инициализации системы.&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''/etc/profile'''&amp;lt;/span&amp;gt;&lt;br /&gt;
::Настройки системы по-умолчанию, главным образом настраивается окружение командной оболочки (все Bourne-подобные оболочки, не только Bash)&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''/etc/bashrc'''&amp;lt;/span&amp;gt;&lt;br /&gt;
::функции и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;псевдонимы&amp;lt;/span&amp;gt; Bash&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$HOME/.bash_profile'''&amp;lt;/span&amp;gt;&lt;br /&gt;
::пользовательские настройки окружения Bash, находится в домашнем каталоге у каждого пользователя (локальная копия файла ''/etc/profile'')&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$HOME/.bashrc'''&amp;lt;/span&amp;gt;&lt;br /&gt;
::пользовательский файл инициализации Bash, находится в домашнем каталоге у каждого пользователя (локальная копия файла ''/etc/bashrc'').&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Сценарий выхода из системы (logout)'''&amp;lt;br /&amp;gt;&lt;br /&gt;
:&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''$HOME/.bash_logout'''&amp;lt;/span&amp;gt;&lt;br /&gt;
::Этот сценарий отрабатывает, когда пользователь выходит из системы.&lt;br /&gt;
&lt;br /&gt;
== /dev и /proc ==&lt;br /&gt;
Как правило, Linux или Unix система имеет каталоги специального назначения: &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''/dev'''&amp;lt;/span&amp;gt; и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''/proc'''&amp;lt;/span&amp;gt;.&lt;br /&gt;
=== /dev ===&lt;br /&gt;
Каталог ''/dev'' содержит файлы физических устройств, которые могут входить в состав аппаратного обеспечения компьютера. Каждому из разделов не жёстком диске соответствует свой файл-устройство в каталоге ''/dev'', информация о которых может быть получена простой командой [[df]].&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ df&lt;br /&gt;
Filesystem          1k-blocks         Used        Available       Use%       Mounted on&lt;br /&gt;
/dev/hda6           495876            222748 2    47527           48%        /&lt;br /&gt;
/dev/hda1           50755             3887        44248           9%         /boot&lt;br /&gt;
/dev/hda8           367013            13262       334803          4%         /home&lt;br /&gt;
/dev/hda5           1714416           1123624     503704          70%        /usr&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Кроме того, каталог ''/dev'' содержит ''loopback''-устройства (&amp;quot;петлевые&amp;quot; устройства), например ''/dev/loop0''. С помощью такого устройства можно представить обычный файл, как блочное устройство ввода/вывода. Это позволяет монтировать целые файловые системы, находящиеся в отдельных больших файлах.&amp;lt;br /&amp;gt;&lt;br /&gt;
Отдельные псевдоустройства в ''/dev'' имеют особое назначение, к таким устройствам можно отнести &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;/dev/null&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;/dev/zero&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;/dev/urandom&amp;lt;/span&amp;gt; и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;/dev/tcp&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример работы с псевдоустройством /dev/tcp.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# dev-tcp.sh: Пример перенаправления на псевдоустройство /dev/tcp&lt;br /&gt;
&lt;br /&gt;
# Автор: Troy Engel.&lt;br /&gt;
# Используется с разрешения автора.&lt;br /&gt;
&lt;br /&gt;
TCP_HOST=www.slashdot.org&lt;br /&gt;
TCP_PORT=80 # 80-й порт — это стандартный порт службы http.&lt;br /&gt;
&lt;br /&gt;
# Попытка выполнить соединение. (Своего рода 'ping.')&lt;br /&gt;
echo &amp;quot;HEAD / HTTP/1.0&amp;quot; &amp;gt;/dev/tcp/${TCP_HOST}/${TCP_PORT}&lt;br /&gt;
MYEXIT=$?&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;&amp;lt; EXPLANATION&lt;br /&gt;
Если bash собран с ключом --enable-net-redirections, то он имеет возможность использовать специальное символьное устройство для перенаправления TCP и UDP.&lt;br /&gt;
Оно практически идентично стандартным устройствам STDIN/STDOUT/STDERR.&lt;br /&gt;
Создать это устройство (если его ещё нет в системе) можно командой(разумеется, что при этом вы должны обладать правами root):&lt;br /&gt;
mknod /dev/tcp c 30 36&lt;br /&gt;
&amp;gt;Из руководства к bash:&lt;br /&gt;
/dev/tcp/host/port&lt;br /&gt;
 Если host является верным именем сетевого узла или IP-адресом, а port — целое число&lt;br /&gt;
или название сетевой службы, то Bash попытается открыть TCP-соединение с соответствующим узлом.&lt;br /&gt;
EXPLANATION&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;X$MYEXIT&amp;quot; = &amp;quot;X0&amp;quot; ]; then&lt;br /&gt;
 echo &amp;quot;Соединение установлено. Код завершения: $MYEXIT&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Ошибка при попытке установить соединение. Код завершения: $MYEXIT&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit $MYEXIT&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== /proc ===&lt;br /&gt;
Фактически, каталог ''/proc'' — это виртуальная файловая система. Файлы, в каталоге ''/proc'', содержат информацию о процессах, о состоянии и конфигурации ядра и системы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat /proc/devices&lt;br /&gt;
Character devices:&lt;br /&gt;
1 mem&lt;br /&gt;
2 pty&lt;br /&gt;
3 ttyp&lt;br /&gt;
4 ttyS&lt;br /&gt;
5 cua&lt;br /&gt;
7 vcs&lt;br /&gt;
10 misc&lt;br /&gt;
14 sound&lt;br /&gt;
29 fb&lt;br /&gt;
36 netlink&lt;br /&gt;
128 ptm&lt;br /&gt;
136 pts&lt;br /&gt;
162 raw&lt;br /&gt;
254 pcmcia&lt;br /&gt;
&lt;br /&gt;
Block devices:&lt;br /&gt;
1 ramdisk&lt;br /&gt;
2 fd&lt;br /&gt;
3 ide0&lt;br /&gt;
9 md&lt;br /&gt;
&lt;br /&gt;
bash$ cat /proc/interrupts&lt;br /&gt;
CPU0&lt;br /&gt;
0: 84505 XT-PIC timer&lt;br /&gt;
1: 3375 XT-PIC keyboard&lt;br /&gt;
2: 0 XT-PIC cascade&lt;br /&gt;
5: 1 XT-PIC soundblaster&lt;br /&gt;
8: 1 XT-PIC rtc&lt;br /&gt;
12: 4231 XT-PIC PS/2 Mouse&lt;br /&gt;
14: 109373 XT-PIC ide0&lt;br /&gt;
NMI: 0&lt;br /&gt;
ERR: 0&lt;br /&gt;
bash$ cat /proc/partitions&lt;br /&gt;
major   minor    #blocks    name    rio    rmerge    rsect    ruse    wio    wmerge    wsect    wuse    running    use     aveq&lt;br /&gt;
3       0        3007872    hda     4472   22260     114520   94240   3551   18703     50384    549710  0          111550  644030&lt;br /&gt;
3       1        52416      hda1    27     395       844      960     4      2         14       180     0          800     1140&lt;br /&gt;
3       2        1          hda2    0      0         0        0       0      0         0        0       0          0       0&lt;br /&gt;
3       4        165280     hda4    10     0         20       210     0      0         0        0       0          210     210&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
bash$ cat /proc/loadavg&lt;br /&gt;
0.13 0.42 0.27 2/44 1119&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сценарии командной оболочки могут извлекать необходимую информацию из соответствующих файлов в каталоге ''/proc''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat /proc/filesystems | grep iso9660&lt;br /&gt;
   iso9660&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
kernel_version=$( awk '{ print $3 }' /proc/version )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
CPU=$( awk '/model name/ {print $4}' &amp;lt; /proc/cpuinfo )&lt;br /&gt;
if [ $CPU = Pentium ]&lt;br /&gt;
then&lt;br /&gt;
 выполнить_ряд_специфичных_команд&lt;br /&gt;
 ...&lt;br /&gt;
else&lt;br /&gt;
 выполнить_ряд_других_специфичных_команд&lt;br /&gt;
 ...&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В каталоге ''/proc'' вы наверняка заметите большое количество подкаталогов, с не совсем обычными именами, состоящими только из цифр. Каждый из них соответствует ''исполняющемуся процессу'', а ''имя'' каталога — это ''ID'' (идентификатор) процесса. Внутри каждого такого подкаталога находится ряд файлов, в которых содержится полезная информация о соответствующих процессах. Файлы ''stat'' и ''status'' хранят статистику работы процесса, ''cmdline'' — команда, которой был запущен процесс, ''exe'' — символическая ссылка на исполняемый файл программы. Здесь же вы найдете ряд других файлов, но, с точки зрения написания сценариев, они не так интересны, как эти четыре.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Поиск файла программы по идентификатору процесса.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# pid-identifier.sh: Возвращает полный путь к исполняемому файлу программы по идентификатору процесса (pid).&lt;br /&gt;
&lt;br /&gt;
ARGNO=1 # Число, ожидаемых из командной строки, аргументов.&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
E_BADPID=66&lt;br /&gt;
E_NOSUCHPROCESS=67&lt;br /&gt;
E_NOPERMISSION=68&lt;br /&gt;
PROCFILE=exe&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne $ARGNO ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` PID-процесса&amp;quot; &amp;gt;&amp;amp;2 # Сообщение об ошибке на &amp;gt;stderr.&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
ps ax&lt;br /&gt;
&lt;br /&gt;
pidno=$( ps ax | grep $1 | awk '{ print $1 }' | grep $1 )&lt;br /&gt;
# Проверка наличия процесса с заданным pid в списке, выданном командой &amp;quot;ps&amp;quot;, поле #1.&lt;br /&gt;
# Затем следует убедиться, что этот процесс не был запущен этим сценарием ('ps').&lt;br /&gt;
# Это делает последний &amp;quot;grep $1&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$pidno&amp;quot; ] # Если после фильтрации получается пустая строка,&lt;br /&gt;
then # то это означает, что в системе нет процесса с заданным pid.&lt;br /&gt;
 echo &amp;quot;Нет такого процесса.&amp;quot;&lt;br /&gt;
 exit $E_NOSUCHPROCESS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Альтернативный вариант:&lt;br /&gt;
#if ! ps $1 &amp;gt; /dev/null 2&amp;gt;&amp;amp;1&lt;br /&gt;
# then &lt;br /&gt;
# в системе нет процесса с заданным pid.&lt;br /&gt;
# echo &amp;quot;Нет такого процесса.&amp;quot;&lt;br /&gt;
# exit $E_NOSUCHPROCESS&lt;br /&gt;
# fi&lt;br /&gt;
&lt;br /&gt;
if [ ! -r &amp;quot;/proc/$1/$PROCFILE&amp;quot; ] # Проверить право на чтение.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Процесс $1 найден, однако...&amp;quot;&lt;br /&gt;
 echo &amp;quot;у вас нет права на чтение файла /proc/$1/$PROCFILE.&amp;quot;&lt;br /&gt;
 exit $E_NOPERMISSION # Обычный пользователь не имеет прав&lt;br /&gt;
                      # на доступ к некоторым файлам в каталоге /proc.&lt;br /&gt;
fi&lt;br /&gt;
# Последние две проверки могут быть заменены на:&lt;br /&gt;
# if ! kill -0 $1 &amp;gt; /dev/null 2&amp;gt;&amp;amp;1 # '0' — это не сигнал, но&lt;br /&gt;
                                   # команда всё равно проверит наличие&lt;br /&gt;
                                   # процесса-получателя.&lt;br /&gt;
# then echo &amp;quot;Процесс с данным PID не найден, либо вы не являетесь его владельцем&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
# exit $E_BADPID&lt;br /&gt;
# fiexe_file=$( ls -l /proc/$1 | grep &amp;quot;exe&amp;quot; | awk '{ print $11 }' )&lt;br /&gt;
&lt;br /&gt;
exe_file=$( ls -l /proc/$1 | grep &amp;quot;exe&amp;quot; | awk '{ print $11 }' )&lt;br /&gt;
# Или exe_file=$( ls -l /proc/$1/exe | awk '{print $11}' )&lt;br /&gt;
#&lt;br /&gt;
#/proc/pid-number/exe — это символическая ссылка&lt;br /&gt;
# на исполняемый файл работающей программы.&lt;br /&gt;
&lt;br /&gt;
if [ -e &amp;quot;$exe_file&amp;quot; ] # Если файл /proc/pid-number/exe существует...&lt;br /&gt;
then # то существует и соответствующий процесс.&lt;br /&gt;
 echo &amp;quot;Исполняемый файл процесса #$1: $exe_file.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Нет такого процесса.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
# В большинстве случаев, этот, довольно сложный сценарий, может быть заменен командой&lt;br /&gt;
# ps ax | grep $1 | awk '{ print $5 }'&lt;br /&gt;
# В большинстве, но не всегда...&lt;br /&gt;
# поскольку пятое поле листинга,выдаваемого командой 'ps', это argv[0] процесса,&lt;br /&gt;
# а не путь к исполняемому файлу.&lt;br /&gt;
#&lt;br /&gt;
# Однако, оба следующих варианта должны работать безотказно.&lt;br /&gt;
# find /proc/$1/exe -printf '%l\n'&lt;br /&gt;
# lsof -aFn -p $1 -d txt | sed -ne 's/^n//p'&lt;br /&gt;
&lt;br /&gt;
# Автор последнего комментария: Stephane Chazelas.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка состояния соединения.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
PROCNAME=pppd # демон ppp&lt;br /&gt;
PROCFILENAME=status # Что смотреть.&lt;br /&gt;
NOTCONNECTED=65&lt;br /&gt;
INTERVAL=2 # Период проверки — раз в 2 секунды.&lt;br /&gt;
&lt;br /&gt;
pidno=$( ps ax | grep -v &amp;quot;ps ax&amp;quot; | grep -v grep | grep $PROCNAME | awk '{ print $1 }' )&lt;br /&gt;
# Найти идентификатор процесса 'pppd', 'ppp daemon'.&lt;br /&gt;
# По пути убрать из листинга записи о процессах, порожденных сценарием.&lt;br /&gt;
#&lt;br /&gt;
# Однако, как отмечает Oleg Philon,&lt;br /&gt;
# Эта последовательность команд может быть заменена командой &amp;quot;pidof&amp;quot;.&lt;br /&gt;
# pidno=$( pidof $PROCNAME )&lt;br /&gt;
#&lt;br /&gt;
# Мораль:&lt;br /&gt;
# Когда последовательность команд становится слишком сложной,&lt;br /&gt;
# это повод к тому, чтобы поискать более короткий вариант.&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$pidno&amp;quot; ] # Если получилась пустая строка, значит процесс не запущен.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Соединение не установлено.&amp;quot;&lt;br /&gt;
 exit $NOTCONNECTED&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Соединение установлено.&amp;quot;; echo&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
while [ true ] # Бесконечный цикл.&lt;br /&gt;
do&lt;br /&gt;
 if [ ! -e &amp;quot;/proc/$pidno/$PROCFILENAME&amp;quot; ]&lt;br /&gt;
 # Пока работает процесс, файл &amp;quot;status&amp;quot; существует.&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Соединение разорвано.&amp;quot;&lt;br /&gt;
  exit $NOTCONNECTED&lt;br /&gt;
 fi&lt;br /&gt;
 netstat -s | grep &amp;quot;packets received&amp;quot; # Получить некоторые сведения о соединении.&lt;br /&gt;
 netstat -s | grep &amp;quot;packets delivered&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 sleep $INTERVAL&lt;br /&gt;
 echo; echo&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# Как обычно, этот сценарий может быть остановлен комбинацией клавиш Control-C.&lt;br /&gt;
&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ----------&lt;br /&gt;
# Добавьте возможность завершения работы сценария, по нажатии на клавишу &amp;quot;q&amp;quot;.&lt;br /&gt;
# Это сделает скрипт более дружественным к пользователю.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Будьте предельно осторожны при работе с файловой системой ''/proc'', так как попытка записи в некоторые файлы может повредить файловую систему или привести к краху системы.&lt;br /&gt;
&lt;br /&gt;
== /dev/zero и /dev/null ==&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''/dev/null''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Псевдоустройство ''/dev/null'' — это, своего рода, &amp;quot;чёрная дыра&amp;quot; в системе. Это, пожалуй, самый близкий смысловой эквивалент. Всё, что записывается в этот файл, &amp;quot;исчезает&amp;quot; навсегда. Попытки записи или чтения из этого файла не дают, ровным счётом, никакого результата. Тем не менее, псевдоустройство ''/dev/null'' вполне может пригодиться.&amp;lt;&amp;gt;&lt;br /&gt;
:&lt;br /&gt;
'''Подавление вывода на stdout.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat $filename &amp;gt;/dev/null&lt;br /&gt;
# Содержимое файла $filename не появится на stdout.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Подавление вывода на stderr.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
rm $badname 2&amp;gt;/dev/null&lt;br /&gt;
# Сообщение об ошибке &amp;quot;уйдёт в никуда&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Подавление вывода, как на stdout, так и на stderr.'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat $filename 2&amp;gt;/dev/null &amp;gt;/dev/null&lt;br /&gt;
# Если &amp;quot;$filename&amp;quot; не будет найден, то вы не увидите сообщения об ошибке.&lt;br /&gt;
# Если &amp;quot;$filename&amp;quot; существует, то вы не увидите его содержимое.&lt;br /&gt;
# Таким образом, вышеприведённая команда ничего не выводит на экран.&lt;br /&gt;
#&lt;br /&gt;
# Такая методика бывает полезной, когда необходимо лишь проверить код завершения команды&lt;br /&gt;
# и нежелательно выводить результат работы команды на экран.&lt;br /&gt;
#&lt;br /&gt;
#cat $filename &amp;amp;&amp;gt;/dev/null&lt;br /&gt;
# даёт тот же результат, автор примечания Baris Cicek.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Удаление содержимого файла, сохраняя, при этом, сам файл, со всеми его правами доступа(очистка файла)'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat /dev/null &amp;gt; /var/log/messages&lt;br /&gt;
# : &amp;gt; /var/log/messages дает тот же эффект, но не порождает дочерний процесс.&lt;br /&gt;
&lt;br /&gt;
cat /dev/null &amp;gt; /var/log/wtmp&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Автоматическая очистка содержимого системного журнала (logfile) (особенно хороша для борьбы с надоедливыми рекламными идентификационными файлами (&amp;quot;cookies&amp;quot;)):&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Удаление cookie-файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ -f ~/.netscape/cookies ] # Удалить, если имеются.&lt;br /&gt;
then&lt;br /&gt;
 rm -f ~/.netscape/cookies&lt;br /&gt;
fi&lt;br /&gt;
ln -s /dev/null ~/.netscape/cookies&lt;br /&gt;
# Теперь, все cookie-файлы, вместо того, чтобы сохраняться на диске, будут &amp;quot;вылетать в трубу&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''/dev/zero''&amp;lt;/span&amp;gt;&lt;br /&gt;
Подобно псевдоустройству ''/dev/null'', ''/dev/zero'' так же является псевдоустройством, с той лишь разницей, что содержит нули (здесь имеются ввиду двоичные нули, а не символы &amp;quot;0&amp;quot; ASCII). Информация, выводимая в этот файл, так же бесследно исчезает. Чтение нулей из этого файла может вызвать некоторые затруднения, однако это можно сделать, к примеру, с помощью команды '''''od''''' или шестнадцатиричного редактора. В основном, ''/dev/zero'' используется для создания заготовки файла с заданой длиной.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание файла подкачки (swapfile), с помощью /dev/zero.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
# Создание файла подкачки.&lt;br /&gt;
# Этот сценарий должен запускаться с правами root.&lt;br /&gt;
ROOT_UID=0 # Для root — $UID 0.&lt;br /&gt;
E_WRONG_USER=65 # Не root?&lt;br /&gt;
&lt;br /&gt;
FILE=/swap&lt;br /&gt;
BLOCKSIZE=1024&lt;br /&gt;
MINBLOCKS=40&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo; echo &amp;quot;Этот сценарий должен запускаться с правами root.&amp;quot;; echo&lt;br /&gt;
 exit $E_WRONG_USER&lt;br /&gt;
fi&lt;br /&gt;
blocks=${1:-$MINBLOCKS} # По-умолчанию — 40 блоков, если размер не задан из командной строки.&lt;br /&gt;
# Ниже приводится эквивалентный набор команд.&lt;br /&gt;
# --------------------------------------------------&lt;br /&gt;
# if [ -n &amp;quot;$1&amp;quot; ]&lt;br /&gt;
# then&lt;br /&gt;
# blocks=$1&lt;br /&gt;
# else&lt;br /&gt;
# blocks=$MINBLOCKS&lt;br /&gt;
# fi&lt;br /&gt;
# --------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$blocks&amp;quot; -lt $MINBLOCKS ]&lt;br /&gt;
then&lt;br /&gt;
 blocks=$MINBLOCKS # Должно быть как минимум 40 блоков.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Создание файла подкачки размером $blocks блоков (KB).&amp;quot;&lt;br /&gt;
dd if=/dev/zero of=$FILE bs=$BLOCKSIZE count=$blocks # &amp;quot;Забить&amp;quot; нулями.&lt;br /&gt;
&lt;br /&gt;
mkswap $FILE $blocks # Назначить как файл подкачки.&lt;br /&gt;
swapon $FILE # Активировать.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Файл подкачки создан и активирован.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit $SUCCESS&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё одна область применения ''/dev/zero'' — &amp;quot;очистка&amp;quot; специального файла заданного размера, например файлов, монтируемых как ''loopback''-устройства или для безопасного удаления файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Создание электронного диска.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ramdisk.sh&lt;br /&gt;
# &amp;quot;электронный диск&amp;quot; — это область в ОЗУ компьютера с которой система взаимодействует как с файловой системой.&lt;br /&gt;
# Основное преимущество — очень высокая скорость чтения/записи.&lt;br /&gt;
# Недостатки — энергозависимость, уменьшение объема ОЗУ, доступного системе, относительно небольшой размер.&lt;br /&gt;
#&lt;br /&gt;
# Чем хорош электронный диск?&lt;br /&gt;
# При хранении наборов данных, таких как таблиц баз данных или словарей, на электронном диске вы получаете высокую скорость работы с этими наборами, поскольку время доступа к ОЗУ &lt;br /&gt;
# неизмеримо меньше времени доступа к жёсткому диску.&lt;br /&gt;
&lt;br /&gt;
E_NON_ROOT_USER=70 # Сценарий должен запускаться с правами root.&lt;br /&gt;
ROOTUSER_NAME=root&lt;br /&gt;
MOUNTPT=/mnt/ramdisk&lt;br /&gt;
SIZE=2000 # 2K блоков (измените, если это необходимо)&lt;br /&gt;
BLOCKSIZE=1024 # размер блока — 1K (1024 байт)&lt;br /&gt;
DEVICE=/dev/ram0 # Первое устройство ram&lt;br /&gt;
&lt;br /&gt;
username=`id -nu`&lt;br /&gt;
if [ &amp;quot;$username&amp;quot; != &amp;quot;$ROOTUSER_NAME&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Сценарий должен запускаться с правами root.&amp;quot;&lt;br /&gt;
 exit $E_NON_ROOT_USER&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ ! -d &amp;quot;$MOUNTPT&amp;quot; ] # Проверка наличия точки монтирования,&lt;br /&gt;
then                   # благодаря этой проверке, при повторных запусках сценария&lt;br /&gt;
 mkdir $MOUNTPT        # ошибки возникать не будет.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
dd if=/dev/zero of=$DEVICE count=$SIZE bs=$BLOCKSIZE # Очистить электронный диск.&lt;br /&gt;
mke2fs $DEVICE # Создать файловую систему ext2.&lt;br /&gt;
mount $DEVICE $MOUNTPT # Смонтировать.&lt;br /&gt;
chmod 777 $MOUNTPT # Сделать электронный диск доступным для обычных пользователей. Но при этом, только root сможет его отмонтировать.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Электронный диск \&amp;quot;$MOUNTPT\&amp;quot; готов к работе.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Теперь электронный диск доступен для любого пользователя в системе.&lt;br /&gt;
# Внимание! Электронный диск — это энергозависимое устройство! Все данные, хранящиеся на нём,&lt;br /&gt;
# будут утеряны при остановке или перезагрузке системы.&lt;br /&gt;
# Если эти данные представляют для вас интерес, то сохраняйте их копии в обычном каталоге.&lt;br /&gt;
# После перезагрузки, чтобы вновь создать электронный диск, запустите этот сценарий.&lt;br /&gt;
# Простое монтирование /mnt/ramdisk, без выполнения подготовительных действий, не будет работать.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Отладка сценариев ==&lt;br /&gt;
Командная оболочка Bash не имеет своего отладчика, и не имеет даже каких либо отладочных команд или конструкций. Синтаксические ошибки или опечатки часто вызывают сообщения об ошибках, которые которые практически никак не помогают при отладке.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий, содержащий ошибку.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ex74.sh&lt;br /&gt;
# Этот сценарий содержит ошибку.&lt;br /&gt;
a=37&lt;br /&gt;
if [$a -gt 27 ]&lt;br /&gt;
then&lt;br /&gt;
 echo $a&lt;br /&gt;
fi&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В результате исполнения этого сценария вы получите такое сообщение:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
./ex74.sh: [37: command not found&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Что в этом сценарии может быть неправильно (подсказка: после ключевого слова '''if'''?)&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пропущено ключевое слово.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# missing-keyword.sh:&lt;br /&gt;
# Какое сообщение об ошибке будет выведено, при попытке запустить этот сценарий?&lt;br /&gt;
for a in 1 2 3&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$a&amp;quot;&lt;br /&gt;
# done # Необходимое ключевое слово 'done' закомментировано.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
На экране появится сообщение:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
missing-keyword.sh: line 11: syntax error: unexpected end of file&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание, сообщение об ошибке будет содержать номер не той строки, в которой возникла ошибка, а той, в которой Bash точно установил наличие ошибочной ситуации. Сообщения об ошибках могут вообще не содержать номера строки, при исполнении которой эта ошибка появилась. А что делать, если сценарий работает, но не так как ожидалось? Вот пример весьма распространенной логической ошибки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''test24.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Ожидается, что этот сценарий будет удалять в текущем каталоге&lt;br /&gt;
# все файлы, имена которых содержат пробелы. &lt;br /&gt;
# Но он не работает. Почему?&lt;br /&gt;
&lt;br /&gt;
badname=`ls | grep ' '`&lt;br /&gt;
&lt;br /&gt;
# echo &amp;quot;$badname&amp;quot;&lt;br /&gt;
rm &amp;quot;$badname&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Попробуйте найти ошибку, раскомментировав строку '''echo &amp;quot;$badname&amp;quot;'''. Инструкция [[echo]] очень полезна при отладке сценариев, она позволяет узнать — действительно ли вы получаете то, что ожидали получить.&lt;br /&gt;
В данном конкретном случае, команда '''rm &amp;quot;$badname&amp;quot;''' не даёт желаемого результата потому, что переменная ''$badname'' взята в кавычки. В результате, [[rm]] получает единственный аргумент (т.е. команда будет считать, что получила имя одного файла). Частично эта проблема может быть решена за счёт удаления кавычек вокруг ''$badname'' и установки переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$IFS&amp;lt;/span&amp;gt; так, чтобы она содержала только символ перевода строки, '''''IFS=$'\n' '''''. Однако, существует более простой способ выполнить эту задачу.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Правильный способ удаления файлов, в чьих именах содержатся пробелы.&lt;br /&gt;
rm *\ *&lt;br /&gt;
rm *&amp;quot; &amp;quot;*&lt;br /&gt;
rm *' '*&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В общих чертах, ошибочными можно считать такие сценарии, которые:&amp;lt;br &amp;gt;&lt;br /&gt;
# &amp;quot;сыплют&amp;quot; сообщениями о &amp;quot;синтаксических ошибках&amp;quot; или&lt;br /&gt;
# запускаются, но работают не так как ожидалось (логические ошибки).&lt;br /&gt;
# запускаются, делают то, что требуется, но имеют побочные эффекты (логическая бомба).&amp;lt;br /&amp;gt;&lt;br /&gt;
Инструменты, которые могут помочь при отладке неработающих сценариев:&lt;br /&gt;
:1. команда [[echo]], в критических точках сценария, поможет отследить состояние переменных и отобразить ход исполнения.&lt;br /&gt;
:2. команда-фильтр [[tee]], которая поможет проверить процессы и потоки данных в критических местах.&lt;br /&gt;
:3. ключи ''-n -v -x''&lt;br /&gt;
:'''''sh -n scriptname''''' — проверит наличие синтаксических ошибок, не запуская сам сценарий. Того же эффекта можно добиться, вставив в сценарий команду '''''set -n''''' или '''''set -o noexec'''''. Обратите внимание, некоторые из синтаксических ошибок не могут быть выявлены таким способом.&lt;br /&gt;
:'''''sh -v scriptname''''' — выводит каждую команду прежде, чем она будет выполнена. Того же эффекта можно добиться, вставив в сценарий команду '''''set -v''''' или '''''set -o verbose'''''.&lt;br /&gt;
:Ключи ''-n'' и ''-v'' могут употребляться совместно: '''''sh -nv scriptname'''''.&lt;br /&gt;
:'''''sh -x scriptname''''' — выводит, в краткой форме, результат исполнения каждой команды. Того же эффекта можно добиться, вставив в сценарий команду '''''set -x''''' или '''''set -o xtrace'''''.&lt;br /&gt;
:Вставив в сценарий '''''set -u''''' или '''''set -o nounset''''', вы будете получать сообщение об ошибке &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''unbound variable''&amp;lt;/span&amp;gt; всякий раз, когда будет производиться попытка обращения к необъявленной переменной.&lt;br /&gt;
:4. Функция &amp;quot;assert&amp;quot;, предназначенная для проверки переменных или условий, в критических точках сценария. (Эта идея заимствована из языка программирования C.)&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Проверка условия с помощью функции &amp;quot;assert&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# assert.sh&lt;br /&gt;
&lt;br /&gt;
assert ()      # Если условие ложно,&lt;br /&gt;
{              # выход из сценария с сообщением об ошибке.&lt;br /&gt;
 E_PARAM_ERR=98&lt;br /&gt;
 E_ASSERT_FAILED=99&lt;br /&gt;
 &lt;br /&gt;
 if [ -z &amp;quot;$2&amp;quot; ] # Недостаточное количество входных параметров.&lt;br /&gt;
 then&lt;br /&gt;
  return $E_PARAM_ERR&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 lineno=$2&lt;br /&gt;
&lt;br /&gt;
 if [ ! $1 ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Утверждение ложно: \&amp;quot;$1\&amp;quot;&amp;quot;&lt;br /&gt;
  echo &amp;quot;Файл: \&amp;quot;$0\&amp;quot;, строка: $lineno&amp;quot;&lt;br /&gt;
  exit $E_ASSERT_FAILED&lt;br /&gt;
 # else&lt;br /&gt;
 # return&lt;br /&gt;
 # и продолжить исполнение сценария.&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
a=5&lt;br /&gt;
b=4&lt;br /&gt;
condition=&amp;quot;$a -lt $b&amp;quot; # Сообщение об ошибке и завершение сценария.&lt;br /&gt;
                      # Попробуйте поменять условие &amp;quot;condition&amp;quot;&lt;br /&gt;
                      # на что-нибудь другое и посмотреть что получится.&lt;br /&gt;
assert &amp;quot;$condition&amp;quot; $LINENO&lt;br /&gt;
# Сценарий продолжит работу только в том случае, если утверждение истинно.&lt;br /&gt;
# Прочие команды.&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Эта строка появится на экране только если утверждение истинно.&amp;quot;&lt;br /&gt;
# ...&lt;br /&gt;
# Прочие команды.&lt;br /&gt;
# ...&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:5. Ловушка на выход в этом сценарии может быть неправильна (подсказка: после ключевого слова).&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''''exit''''', в сценарии, порождает сигнал '''0''', по которому процесс завершает работу, т.е. — сам сценарий. Часто бывает полезным по выходу из сценария выдать &amp;quot;распечатку&amp;quot; переменных.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Установка ловушек на сигналы'''&amp;lt;/span&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''trap'''&amp;lt;br /&amp;gt;&lt;br /&gt;
Определяет действие при получении сигнала; так же полезна при отладке.&amp;lt;br /&amp;gt;&lt;br /&gt;
''Сигнал (signal)'' — это просто сообщение, передаётся процессу либо ядром, либо другим процессом, чтобы побудить процесс выполнить какие-либо действия(обычно — завершить работу). Например, нажатие на ''Control-C'', вызывает передачу сигнала ''SIGINT'', исполняющейся программе.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
trap '' 2&lt;br /&gt;
# Игнорировать прерывание 2 (Control-C), действие по сигналу не указано.&lt;br /&gt;
trap 'echo &amp;quot;Control-C disabled.&amp;quot;' 2&lt;br /&gt;
# Сообщение при нажатии на Control-C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ловушка на выходе.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
trap 'echo Список переменных — a = $a b = $b' EXIT&lt;br /&gt;
# EXIT — это название сигнала, генерируемого при выходе из сценария.&lt;br /&gt;
&lt;br /&gt;
a=39&lt;br /&gt;
b=36&lt;br /&gt;
exit 0&lt;br /&gt;
# Примечательно, что если закомментировать команду 'exit',&lt;br /&gt;
# то это никак не скажется на работе сценария,&lt;br /&gt;
# поскольку &amp;quot;выход&amp;quot; из сценария происходит в любом случае.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Удаление временного файла при нажатии на Control-C.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# logon.sh: Сценарий, написанный &amp;quot;на скорую руку&amp;quot;, контролирует вход в режим on-line.&lt;br /&gt;
&lt;br /&gt;
TRUE=1&lt;br /&gt;
LOGFILE=/var/log/messages&lt;br /&gt;
# Обратите внимание: $LOGFILE должен быть доступен на чтение (chmod 644 /var/log/messages).&lt;br /&gt;
TEMPFILE=temp.$$&lt;br /&gt;
# &amp;quot;Уникальное&amp;quot; имя для временного файла, где расширение в имени -- это pid процесса-сценария.&lt;br /&gt;
KEYWORD=address&lt;br /&gt;
# При входе, в файл /var/log/messages,&lt;br /&gt;
# добавляется строка &amp;quot;remote IP address xxx.xxx.xxx.xxx&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ONLINE=22&lt;br /&gt;
USER_INTERRUPT=13&lt;br /&gt;
CHECK_LINES=100&lt;br /&gt;
# Количество проверяемых строк.&lt;br /&gt;
&lt;br /&gt;
trap 'rm -f $TEMPFILE; exit $USER_INTERRUPT' TERM INT&lt;br /&gt;
# Удалить временный файл, когда сценарий завершает работу по control-c.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
while [ $TRUE ] #Бесконечный цикл.&lt;br /&gt;
do&lt;br /&gt;
 tail -$CHECK_LINES $LOGFILE&amp;gt; $TEMPFILE&lt;br /&gt;
 # Последние 100 строк из системного журнала переписать во временный файл.&lt;br /&gt;
 # Совершенно необходимо, т.к. новейшие версии ядер генерируют много сообщений при входе.&lt;br /&gt;
 search=`grep $KEYWORD $TEMPFILE`&lt;br /&gt;
 # Проверить наличие фразы &amp;quot;address&amp;quot;,&lt;br /&gt;
 # свидетельствующей об успешном входе.&lt;br /&gt;
 if [ ! -z &amp;quot;$search&amp;quot; ] # Кавычки необходимы, т.к. переменная может содержать пробелы.&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;On-line&amp;quot;&lt;br /&gt;
  rm -f $TEMPFILE # Удалить временный файл.&lt;br /&gt;
  exit $ONLINE&lt;br /&gt;
 else&lt;br /&gt;
  echo -n &amp;quot;.&amp;quot; # ключ -n подавляет вывод символа перевода строки,&lt;br /&gt;
              # так вы получите непрерывную строку точек.&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 sleep 1&lt;br /&gt;
done&lt;br /&gt;
# Обратите внимание: если изменить содержимое переменной KEYWORD&lt;br /&gt;
# на &amp;quot;Exit&amp;quot;, то сценарий может использоваться для контроля&lt;br /&gt;
# неожиданного выхода (logoff).&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# Nick Drage предложил альтернативный метод:&lt;br /&gt;
while true&lt;br /&gt;
 do ifconfig ppp0 | grep UP 1&amp;gt; /dev/null &amp;amp;&amp;amp; echo &amp;quot;соединение установлено&amp;quot; &amp;amp;&amp;amp; exit 0&lt;br /&gt;
 echo -n &amp;quot;.&amp;quot; # Печать последовательности точек (.....), пока соединение не будет установлено.&lt;br /&gt;
 sleep 2&lt;br /&gt;
done&lt;br /&gt;
# Проблема: Нажатия Control-C может оказаться недостаточным, чтобы завершить этот процесс.&lt;br /&gt;
# (Точки продолжают выводиться на экран.)&lt;br /&gt;
# Упражнение: Исправьте этот недостаток.&lt;br /&gt;
&lt;br /&gt;
# Stephane Chazelas предложил ещё одну альтернативу:&lt;br /&gt;
CHECK_INTERVAL=1&lt;br /&gt;
&lt;br /&gt;
while ! tail -1 &amp;quot;$LOGFILE&amp;quot; | grep -q &amp;quot;$KEYWORD&amp;quot;&lt;br /&gt;
do echo -n .&lt;br /&gt;
 sleep $CHECK_INTERVAL&lt;br /&gt;
done&lt;br /&gt;
echo &amp;quot;On-line&amp;quot;&lt;br /&gt;
# Упражнение: Найдите сильные и слабые стороны&lt;br /&gt;
# каждого из этих подходов.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Аргумент ''DEBUG'', команды '''''trap''''', заставляет сценарий выполнять указанное действие после выполнения каждой команды. Это можно использовать для трассировки переменных.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Трассировка переменной.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
trap 'echo &amp;quot;VARIABLE-TRACE&amp;gt; $LINENO: \$variable = \&amp;quot;$variable\&amp;quot;&amp;quot;' DEBUG&lt;br /&gt;
# Выводить значение переменной после исполнения каждой команды.&lt;br /&gt;
&lt;br /&gt;
variable=29&lt;br /&gt;
echo &amp;quot;Переменная \&amp;quot;\$variable\&amp;quot; инициализирована числом $variable.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;variable *= 3&amp;quot;&lt;br /&gt;
echo &amp;quot;Значение переменной \&amp;quot;\$variable\&amp;quot; увеличено в 3 раза.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Конструкция &amp;quot;trap 'commands' DEBUG&amp;quot; может оказаться очень полезной&lt;br /&gt;
# при отладке больших и сложных скриптов,&lt;br /&gt;
# когда размещение множества инструкций &amp;quot;echo $variable&amp;quot;&lt;br /&gt;
# может потребовать достаточно большого времени.&lt;br /&gt;
# Спасибо Stephane Chazelas.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Конструкция ''trap'' ' ' ''SIGNAL'' (две одиночных кавычки) — запрещает ''SIGNAL'' для оставшейся части сценария. Конструкция ''trap SIGNAL'' — восстанавливает действие сигнала ''SIGNAL''. Эти конструкции могут использоваться для защиты критических участков сценария от нежелательного прерывания.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
trap '' 2 # Сигнал 2 (Control-C) — запрещён.&lt;br /&gt;
command&lt;br /&gt;
command&lt;br /&gt;
command&lt;br /&gt;
trap 2 # Разрешение реакции на Control-C&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Необязательные параметры(ключи) ==&lt;br /&gt;
'''Необязательные параметры''' — это дополнительные ключи (''опции''), которые оказывают влияние на поведение сценария и/или командной оболочки. Команда '''''set''''' позволяет задавать дополнительные опции прямо внутри сценария. В том месте сценария, где необходимо, чтобы та или иная опция вступила в силу, вставьте такую конструкцию '''''set -o option-name''''', или в более короткой форме — '''''set -option-abbrev'''''. Эти две формы записи совершенно идентичны по своему действию.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
set -o verbose&lt;br /&gt;
# Вывод команд перед их исполнением.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
set -v&lt;br /&gt;
# Имеет тот же эффект, что и выше.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для того, чтобы отключить действие той или иной опции, следует вставить конструкцию '''''set +ooption-name''''', или '''''set +option-abbrev'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
set -o verbose&lt;br /&gt;
# Вывод команд перед их исполнением.&lt;br /&gt;
command&lt;br /&gt;
...&lt;br /&gt;
command&lt;br /&gt;
&lt;br /&gt;
set +o verbose&lt;br /&gt;
Запретить вывод команд перед их исполнением.&lt;br /&gt;
command&lt;br /&gt;
# команда не выводится.&lt;br /&gt;
&lt;br /&gt;
set -v&lt;br /&gt;
# Вывод команд перед их исполнением.&lt;br /&gt;
command&lt;br /&gt;
...&lt;br /&gt;
command&lt;br /&gt;
&lt;br /&gt;
set +v&lt;br /&gt;
# Запретить вывод команд перед их исполнением.&lt;br /&gt;
command&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Как вариант установки опций, можно предложить указывать их в заголовке сценария (в строке sha-bang) — '''#!'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash -x&lt;br /&gt;
#&lt;br /&gt;
# Далее следует текст сценария.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Так же можно указывать дополнительные ключи в командной строке, при запуске сценария. Некоторые из опций работают только если они заданы из командной строки, например ''-i'' — ключ интерактивного режима работы скрипта.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash -v script-name&lt;br /&gt;
&lt;br /&gt;
bash -o verbose script-name&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ниже приводится список некоторых полезных опций, которые могут быть указаны как в полной форме (полная форма ключа начинается с двойного дефиса) так и в сокращенной (краткая форма ключа начинается с одинарного дефиса).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;''Таблица'' '''''Ключи Bash'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Краткое имя !! Полное имя !! Описание&lt;br /&gt;
|-&lt;br /&gt;
| '''-C''' || noclobber || Предотвращает перезапись файла в операциях перенаправления вывода (не распространяется на конвейеры (каналы) &amp;lt;nowiki&amp;gt;--&amp;gt;|&amp;lt;/nowiki&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| '''-D''' || (нет) || Выводит список строк в двойных кавычках, которым предшествует символ $, сам сценарий не исполняется&lt;br /&gt;
|-&lt;br /&gt;
| '''-a''' || allexport || Экспорт всех, определенных в сценарии, переменных&lt;br /&gt;
|-&lt;br /&gt;
| '''-b''' || notify || Выводит уведомление по завершении фоновой задачи (job) (довольно редко используется в сценариях)&lt;br /&gt;
|-&lt;br /&gt;
| '''-c ...''' || (нет) || Читает команды из ...&lt;br /&gt;
|-&lt;br /&gt;
| '''-e''' || errexit || Прерывает исполнения сценария при появлении первой же ошибки, т.е. когда встретится команда, которая&lt;br /&gt;
вернёт ненулевой код возврата(за исключением циклов &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;until&amp;lt;/span&amp;gt; или &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;while&amp;lt;/span&amp;gt;, оператора &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;if&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;цепочек из команд&amp;lt;/span&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
| '''-f''' || noglob || Подстановка имён файлов(globbing) запрещена&lt;br /&gt;
|-&lt;br /&gt;
| '''-i''' || interactive || Сценарий запускается в интерактивном режиме&lt;br /&gt;
|-&lt;br /&gt;
| '''-n''' || noexec || Команды в сценарии считываются, но не исполняются(проверка синтаксиса)&lt;br /&gt;
|-&lt;br /&gt;
| '''-o Option-Name''' || (нет) || Установка опции Option-Name option&lt;br /&gt;
|-&lt;br /&gt;
| '''-o posix''' || POSIX || Изменяет поведение Bash или сценария таким образом, чтобы оно соответствовало стандарту &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;POSIX&amp;lt;/span&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| '''-p''' || privileged || Сценарий запускается как &amp;quot;suid&amp;quot;(осторожно!)&lt;br /&gt;
|-&lt;br /&gt;
| '''-r''' || restricted || Сценарий запускается в ограниченном режиме&lt;br /&gt;
|-&lt;br /&gt;
| '''-s''' || stdin || Читает команды с устройства стандартного ввода ''stdin''&lt;br /&gt;
|-&lt;br /&gt;
| '''-t''' || (нет) || Завершает работу после выполнения первой команды&lt;br /&gt;
|-&lt;br /&gt;
| '''-u''' || nounset || При попытке обращения к неопределённым переменным, выдаёт сообщение об&lt;br /&gt;
ошибке и прерывает работу сценария&lt;br /&gt;
|-&lt;br /&gt;
| '''-v''' || verbose || Выводит на ''stdout'' каждую команду прежде, чем она будет исполнена&lt;br /&gt;
|-&lt;br /&gt;
| '''-x''' || xtrace || Подобна ''-v'', но выполняет подстановку команд&lt;br /&gt;
|-&lt;br /&gt;
| '''-''' || (нет) || Конец списка ключей(опций), последующие аргументы будут восприниматься как &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;позиционные параметры&amp;lt;/span&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| '''--''' || (нет) || Эквивалент предыдущей опции(-).&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Широко распространённые ошибки ==&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::'''Turandot''': ''Gli enigmi sono tre, la morte una!''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::'''Caleph''': ''No, no! Gli enigmi sono tre, una la vita!''&lt;br /&gt;
::::::::::::::::::::::::::::::::::::::::::::::::::::::::'''''Puccini'''''&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование зарезервированных слов и служебных символов в качестве имён переменных.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
case=value0             # Может вызвать проблемы.&lt;br /&gt;
23skidoo=value1         # Тоже самое.&lt;br /&gt;
# Имена переменных, начинающиеся с цифр, зарезервированы командной оболочкой.&lt;br /&gt;
# Если имя переменной начинается с символа подчеркивания: _23skidoo=value1, то это не считается ошибкой.&lt;br /&gt;
# Однако... если имя переменной состоит из единственного символа подчеркивания, то это ошибка.&lt;br /&gt;
_=25&lt;br /&gt;
echo $_                 # $_ — это внутренняя переменная.&lt;br /&gt;
xyz((!*=value2          # Вызывает серьезные проблемы.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование дефиса, и других зарезервированных символов, в именах переменных.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
var-1=23&lt;br /&gt;
# Вместо такой записи используйте 'var_1'.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование одинаковых имён для переменных и функций. Это делает сценарий трудным для понимания.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
do_something ()&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;Эта функция должна что-нибудь сделать с \&amp;quot;$1\&amp;quot;.&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
do_something=do_something&lt;br /&gt;
do_something do_something&lt;br /&gt;
# Всё это будет работать правильно, но слишком уж запутанно.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование лишних &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;пробелов&amp;lt;/span&amp;gt;. В отличие от других языков программирования, Bash весьма привередлив по отношению к пробелам.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
var1 = 23 # Правильный вариант: 'var1=23'.&lt;br /&gt;
# В вышеприведенной строке Bash будет трактовать &amp;quot;var1&amp;quot; как имя команды с аргументами &amp;quot;=&amp;quot; и &amp;quot;23&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
let c = $a - $b # Правильный вариант: 'let c=$a-$b' или 'let &amp;quot;c = $a - $b&amp;quot;'&lt;br /&gt;
&lt;br /&gt;
if [ $a -le 5] # Правильный вариант: if [ $a -le 5 ]&lt;br /&gt;
# if [ &amp;quot;$a&amp;quot; -le 5 ] ещё лучше.&lt;br /&gt;
# [[ $a -le 5 ]] тоже верно.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ошибочным является предположение о том, что неинициализированные переменные содержат &amp;quot;'''ноль'''&amp;quot;. Неинициализированные переменные содержат &amp;quot;пустое&amp;quot; ('''null''') значение, а не '''ноль'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo &amp;quot;uninitialized_var = $uninitialized_var&amp;quot;&lt;br /&gt;
# uninitialized_var =&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Часто программисты путают операторы сравнения '''=''' и '''-eq'''. Запомните, оператор '''=''' используется для сравнения строковых переменных, а '''-eq''' — для сравнения целых чисел.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; = 273 ]   # Как вы полагаете? $a — это целое число или строка?&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq 273 ] # Если $a — целое число.&lt;br /&gt;
&lt;br /&gt;
# Иногда, такого рода ошибка никак себя не проявляет.&lt;br /&gt;
# Однако...&lt;br /&gt;
&lt;br /&gt;
a=273.0 # Не целое число.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; = 273 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Равны.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Не равны.&amp;quot;&lt;br /&gt;
fi # Не равны.&lt;br /&gt;
&lt;br /&gt;
# тоже самое и для a=&amp;quot; 273&amp;quot; и a=&amp;quot;0273&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Подобные проблемы возникают при использовании &amp;quot;-eq&amp;quot; со строковыми значениями.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$a&amp;quot; -eq 273.0 ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;a = $a'&lt;br /&gt;
fi # Исполнение сценария прерывается по ошибке.&lt;br /&gt;
# test.sh: [: 273.0: integer expression expected&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ошибки при сравнении &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;целых чисел&amp;lt;/span&amp;gt; и &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;строковых значений&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Строки и числа нельзя сравнивать напрямую.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# bad-op.sh: Попытка строкового сравнения для целых чисел.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
number=1&lt;br /&gt;
# Следующий цикл &amp;quot;while&amp;quot; порождает две ошибки:&lt;br /&gt;
# одна обнаруживается сразу, другая не так очевидна.&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$number&amp;quot; &amp;lt; 5 ] # Ошибка! Должно быть: while [ &amp;quot;$number&amp;quot; -lt 5 ]&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$number &amp;quot;&lt;br /&gt;
 let &amp;quot;number += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
# При попытке запустить этот сценарий на терминал выводится сообщение:&lt;br /&gt;
# bad-op.sh: line 10: 5: No such file or directory&lt;br /&gt;
# Внутри одиночных квадратных скобок, символ &amp;quot;&amp;lt;&amp;quot; должен экранироваться,&lt;br /&gt;
# но даже если соблюсти синтаксис, то результат сравнения все равно будет неверным.&lt;br /&gt;
echo &amp;quot;---------------------&amp;quot;&lt;br /&gt;
while [ &amp;quot;$number&amp;quot; \&amp;lt; 5 ]      # 1 2 3 4&lt;br /&gt;
do                            #&lt;br /&gt;
 echo -n &amp;quot;$number &amp;quot;           # Здесь вроде бы нет ошибки, но . . .&lt;br /&gt;
 let &amp;quot;number += 1&amp;quot;            # фактически выполняется сравнение строк,&lt;br /&gt;
done                          # а не чисел.&lt;br /&gt;
&lt;br /&gt;
echo; echo &amp;quot;---------------------&amp;quot;&lt;br /&gt;
# Это может породить определённые проблемы, например:&lt;br /&gt;
&lt;br /&gt;
lesser=5&lt;br /&gt;
greater=105&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$greater&amp;quot; \&amp;lt; &amp;quot;$lesser&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;число $greater меньше чем число $lesser&amp;quot;&lt;br /&gt;
fi                             # число 105 меньше чем число 5&lt;br /&gt;
# И действительно! Строка &amp;quot;105&amp;quot; меньше чем строка &amp;quot;5&amp;quot;!&lt;br /&gt;
# (при выполнении сравнения ASCII кодов).&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Иногда, в операциях проверки, с использованием квадратных скобок ('''[ ]'''), переменные необходимо брать в двойные кавычки('''&amp;quot; &amp;quot;''').&amp;lt;br /&amp;gt;&lt;br /&gt;
Иногда сценарий не в состоянии выполнить команду из-за нехватки прав доступа. Если пользователь не сможет запустить команду из командной строки, то эта команда не сможет быть запущена и из сценария. Попробуйте изменить атрибуты команды, возможно вам придется установить бит ''suid''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование символа '''-''' в качестве оператора перенаправления (каковым он не является) может приводить к неожиданным результатам.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
command1 2&amp;gt; - | command2       # Попытка передать сообщения об ошибках команде command1 через конвейер...&lt;br /&gt;
# ...не будет работать.&lt;br /&gt;
command1 2&amp;gt;&amp;amp; - | command2      # Так же бессмысленно.&lt;br /&gt;
#Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование функциональных особенностей Bash версии 2 или выше, может привести к аварийному завершению сценария, работающему под управлением Bash версии 1.XX.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
minimum_version=2# Поскольку Chet Ramey постоянно развивает Bash,&lt;br /&gt;
# вам может потребоваться указать другую минимально допустимую версию $minimum_version=2.XX.&lt;br /&gt;
E_BAD_VERSION=80&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$BASH_VERSION&amp;quot; \&amp;lt; &amp;quot;$minimum_version&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Этот сценарий должен исполняться под управлением Bash, версии $minimum или выше.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Настоятельно рекомендуется обновиться.&amp;quot;&lt;br /&gt;
exit $E_BAD_VERSION&lt;br /&gt;
fi&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Использование специфических особенностей Bash может приводить к аварийному завершению сценария в Bourne shell (#!/bin/sh). Как правило, в дистрибутивах Linux, sh является псевдонимом bash, но это не всегда верно для Unix-систем в целом. Использование недокументированных возможностей Bash весьма небезопасная практика. Предыдущие версии этой книги включали в себя ряд сценариев , которые использовали такие &amp;quot;возможности&amp;quot;, например — возможность возвращать через ''exit'' или ''return'' большие (по абсолютному значению) отрицательные целые числа. К сожалению, в версии 2.05b и более поздних, эта &amp;quot;лазейка&amp;quot; была закрыта.&amp;lt;br /&amp;gt;\&lt;br /&gt;
Сценарий, в котором строки отделяются друг от друга в стиле MS-DOS (''\r\n''), будет завершаться аварийно, поскольку комбинация #!/bin/bash\r\n считается недопустимой. Исправить эту ошибку можно простым удалением символа ''\r'' из сценария.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
echo &amp;quot;Начало&amp;quot;&lt;br /&gt;
&lt;br /&gt;
unix2dos $0        # Сценарий переводит символы перевода строки в формат DOS.&lt;br /&gt;
chmod 755 $0       # Восстановление прав на запуск.&lt;br /&gt;
                   # Команда 'unix2dos' удалит право на запуск из атрибутов файла.&lt;br /&gt;
&lt;br /&gt;
./$0               # Попытка запустить себя самого.&lt;br /&gt;
                   # Но это не сработает из-за того, что теперь строки отделяются друг от друга в стиле DOS.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Конец&amp;quot;&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Сценарий, начинающийся с #!/bin/sh, не может работать в режиме полной совместимости с Bash'''''. Некоторые из специфических функций, присущих Bash, могут оказаться запрещёнными к использованию. '''''Сценарий, который требует полного доступа ко всем расширениям, имеющимся в Bash, должен начинаться строкой #!/bin/bash'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;&amp;quot;Лишние&amp;quot; пробелы перед строкой-ограничителем, завершающей встроенный документ&amp;lt;/span&amp;gt;, будут приводить к ошибкам в работе сценария.&amp;lt;br /&amp;gt;&lt;br /&gt;
Сценарий не может экспортировать переменные &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;родительскому процессу&amp;lt;/span&amp;gt; — оболочке. Здесь как в природе, потомок может унаследовать черты родителя, но не наоборот.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
WHATEVER=/home/bozo&lt;br /&gt;
export WHATEVER&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
bash$ echo $WHATEVER&lt;br /&gt;
bash$&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Будьте уверены — при выходе в командную строку переменная $WHATEVER останется неинициализированной. Использование в подоболочке переменных с теми же именами, что и в родительской оболочке может не давать ожидаемого результата.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Западня в подоболочке.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Западня в подоболочке.&lt;br /&gt;
&lt;br /&gt;
outer_variable=внешняя_переменная&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;outer_variable = $outer_variable&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
(&lt;br /&gt;
# Запуск в подоболочке&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;внутри подоболочки outer_variable = $outer_variable&amp;quot;&lt;br /&gt;
inner_variable=внутренняя_переменная &lt;br /&gt;
# Инициализировать&lt;br /&gt;
echo &amp;quot;внутри подоболочки inner_variable = $inner_variable&amp;quot;&lt;br /&gt;
outer_variable=внутренняя_переменная # Как думаете? Изменит внешнюю переменную?&lt;br /&gt;
echo &amp;quot;внутри подоболочки outer_variable = $outer_variable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Выход из подоболочки&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;за пределами подоболочки inner_variable = $inner_variable&amp;quot; # Ничего не выводится.&lt;br /&gt;
echo &amp;quot;за пределами подоболочки outer_variable = $outer_variable&amp;quot; # внешняя_переменная.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Передача вывода от [[echo]] по конвейеру команде '''''read''''' может давать неожиданные результаты. В этом сценарии, команда '''''read''''' действует так, как будто бы она была запущена в подоболочке. Вместо неё лучше использовать команду '''''set'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача вывода от команды echo команде read, по конвейеру.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# badread.sh:&lt;br /&gt;
# Попытка использования 'echo' и 'read'&lt;br /&gt;
# для записи значений в переменные.&lt;br /&gt;
&lt;br /&gt;
a=aaa&lt;br /&gt;
b=bbb&lt;br /&gt;
c=ccc&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;один два три&amp;quot; | read a b c# Попытка записать значения в переменные a, b и c.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = aaa&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # b = bbb&lt;br /&gt;
echo &amp;quot;c = $c&amp;quot; # c = ccc&lt;br /&gt;
# Присваивания не произошло.&lt;br /&gt;
&lt;br /&gt;
# ------------------------------&lt;br /&gt;
&lt;br /&gt;
# Альтернативный вариант.&lt;br /&gt;
var=`echo &amp;quot;один два три&amp;quot;`&lt;br /&gt;
set -- $var&lt;br /&gt;
a=$1; b=$2; c=$3&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;-------&amp;quot;&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = один&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # b = два&lt;br /&gt;
echo &amp;quot;c = $c&amp;quot; # c = три&lt;br /&gt;
# На этот раз всё в порядке.&lt;br /&gt;
&lt;br /&gt;
# ------------------------------&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание: в подоболочке 'read', для первого варианта, переменные присваиваются нормально.&lt;br /&gt;
# Но только в подоболочке.&lt;br /&gt;
&lt;br /&gt;
a=aaa # Всё сначала.&lt;br /&gt;
b=bbb&lt;br /&gt;
c=ccc&lt;br /&gt;
&lt;br /&gt;
echo; echo&lt;br /&gt;
echo &amp;quot;один два три&amp;quot; | ( read a b c;&lt;br /&gt;
echo &amp;quot;Внутри подоболочки: &amp;quot;; echo &amp;quot;a = $a&amp;quot;; echo &amp;quot;b = $b&amp;quot;; echo &amp;quot;c = $c&amp;quot; )&lt;br /&gt;
# a = один&lt;br /&gt;
# b = два&lt;br /&gt;
# c = три&lt;br /&gt;
echo &amp;quot;-------&amp;quot;&lt;br /&gt;
echo &amp;quot;Снаружи: &amp;quot;&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # a = aaa&lt;br /&gt;
echo &amp;quot;b = $b&amp;quot; # b = bbb&lt;br /&gt;
echo &amp;quot;c = $c&amp;quot; # c = ccc&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Фактически, как указывает Anthony Richardson, передача вывода по конвейеру в любой цикл, может порождать аналогичные проблемы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Проблемы с передачей данных в цикл по конвейеру.&lt;br /&gt;
# Этот пример любезно предоставил Anthony Richardson.&lt;br /&gt;
&lt;br /&gt;
foundone=false&lt;br /&gt;
find $HOME -type f -atime +30 -size 100k |&lt;br /&gt;
while true&lt;br /&gt;
do&lt;br /&gt;
 read f&lt;br /&gt;
 echo &amp;quot;Файл $f имеет размер более 100KB и не использовался более 30 дней&amp;quot;&lt;br /&gt;
 echo &amp;quot;Подумайте о перемещении этого файла в архив.&amp;quot;&lt;br /&gt;
 foundone=true&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# Переменная foundone всегда будет иметь значение false, поскольку&lt;br /&gt;
# она устанавливается в пределах подоболочки&lt;br /&gt;
&lt;br /&gt;
if [ $foundone = false ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Не найдено файлов, которые требуют архивации.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# =====================А теперь правильный вариант:=================&lt;br /&gt;
foundone=false&lt;br /&gt;
for f in $(find $HOME -type f -atime +30 -size 100k) # Здесь нет конвейера.&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;Файл $f имеет размер более 100KB и не использовался более 30 дней&amp;quot;&lt;br /&gt;
 echo &amp;quot;Подумайте о перемещении этого файла в архив.&amp;quot;&lt;br /&gt;
 foundone=true&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
if [ $foundone = false ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Не найдено файлов, которые требуют архивации.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Подобные же проблемы возникают при попытке записать вывод от '''''tail -f''''' в конвейере с [[grep]].&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tail -f /var/log/messages | grep &amp;quot;$ERROR_MSG&amp;quot; &amp;gt;&amp;gt; error.log&lt;br /&gt;
# Ни одна запись не попадёт в файл &amp;quot;error.log&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Огромный риск, для безопасности системы, представляет использование в скриптах команд, с установленным битом &amp;quot;''suid''&amp;quot;. Использование сценариев в качестве CGI-приложений может приводить к серьёзным проблемам из-за отсутствия контроля типов переменных. Более того, они легко могут быть заменены взломщиком на его собственные сценарии.&amp;lt;br /&amp;gt;&lt;br /&gt;
Bash не совсем корректно обрабатывает строки, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;содержащие двойной слэш (//)&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Сценарии на языке Bash, созданные для Linux или BSD систем, могут потребовать доработки, перед тем как они смогут быть запущены в коммерческой версии Unix. Такие сценарии, как правило, используют GNU-версии команд и утилит, которые имеют лучшую функциональность, нежели их аналоги в Unix. Это особенно справедливо для таких утилит обработки текста, как '''''tr'''''.&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::''Danger is near thee —''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::''Beware, beware, beware, beware.''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::''Many brave hearts are asleep in the deep.''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::''So beware —''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::''Beware.''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::::::::'''''A.J. Lamb and H.W. Petrie'''''&lt;br /&gt;
&lt;br /&gt;
== Стиль программирования ==&lt;br /&gt;
Возьмите в привычку структурный и систематический подход к программированию на языке командной оболочки. Даже для сценариев &amp;quot;выходного дня&amp;quot; и &amp;quot;писаных на коленке&amp;quot;, не поленитесь, найдите время для того, чтобы разложить свои мысли по полочкам и продумать структуру будущего скрипта прежде чем приниматься за кодирование.&lt;br /&gt;
Ниже приводится несколько рекомендаций по оформлению сценариев, однако их не следует рассматривать как ''Официальное Руководство''.&lt;br /&gt;
=== Неофициальные рекомендации по оформлению сценариев ===&lt;br /&gt;
* '''''Комментируйте свой код. Это сделает ваши сценарии понятнее для других, и более простыми, в обслуживании, для вас'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
PASS=&amp;quot;$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}&amp;quot;&lt;br /&gt;
# Эта строка имела некоторый смысл в момент написания,&lt;br /&gt;
# но через год-другой будет очень тяжело вспомнить — что она делает.&lt;br /&gt;
# (Из сценария &amp;quot;pw.sh&amp;quot;, автор: Antek Sawicki)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Добавляйте заголовочные комментарии в начале сценария и перед функциями.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
#************************************************#&lt;br /&gt;
#                  xyz.sh                        #&lt;br /&gt;
#           автор: Bozo Bozeman                  #&lt;br /&gt;
#                Июль 05, 2001                   #&lt;br /&gt;
#                                                #&lt;br /&gt;
#           Удаление файлов проекта.             #&lt;br /&gt;
#************************************************#&lt;br /&gt;
BADDIR=65                      # Нет такого каталога.&lt;br /&gt;
projectdir=/home/bozo/projects # Каталог проекта.&lt;br /&gt;
&lt;br /&gt;
# ------------------------------------------------------- #&lt;br /&gt;
# cleanup_pfiles ()                                       #&lt;br /&gt;
# Удаляет все файлы в заданном каталоге.                  #&lt;br /&gt;
# Параметры: $target_directory                            #&lt;br /&gt;
# Возвращаемое значение: 0 — в случае успеха,             #&lt;br /&gt;
# $BADDIR — в случае ошибки.                              #&lt;br /&gt;
# ------------------------------------------------------- #&lt;br /&gt;
&lt;br /&gt;
cleanup_pfiles ()&lt;br /&gt;
{&lt;br /&gt;
if [ ! -d &amp;quot;$1&amp;quot; ] # Проверка существования заданного каталога.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;$1 — не является каталогом.&amp;quot;&lt;br /&gt;
 return $BADDIR&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
 rm -f &amp;quot;$1&amp;quot;/*&lt;br /&gt;
 return 0 # Успешное завершение функции.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
cleanup_pfiles $projectdir&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Не забывайте начинать ваш сценарий с ''sha-bang'' — '''''#!/bin/bash'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''''Заменяйте повторяющиеся значения константами. Это сделает ваш сценарий более простым для понимания и позволит вносить изменения, не опасаясь за его работоспособность'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ -f /var/log/messages ]&lt;br /&gt;
then&lt;br /&gt;
 ...&lt;br /&gt;
fi&lt;br /&gt;
# Представьте себе, что через пару лет&lt;br /&gt;
# вы захотите изменить /var/log/messages на /var/log/syslog.&lt;br /&gt;
# Тогда вам придётся отыскать все строки,&lt;br /&gt;
# содержащие /var/log/messages, и заменить их на /var/log/syslog.&lt;br /&gt;
# И проверить несколько раз — не пропустили ли что-нибудь.&lt;br /&gt;
&lt;br /&gt;
# Использование &amp;quot;констант&amp;quot; даёт лучший способ:&lt;br /&gt;
LOGFILE=/var/log/messages # Если и придётся изменить, то только в этой строке.&lt;br /&gt;
if [ -f &amp;quot;$LOGFILE&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 ...&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''''В качестве имён переменных и функций выбирайте осмысленные названия'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
fl=`ls -al $dirname`             # Не очень удачное имя переменной.&lt;br /&gt;
file_listing=`ls -al $dirname`   # Уже лучше.&lt;br /&gt;
&lt;br /&gt;
MAXVAL=10                        # Пишите имена констант в верхнем регистре.&lt;br /&gt;
while [ &amp;quot;$index&amp;quot; -le &amp;quot;$MAXVAL&amp;quot; ]&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
E_NOTFOUND=75                    # Имена кодов ошибок — в верхнем регистре,&lt;br /&gt;
                                 # к тому же, их желательно дополнять префиксом &amp;quot;E_&amp;quot;.&lt;br /&gt;
if [ ! -e &amp;quot;$filename&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Файл $filename не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOTFOUND&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
MAIL_DIRECTORY=/var/spool/mail/bozo # Имена переменных окружения&lt;br /&gt;
                                    # так же желательно записывать символами&lt;br /&gt;
                                    # в верхнем регистре.&lt;br /&gt;
export MAIL_DIRECTORY&lt;br /&gt;
&lt;br /&gt;
GetAnswer ()                        # Смешивание символов верхнего и нижнего регистров&lt;br /&gt;
                                    # удобно использовать для имён функций.&lt;br /&gt;
{&lt;br /&gt;
 prompt=$1&lt;br /&gt;
 echo -n $prompt&lt;br /&gt;
 read answer&lt;br /&gt;
 return $answer&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
GetAnswer &amp;quot;Ваше любимое число? &amp;quot;&lt;br /&gt;
&lt;br /&gt;
favorite_number=$?&lt;br /&gt;
echo $favorite_number_user&lt;br /&gt;
&lt;br /&gt;
variable=23                         # Допустимо, но не рекомендуется.&lt;br /&gt;
# Желательно, чтобы пользовательские переменные не начинались с символа подчёркивания.&lt;br /&gt;
# Так обычно начинаются системные переменные.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''''Используйте смысловые имена для &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;кодов завершения&amp;lt;span&amp;gt;'''''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
E_WRONG_ARGS=65&lt;br /&gt;
...&lt;br /&gt;
...&lt;br /&gt;
exit $E_WRONG_ARGS&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''''Разделяйте большие сложные сценарии на серию более коротких и простых модулей. Пользуйтесь функциями'''''.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''''Не пользуйтесь сложными конструкциями, если их можно заменить простыми'''''. &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
COMMAND&lt;br /&gt;
if [ $? -eq 0 ]&lt;br /&gt;
...&lt;br /&gt;
# Избыточно и неинтуитивно.&lt;br /&gt;
if COMMAND...&lt;br /&gt;
# Более понятно и коротко.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::''... читая исходные тексты сценариев на Bourne''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::''shell (/bin/sh). Я был потрясен тем, насколько''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::''непонятно и загадочно могут выглядеть очень''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::''простые алгоритмы из-за неправильного''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::''оформления кода. Я не раз спрашивал себя:''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::''&amp;quot;Неужели кто-то может гордиться таким кодом?&amp;quot;''&lt;br /&gt;
:::::::::::::::::::::::::::::::::::::::::::::::::::::::'''Landon Noll'''&lt;br /&gt;
&lt;br /&gt;
== Разное ==&lt;br /&gt;
::::::::::::::::::::::::::::::::::::::::::::''Практически никто не знает грамматики Bourne''&lt;br /&gt;
::::::::::::::::::::::::::::::::::::::::::::''shell-а. Даже изучение исходных текстов не даёт''&lt;br /&gt;
::::::::::::::::::::::::::::::::::::::::::::''её полного понимания''.&lt;br /&gt;
::::::::::::::::::::::::::::::::::::::::::::::::::::::::'''''Tom Duff'''''&lt;br /&gt;
=== Интерактивный и неинтерактивный режим работы ===&lt;br /&gt;
В ''интеракивном режиме'', оболочка читает команды, вводимые пользователем, с устройства ''tty''. Кроме того, такая оболочка считывает конфигурационные файлы на запуске, выводит строку приглашения к вводу (''prompt''), и, по-умолчанию, разрешает управление заданиями. Пользователь имеет возможность взаимодействия с оболочкой.&amp;lt;br /&amp;gt;\&lt;br /&gt;
Сценарий всегда запускается в неинтерактивном режиме. Но, не смотря на это, он сохраняет доступ к своему ''tty''. И даже может эмулировать интерактивный режим работы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
MY_PROMPT='$ '&lt;br /&gt;
while :&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$MY_PROMPT&amp;quot;&lt;br /&gt;
 read line&lt;br /&gt;
 eval &amp;quot;$line&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
# Этот сценарий, как иллюстрация к вышесказанному, предоставлен Stephane Chazelas (спасибо).&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Будем считать интерактивным такой сценарий, который может принимать ввод от пользователя, обычно с помощью команды '''read'''. В &amp;quot;реальной жизни&amp;quot; все намного сложнее. Пока же, будем придерживаться предположения о том, что интерактивный сценарий ограничен рамками ''tty'', с которого сценарий был запущен пользователемa, т.е консоль или окно ''xterm''. Сценарии начальной инициализации системы не являются интерактивными, поскольку они не предполагают вмешательство человека в процессе своей работы. Большая часть сценариев, выполняющих администрирование и обслуживание системы — так же работают в неинтерактивном режиме. Многие задачи автоматизации труда администратора очень трудно представить себе без неинтерактивных сценариев. Неинтерактивные сценарии прекрасно могут работать в фоне, в то время, как интерактивные — подвисают, останавливаясь на операциях, ожидающих ввода пользователя. Сложности, возникающие с запуском интерактивных сценариев в фоновом режиме, могут быть преодолены с помощью expect-сценария или встроенного документа. В простейших случаях, можно организовать перенаправление ввода из файла в команду '''read''' ('''''read variable &amp;lt;file'''''). Эти приёмы позволят создавать сценарии, которые смогут работать как в интерактивном, так и в неинтерактивном режимах.&amp;lt;br /&amp;gt;&lt;br /&gt;
Если внутри сценария необходимо проверить режим работы — интерактивный или неинтерактивный, это можно сделать проверкой переменной окружения &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$PS1&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
if [ -z $PS1 ] # интерактивный режим?&lt;br /&gt;
then&lt;br /&gt;
 # неинтерактивный&lt;br /&gt;
 ...&lt;br /&gt;
else&lt;br /&gt;
 # интерактивный&lt;br /&gt;
 ...&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ещё один способ — проверка установки флага &amp;quot;i&amp;quot; в переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$-&amp;lt;/span&amp;gt;.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
case $- in&lt;br /&gt;
 *i*) # интерактивный режим&lt;br /&gt;
 ;;&lt;br /&gt;
 *) # неинтерактивный режим&lt;br /&gt;
 ;;&lt;br /&gt;
# (Из &amp;quot;Unix F.A.Q.,&amp;quot; 1993)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сценарий может принудительно запускаться в интерактивном режиме, для этого необходимо указать ключ ''-i'' в строке-заголовке '''''#!/bin/bash -i'''''. Однако вы должны помнить о том, что в таких случаях сценарий может выдавать сообщения об ошибках даже тогда, когда ошибок, по сути, нет.&lt;br /&gt;
&lt;br /&gt;
=== Сценарии-обёртки ===&lt;br /&gt;
&amp;quot;Обёртки&amp;quot; — это сценарии, которые содержат один или несколько вызовов системных команд или утилит, с длинным списком параметров. Такой приём освобождает пользователя от необходимости вводить вручную сложные и длинные команды из командной строки. Он особенно полезен при работе с [[sed]] и [[awk]].&amp;lt;br /&amp;gt;&lt;br /&gt;
Сценарии [[sed]] или [[awk]], как правило вызываются в форме: '''''sed -e 'commands' ''''' или '''''awk 'commands' '''''. &amp;quot;Заворачивая&amp;quot; такие вызовы в сценарий на языке командной оболочки, мы делаем их использование более простым для конечного пользователя. Кроме того, этот приём позволяет комбинировать вызовы [[sed]] и [[awk]], например в конвейере, позволяя передавать данные с выхода одной утилиты на вход другой.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий-обёртка.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
# Этот простой сценарий удаляет пустые строки из текстового файла.&lt;br /&gt;
# Проверка входных аргументов не производится.&lt;br /&gt;
#&lt;br /&gt;
# Однако вы можете дополнить сценарий такой проверкой,&lt;br /&gt;
# добавив нечто подобное:&lt;br /&gt;
# if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
# then&lt;br /&gt;
# echo &amp;quot;Порядок использования: `basename $0` текстовый_файл&amp;quot;&lt;br /&gt;
# exit 65&lt;br /&gt;
# fi&lt;br /&gt;
# Для выполнения этих же действий,&lt;br /&gt;
# из командной строки можно набрать&lt;br /&gt;
# sed -e '/^$/d' filename&lt;br /&gt;
&lt;br /&gt;
sed -e /^$/d &amp;quot;$1&amp;quot;&lt;br /&gt;
# '-e' — означает команду &amp;quot;editing&amp;quot; (правка), за которой следуют необязательные параметры.&lt;br /&gt;
# '^' — с начала строки, '$' — до её конца.&lt;br /&gt;
# Что соответствует строкам, которые не содержат символов между началом и концом строки,&lt;br /&gt;
# т.е. — пустым строкам.&lt;br /&gt;
# 'd' — команда &amp;quot;delete&amp;quot; (удалить).&lt;br /&gt;
&lt;br /&gt;
# Использование кавычек даёт возможность&lt;br /&gt;
# обрабатывать файлы, чьи имена содержат пробелы.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Более сложный пример сценария-обёртки.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# &amp;quot;subst&amp;quot;, Сценарий замены по шаблону&lt;br /&gt;
# т.е., &amp;quot;subst Smith Jones letter.txt&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
ARGS=3&lt;br /&gt;
E_BADARGS=65 # Неверное число аргументов.&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
# Проверка числа аргументов.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Проядок использования: `basename $0` old-pattern new-pattern filename&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
old_pattern=$1&lt;br /&gt;
new_pattern=$2&lt;br /&gt;
&lt;br /&gt;
if [ -f &amp;quot;$3&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 file_name=$3&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$3\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
# Здесь, собственно, выполняется сама работа по поиску и замене.&lt;br /&gt;
sed -e &amp;quot;s/$old_pattern/$new_pattern/g&amp;quot; $file_name&lt;br /&gt;
# 's' — команда &amp;quot;substitute&amp;quot; (замены),&lt;br /&gt;
# а /pattern/ — задаёт шаблон искомого текста.&lt;br /&gt;
# &amp;quot;g&amp;quot; — флаг &amp;quot;global&amp;quot; (всеобщий), означает &amp;quot;выполнить подстановку для *каждого*&lt;br /&gt;
# обнаруженного $old_pattern во всех строках, а не только в первой строке.&lt;br /&gt;
&lt;br /&gt;
exit 0 # При успешном завершении сценария — вернуть 0.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий-обертка вокруг сценария awk.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Суммирует числа в заданном столбце из заданного файла.&lt;br /&gt;
&lt;br /&gt;
ARGS=2&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ] # Проверка числа аргументов.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя_файла номер_столбца&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
filename=$1&lt;br /&gt;
column_number=$2&lt;br /&gt;
&lt;br /&gt;
# Здесь используется прием передачи переменных&lt;br /&gt;
# из командной оболочки в сценарий awk .&lt;br /&gt;
# Многострочный сценарий awk должен записываться в виде: awk ' ..... '&lt;br /&gt;
&lt;br /&gt;
# Начало awk-сценария.&lt;br /&gt;
# -----------------------------&lt;br /&gt;
awk '&lt;br /&gt;
{ total += $'&amp;quot;${column_number}&amp;quot;'&lt;br /&gt;
}&lt;br /&gt;
END {&lt;br /&gt;
 print total&lt;br /&gt;
}&lt;br /&gt;
' &amp;quot;$filename&amp;quot;&lt;br /&gt;
# -----------------------------&lt;br /&gt;
# Конец awk-сценария.&lt;br /&gt;
&lt;br /&gt;
# С точки зрения безопасности, передача shell-переменных&lt;br /&gt;
# во встроенный awk-скрипт, потенциально опасна,&lt;br /&gt;
# поэтому, Stephane Chazelas предлагает следующую альтернативу:&lt;br /&gt;
# ---------------------------------------&lt;br /&gt;
# awk -v column_number=&amp;quot;$column_number&amp;quot; '&lt;br /&gt;
# { total += $column_number&lt;br /&gt;
# }&lt;br /&gt;
# END {&lt;br /&gt;
# print total&lt;br /&gt;
# }' &amp;quot;$filename&amp;quot;&lt;br /&gt;
# ---------------------------------------&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Для сценариев, которые должны строиться по принципу швейцарского армейского ножа — &amp;quot;всё водном&amp;quot;, можно порекомендовать '''''Perl'''''. '''''Perl''''' совмещает в себе мощь и гибкость [[sed]], [[awk]] и языка программирования '''''C'''''. Он поддерживает модульность и объектно-ориентированный стиль программирования. Короткие сценарии '''''Perl''''' могут легко встраиваться в сценарии командной оболочки, и даже полностью заменить из (хотя автор весьма скептически относится к последнему утверждению).&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий на языке Perl, встроенный в Bash-скрипт.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
# Это команды shell, предшествующий сценарию на Perl.&lt;br /&gt;
echo &amp;quot;Эта строка выводится средствами Bash, перед выполнением встроенного Perl-скрипта, в \&amp;quot;$0\&amp;quot;.&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&amp;quot;==============================================================================================&amp;quot;&lt;br /&gt;
&lt;br /&gt;
perl -e 'print &amp;quot;Эта строка выводится средствами Perl.\n&amp;quot;;'&lt;br /&gt;
# Подобно sed, Perl тоже использует ключ &amp;quot;-e&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;=====================================&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Допускается даже комбинирование сценариев на Bash и на '''''Perl''''', в пределах одного файла. В зависимости от того, какая часть сценария должна исполняться, сценарий вызывается с указанием требуемого интерпретатора.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Комбинирование сценария Bash и Perl в одном файле.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# bashandperl.sh&lt;br /&gt;
echo &amp;quot;Вас приветствует часть сценария, написанная на Bash.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Далее могут следовать другие команды Bash.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# Конец сценария на Bash.&lt;br /&gt;
&lt;br /&gt;
# =======================================================&lt;br /&gt;
&lt;br /&gt;
#!/usr/bin/perl&lt;br /&gt;
# Эта часть сценария должна вызываться с ключом -x.&lt;br /&gt;
&lt;br /&gt;
print &amp;quot;Вас приветствует часть сценария, написанная на Perl.\n&amp;quot;;&lt;br /&gt;
# Далее могут следовать другие команды Perl.&lt;br /&gt;
&lt;br /&gt;
# Конец сценария на Perl.&lt;br /&gt;
&lt;br /&gt;
bash$ bash bashandperl.sh &lt;br /&gt;
Вас приветствует часть сценария, написанная на Bash.&lt;br /&gt;
&lt;br /&gt;
bash$ perl -x bashandperl.sh&lt;br /&gt;
Вас приветствует часть сценария, написанная на Perl.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== Операции сравнения: Альтернативные решения ===&lt;br /&gt;
Операции сравнения, выполняемые с помощью конструкции '''[[ ]]''', могут оказаться предпочтительнее,чем '''[ ]'''. Аналогично, при сравнении чисел, в более выгодном свете представляется конструкция '''(( ))'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
a=8&lt;br /&gt;
&lt;br /&gt;
# Все, приведенные ниже, операции сравнения — эквивалентны.&lt;br /&gt;
test &amp;quot;$a&amp;quot; -lt 16 &amp;amp;&amp;amp; echo &amp;quot;да, $a &amp;lt; 16&amp;quot; # &amp;quot;И-список&amp;quot;&lt;br /&gt;
/bin/test &amp;quot;$a&amp;quot; -lt 16 &amp;amp;&amp;amp; echo &amp;quot;да, $a &amp;lt; 16&amp;quot;&lt;br /&gt;
[ &amp;quot;$a&amp;quot; -lt 16 ] &amp;amp;&amp;amp; echo &amp;quot;да, $a &amp;lt; 16&amp;quot;&lt;br /&gt;
[[ $a -lt 16 ]] &amp;amp;&amp;amp; echo &amp;quot;да, $a &amp;lt; 16&amp;quot; # Внутри [[ ]] и (( )) переменные&lt;br /&gt;
(( a &amp;lt; 16 )) &amp;amp;&amp;amp; echo &amp;quot;да, $a &amp;lt; 16&amp;quot;    # не обязательно брать в кавычки.&lt;br /&gt;
&lt;br /&gt;
city=&amp;quot;New York&amp;quot;&lt;br /&gt;
# Опять же, все, приведенные ниже, операции — эквивалентны.&lt;br /&gt;
test &amp;quot;$city&amp;quot; \&amp;lt; Paris &amp;amp;&amp;amp; echo &amp;quot;Да, Paris больше, чем $city&amp;quot; # В смысле ASCII-строк.&lt;br /&gt;
/bin/test &amp;quot;$city&amp;quot; \&amp;lt; Paris &amp;amp;&amp;amp; echo &amp;quot;Да, Paris больше, чем $city&amp;quot;&lt;br /&gt;
[ &amp;quot;$city&amp;quot; \&amp;lt; Paris ] &amp;amp;&amp;amp; echo &amp;quot;Да, Paris больше, чем $city&amp;quot;&lt;br /&gt;
[[ $city &amp;lt; Paris ]] &amp;amp;&amp;amp; echo &amp;quot;Да, Paris больше, чем $city&amp;quot; # Кавычки вокруг $city не обязательны.&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
=== Рекурсия ===&lt;br /&gt;
Может ли сценарий &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;рекурсивно&amp;lt;/span&amp;gt; вызывать себя самого? Да, может!&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий (бесполезный), который вызывает себя сам.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# recurse.sh&lt;br /&gt;
&lt;br /&gt;
# Может ли сценарий вызвать себя сам?&lt;br /&gt;
# Да, но есть ли в этом смысл?&lt;br /&gt;
&lt;br /&gt;
RANGE=10&lt;br /&gt;
MAXVAL=9&lt;br /&gt;
i=$RANDOM&lt;br /&gt;
let &amp;quot;i %= $RANGE&amp;quot; # Генерация псевдослучайного числа в диапазоне 0 .. $MAXVAL.&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$i&amp;quot; -lt &amp;quot;$MAXVAL&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;i = $i&amp;quot;&lt;br /&gt;
 ./$0 # Сценарий запускает новый экземпляр себя самого.&lt;br /&gt;
fi # если число $i больше или равно $MAXVAL.&lt;br /&gt;
# Если конструкцию &amp;quot;if/then&amp;quot; заменить на цикл &amp;quot;while&amp;quot;, то это вызовет определенные проблемы.&lt;br /&gt;
# Объясните — почему?.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий (имеющий практическую ценность), который вызывает себя сам.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# pb.sh: телефонная книга&lt;br /&gt;
# Автор: Rick Boivie&lt;br /&gt;
# используется с его разрешения.&lt;br /&gt;
# Дополнен автором документа.&lt;br /&gt;
&lt;br /&gt;
MINARGS=1 # Сценарию должен быть передан, по меньшей мере, один аргумент.&lt;br /&gt;
DATAFILE=./phonebook&lt;br /&gt;
PROGNAME=$0&lt;br /&gt;
E_NOARGS=70 # Ошибка, нет аргументов.&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt $MINARGS ]; then&lt;br /&gt;
 echo &amp;quot;Порядок использования: &amp;quot;$PROGNAME&amp;quot; data&amp;quot;&lt;br /&gt;
 exit $E_NOARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ $# -eq $MINARGS ]; then&lt;br /&gt;
 grep $1 &amp;quot;$DATAFILE&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 ( shift; &amp;quot;$PROGNAME&amp;quot; $* ) | grep $1&lt;br /&gt;
 # Рекурсивный вызов.&lt;br /&gt;
fi&lt;br /&gt;
exit 0 # Сценарий завершает свою работу здесь.&lt;br /&gt;
       # Далее следует пример файла телефонной книги&lt;br /&gt;
       # в котором не используются символы комментария.&lt;br /&gt;
&lt;br /&gt;
# ------------------------------------------------------------------------&lt;br /&gt;
# Пример файла телефонной книги&lt;br /&gt;
#John Doe 1555 Main St., Baltimore, MD 21228 (410) 222-3333&lt;br /&gt;
#Mary Moe 9899 Jones Blvd., Warren, NH 03787 (603) 898-3232&lt;br /&gt;
#Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567&lt;br /&gt;
#Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678&lt;br /&gt;
#Zoe Zenobia 4481 N. Baker St., San Franciso, SF 94338 (415) 501-1631&lt;br /&gt;
# ------------------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
$bash pb.sh Roe&lt;br /&gt;
Richard Roe 856 E. 7th St., New York, NY 10009 (212) 333-4567&lt;br /&gt;
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678&lt;br /&gt;
&lt;br /&gt;
$bash pb.sh Roe Sam&lt;br /&gt;
Sam Roe 956 E. 8th St., New York, NY 10009 (212) 444-5678&lt;br /&gt;
# Если сценарию передаются несколько аргументов,&lt;br /&gt;
# то выводятся только те строки, которые содержат их все.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Ещё один сценарий, который вызывает себя сам.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# usrmnt.sh, автор Anthony Richardson&lt;br /&gt;
# Используется с его разрешения.&lt;br /&gt;
&lt;br /&gt;
# Порядок использования: usrmnt.sh&lt;br /&gt;
# Описание: монтирует устройство, пользователь должен входить в состав группы&lt;br /&gt;
# MNTUSERS в файле /etc/sudoers.&lt;br /&gt;
&lt;br /&gt;
# -----------------------------------------------------------------&lt;br /&gt;
# Этот сценарий рекурсивно вызывает себя самого,&lt;br /&gt;
# используя sudo. Пользователь, наделённый&lt;br /&gt;
# соответствующими правами может просто дать команду&lt;br /&gt;
# usermount /dev/fd0 /mnt/floppy&lt;br /&gt;
# вместо&lt;br /&gt;
# sudo usermount /dev/fd0 /mnt/floppy&lt;br /&gt;
# Подобную технику я использую во всех моих&lt;br /&gt;
# sudo-сценариях, поскольку она кажется мне достаточно удобной.&lt;br /&gt;
# -----------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
# Если переменная SUDO_COMMAND не определена, значит сценарий запущен не через&lt;br /&gt;
# sudo, поэтому повторно вызываем сценарий.&lt;br /&gt;
# Передавая user id и group id через переменные...&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$SUDO_COMMAND&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 mntusr=$(id -u) grpusr=$(id -g) sudo $0 $*&lt;br /&gt;
 exit 0&lt;br /&gt;
fi&lt;br /&gt;
# В эту точку мы попадаем только если сценарий запущен через sudo&lt;br /&gt;
/bin/mount $* -o uid=$mntusr,gid=$grpusr&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# Дополнительные замечания от автора сценария:&lt;br /&gt;
# -------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
# 1) Linux допускает указание опции &amp;quot;users&amp;quot; в файле /etc/fstab,&lt;br /&gt;
# которая позволяет монтировать носители любому пользователю.&lt;br /&gt;
# Но на сервере я предпочитаю дать это право лишь отдельным&lt;br /&gt;
# пользователям. На мой взгляд sudo делает ситуацию более управляемой.&lt;br /&gt;
&lt;br /&gt;
# 2) Я так же считаю, что утилита sudo более удобна, чем&lt;br /&gt;
# выполнение той же задачи посредством групп.&lt;br /&gt;
&lt;br /&gt;
# 3) Эта методика выдает права root на доступ к команде&lt;br /&gt;
# mount, что требует особого внимания при выделении пользователей&lt;br /&gt;
# наделенных таким правом. Используя ту же самую технику,&lt;br /&gt;
# вы можете более точно разграничить права монтирования&lt;br /&gt;
# устройств, написав сценарии mntfloppy, mntcdrom и mntsamba.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Слишком глубокая рекурсия может привести к исчерпанию пространства, выделенного под стек, и &amp;quot;вываливанию&amp;quot; сценария по &amp;quot;''segfault''&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;Цветные&amp;quot; сценарии ===&lt;br /&gt;
Для установки атрибутов отображения информации на экране, таких как: жирный текст, цвет символов, цвет фона и т.п., с давних пор используются ''ANSI'' escape-последовательности. Эти последовательности широко используются в пакетных файлах ''DOS'', эти же последовательности используются и в сценариях Bash.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''&amp;quot;Цветная&amp;quot; адресная книга.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ex30a.sh: Версия сценария ex30.sh, с добавлением цвета .&lt;br /&gt;
# Грубый пример базы данных&lt;br /&gt;
&lt;br /&gt;
clear # Очистка экрана&lt;br /&gt;
&lt;br /&gt;
echo -n &amp;quot;             &amp;quot;&lt;br /&gt;
echo -e '\E[37;44m'&amp;quot;\033[1mСписок\033[0m&amp;quot;&lt;br /&gt;
                    # Белый текст на синем фоне&lt;br /&gt;
echo; echo&lt;br /&gt;
echo -e &amp;quot;\033[1mВыберите интересующую Вас персону:\033[0m&amp;quot;&lt;br /&gt;
                    # Жирный шрифт&lt;br /&gt;
tput sgr0&lt;br /&gt;
echo &amp;quot;(Введите только первую букву имени.)&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo -en '\E[47;34m'&amp;quot;\033[1mE\033[0m&amp;quot; # Синий&lt;br /&gt;
tput sgr0 # сброс цвета&lt;br /&gt;
echo &amp;quot;vans, Roland&amp;quot; # &amp;quot;[E]vans, Roland&amp;quot;&lt;br /&gt;
echo -en '\E[47;35m'&amp;quot;\033[1mJ\033[0m&amp;quot; # Пурпурный&lt;br /&gt;
tput sgr0&lt;br /&gt;
echo &amp;quot;ones, Mildred&amp;quot;&lt;br /&gt;
echo -en '\E[47;32m'&amp;quot;\033[1mS\033[0m&amp;quot; # Зелёный&lt;br /&gt;
tput sgr0&lt;br /&gt;
echo &amp;quot;mith, Julie&amp;quot;&lt;br /&gt;
echo -en '\E[47;31m'&amp;quot;\033[1mZ\033[0m&amp;quot; # Красный&lt;br /&gt;
tput sgr0&lt;br /&gt;
echo &amp;quot;ane, Morris&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
read personcase &amp;quot;$person&amp;quot; in&lt;br /&gt;
# Обратите внимание: переменная взята в кавычки.&lt;br /&gt;
 &amp;quot;E&amp;quot; | &amp;quot;e&amp;quot; )&lt;br /&gt;
 # Пользователь может ввести как заглавную, так и строчную букву.&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Roland Evans&amp;quot;&lt;br /&gt;
 echo &amp;quot;4321 Floppy Dr.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Hardscrabble, CO 80753&amp;quot;&lt;br /&gt;
 echo &amp;quot;(303) 734-9874&amp;quot;&lt;br /&gt;
 echo &amp;quot;(303) 734-9892 fax&amp;quot;&lt;br /&gt;
 echo &amp;quot;revans@zzy.net&amp;quot;&lt;br /&gt;
 echo &amp;quot;Старый друг и партнер по бизнесу&amp;quot;&lt;br /&gt;
 ;;&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;J&amp;quot; | &amp;quot;j&amp;quot; )&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Mildred Jones&amp;quot;&lt;br /&gt;
 echo &amp;quot;249 E. 7th St., Apt. 19&amp;quot;&lt;br /&gt;
 echo &amp;quot;New York, NY 10009&amp;quot;&lt;br /&gt;
 echo &amp;quot;(212) 533-2814&amp;quot;&lt;br /&gt;
 echo &amp;quot;(212) 533-9972 fax&amp;quot;&lt;br /&gt;
 echo &amp;quot;milliej@loisaida.com&amp;quot;&lt;br /&gt;
 echo &amp;quot;Подружка&amp;quot;&lt;br /&gt;
 echo &amp;quot;День рождения: 11 февраля&amp;quot;&lt;br /&gt;
 ;;&lt;br /&gt;
&lt;br /&gt;
# Информация о Smith и Zane будет добавлена позднее.&lt;br /&gt;
 * )&lt;br /&gt;
 # Выбор по-умолчанию.&lt;br /&gt;
 # &amp;quot;Пустой&amp;quot; ввод тоже обрабатывается здесь.&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Нет данных.&amp;quot;&lt;br /&gt;
 ;;&lt;br /&gt;
&lt;br /&gt;
esac&lt;br /&gt;
tput sgr0&lt;br /&gt;
# Сброс цвета&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Самая простая и, на мой взгляд, самая полезная escape-последовательность — это &amp;quot;'''жирный текст'''&amp;quot;, '''\033[1m ... \033[0m'''. Здесь, комбинация '''\033''' представляет escape-символ, комбинация '''[1''' — включает вывод жирным текстом, а '''[0''' — выключает. Символ '''m''' — завершает каждую из escape-последовательностей.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo -e &amp;quot;\033[1mЭто жирный текст.\033[0m&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Простая escape-последовательность, которая управляет атрибутом подчеркивания (в ''rxvt'' и ''aterm'').&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo -e &amp;quot;\033[4mЭто подчеркнутый текст.\033[0m&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''-e'', в команде [[echo]], разрешает интерпретацию escape-последовательностей.&amp;lt;br /&amp;gt;&lt;br /&gt;
Другие escape-последовательности, изменяющие атрибуты цвета:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo -e '\E[34;47mЭтот текст выводится синим цветом.'; tput sgr0&lt;br /&gt;
&lt;br /&gt;
bash$ echo -e '\E[33;44m'&amp;quot;жёлтый текст на синем фоне&amp;quot;; tput sgr0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда '''tput sgr0''' возвращает настройки терминала в первоначальное состояние.&amp;lt;br /&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Вывод цветного текста осуществляется по следующему шаблону:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;echo -e '\E[COLOR1;COLOR2mКакой либо текст.'&amp;lt;/source&amp;gt;&lt;br /&gt;
Где &amp;quot;'''\E['''&amp;quot; — начало escape-последовательности. Числа &amp;quot;'''COLOR1'''&amp;quot; и &amp;quot;'''COLOR2'''&amp;quot;, разделённые точкой с запятой, задают цвет символов и цвет фона, в соответствии с таблицей цветов, приведенной ниже. (Порядок указания цвета текста и фона не имеет значения, поскольку диапазоны числовых значений цвета для текста и фона не пересекаются). Символ &amp;quot;'''m'''&amp;quot; — должен завершать escape-последовательность.&amp;lt;br /&amp;gt;&lt;br /&gt;
Обратите внимание: одиночные кавычки окружают всё, что следует за '''''echo -e'''''.&lt;br /&gt;
|}&lt;br /&gt;
Числовые значения цвета, приведенные ниже, справедливы для ''rxvt''. Для других эмуляторов они могут несколько отличаться.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица. Числовые значения цвета в escape-последовательностях'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Цвет !! Текст !! Фон&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;background-color: white;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:black&amp;quot;&amp;gt;'''Чёрный'''&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; || 30 || 40&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Красный'''&amp;lt;/span&amp;gt; || 31 || 41&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''Зелёный'''&amp;lt;/span&amp;gt; || 32 || 42&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:yellow&amp;quot;&amp;gt;'''Жёлтый'''&amp;lt;/span&amp;gt; || 33 || 43&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Синий'''&amp;lt;/span&amp;gt; || 34 || 44&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:magenta&amp;quot;&amp;gt;'''Пурпурный'''&amp;lt;/span&amp;gt; || 35 || 45&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;color:turquoise&amp;quot;&amp;gt;'''Зеленовато-голубой'''&amp;lt;/span&amp;gt; || 36 || 46&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;span style=&amp;quot;background-color: black;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:white&amp;quot;&amp;gt;'''Белый'''&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt; || 37 || 47&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вывод цветного текста.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# color-echo.sh: Вывод цветных сообщений.&lt;br /&gt;
&lt;br /&gt;
black='\E[30;47m'&lt;br /&gt;
red='\E[31;47m'&lt;br /&gt;
green='\E[32;47m'&lt;br /&gt;
yellow='\E[33;47m'&lt;br /&gt;
blue='\E[34;47m'&lt;br /&gt;
magenta='\E[35;47m'&lt;br /&gt;
cyan='\E[36;47m'&lt;br /&gt;
white='\E[37;47m'&lt;br /&gt;
&lt;br /&gt;
cecho ()                          # Color-echo.&lt;br /&gt;
                                  # Аргумент $1 = текст сообщения&lt;br /&gt;
                                  # Аргумент $2 = цвет&lt;br /&gt;
{&lt;br /&gt;
 local default_msg=&amp;quot;Нет сообщений.&amp;quot;&lt;br /&gt;
                                  # Не обязательно должна быть локальной.&lt;br /&gt;
&lt;br /&gt;
 message=${1:-$default_msg}       # Текст сообщения по-умолчанию.&lt;br /&gt;
 color=${2:-$black}               # Цвет по-умолчанию чёрный.&lt;br /&gt;
&lt;br /&gt;
 echo -e &amp;quot;$color&amp;quot;&lt;br /&gt;
 echo &amp;quot;$message&amp;quot;&lt;br /&gt;
 tput sgr0                        # Восстановление первоначальных настроек терминала.&lt;br /&gt;
 return&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Попробуем что-нибудь вывести.&lt;br /&gt;
# ----------------------------------------------------&lt;br /&gt;
cecho &amp;quot;Синий текст...&amp;quot; $blue&lt;br /&gt;
cecho &amp;quot;Пурпурный текст.&amp;quot; $magenta&lt;br /&gt;
cecho &amp;quot;Позеленевший от зависти.&amp;quot; $green&lt;br /&gt;
cecho &amp;quot;Похоже на красный?&amp;quot; $red&lt;br /&gt;
cecho &amp;quot;Циан, более известный как цвет морской волны.&amp;quot; $cyan&lt;br /&gt;
cecho &amp;quot;Цвет не задан (по-умолчанию чёрный).&amp;quot;&lt;br /&gt;
       # Аргумент $color отсутствует.&lt;br /&gt;
cecho &amp;quot;\&amp;quot;Пустой\&amp;quot; цвет (по-умолчанию чёрный).&amp;quot; &amp;quot;&amp;quot;&lt;br /&gt;
       # Передан &amp;quot;пустой&amp;quot; аргумент цвета.&lt;br /&gt;
cecho&lt;br /&gt;
       # Ни сообщение ни цвет не переданы.&lt;br /&gt;
cecho &amp;quot;&amp;quot; &amp;quot;&amp;quot;&lt;br /&gt;
       # Функции переданы &amp;quot;пустые&amp;quot; аргументы $message и $color.&lt;br /&gt;
# ----------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ---------&lt;br /&gt;
# 1) Добавьте в функцию 'cecho ()' возможность вывода &amp;quot;жирного текста&amp;quot;.&lt;br /&gt;
# 2) Добавьте возможность управления цветом фона.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Однако, как обычно, в бочке меда есть ложка дегтя. Escape-последовательности ''ANSI'' совершенно не переносимы. Вывод в одном эмуляторе терминала (или в консоли) может разительно отличаться от вывода в другом эмуляторе. &amp;quot;Расцвеченные&amp;quot; сценарии, дающие изумительно красивый вывод текста на одном терминале, могут давать совершенно нечитаемый текст на другом. Это ставит под сомнение практическую ценность &amp;quot;расцвечивания&amp;quot; вывода в сценариях, низводя её до уровня никчёмной &amp;quot;игрушки&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
''Moshe Jacobson'' разработал утилиту ''color'' (http://runslinux.net/projects/color), которая значительно упрощает работу с ''ANSI'' escape-последовательностями, заменяя, только что обсуждавшиеся, неуклюжие конструкции, логичным и понятным синтаксисом.&lt;br /&gt;
&lt;br /&gt;
=== Оптимизация ===&lt;br /&gt;
По большей части, сценарии на языке командной оболочки, используются для быстрого решения несложных задач. Поэтому оптимизация сценариев, по скорости исполнения, не является насущной проблемой. Тем не менее, представьте себе ситуацию, когда сценарий, выполняющий довольно важную работу, в принципе справляется со своей задачей, но делает это очень медленно. Написание же аналогичной программы на языке компилирующего типа — неприемлемо. Самое простое решение — переписать самые медленные участки кода сценария. Возможно ли применить принципы оптимизации к сценарию на практике?&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Для начала проверьте все циклы в сценарии. Основная масса времени уходит на работу в циклах. Если это возможно, вынесите все ресурсоёмкие операции за пределы циклов.&lt;br /&gt;
Старайтесь использовать встроенные команды. Они исполняются значительно быстрее и, как правило, не запускают подоболочку при вызове. Избегайте использования избыточных команд, особенно это относится к &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;конвейерам&amp;lt;/span&amp;gt;.'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat &amp;quot;$file&amp;quot; | grep &amp;quot;$word&amp;quot;&lt;br /&gt;
&lt;br /&gt;
grep &amp;quot;$word&amp;quot; &amp;quot;$file&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Эти команды дают один и тот же результат,&lt;br /&gt;
# но вторая работает быстрее, поскольку запускает на один подпроцесс меньше.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Не следует злоупотреблять командой [[cat]]'''. &amp;lt;br /&amp;gt;&lt;br /&gt;
Для профилирования сценариев, можно воспользоваться командами '''''time''''' и '''''times'''''. '''Не следует пренебрегать возможностью переписать особенно критичные участки кода на языке ''C'' или даже на ''ассемблере'' '''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Попробуйте минимизировать количество операций с файлами'''. Bash не &amp;quot;страдает&amp;quot; излишней эффективностью при работе с файлами, попробуйте применить специализированные средства для работы с файлами в сценариях, такие как [[awk]] или '''''Perl'''''. &amp;lt;br /&amp;gt;&lt;br /&gt;
'''Записывайте сценарии в структурированной форме, это облегчит их последующую реорганизацию и оптимизацию'''. Помните, что значительная часть методов оптимизации кода, существующих в языках высокого уровня, вполне применима и к сценариям, однако есть и такие, которые не могут применяться. Основной критерий здесь — это '''''здравый смысл'''''.&lt;br /&gt;
&lt;br /&gt;
=== Разные советы ===&lt;br /&gt;
* '''Для ведения учета использования сценария пользователями, добавьте следующие строки в сценарий. Они запишут в файл отчёта название сценария и время запуска'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Добавление (&amp;gt;&amp;gt;) учетной записи, об использовании сценария, в файл отчета.&lt;br /&gt;
&lt;br /&gt;
date&amp;gt;&amp;gt; $SAVE_FILE       # Дата и время.&lt;br /&gt;
echo $0&amp;gt;&amp;gt; $SAVE_FILE    # Название сценария.&lt;br /&gt;
echo&amp;gt;&amp;gt; $SAVE_FILE       # Пустая строка — как разделитель записей.&lt;br /&gt;
&lt;br /&gt;
# Не забудьте определить переменную окружения SAVE_FILE в ~/.bashrc&lt;br /&gt;
# (что нибудь, типа: ~/.scripts-run)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Оператор '''&amp;gt;&amp;gt;''' производит добавление строки в конец файла. А как быть, если надо добавить строку в начало существующего файла'''?&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
file=data.txt&lt;br /&gt;
title=&amp;quot;***Это титульная строка в текстовом файле***&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo $title | cat - $file &amp;gt;$file.new&lt;br /&gt;
# &amp;quot;cat -&amp;quot; объединяет stdout с содержимым $file.&lt;br /&gt;
# В результате получится&lt;br /&gt;
# новый файл $file.new, в начало которого добавлена строка $title.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Само собой разумеется, то же самое можно сделать с помощью [[sed]].&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Сценарий командной оболочки может использоваться как команда внутри другого сценария командной оболочки, '''Tcl''', или '''wish''' сценария или, даже в ''Makefile'' '''. Он может быть вызван как внешняя команда из программы на языке ''C'', с помощью функции ''system()'', т.е. ''system(&amp;quot;script_name&amp;quot;);''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Собирайте свои библиотеки часто используемых функций и определений '''. Эти &amp;quot;библиотеки&amp;quot; могут быть &amp;quot;подключены&amp;quot; к сценариям, с помощью команды точка ('''.''') или '''source'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Сценарий-библиотека&lt;br /&gt;
# ------ -------&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание:&lt;br /&gt;
# Здесь нет sha-bang (&amp;quot;#!&amp;quot;).&lt;br /&gt;
# И нет &amp;quot;живого кода&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Определения переменных&lt;br /&gt;
ROOT_UID=0               # UID root-а, 0.&lt;br /&gt;
E_NOTROOT=101            # Ошибка — &amp;quot;обычный пользователь&amp;quot;.&lt;br /&gt;
MAXRETVAL=255            # Максимальное значение, которое могут возвращать функции.&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
FAILURE=-1&lt;br /&gt;
# Функции&lt;br /&gt;
Usage ()                 # Сообщение &amp;quot;Порядок использования:&amp;quot;.&lt;br /&gt;
{&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; ]          # Нет аргументов.&lt;br /&gt;
 then&lt;br /&gt;
  msg=filename&lt;br /&gt;
 else&lt;br /&gt;
  msg=$@&lt;br /&gt;
 fi&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` &amp;quot;$msg&amp;quot;&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Check_if_root ()          # Проверка прав пользователя.&lt;br /&gt;
{                         # из примера &amp;quot;ex39.sh&amp;quot;.&lt;br /&gt;
 if [ &amp;quot;$UID&amp;quot; -ne &amp;quot;$ROOT_UID&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  echo &amp;quot;Этот сценарий должен запускаться с привилегиями root.&amp;quot;&lt;br /&gt;
  exit $E_NOTROOT&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
CreateTempfileName ()      # Создание &amp;quot;уникального&amp;quot; имени для временного файла.&lt;br /&gt;
{                          # Из примера &amp;quot;ex51.sh&amp;quot;.&lt;br /&gt;
 prefix=temp&lt;br /&gt;
 suffix=`eval date +%s`&lt;br /&gt;
 Tempfilename=$prefix.$suffix&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
isalpha2 ()                 # Проверка, состоит ли строка только из алфавитных символов.&lt;br /&gt;
{                           # Из примера &amp;quot;isalpha.sh&amp;quot;.&lt;br /&gt;
 [ $# -eq 1 ] || return $FAILURE&lt;br /&gt;
&lt;br /&gt;
 case $1 in&lt;br /&gt;
 *[!a-zA-Z]*|&amp;quot;&amp;quot;) return $FAILURE;;&lt;br /&gt;
 *) return $SUCCESS;;&lt;br /&gt;
 esac                       # Спасибо S.C.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abs ()                      # Абсолютное значение.&lt;br /&gt;
{                           # Внимание: Максимально возможное возвращаемое значение&lt;br /&gt;
                            # не может превышать 255.&lt;br /&gt;
 E_ARGERR=-999999&lt;br /&gt;
&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; ]             # Проверка наличия входного аргумента.&lt;br /&gt;
 then&lt;br /&gt;
  return $E_ARGERR          # Код ошибки, обычно возвращаемый в таких случаях.&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$1&amp;quot; -ge 0 ]            # Если не отрицательное,&lt;br /&gt;
 then                         #&lt;br /&gt;
  absval=$1                   # оставить как есть.&lt;br /&gt;
 else                         # Иначе,&lt;br /&gt;
  let &amp;quot;absval = (( 0 - $1 ))&amp;quot; # изменить знак.&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 return $absval&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
tolower ()                    # Преобразование строк символов в нижний регистр&lt;br /&gt;
{&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; ]               # Если нет входного аргумента,&lt;br /&gt;
 then                         # выдать сообщение об ошибке&lt;br /&gt;
 echo &amp;quot;(null)&amp;quot;&lt;br /&gt;
 return                       # и выйти из функции.&lt;br /&gt;
 fi&lt;br /&gt;
 echo &amp;quot;$@&amp;quot; | tr A-Z a-z&lt;br /&gt;
 # Преобразовать все входные аргументы ($@).&lt;br /&gt;
 return&lt;br /&gt;
# Для записи результата работы функции в переменную, используйте операцию подстановки команды.&lt;br /&gt;
# Например:&lt;br /&gt;
# oldvar=&amp;quot;A seT of miXed-caSe LEtTerS&amp;quot;&lt;br /&gt;
# newvar=`tolower &amp;quot;$oldvar&amp;quot;`&lt;br /&gt;
# echo &amp;quot;$newvar&amp;quot; # a set of mixed-case letters&lt;br /&gt;
#&lt;br /&gt;
# Упражнение: Добавьте в эту библиотеку функцию перевода символов в верхний регистр.&lt;br /&gt;
# toupper() [это довольно просто].&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Для повышения ясности комментариев, выделяйте их особым образом'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
## Внимание!&lt;br /&gt;
rm -rf *.zzy           ## Комбинация ключей &amp;quot;-rf&amp;quot;, в команде &amp;quot;rm&amp;quot;, чрезвычайно опасна,&lt;br /&gt;
                       ## особенно при удалении по шаблону.&lt;br /&gt;
# Продолжение комментария на новой строке.&lt;br /&gt;
# Это первая строка комментария&lt;br /&gt;
# это вторая строка комментария,&lt;br /&gt;
# это последняя строка комментария.&lt;br /&gt;
&lt;br /&gt;
#* Обратите внимание.&lt;br /&gt;
#o Элемент списка.&lt;br /&gt;
#&amp;gt; Альтернативный вариант.&lt;br /&gt;
while [ &amp;quot;$var1&amp;quot; != &amp;quot;end&amp;quot; ] #&amp;gt; while test &amp;quot;$var1&amp;quot; != &amp;quot;end&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Для создания блочных комментариев, можно использовать конструкцию &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;if-test&amp;lt;/span&amp;gt;'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
COMMENT_BLOCK=&lt;br /&gt;
# Если попробовать инициализировать эту переменную чем-нибудь,&lt;br /&gt;
# то вы получите неожиданный результат.&lt;br /&gt;
&lt;br /&gt;
if [ $COMMENT_BLOCK ]; then&lt;br /&gt;
Блок комментария --&lt;br /&gt;
=================================&lt;br /&gt;
Это строка комментария.&lt;br /&gt;
Это другая строка комментария.&lt;br /&gt;
Это ещё одна строка комментария.&lt;br /&gt;
=================================&lt;br /&gt;
echo &amp;quot;Эта строка не выводится.&amp;quot;&lt;br /&gt;
Этот блок комментария не вызывает сообщения об ошибке! Круто!&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Эта строка будет выведена на stdout.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Сравните этот вариант создания блочных комментариев со &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;встроенным документом&amp;lt;/span&amp;gt;, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;использующимся для создания блочных комментариев&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''С помощью служебной переменной &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;$?&amp;lt;/span&amp;gt;, можно проверить — является ли входной аргумент целым числом'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
SUCCESS=0&lt;br /&gt;
E_BADINPUT=65&lt;br /&gt;
test &amp;quot;$1&amp;quot; -ne 0 -o &amp;quot;$1&amp;quot; -eq 0 2&amp;gt;/dev/null&lt;br /&gt;
# Проверка: &amp;quot;равно нулю или не равно нулю&amp;quot;.&lt;br /&gt;
# 2&amp;gt;/dev/null подавление вывода сообщений об ошибках.&lt;br /&gt;
&lt;br /&gt;
if [ $? -ne &amp;quot;$SUCCESS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` целое_число&amp;quot;&lt;br /&gt;
 exit $E_BADINPUT&lt;br /&gt;
fi&lt;br /&gt;
let &amp;quot;sum = $1 + 25&amp;quot;       # Будет выдавать ошибку, если $1 не является целым числом.&lt;br /&gt;
echo &amp;quot;Sum = $sum&amp;quot;&lt;br /&gt;
# Любая переменная может быть проверена таким образом, а не только входные аргументы.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Диапазон, возвращаемых функциями значений, 0-255 — серьёзное ограничение. Иногда может оказаться весьма проблематичным использование глобальных переменных, для передачи результата из функции. В таких случаях можно порекомендовать передачу результатов работы функции через запись в ''stdout''. Фактически этот приём является разновидностью &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;подстановки команд&amp;lt;/span&amp;gt;'''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Необычный способ передачи возвращаемого значения.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# multiplication.sh&lt;br /&gt;
multiply ()                                  # Функции выполняет перемножение всех переданных аргументов.&lt;br /&gt;
{&lt;br /&gt;
 local product=1&lt;br /&gt;
 until [ -z &amp;quot;$1&amp;quot; ]                           # Пока не дошли до последнего аргумента...&lt;br /&gt;
 do&lt;br /&gt;
  let &amp;quot;product *= $1&amp;quot;&lt;br /&gt;
  shift&lt;br /&gt;
 done&lt;br /&gt;
 echo $product                               # Значение не будет выведено на экран,&lt;br /&gt;
}                                            # поскольку оно будет записано в переменную.&lt;br /&gt;
&lt;br /&gt;
mult1=15383; mult2=25211&lt;br /&gt;
val1=`multiply $mult1 $mult2`&lt;br /&gt;
echo &amp;quot;$mult1 X $mult2 = $val1&amp;quot;&lt;br /&gt;
                                              # 387820813&lt;br /&gt;
mult1=25; mult2=5; mult3=20&lt;br /&gt;
val2=`multiply $mult1 $mult2 $mult3`&lt;br /&gt;
echo &amp;quot;$mult1 X $mult2 X $mult3 = $val2&amp;quot;&lt;br /&gt;
                                 # 2500&lt;br /&gt;
&lt;br /&gt;
mult1=188; mult2=37; mult3=25; mult4=47&lt;br /&gt;
val3=`multiply $mult1 $mult2 $mult3 $mult4`&lt;br /&gt;
echo &amp;quot;$mult1 X $mult2 X $mult3 X mult4 = $val3&amp;quot;&lt;br /&gt;
                                # 8173300&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Такой приём срабатывает и для строковых значений. Таким образом, функция может &amp;quot;возвращать&amp;quot; и нечисловой результат.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
capitalize_ichar ()       # Первый символ всех строковых аргументов&lt;br /&gt;
{                         # переводится в верхний регистр.&lt;br /&gt;
 string0=&amp;quot;$@&amp;quot;             # Принять все аргументы.&lt;br /&gt;
&lt;br /&gt;
 firstchar=${string0:0:1} # Первый символ.&lt;br /&gt;
 string1=${string0:1}     # Остаток строки.&lt;br /&gt;
 FirstChar=`echo &amp;quot;$firstchar&amp;quot; | tr a-z A-Z`&lt;br /&gt;
                              # Преобразовать в верхний регистр.&lt;br /&gt;
 echo &amp;quot;$FirstChar$string1&amp;quot; # Выдать на stdout.&lt;br /&gt;
}&lt;br /&gt;
newstring=`capitalize_ichar &amp;quot;each sentence should start with a capital letter.&amp;quot;`&lt;br /&gt;
echo &amp;quot;$newstring&amp;quot; # Each sentence should start with a capital letter.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Используя этот приём, функция может &amp;quot;возвращать&amp;quot; даже несколько значений.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Необычный способ получения нескольких возвращаемых значений.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# sum-product.sh&lt;br /&gt;
# Функция может &amp;quot;возвращать&amp;quot; несколько значений.&lt;br /&gt;
&lt;br /&gt;
sum_and_product () # Вычисляет сумму и произведение аргументов.&lt;br /&gt;
{&lt;br /&gt;
 echo $(( $1 + $2 )) $(( $1 * $2 ))&lt;br /&gt;
# Вывод на stdout двух значений, разделенных пробелом.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Первое число: &amp;quot;&lt;br /&gt;
read first&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Второе число: &amp;quot;&lt;br /&gt;
read second&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
retval=`sum_and_product $first $second` # Получить результат.&lt;br /&gt;
sum=`echo &amp;quot;$retval&amp;quot; | awk '{print $1}'` # Первое значение (поле).&lt;br /&gt;
product=`echo &amp;quot;$retval&amp;quot; | awk '{print $2}'` # Второе значение (поле).&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;$first + $second = $sum&amp;quot;&lt;br /&gt;
echo &amp;quot;$first * $second = $product&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Следующая хитрость — передача &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;массива&amp;lt;/span&amp;gt; в &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;функцию&amp;lt;/span&amp;gt;, и &amp;quot;возврат&amp;quot; массива из функции'''.&lt;br /&gt;
Передача массива в функцию выполняется посредством записи элементов массива,разделенных пробелами, в переменную, с помощью операции подстановки команды. Получить массив обратно можно, следуя вышеописанной стратегии, через вывод на ''stdout'', а затем, с помощью всё той же операции подстановки команды и оператора '''( ... )''' — записать в массив.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Передача массива в функцию и возврат массива из функции.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# array-function.sh: Передача массива в функцию и...&lt;br /&gt;
# &amp;quot;возврат&amp;quot; массива из функции&lt;br /&gt;
Pass_Array ()&lt;br /&gt;
{&lt;br /&gt;
 local passed_array # Локальная переменная.&lt;br /&gt;
 passed_array=( `echo &amp;quot;$1&amp;quot;` )&lt;br /&gt;
 echo &amp;quot;${passed_array[@]}&amp;quot;&lt;br /&gt;
 # Список всех элементов в новом массиве,&lt;br /&gt;
 # объявленном и инициализированном в функции.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
original_array=( element1 element2 element3 element4 element5 )&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;original_array = ${original_array[@]}&amp;quot;&lt;br /&gt;
#                       Список всех элементов исходного массива.&lt;br /&gt;
&lt;br /&gt;
# Так можно отдать массив в функцию.&lt;br /&gt;
# **********************************&lt;br /&gt;
argument=`echo ${original_array[@]}`&lt;br /&gt;
# **********************************&lt;br /&gt;
# Поместив все элементы массива в переменную, разделяя их пробелами.&lt;br /&gt;
#&lt;br /&gt;
# Обратите внимание: метод прямой передачи массива в функцию не сработает.&lt;br /&gt;
&lt;br /&gt;
# Так можно получить массив из функции.&lt;br /&gt;
# *****************************************&lt;br /&gt;
returned_array=( `Pass_Array &amp;quot;$argument&amp;quot;` )&lt;br /&gt;
# *****************************************&lt;br /&gt;
# Записать результат в переменную-массив.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;returned_array = ${returned_array[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;=============================================================&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# А теперь попробуйте получить доступ к локальному массиву&lt;br /&gt;
# за пределами функции.&lt;br /&gt;
Pass_Array &amp;quot;$argument&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Функция выведет массив, но...&lt;br /&gt;
# доступ к локальному массиву, за пределами функции, окажется невозможен.&lt;br /&gt;
echo &amp;quot;Результирующий массив (внутри функции) = ${passed_array[@]}&amp;quot;&lt;br /&gt;
# &amp;quot;ПУСТОЕ&amp;quot; ЗНАЧЕНИЕ, поскольку это локальная переменная.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Использование конструкций с двойными круглыми скобками позволяет применять ''C''-подобный синтаксис операций присвоения и инкремента переменных, а также оформления циклов ''for'' и ''while'' '''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Иногда очень удобно &amp;quot;пропускать&amp;quot; данные через один и тот же фильтр, но с разными параметрами, используя конвейерную обработку. Особенно это относится к '''''tr''''' и [[grep]]'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Из примера &amp;quot;wstrings.sh&amp;quot;.&lt;br /&gt;
wlist=`strings &amp;quot;$1&amp;quot; | tr A-Z a-z | tr '[:space:]' Z | \&lt;br /&gt;
tr -cs '[:alpha:]' Z | tr -s '\173-\377' Z | tr Z ' '`&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Игры с анаграммами.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# agram.sh: Игры с анаграммами.&lt;br /&gt;
&lt;br /&gt;
# Поиск анаграмм...&lt;br /&gt;
LETTERSET=etaoinshrdlu&lt;br /&gt;
anagram &amp;quot;$LETTERSET&amp;quot; |          # Найти все анаграммы в наборе символов...&lt;br /&gt;
grep '.......' |                # состоящие, как минимум из 7 символов,&lt;br /&gt;
grep '^is' |                    # начинающиеся с 'is'&lt;br /&gt;
grep -v 's$' |                  # исключая множественное число&lt;br /&gt;
grep -v 'ed$'                   # и глаголы в прошедшем времени&lt;br /&gt;
&lt;br /&gt;
# Здесь используется утилита &amp;quot;anagram&amp;quot;&lt;br /&gt;
# которая входит в состав пакета &amp;quot;yawl&amp;quot; , разработанного автором.&lt;br /&gt;
# http://ibiblio.org/pub/Linux/libs/yawl-0.2.tar.gz&lt;br /&gt;
exit 0 &lt;br /&gt;
# Конец.&lt;br /&gt;
&lt;br /&gt;
bash$ sh agram.sh&lt;br /&gt;
islander&lt;br /&gt;
isolate&lt;br /&gt;
isolead&lt;br /&gt;
isotheral&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''Для создания блочных комментариев можно использовать &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;&amp;quot;анонимные встроенные документы&amp;quot;&amp;lt;/span&amp;gt;'''.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Попытка вызова утилиты из сценария на машине, где эта утилита отсутствует, потенциально опасна. Для обхода подобных проблем можно воспользоваться утилитой &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;whatis&amp;lt;/span&amp;gt;'''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
CMD=command1 # Основной вариант.&lt;br /&gt;
PlanB=command2 # Запасной вариант.&lt;br /&gt;
&lt;br /&gt;
command_test=$(whatis &amp;quot;$CMD&amp;quot; | grep 'nothing appropriate')&lt;br /&gt;
# Если 'command1' не найдена в системе, то 'whatis' вернёт&lt;br /&gt;
# &amp;quot;command1: nothing appropriate.&amp;quot;&lt;br /&gt;
#==&amp;gt; От переводчика: Будьте внимательны! Если у вас локализованная версия whatis&lt;br /&gt;
#==&amp;gt; то вывод от неё может отличаться от используемого здесь ('nothing appropriate')&lt;br /&gt;
&lt;br /&gt;
if [[ -z &amp;quot;$command_test&amp;quot; ]] # Проверка наличия утилиты в системе.&lt;br /&gt;
then&lt;br /&gt;
 $CMD option1 option2       # Запуск команды с параметрами.&lt;br /&gt;
else                        # Иначе,&lt;br /&gt;
$PlanB                      # запустить command2 (запасной вариант).&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Команда &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;run-parts&amp;lt;/span&amp;gt; удобна для запуска нескольких сценариев, особенно в комбинации с '''''cron''''' или '''''at''''' '''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Иногда было бы неплохо снабдить сценарий графическим интерфейсом ''X-Window'' '''. Для этого можно порекомендовать пакеты ''Xscript'', ''Xmenu'' и ''widtools''. Правда, первые два, кажется больше не поддерживаются разработчиками. Зато ''widtools'' можно получить [http://www.batse.msfc.nasa.gov/~mallozzi/home/software/xforms/src/widtools-2.0.tgz здесь].&lt;br /&gt;
Пакет ''widtools'' (widget tools) требует наличия библиотеки ''XForms''. Кроме того, необходимо слегка подправить ''Makefile'', чтобы этот пакет можно было собрать на типичной Linux-системе. Но хуже всего то, что три из шести виджетов не работают :-(( (segfault).&amp;lt;br /&amp;gt;&lt;br /&gt;
Утилита ''dialog'' — ещё один способ создания диалоговых форм из сценариев командной оболочки. Эта утилита предназначена для работы в текстовой консоли, но имеются её &amp;quot;наследники&amp;quot; — ''gdialog'', ''Xdialog'' и ''kdialog'', которые используют графические элементы ''X-Windows'' для построения диалоговых форм.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Сценарий с графическим интерфейсом.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# dialog.sh: Использование виджетов 'gdialog'.&lt;br /&gt;
# В вашей системе должна быть установлена утилита 'gdialog'.&lt;br /&gt;
&lt;br /&gt;
# Идея создания этого сценария появилась после прочтения статьи&lt;br /&gt;
# &amp;quot;Scripting for X Productivity,&amp;quot; by Marco Fioretti,&lt;br /&gt;
# LINUX JOURNAL, Issue 113, September 2003, pp. 86-9.&lt;br /&gt;
# Спасибо всем сотрудникам LJ.&lt;br /&gt;
&lt;br /&gt;
# Ошибка ввода в диалоговом окне.&lt;br /&gt;
E_INPUT=65&lt;br /&gt;
# Размеры окна.&lt;br /&gt;
HEIGHT=50&lt;br /&gt;
WIDTH=60&lt;br /&gt;
&lt;br /&gt;
# Имя выходного файла (конструируется добавлением суффикса к имени файла-сценария).&lt;br /&gt;
OUTFILE=$0.output&lt;br /&gt;
&lt;br /&gt;
# Вывести содержимое файла-сценария в отдельном окне.&lt;br /&gt;
gdialog --title &amp;quot;Displaying: $0&amp;quot; --textbox $0 $HEIGHT $WIDTH&lt;br /&gt;
&lt;br /&gt;
# Попробуем записать значение, введенное в окне.&lt;br /&gt;
echo -n &amp;quot;VARIABLE=\&amp;quot;&amp;quot; &amp;gt; $OUTFILE # Кавычка на случай, если пользователь введет несколько слов, разделенных пробелами.&lt;br /&gt;
gdialog --title &amp;quot;User Input&amp;quot; --inputbox &amp;quot;Введите значение переменной:&amp;quot; \&lt;br /&gt;
$HEIGHT $WIDTH &amp;gt;&amp;gt; $OUTFILE&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$?&amp;quot; -eq 0 ]&lt;br /&gt;
# Хороший тон — проверка кода завершения.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Диалог с пользователем завершился без ошибок.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Обнаружены ошибки во время диалога с пользователем.&amp;quot;&lt;br /&gt;
      # Или была нажата кнопка &amp;quot;Отменить&amp;quot; (&amp;quot;Cancel&amp;quot;) вместо &amp;quot;OK&amp;quot;.&lt;br /&gt;
 rm $OUTFILE&lt;br /&gt;
 exit $E_INPUT&lt;br /&gt;
fi&lt;br /&gt;
echo -n &amp;quot;\&amp;quot;&amp;quot; &amp;gt;&amp;gt; $OUTFILE # Завершающая кавычка.&lt;br /&gt;
# Теперь прочитаем значение переменной из файла и выведем его.&lt;br /&gt;
. $OUTFILE # 'Выходной' файл.&lt;br /&gt;
echo &amp;quot;Было введено значение переменной: &amp;quot;$VARIABLE&amp;quot;&amp;quot;&lt;br /&gt;
rm $OUTFILE # Удалить временный файл.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Кроме того, для построения приложений с графическим интерфейсом, можно попробовать ''Tk'', или ''wish'' (надстройка над ''Tcl''), ''PerlTk'' (''Perl'' с поддержкой ''Tk''), ''tksh'' (''ksh'' с поддержкой ''Tk''), ''XForms4Perl'' (''Perl'' с поддержкой ''XForms''), ''Gtk-Perl'' (''Perl'' с поддержкой ''Gtk'') или ''PyQt'' (''Python'' с поддержкой ''Qt'').&lt;br /&gt;
=== Проблемы безопасности ===&lt;br /&gt;
Уместным будет лишний раз предупредить о соблюдении мер предосторожности при работе с незнакомыми сценариями. Сценарий может содержать червя, трояна или даже вирус. Если вы получили сценарий не из источника, которому доверяете, то никогда не запускайте его с привилегиями ''root'' и не позволяйте вставлять его в список сценариев начальной инициализации системы в ''/etc/rc.d'', пока не убедитесь в том, что он безвреден для системы. Исследователи из Bell Labs и других организаций, включая ''M. Douglas McIlroy'', ''Tom Duff'', и ''Fred Cohen'' исследовали вопрос о возможности создания вирусов на языке сценариев командной оболочки, и пришли к выводу, что это делается очень легко и доступно даже для новичков.&lt;br /&gt;
Это ещё одна из причин, по которым следует изучать язык командной оболочки. Способность читать и понимать сценарии поможет вам предотвратить возможность взлома и/или разрушения вашей системы.&lt;br /&gt;
=== Проблемы переносимости ===&lt;br /&gt;
Эта книга делает упор на создании сценариев для командной оболочки Bash, для операционной системы GNU/Linux. Тем не менее, многие рекомендации, приводимые здесь, могут быть вполне применимы и для других командных оболочек, таких как ''sh'' и ''ksh''. Многие версии командных оболочек стремятся следовать стандарту POSIX 1003.2. Вызывая Bash с ключом ''--posix'', или вставляя ''set -o posix'' в начало сценария, вы можете заставить Bash очень близко следовать этому стандарту. Но, даже без этого ключа, большинство сценариев, написанных для Bash, будут работать под управлением ''ksh'', и наоборот, т.к. Chet Ramey перенес многие особенности, присущие ''ksh'', в последние версии Bash. В коммерческих версиях Unix, сценарии, использующие GNU-версии стандартных утилит и команд, могут оказаться неработоспособными. Однако, с течением времени, таких проблем остается всё меньше и меньше, поскольку утилиты GNU, в большинстве своем, заместили свои проприетарные аналоги в Unix. После того, как Caldera дала разрешение на публикацию исходного кода некоторых версий оригинальных утилит Unix, этот процесс значительно ускорился. Bash имеет некоторые особенности, недоступные в традиционном Bourne shell. Среди них:&amp;lt;br /&amp;gt;&lt;br /&gt;
* Некоторые дополнительные ключи вызова&amp;lt;br /&amp;gt;&lt;br /&gt;
* Подстановка команд, с использованием нотации $( )&amp;lt;br /&amp;gt;&lt;br /&gt;
* Некоторые операции над строками&amp;lt;br /&amp;gt;&lt;br /&gt;
* Подстановка процессов&amp;lt;br /&amp;gt;&lt;br /&gt;
* Встроенные команды Bash&amp;lt;br /&amp;gt;&lt;br /&gt;
Более подробный список характерных особенностей Bash, вы найдете в [ftp://ftp.cwru.edu/pub/bash/FAQ/ Bash F.A.Q.].&lt;br /&gt;
&lt;br /&gt;
=== Сценарии командной оболочки под Windows ===&lt;br /&gt;
Даже те пользователи, которые работают в другой, не Unix-подобной операционной системе, смогут запускать сценарии командной оболочки, а потому — найти для себя много полезного в этой книге. Пакеты '''''Cygwin''''' от ''Cygnus'', и '''''MKS utilities''''' от ''Mortice Kern Associates'', позволяют дополнить Windows возможностями командной оболочки.&lt;br /&gt;
&lt;br /&gt;
== Bash, версия 2 ==&lt;br /&gt;
Текущая версия Bash, та, которая скорее всего установлена в вашей системе, фактически — 2.XX.Y(&amp;lt;span style=&amp;quot;color:cyan&amp;quot;&amp;gt;На момент написания/перевода книги&amp;lt;/span&amp;gt;).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ echo $BASH_VERSION&lt;br /&gt;
2.05.b.0(1)-release&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В этой версии классического языка сценариев Bash были добавлены переменные-массивы, расширение строк и подстановка параметров, улучшен метод косвенных ссылок на переменные.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Расширение строк.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# &amp;quot;Расширение&amp;quot; строк (String expansion).&lt;br /&gt;
# Введено в Bash, начиная с версии 2.&lt;br /&gt;
# Строки вида $'xxx'&lt;br /&gt;
# могут содержать дополнительные экранированные символы.&lt;br /&gt;
&lt;br /&gt;
echo $'Звонок звенит 3 раза \a \a \a'&lt;br /&gt;
echo $'Три перевода формата \f \f \f'&lt;br /&gt;
echo $'10 новых строк \n\n\n\n\n\n\n\n\n\n'&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Косвенные ссылки на переменные — новый метод.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Косвенные ссылки на переменные.&lt;br /&gt;
&lt;br /&gt;
a=letter_of_alphabet&lt;br /&gt;
letter_of_alphabet=z&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;a = $a&amp;quot; # Прямая ссылка.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Now a = ${!a}&amp;quot; # Косвенная ссылка.&lt;br /&gt;
# Форма записи ${!variable} намного удобнее старой &amp;quot;eval var1=\$$var2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
t=table_cell_3&lt;br /&gt;
table_cell_3=24&lt;br /&gt;
echo &amp;quot;t = ${!t}&amp;quot; # t = 24&lt;br /&gt;
table_cell_3=387&lt;br /&gt;
echo &amp;quot;Значение переменной t изменилось на ${!t}&amp;quot; # 387&lt;br /&gt;
# Теперь их можно использовать для ссылок на элементы массива,&lt;br /&gt;
# или для эмуляции многомерных массивов.&lt;br /&gt;
# Было бы здорово, если бы косвенные ссылки допускали индексацию.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простая база данных, с применением косвенных ссылок.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# resistor-inventory.sh&lt;br /&gt;
&lt;br /&gt;
# Простая база данных, с применением косвенных ссылок.&lt;br /&gt;
# ============================================================== #&lt;br /&gt;
# Данные&lt;br /&gt;
&lt;br /&gt;
B1723_value=470                                # сопротивление (Ом)&lt;br /&gt;
B1723_powerdissip=.25                          # рассеиваемая мощность (Вт)&lt;br /&gt;
B1723_colorcode=&amp;quot;желтый-фиолетовый-коричневый&amp;quot; # цветовая маркировка&lt;br /&gt;
B1723_loc=173                                  # где&lt;br /&gt;
B1723_inventory=78                             # количество (шт)&lt;br /&gt;
&lt;br /&gt;
B1724_value=1000&lt;br /&gt;
B1724_power&lt;br /&gt;
dissip=.25&lt;br /&gt;
B1724_colorcode=&amp;quot;коричневый-черный-красный&amp;quot;&lt;br /&gt;
B1724_loc=24&lt;br /&gt;
NB1724_inventory=243&lt;br /&gt;
&lt;br /&gt;
B1725_value=10000&lt;br /&gt;
B1725_powerdissip=.25&lt;br /&gt;
B1725_colorcode=&amp;quot;коричневый-черный-оранжевый&amp;quot;&lt;br /&gt;
B1724_loc=24&lt;br /&gt;
NB1724_inventory=243&lt;br /&gt;
&lt;br /&gt;
B1725_value=10000&lt;br /&gt;
B1725_powerdissip=.25&lt;br /&gt;
B1725_colorcode=&amp;quot;коричневый-черный-оранжевый&amp;quot;&lt;br /&gt;
B1725_loc=24&lt;br /&gt;
NB1725_inventory=89&lt;br /&gt;
&lt;br /&gt;
# ============================================================== #&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
PS3='Введите номер: '&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
select catalog_number in &amp;quot;B1723&amp;quot; &amp;quot;B1724&amp;quot; &amp;quot;B1725&amp;quot;&lt;br /&gt;
do&lt;br /&gt;
 Inv=${catalog_number}_inventory&lt;br /&gt;
 Val=${catalog_number}_value&lt;br /&gt;
 Pdissip=${catalog_number}_powerdissip&lt;br /&gt;
 Loc=${catalog_number}_loc&lt;br /&gt;
 Ccode=${catalog_number}_colorcode&lt;br /&gt;
&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Номер по каталогу $catalog_number:&amp;quot;&lt;br /&gt;
 echo &amp;quot;Имеется в наличии ${!Inv} шт. [${!Val} Ом / ${!Pdissip} Вт].&amp;quot;&lt;br /&gt;
 echo &amp;quot;Находятся в лотке # ${!Loc}.&amp;quot;&lt;br /&gt;
 echo &amp;quot;Цветовая маркировка: \&amp;quot;${!Ccode}\&amp;quot;.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 break&lt;br /&gt;
&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo; echo# Упражнение:&lt;br /&gt;
# ----------&lt;br /&gt;
# Переделайте этот сценарий так, чтобы он использовал массивы вместо косвенных ссылок.&lt;br /&gt;
# Какой из вариантов более простой и интуитивный?&lt;br /&gt;
&lt;br /&gt;
# Примечание:&lt;br /&gt;
# ----------&lt;br /&gt;
# Язык командной оболочки не очень удобен для написания приложений,&lt;br /&gt;
# работающих с базами данных.&lt;br /&gt;
# Для этой цели лучше использовать языки программирования, имеющие&lt;br /&gt;
# развитые средства для работы со структурами данных,&lt;br /&gt;
# такие как C++ или Java (может быть Perl).&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Массивы и другие хитрости для раздачи колоды карт в четыре руки.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# На старых системах может потребоваться вставить #!/bin/bash2.&lt;br /&gt;
&lt;br /&gt;
# Карты:&lt;br /&gt;
# раздача в четыре руки.&lt;br /&gt;
&lt;br /&gt;
UNPICKED=0&lt;br /&gt;
PICKED=1&lt;br /&gt;
&lt;br /&gt;
DUPE_CARD=99&lt;br /&gt;
LOWER_LIMIT=0&lt;br /&gt;
UPPER_LIMIT=51&lt;br /&gt;
CARDS_IN_SUIT=13&lt;br /&gt;
CARDS=52&lt;br /&gt;
&lt;br /&gt;
declare -a Deckdeclare -a Suitsdeclare -a Cards&lt;br /&gt;
# Проще и понятнее было бы, имей мы дело&lt;br /&gt;
# с одним 3-мерным массивом.&lt;br /&gt;
# Будем надеяться, что в будущем, поддержка многомерных массивов будет введена в Bash.&lt;br /&gt;
&lt;br /&gt;
initialize_Deck ()&lt;br /&gt;
{&lt;br /&gt;
 i=$LOWER_LIMIT&lt;br /&gt;
 until [ &amp;quot;$i&amp;quot; -gt $UPPER_LIMIT ]&lt;br /&gt;
 do&lt;br /&gt;
  Deck[i]=$UNPICKED # Пометить все карты в колоде &amp;quot;Deck&amp;quot;, как &amp;quot;невыданная&amp;quot;.&lt;br /&gt;
  let &amp;quot;i += 1&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
 echo&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
initialize_Suits ()&lt;br /&gt;
{&lt;br /&gt;
 Suits[0]=Т # Трефы&lt;br /&gt;
 Suits[1]=Б # Бубны&lt;br /&gt;
 Suits[2]=Ч # Червы&lt;br /&gt;
 Suits[3]=П # Пики&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
initialize_Cards ()&lt;br /&gt;
{&lt;br /&gt;
 Cards=(2 3 4 5 6 7 8 9 10 В Д K Т)&lt;br /&gt;
 # Альтернативный способ инициализации массива.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
pick_a_card ()&lt;br /&gt;
{&lt;br /&gt;
 card_number=$RANDOM&lt;br /&gt;
 let &amp;quot;card_number %= $CARDS&amp;quot;&lt;br /&gt;
 if [ &amp;quot;${Deck[card_number]}&amp;quot; -eq $UNPICKED ]&lt;br /&gt;
 then&lt;br /&gt;
  Deck[card_number]=$PICKED&lt;br /&gt;
  return $card_number&lt;br /&gt;
 else&lt;br /&gt;
  return $DUPE_CARD&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
parse_card ()&lt;br /&gt;
{&lt;br /&gt;
 number=$1&lt;br /&gt;
 let &amp;quot;suit_number = number / CARDS_IN_SUIT&amp;quot;&lt;br /&gt;
 suit=${Suits[suit_number]}&lt;br /&gt;
 echo -n &amp;quot;$suit-&amp;quot;&lt;br /&gt;
 let &amp;quot;card_no = number % CARDS_IN_SUIT&amp;quot;&lt;br /&gt;
 Card=${Cards[card_no]}&lt;br /&gt;
 printf %-4s $Card&lt;br /&gt;
 # Вывод по столбцам.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
seed_random () # Переустановка генератора случайных чисел.&lt;br /&gt;
{&lt;br /&gt;
 seed=`eval date +%s`&lt;br /&gt;
 let &amp;quot;seed %= 32766&amp;quot;&lt;br /&gt;
 RANDOM=$seed&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
deal_cards ()&lt;br /&gt;
{&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
cards_picked=0&lt;br /&gt;
while [ &amp;quot;$cards_picked&amp;quot; -le $UPPER_LIMIT ]&lt;br /&gt;
do&lt;br /&gt;
 pick_a_card&lt;br /&gt;
 t=$?&lt;br /&gt;
 if [ &amp;quot;$t&amp;quot; -ne $DUPE_CARD ]&lt;br /&gt;
 then&lt;br /&gt;
  parse_card $t&lt;br /&gt;
  u=$cards_picked+1&lt;br /&gt;
  # Возврат к индексации с 1 (временно).&lt;br /&gt;
  let &amp;quot;u %= $CARDS_IN_SUIT&amp;quot;&lt;br /&gt;
  if [ &amp;quot;$u&amp;quot; -eq 0 ] # вложенный if/then.&lt;br /&gt;
  then&lt;br /&gt;
   echo&lt;br /&gt;
   echo&lt;br /&gt;
  fi&lt;br /&gt;
  # Смена руки.&lt;br /&gt;
  let &amp;quot;cards_picked += 1&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
return 0&lt;br /&gt;
}&lt;br /&gt;
# Структурное программирование:&lt;br /&gt;
# вся логика приложения построена на вызове функций.&lt;br /&gt;
#================&lt;br /&gt;
&lt;br /&gt;
seed_random&lt;br /&gt;
initialize_Deck&lt;br /&gt;
initialize_Suits&lt;br /&gt;
initialize_Cards&lt;br /&gt;
deal_cards&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
#================  &lt;br /&gt;
# Упражнение 1:&lt;br /&gt;
# Добавьте комментарии, чтобы до конца задокументировать этот сценарий.&lt;br /&gt;
# Упражнение 2:&lt;br /&gt;
# Исправьте сценарий так, чтобы карты в каждой руке выводились отсортированными по масти.&lt;br /&gt;
# Вы можете добавить и другие улучшения.&lt;br /&gt;
# Упражнение 3:&lt;br /&gt;
# Упростите логику сценария.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Замечания и дополнения =&lt;br /&gt;
&lt;br /&gt;
== От автора ==&lt;br /&gt;
Как я пришёл к мысли о написании этой книги? Это необычная история. Случилось это лет несколько тому назад. Мне потребовалось изучить язык командной оболочки — а что может быть лучше, как нечтение хорошей книги!? Я надеялся купить учебник и справочник, которые охватывали бы в полной мере данную тематику. Я искал книгу, которая возьмёт трудные понятия, вывернет их наизнанку и подробно разжует на хорошо откомментированных примерах. В общем, я искал очень хорошую книгу. К сожалению, в природе таковой не существовало, поэтому я счёл необходимым написать её.&amp;lt;br /&amp;gt;&lt;br /&gt;
Это напоминает мне сказку о сумасшедшем профессоре. Помешанный, до безумия, при виде книги, любой книги — в библиотеке, в книжном магазине — не важно где, им овладевала уверенность в том, что и он мог бы написать эту книгу, причём мог бы сделать это гораздо лучше. Он стремительно мчался домой и садился за создание своей собственной книги с тем же названием. Когда он умер, в его доме нашли несколько тысяч, написанных им книг, этого количества хватило бы, чтобы посрамить самого Айзека Азимова. Книги, может быть и не были так хороши — кто знает, но разве это имеет какое-то значение? Вот — человек, жил своими грёзами, пусть одержимый и движимый ими, но я не могу удержаться от восхищения старым чудаком...&lt;br /&gt;
&lt;br /&gt;
== Об авторе ==&lt;br /&gt;
Автор не стремится ни к званиям, ни к наградам, им движет неодолимое желание писать. Эта книга — своего рода отдых от основной работы, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;HOW-2 Meet Women: The Shy Man's Guide to Relationships&amp;lt;/span&amp;gt; (Руководство Застенчивого Мужчины о том Как Познакомиться С Женщиной) . Он также написал &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Software-Building HOWTO&amp;lt;/span&amp;gt;. В последнее время он пробует себя в беллетристике.&amp;lt;br /&amp;gt;&lt;br /&gt;
Пользуется Linux с 1995 года (Slackware 2.2, kernel 1.2.1). Выпустил несколько программ, среди которых '''cruft''' — утилита шифрования, заменявшая стандартную Unix-овую '''crypt''', '''mcalc''' — финансовый калькулятор, для выполнения расчетов по займам, '''judge''' и '''yawl''' — пакет игр со словами. Программировать начинал с языка ''FORTRAN IV'' на ''CDC 3800'', но не испытывает ностальгии по тем дням. Живёт в глухой, заброшенной деревушке со своей женой и собакой.&lt;br /&gt;
&lt;br /&gt;
== Куда обращаться за помощью ==&lt;br /&gt;
Автор('''''thegrendel@theriver.com''''') этой книги обычно не оставляет без ответа задаваемые ему вопросы (если он не слишком занят и пребывает в добром расположении духа). Однако, если вы испытываете проблемы со специфическим сценарием, то вам лучше обратиться на [comp.os.unix.shell] ''Usenet newsgroup''.&lt;br /&gt;
&lt;br /&gt;
== Инструменты, использовавшиеся при создании книги ==&lt;br /&gt;
&lt;br /&gt;
=== Аппаратура ===&lt;br /&gt;
IBM Thinkpad, model 760XL laptop (P166, 104 Mb RAM) под управлением Red Hat 7.1/7.3. Несомненно,это довольно медлительный агрегат, но он имеет отличную клавиатуру, и это много лучше, чем пара карандашей и письменный стол.&lt;br /&gt;
&lt;br /&gt;
=== Программное обеспечение ===&lt;br /&gt;
* Мощный текстовый редактор [[vim]] (автор: Bram Moolenaar).&lt;br /&gt;
* [http://openjade.sourceforge.net/ OpenJade] — инструмент, выполняющий, на основе DSSSL, верификацию и преобразование SGML-документов в другие форматы.&lt;br /&gt;
* Таблицы стилей DSSSL от Norman Walsh.&lt;br /&gt;
* ''DocBook'', ''The Definitive Guide'' (Norman Walsh, Leonard Muellner O'Reilly, ISBN 1-56592-580-7). Полное руководство по созданию документов в формате Docbook SGML.&lt;br /&gt;
&lt;br /&gt;
== Благодарности ==&lt;br /&gt;
Без участия сообщества этот проект был бы невозможен. Автор признаёт, что без посторонней помощи, написание этой книги стало бы невыполнимой задачей и благодарит всех, кто оказал посильную помощь.&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Philippe Martin&amp;lt;/span&amp;gt; — перевёл этот документ в формат DocBook/SGML. Работает в маленькой французской компании, в качестве разработчика программного обеспечения. В свободное от работы время — любит работать над документацией или программным обеспечением для ''GNU/Linux'', читать книги, слушать музыку и веселиться с друзьями. Вы можете столкнуться с ним, где-нибудь во Франции, в провинции Басков, или написать ему письмо на ''feloy@free.fr''. &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Philippe Martin&amp;lt;/span&amp;gt; также отметил, что возможно использование позиционных параметров за '''$9''', при использовании '''{фигурных скобок}'''.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Stephane Chazelas&amp;lt;/span&amp;gt; — выполнил титаническую работу по корректировке, дополнению и написанию примеров сценариев. Фактически, он взвалил на свои плечи обязанности редактора этого документа. Огромное спасибо! &lt;br /&gt;
&lt;br /&gt;
* &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Paulo Marcel Coelho Aragao&amp;lt;/span&amp;gt; предложил большое количество дополнений и изменений, как важных, таки не очень. А также дал ряд дельных советов.&amp;lt;br /&amp;gt;&lt;br /&gt;
Особенно я хотел бы поблагодарить ''Patrick Callahan'', ''Mike Novak'' и ''Pal Domokos'' за исправление ошибок и неточностей, за разъяснения и дополнения. Их живое обсуждение проблем, связанных с созданием сценариев на языке командной оболочки вдохновило меня на попытку сделать этот документ более удобочитаемым.&amp;lt;br /&amp;gt;&lt;br /&gt;
Я благодарен ''Jim Van Zandt'' за выявленные им ошибки и упущения, в версии 0.2 этого документа, и за поучительный пример сценария.&amp;lt;br /&amp;gt;&lt;br /&gt;
Большое спасибо &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Jordi Sanfeliu&amp;lt;/span&amp;gt; за то, что он дал возможность использовать его прекрасный сценарий в этой книге.&amp;lt;br /&amp;gt;&lt;br /&gt;
Выражаю свою благодарность &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Michel Charpentier&amp;lt;/span&amp;gt;  за разрешение использовать его '''''dc''''' сценарий разложения на простые множители.&amp;lt;br /&amp;gt;&lt;br /&gt;
Спасибо &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Noah Friedman&amp;lt;/span&amp;gt;, предоставившему право использовать его сценарий.&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Emmanuel Rouat&amp;lt;/span&amp;gt; предложил несколько изменений и дополнений в разделах, посвящённых подстановке команд и псевдонимам. Он так же предоставил замечательный пример файла ''.bashrc'' (Приложение I).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Heiner Steven&amp;lt;/span&amp;gt; любезно разрешил опубликовать его сценарий. Он сделал множество исправлений и внёс большое количество предложений. Особое спасибо!&amp;lt;br /&amp;gt;&lt;br /&gt;
''Rick Boivie'' предоставил отличный сценарий, демонстрирующий рекурсию, pb.sh и внёс предложения по повышению производительности сценария monthlypmt.sh. ''Florian Wisser'' оказывал содействие при написании разделов, посвящённых строкам. ''Oleg Philon'' передал свои предложения относительно команд '''cut''' и '''pidof'''. ''Michael Zick'' расширил пример с пустыми массивами, введя туда демонстрацию необычных свойств массивов. Он также предоставил ряд других примеров. ''Marc-Jano Knopp'' выполнил исправления в разделе, посвящённом пакетным файлам DOS. ''Hyun Jin Cha'', в процессе работы над корейским переводом, обнаружил несколько опечаток в документе. Спасибо ему за это! ''Andreas Abraham'' передал большое число типографских ошибок и внёс ряд исправлений. Особое спасибо!&amp;lt;br /&amp;gt;&lt;br /&gt;
Кроме того, я хотел бы выразить свою признательность за примеры сценариев, исправление моих ошибок и полезные советы ''Gabor Kiss, Leopold Toetsch, Peter Tillier, Marcus Berglof, Tony Richardson,Nick Drage, Rich Bartell, Jess Thrysoee, Adam Lazur, Bram Moolenaar, Baris Cicek, Greg Keraunen, KeithMatthews, Sandro Magi, Albert Reiner, Dim Segebart, Rory Winston, Lee Bigelow, Wayne Pollock, &amp;quot;jipe,&amp;quot;Emilio Conti, Dennis Leeuw, Dan Jacobson, Aurelio Marinho Jargas, Edward Scholtz, Jean Helou, ChrisMartin, Lee Maschmeyer, Bruno Haible, Sebastien Godard, Bjіn Eriksson, &amp;quot;nyal,&amp;quot; John MacDonald, JoshuaTschida, Troy Engel, Manfred Schwarb, Amit Singh, Bill Gradwohl, David Lombard, Jason Parker, Bruce W.Clare, William Park, and David Lawyer''(автор 4-х HOWTO).&amp;lt;br /&amp;gt;&lt;br /&gt;
Мои благодарности &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Chet Ramey(chet@po.cwru.edu)&amp;lt;/span&amp;gt; и ''Brian Fox'' за создание '''''Bash''''' — этого элегантного и мощного инструмента!&amp;lt;br /&amp;gt;&lt;br /&gt;
Особое спасибо добровольцам из [http://www.tldp.org/ Linux Documentation Project]. Проект LDP сделал возможным публикацию этой книги в своём архиве.&amp;lt;br /&amp;gt;&lt;br /&gt;
Особую признательность хочу выразить IBM, Novell, Red Hat, [http://www.fsf.org/ Free Software Foundation] и всем замечательным людям, которые бьются за то, чтобы программное обеспечение ''Open Source'' оставалось свободным и открытым.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Больше всего я хотел бы выразить свою благодарность моей супруге, &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Anita&amp;lt;/span&amp;gt;, за ее эмоциональную поддержку'''''.&lt;br /&gt;
&lt;br /&gt;
= Библиография =&lt;br /&gt;
* '''Jeffrey Friedl, Mastering Regular Expressions, O'Reilly and Associates, 2002, 0-596-00289-0'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Прекрасное руководство по Регулярным Выражениям''.&lt;br /&gt;
* '''Edited by Peter Denning, Computers Under Attack: Intruders, Worms, and Viruses, ACM Press, 1990, 0-201-53067-8'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Содержит несколько статей о вирусах, написанных на языке командной оболочки''.&lt;br /&gt;
* '''Dale Dougherty and Arnold Robbins, Sed and Awk, 2nd edition, O'Reilly and Associates, 1997, 1-156592-225-5'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Чтобы раскрыть всю мощь командной оболочки, вам наверняка потребуется знакомство с sed иawk. Это обычный учебник. Здесь вы найдете превосходное введение в &amp;quot;регулярныевыражения&amp;quot;. Обязательно прочитайте эту книгу''.&lt;br /&gt;
* '''Chet Ramey and Brian Fox, The GNU Bash Reference Manual, Network Theory Ltd, 2003, 0-9541617-7-7'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Это руководство является официальной документацией по GNU Bash. Авторы руководства, ChetRamey и Brian Fox, занимаются разработкой GNU Bash с самого начала. Издатель передаёт $1 в Фонд Свободного Программного Обеспечения (Free Software Foundation) с каждой проданной копии руководства''.&lt;br /&gt;
* '''Aeleen Frisch, Essential System Administration, 3rd edition, O'Reilly and Associates, 2002, 0-596-00343-9.'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Это замечательное руководство для системных администраторов. Может служить неплохим введением в программирование сценариев. Содержит подробные пояснения к сценариям загрузки и инициализации системы''.&lt;br /&gt;
* '''Stephen Kochan and Patrick Woods, Unix Shell Programming, Hayden, 1990, 067248448X'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Стандартный справочник, хотя немного устаревший''.&lt;br /&gt;
* '''Neil Matthew and Richard Stones, Beginning Linux Programming, Wrox Press, 1996, 1874416680'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Даёт хороший, глубокий охват различных языков программирования, доступных в Linux,включая довольно сильную главу по программированию в командной оболочке''.&lt;br /&gt;
* '''Herbert Mayer, Advanced C Programming on the IBM PC, Windcrest Books, 1989, 0830693637'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Замечательная книга по алгоритмам и практическому программированию''.&lt;br /&gt;
* '''David Medinets, Unix Shell Programming Tools, McGraw-Hill, 1999, 0070397333'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Отличная книга по программированию в командной оболочке, с примерами, и кратким введением в Tcl и Perl''.&lt;br /&gt;
* '''Cameron Newham and Bill Rosenblatt, Learning the Bash Shell, 2nd edition, O'Reilly and Associates, 1998,1-56592-347-2'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Это отважная попытка создать учебник для начинающих, но он получился несколько несовершенным, к тому же не изобилует примерами сценариев.''.&lt;br /&gt;
* '''Anatole Olczak, Bourne Shell Quick Reference Guide, ASP, Inc., 1991, 093573922X'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Очень удобный карманный справочник, несмотря на недостатки, при охвате специфичных свойств Bash''.&lt;br /&gt;
* '''Jerry Peek, Tim O'Reilly, and Mike Loukides, Unix Power Tools, 2nd edition, O'Reilly and Associates,Random House, 1997, 1-56592-260-3'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Содержит ряд очень информативных разделов, посвященных программированию в командной оболочке, но не может рассматриваться как учебное пособие''.&lt;br /&gt;
* '''Clifford Pickover, Computers, Pattern, Chaos, and Beauty, St. Martin's Press, 1990, 0-312-04123-3'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Сокровищница идей и рецептов по машинным вычислениям''.&lt;br /&gt;
* '''George Polya, How To Solve It, Princeton University Press, 1973, 0-691-02356-5'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Классический учебник по методам решения задач''.&lt;br /&gt;
* '''Arnold Robbins, Bash Reference Card, SSC, 1998, 1-58731-010-5'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Замечательный карманный справочник по Bash. Стоит всего $4.95, но также доступен для свободного скачивания [http://www.ssc.com/ssc/bash/ on-line] в формате PDF''.&lt;br /&gt;
* '''Arnold Robbins, Effective Awk Programming, Free Software Foundation / O'Reilly and Associates, 2000, 1-882114-26-4'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Самое лучшее учебное руководство и справочник по awk. Свободная электронная версия книги включена в состав документации к [[awk]]. Печатное издание последней версии доступно на сайте O'Reilly and Associates''. '''''Эта книга служила источником вдохновения для автора этой книги'''''.&lt;br /&gt;
* '''Bill Rosenblatt, Learning the Korn Shell, O'Reilly and Associates, 1993, 1-56592-054-6'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Эта, хорошо написанная книга, содержит массу указаний по созданию сценариев командной оболочки''.&lt;br /&gt;
* '''Paul Sheer, LINUX: Rute User's Tutorial and Exposition, 1st edition, , 2002, 0-13-033351-4'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Очень хорошее введение в системное администрирование Linux. Эта книга доступна в [https://sourceforge.net/projects/rute/ on-line]''.&lt;br /&gt;
* '''Ellen Siever and the staff of O'Reilly and Associates, Linux in a Nutshell, 2nd edition, O'Reilly andAssociates, 1999, 1-56592-585-8'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Один из лучших справочников по командам Linux, имеет раздел, посвященный Bash''.&lt;br /&gt;
* '''The Unix CD Bookshelf, 3rd edition, O'Reilly and Associates, 2003, 0-596-00392-7'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Сборник из 7-ми книг по Unix на CD-ROM. В состав сборника входят такие книги, как Unix PowerTools, Sed and Awk и Learning the Korn Shell. Полный набор необходимых справочных и учебных материалов, который вам только может понадобиться. Стоит примерно $130''.&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;background:yellow&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Книги издательства O'Reilly, посвящённые '''Perl'''&amp;lt;/span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;.&lt;br /&gt;
* '''Ben Okopnik опубликовал серию отличных статей introductory Bash scripting в выпусках 53, 54,55, 57 и 59 на сайте Linux Gazette, и статью &amp;quot;The Deep, Dark Secrets of Bash&amp;quot; в выпуске 56'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Chet Ramey bash - The GNU Shell — серия статей в 3 и 4 выпусках Linux Journal, Июль-Август 1994.'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Mike G [http://www.tldp.org/HOWTO/Bash-Prog-Intro-HOWTO.html Bash-Programming-Intro HOWTO]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Richard [http://www.injunea.demon.co.uk/index.htm Unix Scripting Universe]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Chet Ramey [ftp://ftp.cwru.edu/pub/bash/FAQ/ Bash F.A.Q]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Ed Schaefer [http://www.unixreview.com/columns/schaefer/ Shell Corner] на [http://networkcomputing.com/ Unix Review]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Примеры сценариев: [http://alge.anart.no/linux/scripts/ Lucc's Shell Scripts]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Примеры сценариев: [http://www.shelldorado.com/ SHELLdorado]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Примеры сценариев: [http://clri6f.gsi.de/gnu/bash-2.01/examples/scripts.noah/ Noah Friedman's script site]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Steve Parker [https://www.shellscript.sh/ Shell Programming Stuff]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Примеры сценариев: [https://sourceforge.net/snippet/browse.php?by=lang&amp;amp;lang=7 SourceForge Snippet Library - shell scripts]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Giles Orr [http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/ Bash-Prompt HOWTO]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Замечательное руководство по регулярным выражениям, sed и awk [http://www.grymoire.com/Unix/index.html The Unix Grymoire]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Eric Pement [http://www.student.northpark.edu/pemente/sed/ sed resources page]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''[https://www.gnu.org/software/gawk/manual/gawk.html The GNU gawk reference manual] (gawk — GNU-версия awk для ОС Linux и BSD)'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Trent Fisher [http://web.cecs.pdx.edu/~trent/gnu/groff/groff.html groff tutorial]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Mark Komarinski [http://www.tldp.org/HOWTO/Printing-Usage-HOWTO.html Printing-Usage HOWTO]'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Rick Hohensee osimpa — ассемблер для процессора i386, написан полностью на Bash'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Fioretti, Marco, &amp;quot;Scripting for X Productivity,&amp;quot; LINUX JOURNAL, Выпуск 113, Сентябрь, 2003, стр.86-9'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Aurelio Marinho Jargas написал [http://aurelio.net/projects/txt2regex/ Regular expression wizard]. Он так же написал поучительную [http://aurelio.net/regex/guia/ книгу], посвященную регулярным выражениям, на португальском(!) языке.'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Ben Tomkins создал [http://bashnavigator.sourceforge.net/ Bash Navigator] — средство навигации по каталогам'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''William Park работает над проектом по переносу некоторых возможностей из Awk и Python в Bash'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Rocky Bernstein ведет разработку &amp;quot;полнофункционального&amp;quot; [http://bashdb.sourceforge.net/ отладчика] для Bash.'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Отличное руководство &amp;quot;Bash Reference Manual&amp;quot;, авторы Chet Ramey и Brian Fox,распространяется в составе пакета &amp;quot;bash-2-doc&amp;quot; (доступен как rpm). В этом пакете вы найдёте особенно поучительные примеры.'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Группа новостей &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;comp.os.unix.shell&amp;lt;/span&amp;gt;'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
* '''Страницы руководства man по bash и bash2, date, expect, expr, find, grep, gzip, ln, patch,tar, tr, bc, xargs. Странички info по bash, dd, m4, gawk и sed'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Приложение А. Дополнительные примеры сценариев =&lt;br /&gt;
В этом приложении собраны сценарии, которые не попали в основной текст документа. Однако, они определенно стоят того, что бы вы потратили время на их изучение.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-1. manview: Просмотр страниц руководств man.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# manview.sh: Просмотр страниц руководств man в форматированном виде.&lt;br /&gt;
&lt;br /&gt;
# Полезен писателям страниц руководств, позволяет просмотреть страницы в исходном коде&lt;br /&gt;
# как они будут выглядеть в конечном виде.&lt;br /&gt;
&lt;br /&gt;
E_WRONGARGS=65&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя_файла&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
groff -Tascii -man $1 | less&lt;br /&gt;
# Если страница руководства включает в себя таблицы и/или выражения,&lt;br /&gt;
# то этот сценарий &amp;quot;стошнит&amp;quot;.&lt;br /&gt;
# Для таких случаев можно использовать следующую строку.&lt;br /&gt;
#&lt;br /&gt;
#gtbl &amp;lt; &amp;quot;$1&amp;quot; | geqn -Tlatin1 | groff -Tlatin1 -mtty-char -man&lt;br /&gt;
#&lt;br /&gt;
# Спасибо S.C.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-2. mailformat: Форматирование электронных писем.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# mail-format.sh: Форматирование электронных писем.&lt;br /&gt;
&lt;br /&gt;
# Удаляет символы &amp;quot;^&amp;quot;, табуляции и ограничивает чрезмерно длинные строки.&lt;br /&gt;
&lt;br /&gt;
# =================================================================&lt;br /&gt;
#                Стандартная проверка аргументов&lt;br /&gt;
ARGS=1&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
E_NOFILE=66&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne $ARGS ] # Проверка числа аргументов&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя_файла&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ -f &amp;quot;$1&amp;quot; ] # Проверка наличия файла.&lt;br /&gt;
then&lt;br /&gt;
 file_name=$1&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Файл \&amp;quot;$1\&amp;quot; не найден.&amp;quot;&lt;br /&gt;
 exit $E_NOFILE&lt;br /&gt;
fi&lt;br /&gt;
# =================================================================&lt;br /&gt;
&lt;br /&gt;
MAXWIDTH=70 # Максимальная длина строки.&lt;br /&gt;
&lt;br /&gt;
# Удаление символов &amp;quot;^&amp;quot; начиная с первого символа строки,&lt;br /&gt;
# и ограничить длину строки 70-ю символами.&lt;br /&gt;
sed '&lt;br /&gt;
s/^&amp;gt;//&lt;br /&gt;
s/^  *&amp;gt;//&lt;br /&gt;
s/^  *//&lt;br /&gt;
s/              *//&lt;br /&gt;
' $1 | fold -s --width=$MAXWIDTH&lt;br /&gt;
             # ключ -s команды &amp;quot;fold&amp;quot; разрывает, если это возможно, строку по пробельному символу.&lt;br /&gt;
# Этот сценарий был написан после прочтения статьи, в котором расхваливалась&lt;br /&gt;
# утилита под Windows, размером в 164K, с подобной функциональностью.&lt;br /&gt;
#&lt;br /&gt;
# Хороший набор утилит для обработки текста и эффективный&lt;br /&gt;
# скриптовый язык — это всё, что необходимо, чтобы составить серьезную конкуренцию&lt;br /&gt;
# чрезмерно &amp;quot;раздутым&amp;quot; программам.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-3. rn: Очень простая утилита для переименования файлов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Очень простая утилита для переименования файлов&lt;br /&gt;
#&lt;br /&gt;
# Утилита &amp;quot;ren&amp;quot;, автор Vladimir Lanin (lanin@csd2.nyu.edu),&lt;br /&gt;
# выполняет эти же действия много лучше.&lt;br /&gt;
&lt;br /&gt;
ARGS=2&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
ONE=1 # Единственное или множественное число (см. ниже).&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` старый_шаблон новый_шаблон&amp;quot;&lt;br /&gt;
 # Например: &amp;quot;rn gif jpg&amp;quot;, поменяет расширения всех файлов в текущем каталоге с gif на jpg.&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
number=0                       # Количество переименованных файлов.&lt;br /&gt;
&lt;br /&gt;
for filename in *$1*           # Проход по списку файлов в текущем каталоге.&lt;br /&gt;
do&lt;br /&gt;
 if [ -f &amp;quot;$filename&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  fname=`basename $filename`            # Удалить путь к файлу из имени.&lt;br /&gt;
  n=`echo $fname | sed -e &amp;quot;s/$1/$2/&amp;quot;`   # Поменять старое имя на новое.&lt;br /&gt;
  mv $fname $n                          # Переименовать.&lt;br /&gt;
  let &amp;quot;number += 1&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$number&amp;quot; -eq &amp;quot;$ONE&amp;quot; ] # Соблюдение правил грамматики.&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;$number файл переименован.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Переименовано файлов: $number.&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
# Упражнения:&lt;br /&gt;
# ----------&lt;br /&gt;
# С какими типами файлов этот сценарий не будет работать?&lt;br /&gt;
# Как это исправить?&lt;br /&gt;
#&lt;br /&gt;
# Переделайте сценарий таким образом, чтобы он мог обрабатывать все файлы в каталоге,&lt;br /&gt;
# в именах которых содержатся пробелы, заменяя пробелы символом подчеркивания.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-4. blank-rename: переименование файлов, чьи имена содержат пробелы.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
Это даже более простая версия предыдущего примера.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
# blank-rename.sh&lt;br /&gt;
#&lt;br /&gt;
# Заменяет пробелы символом подчеркивания в именах файлов в текущем каталоге.&lt;br /&gt;
&lt;br /&gt;
ONE=1                                  # единственное или множественное число (см. ниже).&lt;br /&gt;
number=0                               # Количество переименованных файлов.&lt;br /&gt;
FOUND=0                                # Код завершения в случае успеха.&lt;br /&gt;
&lt;br /&gt;
for filename in *                      # Перебор всех файлов в текущем каталоге.&lt;br /&gt;
do&lt;br /&gt;
 echo &amp;quot;$filename&amp;quot; | grep -q &amp;quot; &amp;quot;        # Проверить — содержит ли имя файла&lt;br /&gt;
 if [ $? -eq $FOUND ]                  # пробелы.&lt;br /&gt;
 then&lt;br /&gt;
  fname=$filename                      # Удалить путь из имени файла.&lt;br /&gt;
  n=`echo $fname | sed -e &amp;quot;s/ /_/g&amp;quot;`   # Заменить пробелы символом подчеркивания.&lt;br /&gt;
  mv &amp;quot;$fname&amp;quot; &amp;quot;$n&amp;quot;                     # Переименование.&lt;br /&gt;
  let &amp;quot;number += 1&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$number&amp;quot; -eq &amp;quot;$ONE&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;$number файл переименован.&amp;quot;&lt;br /&gt;
else&lt;br /&gt;
 echo &amp;quot;Переименовано файлов: $number&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-5. encryptedpw: Передача файла на ftp-сервер, с использованием пароля.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Модификация примера &amp;quot;ex72.sh&amp;quot;, добавлено шифрование пароля.&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание: этот вариант всё еще нельзя считать безопасным,&lt;br /&gt;
# поскольку в сеть пароль уходит в незашифрованном виде.&lt;br /&gt;
# Используйте &amp;quot;ssh&amp;quot;, если вас это беспокоит.&lt;br /&gt;
&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя_файла&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
Username=bozo            # Измените на свой.&lt;br /&gt;
pword=/home/bozo/secret/password_encrypted.file&lt;br /&gt;
# Файл, содержащий пароль в зашифрованном виде.&lt;br /&gt;
&lt;br /&gt;
Filename=`basename $1`   # Удалить путь из имени файла&lt;br /&gt;
&lt;br /&gt;
Server=&amp;quot;XXX&amp;quot;&lt;br /&gt;
Directory=&amp;quot;YYY&amp;quot;          # Подставьте фактические имя сервера и каталога.&lt;br /&gt;
&lt;br /&gt;
Password=`cruft &amp;lt;$pword` # Расшифровка.&lt;br /&gt;
# Используется авторская программа &amp;quot;cruft&amp;quot;,&lt;br /&gt;
# основанная на алгоритме &amp;quot;onetime pad&amp;quot;,&lt;br /&gt;
# её можно скачать с :&lt;br /&gt;
# Primary-site: ftp://ibiblio.org/pub/Linux/utils/file&lt;br /&gt;
# cruft-0.2.tar.gz [16k]&lt;br /&gt;
&lt;br /&gt;
ftp -n $Server &amp;lt;&amp;lt;End-Of-Sessionuser &lt;br /&gt;
$Username $Password&lt;br /&gt;
binary&lt;br /&gt;
bell&lt;br /&gt;
cd $Directory&lt;br /&gt;
put $Filename&lt;br /&gt;
bye&lt;br /&gt;
End-Of-Session&lt;br /&gt;
# ключ -n, команды &amp;quot;ftp&amp;quot;, запрещает автоматический вход.&lt;br /&gt;
# &amp;quot;bell&amp;quot; — звонок (звуковой сигнал) после передачи каждого файла.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-6. copy-cd: Копирование компакт-дисков с данными.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# copy-cd.sh: copying a data &lt;br /&gt;
&lt;br /&gt;
CDCDROM=/dev/cdrom                    # устройство CD-ROM&lt;br /&gt;
OF=/home/bozo/projects/cdimage.iso    # промежуточный файл&lt;br /&gt;
#       /xxxx/xxxxxxx/      измените для своей системы.&lt;br /&gt;
BLOCKSIZE=2048&lt;br /&gt;
SPEED=2                               # Можно задать более высокую скорость, если поддерживается.&lt;br /&gt;
&lt;br /&gt;
echo; echo &amp;quot;Вставьте исходный CD, но *НЕ* монтируйте его.&amp;quot;&lt;br /&gt;
echo &amp;quot;Нажмите ENTER, когда будете готовы. &amp;quot;&lt;br /&gt;
read ready                            # Ожидание.&lt;br /&gt;
&lt;br /&gt;
echo; echo &amp;quot;Создаётся промежуточный файл $OF.&amp;quot;&lt;br /&gt;
echo &amp;quot;Это может занять какое-то время. Пожалуйста, подождите.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
dd if=$CDROM of=$OF bs=$BLOCKSIZE     # Копирование.&lt;br /&gt;
&lt;br /&gt;
echo; echo &amp;quot;Выньте исходный CD.&amp;quot;&lt;br /&gt;
echo &amp;quot;Вставьте чистую болванку CD-R.&amp;quot;&lt;br /&gt;
echo &amp;quot;Нажмите ENTER, когда будете готовы. &amp;quot;&lt;br /&gt;
read ready                            # Ожидание.&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Копируется файл $OF на болванку.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
cdrecord -v -isosize speed=$SPEED dev=0,0 $OF&lt;br /&gt;
# Используется пакет Joerg Schilling — &amp;quot;cdrecord&amp;quot;.&lt;br /&gt;
# http://www.fokus.gmd.de/nthp/employees/schilling/cdrecord.html&lt;br /&gt;
&lt;br /&gt;
echo; echo &amp;quot;Копирование завершено.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Желаете удалить промежуточный файл (y/n)? &amp;quot; # Наверняка большой файл получился.&lt;br /&gt;
read answer&lt;br /&gt;
&lt;br /&gt;
case &amp;quot;$answer&amp;quot; &lt;br /&gt;
 in[yY]) rm -f $OF; echo &amp;quot;Файл $OF удален.&amp;quot;;;&lt;br /&gt;
 *) echo &amp;quot;Файл $OF не был удален.&amp;quot;;;&lt;br /&gt;
esac&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# Добавьте в оператор &amp;quot;case&amp;quot; возможность обработки, введенных пользователем, &amp;quot;yes&amp;quot; и &amp;quot;Yes&amp;quot;.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-7. Последовательности Коллаца (Collatz).'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# collatz.sh&lt;br /&gt;
&lt;br /&gt;
# Широко известная последовательность Коллаца (Collatz) (гипотеза Коллаца).&lt;br /&gt;
# -------------------------------------------&lt;br /&gt;
# 1) Принимает из командной строки &amp;quot;начальное&amp;quot; целое число.&lt;br /&gt;
# 2) ЧИСЛО &amp;lt;--- НАЧАЛЬНОЕ ЗНАЧЕНИЕ&lt;br /&gt;
# 3) Вывести ЧИСЛО.&lt;br /&gt;
# 4) Если ЧИСЛО чётное, разделить на 2,&lt;br /&gt;
# 5) Если не чётное — умножить на 3 и прибавить 1.&lt;br /&gt;
# 6) ЧИСЛО &amp;lt;--- РЕЗУЛЬТАТ&lt;br /&gt;
# 7) Повторить, начиная с п. 3, заданное число раз.&lt;br /&gt;
#&lt;br /&gt;
# Теоретически, такая последовательность должна сходиться,&lt;br /&gt;
# не зависимо от величины начального значения,&lt;br /&gt;
# к повторению циклов &amp;quot;4,2,1...&amp;quot;,&lt;br /&gt;
# даже после значительных флуктуаций в самом начале.&lt;br /&gt;
&lt;br /&gt;
MAX_ITERATIONS=200&lt;br /&gt;
# Для больших начальных значений (&amp;gt;32000), это значение придется увеличить.&lt;br /&gt;
h=${1:-$$}             # Начальное значение&lt;br /&gt;
                       # если из командной строки ничего не задано, то берется $PID,&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;C($h) --- $MAX_ITERATIONS итераций&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
for ((i=1; i&amp;lt;=MAX_ITERATIONS; i++))&lt;br /&gt;
do&lt;br /&gt;
 echo -n &amp;quot;$h      &amp;quot;&lt;br /&gt;
#           ^^^^^&lt;br /&gt;
#         табуляция&lt;br /&gt;
 let &amp;quot;remainder = h % 2&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$remainder&amp;quot; -eq 0 ] # Чётное?&lt;br /&gt;
 then&lt;br /&gt;
  let &amp;quot;h /= 2&amp;quot;             # Разделить на 2.&lt;br /&gt;
 else                      # Иначе&lt;br /&gt;
  let &amp;quot;h = h*3 + 1&amp;quot;        # Умножить на 3 и прибавить 1.&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 COLUMNS=0                 # Выводить по 10 значений в строке.&lt;br /&gt;
 let &amp;quot;line_break = i % $COLUMNS&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$line_break&amp;quot; -eq 0 ]&lt;br /&gt;
 then&lt;br /&gt;
  echo&lt;br /&gt;
 fi&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-8. days-between: Подсчет числа дней между двумя датами.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# days-between.sh: Подсчёт числа дней между двумя датами.&lt;br /&gt;
&lt;br /&gt;
# Порядок использования: ./days-between.sh [M]M/[D]D/YYYY [M]M/[D]D/YYYY&lt;br /&gt;
&lt;br /&gt;
ARGS=2 # Ожидается два аргумента из командной строки.&lt;br /&gt;
E_PARAM_ERR=65 # Ошибка в числе ожидаемых аргументов.&lt;br /&gt;
&lt;br /&gt;
REFYR=1600 # Начальный год.&lt;br /&gt;
&lt;br /&gt;
CENTURY=100&lt;br /&gt;
DIY=365&lt;br /&gt;
ADJ_DIY=367 # Корректировка на високосный год + 1.&lt;br /&gt;
MIY=12&lt;br /&gt;
DIM=31&lt;br /&gt;
LEAPCYCLE=4&lt;br /&gt;
&lt;br /&gt;
MAXRETVAL=255 # Максимально возможное возвращаемое значение для положительных чисел.&lt;br /&gt;
&lt;br /&gt;
diff=         # Количество дней между датами.&lt;br /&gt;
value=        # Абсолютное значение.&lt;br /&gt;
day=          # день, месяц, год.&lt;br /&gt;
month=&lt;br /&gt;
year=&lt;br /&gt;
&lt;br /&gt;
Param_Error () # Ошибка в параметрах командной строки.&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` [M]M/[D]D/YYYY [M]M/[D]D/YYYY&amp;quot;&lt;br /&gt;
 echo &amp;quot; (даты должны быть после 1/3/1600)&amp;quot;&lt;br /&gt;
 exit $E_PARAM_ERR&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Parse_Date ()               # Разбор даты.&lt;br /&gt;
{&lt;br /&gt;
 month=${1%%/**}&lt;br /&gt;
 dm=${1%/**}                # День и месяц. &lt;br /&gt;
 day=${dm#*/}&lt;br /&gt;
 let &amp;quot;year = `basename $1`&amp;quot; # Хотя это и не имя файла, но результат тот же.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
check_date ()               # Проверка даты.&lt;br /&gt;
{&lt;br /&gt;
 [ &amp;quot;$day&amp;quot; -gt &amp;quot;$DIM&amp;quot; ] || [ &amp;quot;$month&amp;quot; -gt &amp;quot;$MIY&amp;quot; ] || [ &amp;quot;$year&amp;quot; -lt &amp;quot;$REFYR&amp;quot; ] &amp;amp;&amp;amp; Param_Error&lt;br /&gt;
 # Выход из сценария при обнаружении ошибки.&lt;br /&gt;
 # Используется комбинация &amp;quot;ИЛИ-списка / И-списка&amp;quot;.&lt;br /&gt;
 #&lt;br /&gt;
 # Упражнение: Реализуйте более строгую проверку даты.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
strip_leading_zero ()        # Удалить ведущий ноль&lt;br /&gt;
{&lt;br /&gt;
 val=${1#0}                  # иначе Bash будет считать числа&lt;br /&gt;
 return $val                 # восьмеричными (POSIX.2, sect 2.9.2.1).&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
day_index ()                 # Формула Гаусса:&lt;br /&gt;
{                            # Количество дней от 3 Янв. 1600 до заданной даты.&lt;br /&gt;
 day=$1&lt;br /&gt;
 month=$2&lt;br /&gt;
 year=$3&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;month = $month - 2&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$month&amp;quot; -le 0 ]&lt;br /&gt;
 then&lt;br /&gt;
  let &amp;quot;month += 12&amp;quot;&lt;br /&gt;
  let &amp;quot;year -= 1&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;year -= $REFYR&amp;quot;&lt;br /&gt;
 let &amp;quot;indexyr = $year / $CENTURY&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;Days = $DIY*$year + $year/$LEAPCYCLE - $indexyr + $indexyr/$LEAPCYCLE + $ADJ_DIY*$month/$MIY + $day - $DIM&amp;quot;&lt;br /&gt;
 # Более подробное объяснение алгоритма вы найдете в&lt;br /&gt;
 # http://home.t-online.de/home/berndt.schwerdtfeger/cal.htm&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$Days&amp;quot; -gt &amp;quot;$MAXRETVAL&amp;quot; ] # Если больше 255,&lt;br /&gt;
 then                            # то поменять знак&lt;br /&gt;
  let &amp;quot;dindex = 0 - $Days&amp;quot;       # чтобы функция смогла вернуть полное значение.&lt;br /&gt;
 else let &amp;quot;dindex = $Days&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 return $dindex&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
calculate_difference ()        # Разница между двумя датами.&lt;br /&gt;
{&lt;br /&gt;
 let &amp;quot;diff = $1 - $2&amp;quot;          # Глобальная переменная.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
abs ()                         # Абсолютное значение&lt;br /&gt;
{                              # Используется глобальная переменная &amp;quot;value&amp;quot;.&lt;br /&gt;
 if [ &amp;quot;$1&amp;quot; -lt 0 ]             # Если число отрицательное,&lt;br /&gt;
 then                          # то&lt;br /&gt;
  let &amp;quot;value = 0 - $1&amp;quot;         # изменить знак,&lt;br /&gt;
 else                          # иначе&lt;br /&gt;
  let &amp;quot;value = $1&amp;quot;             # оставить как есть.&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGS&amp;quot; ]          # Требуется два аргумента командной строки.&lt;br /&gt;
then&lt;br /&gt;
 Param_Error&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
Parse_Date $1&lt;br /&gt;
check_date $day $month $year               # Проверка даты.&lt;br /&gt;
strip_leading_zero $day                    # Удалить ведущие нули&lt;br /&gt;
day=$?                                     # в номере дня и/или месяца.&lt;br /&gt;
strip_leading_zero $month&lt;br /&gt;
month=$?&lt;br /&gt;
&lt;br /&gt;
day_index $day $month $year&lt;br /&gt;
date1=$?&lt;br /&gt;
&lt;br /&gt;
abs $date1                                 # Абсолютное значение&lt;br /&gt;
date1=$value&lt;br /&gt;
&lt;br /&gt;
Parse_Date $2&lt;br /&gt;
check_date $day $month $yearstrip_leading_zero $day&lt;br /&gt;
day=$?&lt;br /&gt;
&lt;br /&gt;
strip_leading_zero $month&lt;br /&gt;
month=$?&lt;br /&gt;
&lt;br /&gt;
day_index $day $month $year&lt;br /&gt;
date2=$?&lt;br /&gt;
&lt;br /&gt;
abs $date2                                  # Абсолютное значение&lt;br /&gt;
date2=$value&lt;br /&gt;
&lt;br /&gt;
calculate_difference $date1 $date2&lt;br /&gt;
&lt;br /&gt;
abs $diff                                   # Абсолютное значение&lt;br /&gt;
diff=$value&lt;br /&gt;
&lt;br /&gt;
echo $diff&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# Сравните этот сценарий с реализацией формулы Гаусса на C&lt;br /&gt;
# http://buschencrew.hypermart.net/software/datedif&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-9. Создание &amp;quot;словаря&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# makedict.sh [создание словаря]&lt;br /&gt;
&lt;br /&gt;
# Модификация сценария /usr/sbin/mkdict.&lt;br /&gt;
# Авторские права на оригинальный сценарий принадлежат Alec Muffett.&lt;br /&gt;
#&lt;br /&gt;
# Этот модифицированный вариант включен в документ на основе&lt;br /&gt;
# документа &amp;quot;LICENSE&amp;quot; из пакета &amp;quot;Crack&amp;quot;&lt;br /&gt;
# с которым распространяется оригинальный сценарий.&lt;br /&gt;
&lt;br /&gt;
# Этот скрипт обрабатывает текстовые файлы и создаёт отсортированный список&lt;br /&gt;
# слов, найденных в этих файлах.&lt;br /&gt;
&lt;br /&gt;
# Он может оказаться полезным для сборки словарей&lt;br /&gt;
# и проведения лексикографического анализа.&lt;br /&gt;
&lt;br /&gt;
E_BADARGS=65&lt;br /&gt;
&lt;br /&gt;
if [ ! -r &amp;quot;$1&amp;quot; ]                   # Необходим хотя бы один аргумент --&lt;br /&gt;
then                               # имя файла.&lt;br /&gt;
 echo &amp;quot;Порядок использования: $0 имена_файлов&amp;quot;&lt;br /&gt;
 exit $E_BADARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# SORT=&amp;quot;sort&amp;quot;                      # Необходимость задания ключей сортировки отпала.&lt;br /&gt;
                                   # Изменено, по отношению к оригинальному сценарию.&lt;br /&gt;
&lt;br /&gt;
cat $* |                           # Выдать содержимое файлов на stdout.&lt;br /&gt;
        tr A-Z a-z |               # Преобразовать в нижний регистр.&lt;br /&gt;
        tr ' ' '\012' |            # Новое: заменить пробелы символами перевода строки.&lt;br /&gt;
# tr -cd '\012[a-z][0-9]' |        # В оригинальном сценарии: удалить все символы,&lt;br /&gt;
                                   # которые не являются буквами или цифрами.&lt;br /&gt;
        tr -c '\012a-z' '\012' |   # Вместо удаления&lt;br /&gt;
                                   # не алфавитно-цифровые символы заменяются на перевод строки.&lt;br /&gt;
        sort |&lt;br /&gt;
        uniq |                     # Удалить повторяющиеся слова.&lt;br /&gt;
        grep -v '^#' |             # Удалить строки, начинающиеся с &amp;quot;#&amp;quot;.&lt;br /&gt;
        grep -v '^$'               # Удалить пустые строки.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-10. Расчет индекса &amp;quot;созвучности&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# soundex.sh: Расчет индекса &amp;quot;созвучности&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# =======================================================&lt;br /&gt;
#                 Сценарий Soundex&lt;br /&gt;
#                     Автор&lt;br /&gt;
#                 Mendel Cooper&lt;br /&gt;
#             thegrendel@theriver.com&lt;br /&gt;
#                 23 Января 2002 г.&lt;br /&gt;
#&lt;br /&gt;
#          Условия распространения: Public Domain.&lt;br /&gt;
#&lt;br /&gt;
# Несколько отличающаяся версия этого сценария была опубликована&lt;br /&gt;
# Эдом Шэфером (Ed Schaefer) в Июле 2002 года в колонке &amp;quot;Shell Corner&amp;quot;&lt;br /&gt;
# &amp;quot;Unix Review&amp;quot; on-line,&lt;br /&gt;
# http://www.unixreview.com/documents/uni1026336632258/&lt;br /&gt;
# =======================================================&lt;br /&gt;
&lt;br /&gt;
ARGCOUNT=1                      # Требуется аргумент командной строки.&lt;br /&gt;
E_WRONGARGS=70&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne &amp;quot;$ARGCOUNT&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 echo &amp;quot;Порядок использования: `basename $0` имя&amp;quot;&lt;br /&gt;
 exit $E_WRONGARGS&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
assign_value ()                  # Присвоить числовые значения&lt;br /&gt;
{                                # символам в имени.&lt;br /&gt;
 val1=bfpv                       # 'b,f,p,v' = 1&lt;br /&gt;
 val2=cgjkqsxz                   # 'c,g,j,k,q,s,x,z' = 2&lt;br /&gt;
 val3=dt                         # и т.п.&lt;br /&gt;
 val4=l&lt;br /&gt;
 val5=mn&lt;br /&gt;
 val6=r                          &lt;br /&gt;
# Попробуйте разобраться в том, что здесь происходит.&lt;br /&gt;
&lt;br /&gt;
 value=$( echo &amp;quot;$1&amp;quot; \&lt;br /&gt;
 | tr -d wh \&lt;br /&gt;
 | tr $val1 1 | tr $val2 2 | tr $val3 3 \&lt;br /&gt;
 | tr $val4 4 | tr $val5 5 | tr $val6 6 \&lt;br /&gt;
 | tr -s 123456 \&lt;br /&gt;
 | tr -d aeiouy )&lt;br /&gt;
&lt;br /&gt;
 # Символам в имени присваиваются числовые значения.&lt;br /&gt;
 # Удаляются повторяющиеся числа, если они не разделены гласными.&lt;br /&gt;
 # Гласные игнорируются, если они не являются разделителями, которые удаляются в последнюю очередь.&lt;br /&gt;
 # Символы 'w' и 'h' удаляются в первую очередь.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
input_name=&amp;quot;$1&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Имя = $input_name&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Перевести все символы в имени в нижний регистр.&lt;br /&gt;
# ------------------------------------------------&lt;br /&gt;
name=$( echo $input_name | tr A-Z a-z )&lt;br /&gt;
# ------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
# Начальный символ в индекса &amp;quot;созвучия&amp;quot;: первая буква в имени.&lt;br /&gt;
# --------------------------------------------&lt;br /&gt;
&lt;br /&gt;
char_pos=0                            # Начальная позиция в имени.&lt;br /&gt;
prefix0=${name:$char_pos:1}&lt;br /&gt;
prefix=`echo $prefix0 | tr a-z A-Z`   # Первую букву в имени — в верхний регистр.&lt;br /&gt;
let &amp;quot;char_pos += 1&amp;quot;                   # Передвинуть &amp;quot;указатель&amp;quot; на один символ.&lt;br /&gt;
name1=${name:$char_pos}&lt;br /&gt;
&lt;br /&gt;
# ++++++++++++++++++++++++++++ Исключение отдельных ситуаций +++++++++++++++++++++++++++++++&lt;br /&gt;
# Теперь мы передвинулись на один символ вправо.&lt;br /&gt;
# Если второй символ в имени совпадает с первым&lt;br /&gt;
# то его нужно отбросить.&lt;br /&gt;
# Кроме того, мы должны проверить  не является ли первый символ&lt;br /&gt;
# гласной, 'w' или 'h'.&lt;br /&gt;
&lt;br /&gt;
char1=`echo $prefix | tr A-Z a-z` # Первый символ -- в нижний регистр.&lt;br /&gt;
assign_value $name&lt;br /&gt;
s1=$value&lt;br /&gt;
assign_value $name1&lt;br /&gt;
s2=$value&lt;br /&gt;
assign_value $char1&lt;br /&gt;
s3=$value&lt;br /&gt;
s3=9$s3                           # Если первый символ в имени — гласная буква&lt;br /&gt;
                                  # или 'w' или 'h',&lt;br /&gt;
                                  # то её &amp;quot;значение&amp;quot; нужно отбросить. &lt;br /&gt;
                                  # Поэтому ставим 9, или другое &lt;br /&gt;
                                  # неиспользуемое значение, которое можно будет проверить.&lt;br /&gt;
&lt;br /&gt;
if [[ &amp;quot;$s1&amp;quot; -ne &amp;quot;$s2&amp;quot; || &amp;quot;$s3&amp;quot; -eq 9 ]]&lt;br /&gt;
then&lt;br /&gt;
 suffix=$s2&lt;br /&gt;
else&lt;br /&gt;
 suffix=${s2:$char_pos}&lt;br /&gt;
fi&lt;br /&gt;
# ++++++++++++++++++++++++ Конец исключения отдельных ситуаций +++++++++++++++++++++++++++++++&lt;br /&gt;
&lt;br /&gt;
padding=000                       # Дополнить тремя нулями.&lt;br /&gt;
&lt;br /&gt;
soun=$prefix$suffix$padding       # Нули добавить в конец получившегося индекса.&lt;br /&gt;
&lt;br /&gt;
MAXLEN=4                          # Ограничить длину индекса 4-мя символами.&lt;br /&gt;
soundex=${soun:0:$MAXLEN}&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Индекс созвучия = $soundex&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Индекс &amp;quot;созвучия&amp;quot; - это метод индексации и классификации имён&lt;br /&gt;
# по подобию звучания.&lt;br /&gt;
# Индекс &amp;quot;созвучия&amp;quot; начинается с первого символа в имени,&lt;br /&gt;
# за которым следуют 3-значный расчетный код.&lt;br /&gt;
# Имена, которые произносятся примерно одинаково, имеют близкие индексы &amp;quot;созвучия&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Например:&lt;br /&gt;
# Smith и Smythe — оба имеют индекс &amp;quot;созвучия&amp;quot; &amp;quot;S530&amp;quot;.&lt;br /&gt;
# Harrison = H625&lt;br /&gt;
# Hargison = H622&lt;br /&gt;
# Harriman = H655&lt;br /&gt;
# Как правило эта методика дает неплохой результат, но имеются и аномалии.&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# Дополнительную информацию вы найдете на&lt;br /&gt;
# &amp;quot;National Archives and Records Administration home page&amp;quot;,&lt;br /&gt;
# http://www.nara.gov/genealogy/soundex/soundex.html&lt;br /&gt;
&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ----------&lt;br /&gt;
# Упростите блок &amp;quot;Исключение отдельных ситуаций&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-11. &amp;quot;Игра &amp;quot;Жизнь&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# life.sh: Игра &amp;quot;Жизнь&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# ##################################################################### #&lt;br /&gt;
# Это Bash-версия известной игры Джона Конвея (John Conway) &amp;quot;Жизнь&amp;quot;.    #&lt;br /&gt;
#                                                                       #&lt;br /&gt;
# --------------------------------------------------------------------- #&lt;br /&gt;
# Прямоугольное игровое поле разбито на ячейки, в каждой ячейке может   #&lt;br /&gt;
# располагаться живая особь.                                            #&lt;br /&gt;
# Соответственно, ячейка с живой особью отмечается точкой,              #&lt;br /&gt;
# не занятая ячейка — остаётся пустой.                                  #&lt;br /&gt;
# Изначально, ячейки заполняются из файла —                             #&lt;br /&gt;
# это первое поколение, или &amp;quot;поколение 0&amp;quot;                               #&lt;br /&gt;
# Воспроизводство особей, в каждом последующем поколении,               #&lt;br /&gt;
# определяется следующими правилами                                     #&lt;br /&gt;
# 1) Каждая ячейка имеет &amp;quot;соседей&amp;quot;                                      #&lt;br /&gt;
# слева, справа, сверху, снизу и 4 по диагоналям.                       #&lt;br /&gt;
#                         123                                           #&lt;br /&gt;
#                         4*5                                           #&lt;br /&gt;
#                         678                                           #&lt;br /&gt;
#                                                                       #&lt;br /&gt;
# 2) Если живая особь имеет 2 или 3 живых соседей, то она остаётся жить.#&lt;br /&gt;
# 3) Если пустая ячейка имеет 3 живых соседей —                         #&lt;br /&gt;
# в ней &amp;quot;рождается&amp;quot; новая особь                                         #&lt;br /&gt;
SURVIVE=2                                                               #&lt;br /&gt;
BIRTH=3                                                                 #&lt;br /&gt;
# 4) В любом другом случае, живая особь &amp;quot;погибает&amp;quot;                      #&lt;br /&gt;
# ##################################################################### #&lt;br /&gt;
&lt;br /&gt;
startfile=gen0                   # Начальное поколение из файла по-умолчанию — &amp;quot;gen0&amp;quot;.&lt;br /&gt;
                                 # если не задан другой файл, из командной строки.&lt;br /&gt;
                                 #&lt;br /&gt;
if [ -n &amp;quot;$1&amp;quot; ]                   # Проверить аргумент командной строки — файл с &amp;quot;поколением 0&amp;quot;.&lt;br /&gt;
then&lt;br /&gt;
 if [ -e &amp;quot;$1&amp;quot; ]                  # Проверка наличия файла.&lt;br /&gt;
 then&lt;br /&gt;
  startfile=&amp;quot;$1&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
ALIVE1=.&lt;br /&gt;
DEAD1=_&lt;br /&gt;
                                  # Представление &amp;quot;живых&amp;quot; особей и пустых ячеек в файле с &amp;quot;поколением 0&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Этот сценарий работает с игровым полем 10 x 10 grid (может быть увеличено,&lt;br /&gt;
# но большое игровое поле будет обрабатываться очень медленно).&lt;br /&gt;
&lt;br /&gt;
ROWS=10&lt;br /&gt;
COLS=10&lt;br /&gt;
&lt;br /&gt;
GENERATIONS=10                     # Максимальное число поколений.&lt;br /&gt;
&lt;br /&gt;
NONE_ALIVE=80                      # Код завершения на случай,&lt;br /&gt;
                                   # если не осталось ни одной &amp;quot;живой&amp;quot; особи.&lt;br /&gt;
&lt;br /&gt;
TRUE=0&lt;br /&gt;
FALSE=1&lt;br /&gt;
ALIVE=0&lt;br /&gt;
DEAD=1&lt;br /&gt;
&lt;br /&gt;
avar=                              # Текущее поколение.&lt;br /&gt;
generation=0                       # Инициализация счетчика поколений.&lt;br /&gt;
# =================================================================&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;cells = $ROWS * $COLS&amp;quot;        # Количество ячеек на игровом поле.&lt;br /&gt;
declare -a initial                 # Массивы ячеек.&lt;br /&gt;
declare -a current&lt;br /&gt;
&lt;br /&gt;
display ()&lt;br /&gt;
{&lt;br /&gt;
 alive=0                            # Количество &amp;quot;живых&amp;quot; особей.&lt;br /&gt;
                                    # Изначально — ноль.&lt;br /&gt;
 declare -a  arr&lt;br /&gt;
 arr=( `echo &amp;quot;$1&amp;quot;` )                # Преобразовать аргумент в массив.&lt;br /&gt;
&lt;br /&gt;
 element_count=${#arr[*]}&lt;br /&gt;
&lt;br /&gt;
 local i&lt;br /&gt;
 local rowcheck&lt;br /&gt;
&lt;br /&gt;
 for ((i=0; i&amp;lt;$elementcount; i++))&lt;br /&gt;
 do&lt;br /&gt;
  # Символ перевода строки — в конец каждой строки.&lt;br /&gt;
  let &amp;quot;rowcheck = $i % ROWS&amp;quot;&lt;br /&gt;
  if [ &amp;quot;$rowcheck&amp;quot; -eq 0 ]&lt;br /&gt;
  then&lt;br /&gt;
   echo                           # Перевод строки.&lt;br /&gt;
   echo -n &amp;quot;      &amp;quot;               # Выравнивание.&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
 cell=${arr[i]}&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$cell&amp;quot; = . ]&lt;br /&gt;
 then&lt;br /&gt;
  let &amp;quot;alive += 1&amp;quot;&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 echo -n &amp;quot;$cell&amp;quot; | sed -e 's/_/ /g'&lt;br /&gt;
 # Вывести массив, по пути заменяя символы подчеркивания на пробелы.&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
return&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
IsValid ()                       # Проверка корректности координат ячейки.&lt;br /&gt;
{&lt;br /&gt;
 if [ -z &amp;quot;$1&amp;quot; -o -z &amp;quot;$2&amp;quot; ]       # Проверка наличия входных аргументов.&lt;br /&gt;
 then&lt;br /&gt;
  return $FALSE&lt;br /&gt;
 fi&lt;br /&gt;
 local row&lt;br /&gt;
 local lower_limit=0             # Запрет на отрицательные координаты.&lt;br /&gt;
 local upper_limit&lt;br /&gt;
 local leftlocal right&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;upper_limit = $ROWS * $COLS - 1&amp;quot; # Номер последней ячейки на игровом поле.&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$1&amp;quot; -lt &amp;quot;$lower_limit&amp;quot; -o &amp;quot;$1&amp;quot; -gt &amp;quot;$upper_limit&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return $FALSE                   # Выход за границы массива.&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 row=$2&lt;br /&gt;
 let &amp;quot;left = $row * $ROWS&amp;quot;         # Левая граница.&lt;br /&gt;
 let &amp;quot;right = $left + $COLS - 1&amp;quot;   # Правая граница.&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$1&amp;quot; -lt &amp;quot;$left&amp;quot; -o &amp;quot;$1&amp;quot; -gt &amp;quot;$right&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  return $FALSE                    # Выход за нижнюю строку.&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 return $TRUE # Координаты корректны.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
IsAlive ()                         # Проверка наличия &amp;quot;живой&amp;quot; особи в ячейке.&lt;br /&gt;
                                   # Принимает массив и номер ячейки в качестве входных аргументов.&lt;br /&gt;
{&lt;br /&gt;
 GetCount &amp;quot;$1&amp;quot; $2                  # Подсчитать кол-во &amp;quot;живых&amp;quot; соседей.&lt;br /&gt;
 local nhbd=$?&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$nhbd&amp;quot; -eq &amp;quot;$BIRTH&amp;quot; ]       # &amp;quot;Живая&amp;quot;.&lt;br /&gt;
 then&lt;br /&gt;
  return $ALIVE&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 if [ &amp;quot;$3&amp;quot; = &amp;quot;.&amp;quot; -a &amp;quot;$nhbd&amp;quot; -eq &amp;quot;$SURVIVE&amp;quot; ]&lt;br /&gt;
 then                              # &amp;quot;Живая&amp;quot; если перед этим была &amp;quot;живая&amp;quot;.&lt;br /&gt;
  return $ALIVE&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 return $DEAD                      # По-умолчанию.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
GetCount ()                        # Подсчёт &amp;quot;живых&amp;quot; соседей.&lt;br /&gt;
                                   # Необходимо 2 аргумента:&lt;br /&gt;
                                   # $1) переменная-массив&lt;br /&gt;
                                   # $2) cell номер ячейки&lt;br /&gt;
{&lt;br /&gt;
 local cell_number=$2&lt;br /&gt;
 local array&lt;br /&gt;
 local top &lt;br /&gt;
 local center &lt;br /&gt;
 local bottom &lt;br /&gt;
 local r &lt;br /&gt;
 local row &lt;br /&gt;
 local i &lt;br /&gt;
 local t_top &lt;br /&gt;
 local t_cen &lt;br /&gt;
 local t_bot &lt;br /&gt;
 local count=0&lt;br /&gt;
 local ROW_NHBD=3&lt;br /&gt;
&lt;br /&gt;
 array=( `echo &amp;quot;$1&amp;quot;` )&lt;br /&gt;
 &lt;br /&gt;
 let &amp;quot;top = $cell_number - $COLS - 1&amp;quot; # Номера соседних ячеек.&lt;br /&gt;
 let &amp;quot;center = $cell_number - 1&amp;quot;&lt;br /&gt;
 let &amp;quot;bottom = $cell_number + $COLS - 1&amp;quot;&lt;br /&gt;
 let &amp;quot;r = $cell_number / $ROWS&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 for ((i=0; i&amp;lt;$ROW_NHBD; i++))        # Просмотр слева-направо.&lt;br /&gt;
 do&lt;br /&gt;
  let &amp;quot;t_top = $top + $i&amp;quot;&lt;br /&gt;
  let &amp;quot;t_cen = $center + $i&amp;quot;&lt;br /&gt;
  let &amp;quot;t_bot = $bottom + $i&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  let &amp;quot;row = $r&amp;quot;                      # Пройти по соседям в средней строке.&lt;br /&gt;
  IsValid $t_cen $row                 # Координаты корректны?&lt;br /&gt;
  if [ $? -eq &amp;quot;$TRUE&amp;quot; ]&lt;br /&gt;
  then&lt;br /&gt;
   if [ ${array[$t_cen]} = &amp;quot;$ALIVE1&amp;quot; ] # &amp;quot;Живая&amp;quot;?&lt;br /&gt;
   then                                # Да!&lt;br /&gt;
    let &amp;quot;count += 1&amp;quot;                   # Нарастить счётчик.&lt;br /&gt;
   fi&lt;br /&gt;
  fi&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;row = $r - 1&amp;quot;                    # По верхней строке.&lt;br /&gt;
 IsValid $t_top $row&lt;br /&gt;
 if [ $? -eq &amp;quot;$TRUE&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  if [ ${array[$t_top]} = &amp;quot;$ALIVE1&amp;quot; ]&lt;br /&gt;
  then&lt;br /&gt;
   let &amp;quot;count += 1&amp;quot;&lt;br /&gt;
  fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;row = $r + 1&amp;quot; # По нижней строке.&lt;br /&gt;
 IsValid $t_bot $row&lt;br /&gt;
 if [ $? -eq &amp;quot;$TRUE&amp;quot; ]&lt;br /&gt;
 then&lt;br /&gt;
  if [ ${array[$t_bot]} = &amp;quot;$ALIVE1&amp;quot; ]&lt;br /&gt;
  then&lt;br /&gt;
   let &amp;quot;count += 1&amp;quot;&lt;br /&gt;
  fi&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
if [ ${array[$cell_number]} = &amp;quot;$ALIVE1&amp;quot; ]&lt;br /&gt;
then&lt;br /&gt;
 let &amp;quot;count -= 1&amp;quot;                         # Убедиться, что сама проверяемая ячейка&lt;br /&gt;
fi                                        # не была подсчитана.&lt;br /&gt;
&lt;br /&gt;
return $count&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
next_gen ()                               # Обновить массив, в котором содержится информация о новом &amp;quot;поколении&amp;quot;.&lt;br /&gt;
{&lt;br /&gt;
local array&lt;br /&gt;
local i=0&lt;br /&gt;
&lt;br /&gt;
array=( `echo &amp;quot;$1&amp;quot;` )                     # Преобразовать в массив.&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$i&amp;quot; -lt &amp;quot;$cells&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 IsAlive &amp;quot;$1&amp;quot; $i ${array[$i]}             # &amp;quot;Живая&amp;quot;?&lt;br /&gt;
 if [ $? -eq &amp;quot;$ALIVE&amp;quot; ]&lt;br /&gt;
 then                                     # Если &amp;quot;живая&amp;quot;, то&lt;br /&gt;
  array[$i]=.                             # записать точку.&lt;br /&gt;
 else&lt;br /&gt;
  array[$i]=&amp;quot;_&amp;quot;                           # Иначе — символ подчеркивания&lt;br /&gt;
 fi                                       # (который позднее заменится на пробел).&lt;br /&gt;
 let &amp;quot;i += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# let &amp;quot;generation += 1&amp;quot;                   # Увеличить счетчик поколений.&lt;br /&gt;
&lt;br /&gt;
# Подготовка переменных, для передачи в функцию &amp;quot;display&amp;quot;.&lt;br /&gt;
avar=`echo ${array[@]}`                   # Преобразовать массив в строку.&lt;br /&gt;
display &amp;quot;$avar&amp;quot;                           # Вывести его.&lt;br /&gt;
echo; echo&lt;br /&gt;
echo &amp;quot;Поколение $generation — живых особей $alive&amp;quot;&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;$alive&amp;quot; -eq 0 ]&lt;br /&gt;
then&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;Преждевременное завершение: не осталось ни одной живой особи!&amp;quot;&lt;br /&gt;
 exit $NONE_ALIVE                          # Нет смысла продолжать&lt;br /&gt;
fi                                         # если не осталось ни одной живой особи&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# =========================================================&lt;br /&gt;
&lt;br /&gt;
# main ()&lt;br /&gt;
&lt;br /&gt;
# Загрузить начальное поколение из файла.&lt;br /&gt;
initial=( `cat &amp;quot;$startfile&amp;quot; | sed -e '/#/d' | tr -d '\n' |\&lt;br /&gt;
sed -e 's/\./\. /g' -e 's/_/_ /g'` )&lt;br /&gt;
# Удалить строки, начинающиеся с символа '#' — комментарии.&lt;br /&gt;
# Удалить строки перевода строки и вставить пробелы между элементами.&lt;br /&gt;
&lt;br /&gt;
clear                                       # Очистка экрана.&lt;br /&gt;
&lt;br /&gt;
echo # Заголовок&lt;br /&gt;
echo &amp;quot;=======================&amp;quot;&lt;br /&gt;
echo &amp;quot; $GENERATIONS поколений&amp;quot;&lt;br /&gt;
echo &amp;quot; в&amp;quot;&lt;br /&gt;
echo &amp;quot; игре \&amp;quot; ЖИЗНЬ\&amp;quot;&amp;quot;&lt;br /&gt;
echo &amp;quot;=======================&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# -------- Вывести первое поколение. --------&lt;br /&gt;
Gen0=`echo ${initial[@]}`&lt;br /&gt;
display &amp;quot;$Gen0&amp;quot;                              # Только вывод.&lt;br /&gt;
echo; echo&lt;br /&gt;
echo &amp;quot;Поколение $generation — живых особей $alive&amp;quot;&lt;br /&gt;
# -------------------------------------------&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;generation += 1&amp;quot;                        # Нарастить счётчик поколений.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# ------- Вывести второе поколение. -------&lt;br /&gt;
Cur=`echo ${initial[@]}`&lt;br /&gt;
next_gen &amp;quot;$Cur&amp;quot;                               # Обновить и вывести.&lt;br /&gt;
# ------------------------------------------&lt;br /&gt;
&lt;br /&gt;
let &amp;quot;generation += 1&amp;quot;                         # Нарастить счётчик поколений.&lt;br /&gt;
&lt;br /&gt;
# ------ Основной цикл игры ------&lt;br /&gt;
while [ &amp;quot;$generation&amp;quot; -le &amp;quot;$GENERATIONS&amp;quot; ]&lt;br /&gt;
do&lt;br /&gt;
 Cur=&amp;quot;$avar&amp;quot;&lt;br /&gt;
 next_gen &amp;quot;$Cur&amp;quot;&lt;br /&gt;
 let &amp;quot;generation += 1&amp;quot;&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# ==============================================================&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
# --------------------------------------------------------------&lt;br /&gt;
# Этот сценарий имеет недоработку.&lt;br /&gt;
# Граничные ячейки сверху, снизу и с боков остаются пустыми.&lt;br /&gt;
# Упражнение: Доработайте сценарий таким образом, чтобы&lt;br /&gt;
# левая и правая стороны как бы &amp;quot;соприкасались&amp;quot;,&lt;br /&gt;
# так же и верхняя и нижняя стороны.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-12. Файл с первым поколением для игры &amp;quot;Жизнь&amp;quot;.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Это файл-пример, содержащий &amp;quot;поколение 0&amp;quot;, для сценария &amp;quot;life.sh&amp;quot;.&lt;br /&gt;
# --------------------------------------------------------------&lt;br /&gt;
# Игровое поле имеет размер 10 x 10, точкой обозначается &amp;quot;живая&amp;quot; особь,&lt;br /&gt;
# символом подчеркивания — пустая ячейка. Мы не можем использовать пробелы,&lt;br /&gt;
# для обозначения пустых ячеек, из-за особенностей строения массивов в Bash.&lt;br /&gt;
# [Упражнение для читателей: объясните, почему?]&lt;br /&gt;
#&lt;br /&gt;
# Строки, начинающиеся с символа '#' считаются комментариями, сценарий их игнорирует.&lt;br /&gt;
__.__..___&lt;br /&gt;
___._.____&lt;br /&gt;
____.___..&lt;br /&gt;
_._______.&lt;br /&gt;
____._____&lt;br /&gt;
..__...___&lt;br /&gt;
____._____&lt;br /&gt;
___...____&lt;br /&gt;
__.._..___&lt;br /&gt;
_..___..__&lt;br /&gt;
+++&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Следующие два сценария предоставил ''Mark Moraes'', из университета в Торонто. См. файл &amp;quot;Moraes-COPYRIGHT&amp;quot;, который содержит указание на авторские права.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-13. behead: Удаление заголовков из электронных писем и новостей.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/sh&lt;br /&gt;
# Удаление заголовков из электронных писем и новостей т.е. до первой&lt;br /&gt;
# пустой строки# Mark Moraes, Университет в Торонто&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; Такие комментарии добавлены автором документа.&lt;br /&gt;
&lt;br /&gt;
if [ $# -eq 0 ]; then&lt;br /&gt;
# ==&amp;gt; Если входной аргумент не задан (файл), то выводить результат на stdin.&lt;br /&gt;
 sed -e '1,/^$/d' -e '/^[ ]*$/d'&lt;br /&gt;
 # --&amp;gt; Удалить пустые строки и все строки предшествующие им&lt;br /&gt;
else&lt;br /&gt;
# ==&amp;gt; Если аргумент командной строки задан, то использовать его как имя файла.&lt;br /&gt;
 for i do&lt;br /&gt;
  sed -e '1,/^$/d' -e '/^[ ]*$/d' $i&lt;br /&gt;
  # --&amp;gt; То же, что и выше.&lt;br /&gt;
 done&lt;br /&gt;
fi&lt;br /&gt;
# ==&amp;gt; Упражнение: Добавьте проверку на наличие ошибок.&lt;br /&gt;
# ==&amp;gt;&lt;br /&gt;
# ==&amp;gt; Обратите внимание — как похожи маленькие сценарии sed, за исключением передачи аргумента.&lt;br /&gt;
# ==&amp;gt; Можно ли его оформит в виде функции? Почему да или почему нет?&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-14. ftpget: Скачивание файлов по ftp.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/sh&lt;br /&gt;
# $Id: ftpget,v 1.2 91/05/07 21:15:43 moraes Exp $&lt;br /&gt;
# Сценарий устанавливает анонимное соединение с ftp-сервером.&lt;br /&gt;
# Простой и быстрый - написан как дополнение к ftplist&lt;br /&gt;
# -h — удалённый сервер (по-умолчанию prep.ai.mit.edu)&lt;br /&gt;
# -d -- каталог на сервере - вы можете указать последовательность из нескольких ключей -d\&lt;br /&gt;
# Если вы используете относительные пути,&lt;br /&gt;
# будьте внимательны при задании последовательности.&lt;br /&gt;
# (по-умолчанию — каталог пользователя ftp)&lt;br /&gt;
# -v — &amp;quot;многословный&amp;quot; режим, будет показывать все ответы ftp-сервера&lt;br /&gt;
# -f — file[:localfile] скачивает удаленный file и записывает под именем localfile&lt;br /&gt;
# -m — шаблон для mget. Не забудьте взять в кавычки!&lt;br /&gt;
# -c — локальный каталог# Например,&lt;br /&gt;
# ftpget -h expo.lcs.mit.edu -d contrib -f xplaces.shar:xplaces.sh \&lt;br /&gt;
#  -d ../pub/R3/fixes -c ~/fixes -m 'fix*'&lt;br /&gt;
# Эта команда загрузит файл xplaces.shar из ~ftp/contrib с expo.lcs.mit.edu&lt;br /&gt;
# и сохранит под именем xplaces.sh в текущем каталоге, затем заберет все исправления (fixes)&lt;br /&gt;
# из ~ftp/pub/R3/fixes и поместит их в каталог ~/fixes.&lt;br /&gt;
# Очевидно, что последовательность ключей и аргументов очень важна, поскольку&lt;br /&gt;
# она определяет последовательность операций, выполняемых с удаленным ftp-сервером&lt;br /&gt;
#&lt;br /&gt;
# Mark Moraes (moraes@csri.toronto.edu), Feb 1, 1989&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; Эти комментарии добавлены автором документа.&lt;br /&gt;
&lt;br /&gt;
# PATH=/local/bin:/usr/ucb:/usr/bin:/bin&lt;br /&gt;
# export PATH&lt;br /&gt;
# ==&amp;gt; Первые две строки в оригинальном сценарии вероятно излишни.&lt;br /&gt;
&lt;br /&gt;
TMPFILE=/tmp/ftp.$$&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; Создан временный файл&lt;br /&gt;
SITE=`domainname`.toronto.edu&lt;br /&gt;
# ==&amp;gt; 'domainname' подобен 'hostname'&lt;br /&gt;
usage=&amp;quot;Порядок использования: $0 [-h удаленный_сервер] [-d удаленный_каталог]... [-f удаленный_файл:локальный_файл]... \&lt;br /&gt;
                              [-c локальный_каталог] [-m шаблон_имен_файлов] [-v]&amp;quot;&lt;br /&gt;
ftpflags=&amp;quot;-i -n&amp;quot;&lt;br /&gt;
verbflag=&lt;br /&gt;
set -f                 # разрешить подстановку имен файлов (globbing) для опции -m&lt;br /&gt;
set x `getopt vh:d:c:m:f: $*`&lt;br /&gt;
if [ $? != 0 ]; then&lt;br /&gt;
 echo $usage&lt;br /&gt;
 exit 65&lt;br /&gt;
fi&lt;br /&gt;
shift&lt;br /&gt;
trap 'rm -f ${TMPFILE} ; exit' 0 1 2 3 15&lt;br /&gt;
echo &amp;quot;user anonymous ${USER-gnu}@${SITE} &amp;gt; ${TMPFILE}&amp;quot;&lt;br /&gt;
# ==&amp;gt; Добавлены кавычки (рекомендуется).&lt;br /&gt;
echo binary &amp;gt;&amp;gt; ${TMPFILE}&lt;br /&gt;
for i in $* # ==&amp;gt; Разбор командной строки.&lt;br /&gt;
do&lt;br /&gt;
 case $i in&lt;br /&gt;
 -v) verbflag=-v; echo hash &amp;gt;&amp;gt; ${TMPFILE}; shift;;&lt;br /&gt;
 -h) remhost=$2; shift 2;;&lt;br /&gt;
 -d) echo cd $2 &amp;gt;&amp;gt; ${TMPFILE};&lt;br /&gt;
     if [ x${verbflag} != x ]; then&lt;br /&gt;
      echo pwd &amp;gt;&amp;gt; ${TMPFILE};&lt;br /&gt;
     fi;&lt;br /&gt;
     shift 2;;&lt;br /&gt;
 -c) echo lcd $2 &amp;gt;&amp;gt; ${TMPFILE}; shift 2;;&lt;br /&gt;
 -m) echo mget &amp;quot;$2&amp;quot; &amp;gt;&amp;gt; ${TMPFILE}; shift 2;;&lt;br /&gt;
 -f) f1=`expr &amp;quot;$2&amp;quot; : &amp;quot;\([^:]*\).*&amp;quot;`; f2=`expr &amp;quot;$2&amp;quot; : &amp;quot;[^:]*:\(.*\)&amp;quot;`;&lt;br /&gt;
     echo get ${f1} ${f2} &amp;gt;&amp;gt; ${TMPFILE}; shift 2;;&lt;br /&gt;
 --) shift; break;;&lt;br /&gt;
 esac&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
if [ $# -ne 0 ]; then&lt;br /&gt;
 echo $usage&lt;br /&gt;
 exit 65 # ==&amp;gt; В оригинале было &amp;quot;exit 2&amp;quot;, изменено в соответствии со стандартами.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ x${verbflag} != x ]; then&lt;br /&gt;
 ftpflags=&amp;quot;${ftpflags} -v&amp;quot;&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ x${remhost} = x ]; then&lt;br /&gt;
 remhost=prep.ai.mit.edu&lt;br /&gt;
 # ==&amp;gt; Здесь можете указать свой ftp-сервер по-умолчанию.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
echo quit &amp;gt;&amp;gt; ${TMPFILE}&lt;br /&gt;
# ==&amp;gt; Все команды сохранены во временном файле.&lt;br /&gt;
ftp ${ftpflags} ${remhost} &amp;lt; ${TMPFILE}&lt;br /&gt;
# ==&amp;gt; Теперь обработать пакетный файл.&lt;br /&gt;
&lt;br /&gt;
rm -f ${TMPFILE}&lt;br /&gt;
# ==&amp;gt; В заключение, удалить временный файл (можно скопировать его в системный журнал).&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; Упражнения:&lt;br /&gt;
# ==&amp;gt; ----------&lt;br /&gt;
# ==&amp;gt; 1) Добавьте обработку ошибок.&lt;br /&gt;
# ==&amp;gt; 2) Добавьте уведомление звуковым сигналом.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-15. Указание на авторские права.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
Следующее соглашение об авторских правах относится к двум, включенным в книгу,сценариям от Mark Moraes: &amp;quot;behead.sh&amp;quot; и &amp;quot;ftpget.sh&amp;quot;&lt;br /&gt;
/*&lt;br /&gt;
 * Copyright University of Toronto 1988, 1989.&lt;br /&gt;
 * Автор: Mark Moraes&lt;br /&gt;
 *&lt;br /&gt;
 * Автор даёт право на использование этого программного обеспечения&lt;br /&gt;
 * его изменение и распространение со следующими ограничениями:&lt;br /&gt;
 *&lt;br /&gt;
 * 1. Автор и Университет Торонто не отвечают за&lt;br /&gt;
 *    последствия использования этого программного&lt;br /&gt;
 *    обеспечения, какими ужасными бы они ни были,&lt;br /&gt;
 *    даже если эти последствия вызваны ошибками&lt;br /&gt;
 *    в данном программном обеспечении.&lt;br /&gt;
 *&lt;br /&gt;
 * 2. Указание на происхождение программного обеспечения&lt;br /&gt;
 *    не должно подвергаться изменениям, явно или по&lt;br /&gt;
 *    оплошности. Так как некоторые пользователи обращаются&lt;br /&gt;
 *    к исходным текстам, они обязательно должны быть&lt;br /&gt;
 *    включены в состав документа.&lt;br /&gt;
 *&lt;br /&gt;
 * 3. Измененная версия должна содержать явное упоминание&lt;br /&gt;
 *    об этом и не должна выдаваться за оригинал.&lt;br /&gt;
 *    Так как некоторые пользователи обращаются к исходным текстам,&lt;br /&gt;
 *    они обязательно должны быть включены в состав документа.&lt;br /&gt;
 *&lt;br /&gt;
 * 4. Это соглашение не может удаляться и/или изменяться.&lt;br /&gt;
 */&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;+&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Antek Sawicki предоставил следующий сценарий, который демонстрирует операцию подстановки параметров.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-16. password: Генератор случайного 8-ми символьного пароля.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Для старых систем может потребоваться указать #!/bin/bash2.&lt;br /&gt;
#&lt;br /&gt;
# Генератор случайных паролей для bash 2.x&lt;br /&gt;
# Автор: Antek Sawicki &amp;lt;tenox@tenox.tc&amp;gt;,&lt;br /&gt;
# который великодушно позволил использовать его в данном документе.&lt;br /&gt;
#&lt;br /&gt;
#==&amp;gt; Комментарии, добавленные автором документа ==&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MATRIX=&amp;quot;0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&amp;quot;&lt;br /&gt;
LENGTH=&amp;quot;8&amp;quot;&lt;br /&gt;
# ==&amp;gt; 'LENGTH' можно увеличить, для генерации более длинных паролей.&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;${n:=1}&amp;quot; -le &amp;quot;$LENGTH&amp;quot; ]&lt;br /&gt;
# ==&amp;gt; Напоминаю, что &amp;quot;:=&amp;quot; — это оператор &amp;quot;подстановки значения по-умолчанию&amp;quot;.&lt;br /&gt;
# ==&amp;gt; Таким образом, если 'n' не инициализирована, то в неё заносится 1.&lt;br /&gt;
do&lt;br /&gt;
 PASS=&amp;quot;$PASS${MATRIX:$(($RANDOM%${#MATRIX})):1}&amp;quot;&lt;br /&gt;
 # ==&amp;gt; Хитро, хитро....&lt;br /&gt;
&lt;br /&gt;
 # ==&amp;gt; Начнём с самых внутренних скобок...&lt;br /&gt;
 # ==&amp;gt; ${#MATRIX} — возвращает длину массива MATRIX.&lt;br /&gt;
 # ==&amp;gt; $RANDOM%${#MATRIX} — возвращает случайное число&lt;br /&gt;
 # ==&amp;gt; в диапазоне 1 .. ДЛИНА_МАССИВА(MATRIX) - 1.&lt;br /&gt;
&lt;br /&gt;
 # ==&amp;gt; ${MATRIX:$(($RANDOM%${#MATRIX})):1}&lt;br /&gt;
 # ==&amp;gt; возвращает символ из MATRIX, из случайной позиции (найденной выше).&lt;br /&gt;
 # ==&amp;gt; См. подстановку параметров {var:pos:len} в Разделе 3.3.1&lt;br /&gt;
 # ==&amp;gt; и примеры в этом разделе.&lt;br /&gt;
 # ==&amp;gt; PASS=... -- добавление символа к строке PASS, полученной на предыдущих итерациях.&lt;br /&gt;
&lt;br /&gt;
 # ==&amp;gt; Чтобы детальнее проследить ход работы цикла, раскомментируйте следующую строку&lt;br /&gt;
 # ==&amp;gt;            echo &amp;quot;$PASS&amp;quot;&lt;br /&gt;
 # ==&amp;gt; Вы увидите, как на каждом проходе цикла,&lt;br /&gt;
 # ==&amp;gt; к строке PASS добавляется по одному символу.&lt;br /&gt;
&lt;br /&gt;
 let n+=1&lt;br /&gt;
 # ==&amp;gt; Увеличить 'n' перед началом следующей итерации.&lt;br /&gt;
&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;$PASS&amp;quot; # ==&amp;gt; Или перенаправьте в файл, если пожелаете.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;+&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''James R. Van Zandt'' предоставил следующий сценарий, который демонстрирует применение именованных каналов, по его словам, &amp;quot;на самом деле — упражнение на применение кавычек и на экранирование&amp;quot;.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-17. fifo: Создание резервных копий с помощью именованных каналов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ==&amp;gt; Автор:James R. Van Zandt&lt;br /&gt;
# ==&amp;gt; используется с его разрешения.&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; Комментарии, добавленные автором документа.&lt;br /&gt;
&lt;br /&gt;
HERE=`uname -n`     # ==&amp;gt; hostname&lt;br /&gt;
THERE=bilbo&lt;br /&gt;
echo &amp;quot;начало создания резервной копии на $THERE, за `date +%r`&amp;quot;&lt;br /&gt;
# ==&amp;gt; `date +%r` возвращает время в 12-ти часовом формате, т.е. &amp;quot;08:08:34 PM&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# убедиться в том, что /pipe — это действительно канал, а не простой файл&lt;br /&gt;
rm -rf /pipe&lt;br /&gt;
mkfifo /pipe # ==&amp;gt; Создание &amp;quot;именованного канала&amp;quot;, с именем &amp;quot;/pipe&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; 'su xyz' — запускает команду от имени пользователя &amp;quot;xyz&amp;quot;.&lt;br /&gt;
# ==&amp;gt; 'ssh' — вызов secure shell (вход на удаленную систему).&lt;br /&gt;
su xyz -c &amp;quot;ssh $THERE \&amp;quot;cat &amp;gt;/home/xyz/backup/${HERE}-daily.tar.gz\&amp;quot; &amp;lt; /pipe&amp;quot;&amp;amp;&lt;br /&gt;
cd /&lt;br /&gt;
tar -czf - bin boot dev etc home info lib man root sbin share usr var &amp;gt;/pipe&lt;br /&gt;
# ==&amp;gt; Именованный канал /pipe, используется для передачи данных между процессами:&lt;br /&gt;
# ==&amp;gt; 'tar/gzip' пишет в /pipe, а 'ssh' -- читает из /pipe.&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; В результате будет получена резервная копия всех основных каталогов.&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; В чём состоит преимущество именованного канала, в данной ситуации,&lt;br /&gt;
# ==&amp;gt; перед неименованным каналом &amp;quot;|&amp;quot; ?&lt;br /&gt;
# ==&amp;gt; Будет ли работать неименованный канал в данной ситуации?&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;+&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Stephane Chazelas'' предоставил следующий сценарий, который демонстрирует возможность генерации простых чисел без использования массивов.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-18. Генерация простых чисел, с использованием оператора деления по модулю(остаток от деления).'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# primes.sh: Генерация простых чисел, без использования массивов.&lt;br /&gt;
# Автор: Stephane Chazelas.&lt;br /&gt;
&lt;br /&gt;
# Этот сценарий не использует классический алгоритм &amp;quot;Решето Эратосфена&amp;quot;,&lt;br /&gt;
# вместо него используется более понятный метод проверки каждого кандидата в простые числа&lt;br /&gt;
# путём поиска делителей, с помощью оператора нахождения остатка от деления &amp;quot;%&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
LIMIT=1000               # Простые от 2 до 1000&lt;br /&gt;
&lt;br /&gt;
Primes()&lt;br /&gt;
{&lt;br /&gt;
 (( n = $1 + 1 ))        # Перейти к следующему числу.&lt;br /&gt;
 shift                   # Следующий параметр в списке.&lt;br /&gt;
 # echo &amp;quot;_n=$n i=$i_&amp;quot;&lt;br /&gt;
 if (( n == LIMIT ))&lt;br /&gt;
 then&lt;br /&gt;
  echo $*&lt;br /&gt;
 return&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 for i; do                 # &amp;quot;i&amp;quot; устанавливается в &amp;quot;@&amp;quot;, предыдущее значение $n.&lt;br /&gt;
# echo &amp;quot;-n=$n i=$i-&amp;quot;&lt;br /&gt;
 (( i * i &amp;gt; n )) &amp;amp;&amp;amp; break  # Оптимизация.&lt;br /&gt;
 (( n % i )) &amp;amp;&amp;amp; continue   # Отсечь составное число с помощью оператора &amp;quot;%&amp;quot;.&lt;br /&gt;
 Primes $n $@              # Рекурсивный вызов внутри цикла.&lt;br /&gt;
 return&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
 Primes $n $@ $n           # Рекурсивный вызов за пределами цикла.&lt;br /&gt;
                           # Последовательное накопление позиционных параметров.&lt;br /&gt;
                           # в &amp;quot;$@&amp;quot; накапливаются простые числа.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Primes 1&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&lt;br /&gt;
# Раскомментируйте строки 16 и 24, это поможет понять суть происходящего.&lt;br /&gt;
&lt;br /&gt;
# Сравните скоростные характеристики этого сценария и сценария (ex68.sh),&lt;br /&gt;
# реализующего алгоритм &amp;quot;Решето Эратосфена&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
# Упражнение: Попробуйте реализовать этот сценарий без использования рекурсии.&lt;br /&gt;
# Это даст некоторый выигрыш в скорости.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;+&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Jordi Sanfeliu'' дал согласие на публикацию своего сценария '''tree'''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-19. tree: Вывод дерева каталогов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# @(#) tree 1.1 30/11/95 by Jordi Sanfeliu&lt;br /&gt;
# email: mikaku@fiwix.org&lt;br /&gt;
#&lt;br /&gt;
# Начальная версия: 1.0 30/11/95&lt;br /&gt;
# Следующая версия: 1.1 24/02/97 Now, with symbolic links&lt;br /&gt;
# Исправления : Ian Kjos, поддержка недоступных каталогов&lt;br /&gt;
# email: beth13@mail.utexas.edu&lt;br /&gt;
#&lt;br /&gt;
# Tree — средство просмотра дерева каталогов (очевидно :-) )&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
# ==&amp;gt; Используется в данном документе с разрешения автора сценария, Jordi Sanfeliu.&lt;br /&gt;
# ==&amp;gt; Комментарии, добавленные автором документа.&lt;br /&gt;
# ==&amp;gt; Добавлено &amp;quot;окавычивание&amp;quot; аргументов.&lt;br /&gt;
&lt;br /&gt;
search ()&lt;br /&gt;
{&lt;br /&gt;
 for dir in `echo *`&lt;br /&gt;
 # ==&amp;gt; `echo *` список всех файлов в текущем каталоге, без символов перевода строки.&lt;br /&gt;
 # ==&amp;gt; Тот же эффект дает for dir in *&lt;br /&gt;
 # ==&amp;gt; но &amp;quot;dir in `echo *`&amp;quot; не обрабатывает файлы, чьи имена содержат пробелы.&lt;br /&gt;
 do&lt;br /&gt;
  if [ -d &amp;quot;$dir&amp;quot; ] ; then # ==&amp;gt; Если это каталог (-d)...&lt;br /&gt;
   zz=0 # ==&amp;gt; Временная переменная, для сохранения уровня вложенности каталога.&lt;br /&gt;
   while [ $zz != $deep ] # Keep track of inner nested loop.&lt;br /&gt;
    do&lt;br /&gt;
     echo -n &amp;quot;| &amp;quot; # ==&amp;gt; Показать символ вертикальной связи,&lt;br /&gt;
                  # ==&amp;gt; с 2 пробелами и без перевода строки.&lt;br /&gt;
     zz=`expr $zz + 1` # ==&amp;gt; Нарастить zz.&lt;br /&gt;
    done&lt;br /&gt;
    if [ -L &amp;quot;$dir&amp;quot; ] ; then # ==&amp;gt; Если символическая ссылка на каталог...&lt;br /&gt;
     echo &amp;quot;+---$dir&amp;quot; `ls -l $dir | sed 's/^.*'$dir' //'`&lt;br /&gt;
     # ==&amp;gt; Показать горизонтальный соединитель и имя связянного каталога, но...&lt;br /&gt;
     # ==&amp;gt; без указания даты/времени.&lt;br /&gt;
    else&lt;br /&gt;
     echo &amp;quot;+---$dir&amp;quot; # ==&amp;gt; Вывести горизонтальный соединитель...&lt;br /&gt;
                     # ==&amp;gt; и название каталога.&lt;br /&gt;
     if cd &amp;quot;$dir&amp;quot; ; then # ==&amp;gt; Если можно войти в каталог...&lt;br /&gt;
      deep=`expr $deep + 1` # ==&amp;gt; Нарастить уровень вложенности.&lt;br /&gt;
      search # рекурсия ;-)&lt;br /&gt;
      numdirs=`expr $numdirs + 1` # ==&amp;gt; Нарастить счетчик каталогов.&lt;br /&gt;
     fi&lt;br /&gt;
    fi&lt;br /&gt;
  fi&lt;br /&gt;
 done&lt;br /&gt;
 cd .. # ==&amp;gt; Подняться на один уровень вверх.&lt;br /&gt;
 if [ &amp;quot;$deep&amp;quot; ] ; then # ==&amp;gt; Если depth = 0 (возвращает TRUE)...&lt;br /&gt;
  swfi=1 # ==&amp;gt; выставить признак окончания поиска.&lt;br /&gt;
 fi&lt;br /&gt;
 deep=`expr $deep - 1` # ==&amp;gt; Уменьшить уровень вложенности.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# - Main -&lt;br /&gt;
if [ $# = 0 ] ; then&lt;br /&gt;
 cd `pwd` # ==&amp;gt; Если аргумент командной строки отсутствует, то используется текущий каталог.&lt;br /&gt;
else&lt;br /&gt;
 cd $1 # ==&amp;gt; иначе перейти в заданный каталог.&lt;br /&gt;
fi&lt;br /&gt;
echo &amp;quot;Начальный каталог = `pwd`&amp;quot;&lt;br /&gt;
swfi=0 # ==&amp;gt; Признак завершения поиска.&lt;br /&gt;
deep=0 # ==&amp;gt; Уровень вложенности.&lt;br /&gt;
numdirs=0&lt;br /&gt;
zz=0&lt;br /&gt;
&lt;br /&gt;
while [ &amp;quot;$swfi&amp;quot; != 1 ] # Пока поиск не закончен...&lt;br /&gt;
do&lt;br /&gt;
 search # ==&amp;gt; Вызвать функцию поиска.&lt;br /&gt;
done&lt;br /&gt;
echo &amp;quot;Всего каталогов = $numdirs&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
# ==&amp;gt; Попробуйте разобраться в том как этот сценарий работает.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Noah Friedman'' дал разрешение на публикацию своей библиотеки функций для работы со строками, которая, по сути, воспроизводит некоторые библиотечные функции языка ''C''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-20. Функции для работы со строками.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# string.bash --- эмуляция библиотеки функций string(3)&lt;br /&gt;
# Автор: Noah Friedman &amp;lt;friedman@prep.ai.mit.edu&amp;gt;&lt;br /&gt;
# ==&amp;gt; Используется с его разрешения.&lt;br /&gt;
# Дата создания: 1992-07-01&lt;br /&gt;
# Дата последней модификации: 1993-09-29&lt;br /&gt;
# Public domain&lt;br /&gt;
# Преобразование в синтаксис bash v2 выполнил Chet Ramey&lt;br /&gt;
# Комментарий:&lt;br /&gt;
# Код:&lt;br /&gt;
&lt;br /&gt;
#:docstring strcat:&lt;br /&gt;
# Порядок использования: strcat s1 s2&lt;br /&gt;
#&lt;br /&gt;
# Strcat добавляет содержимое переменной s2 к переменной s1.&lt;br /&gt;
#&lt;br /&gt;
# Пример:&lt;br /&gt;
#        a=&amp;quot;foo&amp;quot;&lt;br /&gt;
#        b=&amp;quot;bar&amp;quot;&lt;br /&gt;
#        strcat a b&lt;br /&gt;
#        echo $a&lt;br /&gt;
#        =&amp;gt; foobar&lt;br /&gt;
#&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strcat ()&lt;br /&gt;
{&lt;br /&gt;
 local s1_val s2_val&lt;br /&gt;
 s1_val=${!1} # косвенная ссылка&lt;br /&gt;
 s2_val=${!2}&lt;br /&gt;
 eval &amp;quot;$1&amp;quot;=\'&amp;quot;${s1_val}${s2_val}&amp;quot;\'&lt;br /&gt;
 # ==&amp;gt; eval $1='${s1_val}${s2_val}' во избежание проблем,&lt;br /&gt;
 # ==&amp;gt; если одна из переменных содержит одиночную кавычку.&lt;br /&gt;
}&lt;br /&gt;
#:docstring strncat:&lt;br /&gt;
# Порядок использования: strncat s1 s2 $n&lt;br /&gt;
#&lt;br /&gt;
# Аналог strcat, но добавляет не более n символов из&lt;br /&gt;
# переменной s2. Результат выводится на stdout.&lt;br /&gt;
#&lt;br /&gt;
# Пример:&lt;br /&gt;
#        a=foo&lt;br /&gt;
#        b=barbaz&lt;br /&gt;
#        strncat a b 3&lt;br /&gt;
#        echo $a&lt;br /&gt;
#        =&amp;gt; foobar&lt;br /&gt;
#&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strncat ()&lt;br /&gt;
{&lt;br /&gt;
 local s1=&amp;quot;$1&amp;quot;&lt;br /&gt;
 local s2=&amp;quot;$2&amp;quot;&lt;br /&gt;
 local -i n=&amp;quot;$3&amp;quot;&lt;br /&gt;
 local s1_val s2_val&lt;br /&gt;
 &lt;br /&gt;
 s1_val=${!s1} # ==&amp;gt; косвенная ссылка&lt;br /&gt;
 s2_val=${!s2}&lt;br /&gt;
&lt;br /&gt;
 if [ ${#s2_val} -gt ${n} ]; then&lt;br /&gt;
  s2_val=${s2_val:0:$n} # ==&amp;gt; выделение подстроки&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 eval &amp;quot;$s1&amp;quot;=\'&amp;quot;${s1_val}${s2_val}&amp;quot;\'&lt;br /&gt;
 # ==&amp;gt; eval $1='${s1_val}${s2_val}' во избежание проблем,&lt;br /&gt;
 # ==&amp;gt; если одна из переменных содержит одиночную кавычку.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strcmp:&lt;br /&gt;
# Порядок использования: strcmp $s1 $s2&lt;br /&gt;
#&lt;br /&gt;
# Strcmp сравнивает две строки и возвращает число меньше, равно&lt;br /&gt;
# или больше нуля, в зависимости от результатов сравнения.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strcmp ()&lt;br /&gt;
{&lt;br /&gt;
 [ &amp;quot;$1&amp;quot; = &amp;quot;$2&amp;quot; ] &amp;amp;&amp;amp; return 0&lt;br /&gt;
 [ &amp;quot;${1}&amp;quot; '&amp;lt;' &amp;quot;${2}&amp;quot; ] &amp;gt; /dev/null &amp;amp;&amp;amp; return -1&lt;br /&gt;
 return 1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strncmp:&lt;br /&gt;
# Порядок использования: strncmp $s1 $s2 $n&lt;br /&gt;
#&lt;br /&gt;
# Подобна strcmp, но сравнивает не более n символов&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strncmp ()&lt;br /&gt;
{&lt;br /&gt;
 if [ -z &amp;quot;${3}&amp;quot; -o &amp;quot;${3}&amp;quot; -le &amp;quot;0&amp;quot; ]; then&lt;br /&gt;
  return 0&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 if [ ${3} -ge ${#1} -a ${3} -ge ${#2} ]; then&lt;br /&gt;
  strcmp &amp;quot;$1&amp;quot; &amp;quot;$2&amp;quot;&lt;br /&gt;
  return $?&lt;br /&gt;
 else&lt;br /&gt;
  s1=${1:0:$3}&lt;br /&gt;
  s2=${2:0:$3}&lt;br /&gt;
  strcmp $s1 $s2&lt;br /&gt;
  return $?&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strlen:&lt;br /&gt;
# Порядок использования: strlen s&lt;br /&gt;
#&lt;br /&gt;
# возвращает количество символов в строке s.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strlen ()&lt;br /&gt;
{&lt;br /&gt;
 eval echo &amp;quot;\${#${1}}&amp;quot;&lt;br /&gt;
 # ==&amp;gt; Возвращает длину переменной,&lt;br /&gt;
 # ==&amp;gt; чье имя передаётся как аргумент.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strspn:&lt;br /&gt;
# Порядок использования: strspn $s1 $s2&lt;br /&gt;
#&lt;br /&gt;
# Strspn возвращает максимальную длину сегмента в строке s1,&lt;br /&gt;
# который полностью состоит из символов строки s2.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strspn ()&lt;br /&gt;
{&lt;br /&gt;
 # Сброс содержимого переменной IFS позволяет обрабатывать пробелы как обычные символы.&lt;br /&gt;
 local IFS=&lt;br /&gt;
 local result=&amp;quot;${1%%[!${2}]*}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 echo ${#result}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strcspn:&lt;br /&gt;
# Порядок использования: strcspn $s1 $s2&lt;br /&gt;
#&lt;br /&gt;
# Strcspn возвращает максимальную длину сегмента в строке s1,&lt;br /&gt;
# который полностью не содержит символы из строки s2.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strcspn ()&lt;br /&gt;
{&lt;br /&gt;
 # Сброс содержимого переменной IFS позволяет обрабатывать пробелы как обычные символы.&lt;br /&gt;
 local IFS=&lt;br /&gt;
 local result=&amp;quot;${1%%[${2}]*}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 echo ${#result}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strstr:&lt;br /&gt;
# Порядок использования: strstr s1 s2&lt;br /&gt;
#&lt;br /&gt;
# Strstr выводит подстроку первого вхождения строки s2&lt;br /&gt;
# в строке s1, или ничего не выводит, если подстрока s2 в строке s1 не найдена.&lt;br /&gt;
# Если s2 содержит строку нулевой длины, то strstr выводит строку s1.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strstr ()&lt;br /&gt;
{&lt;br /&gt;
 # Если s2 — строка нулевой длины, то вывести строку s1&lt;br /&gt;
 [ ${#2} -eq 0 ] &amp;amp;&amp;amp; { echo &amp;quot;$1&amp;quot; ; return 0; }&lt;br /&gt;
 # не выводить ничего, если s2 не найдена в s1&lt;br /&gt;
 case &amp;quot;$1&amp;quot; in&lt;br /&gt;
 *$2*) ;;&lt;br /&gt;
 *) return 1;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 # использовать шаблон, для удаления всех несоответствий после s2 в s1&lt;br /&gt;
 first=${1/$2*/}&lt;br /&gt;
&lt;br /&gt;
 # Затем удалить все несоответствия с начала строки&lt;br /&gt;
 echo &amp;quot;${1##$first}&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strtok:&lt;br /&gt;
# Порядок использования: strtok s1 s2&lt;br /&gt;
#&lt;br /&gt;
# Strtok рассматривает строку s1, как последовательность из 0, или более,&lt;br /&gt;
# лексем (токенов), разделённых символами строки s2&lt;br /&gt;
# При первом вызове (с непустым аргументом s1)&lt;br /&gt;
# выводит первую лексему на stdout.&lt;br /&gt;
# Функция запоминает свое положение в строке s1 от вызова к вызову,&lt;br /&gt;
# так что последующие вызовы должны производиться с пустым первым аргументом,&lt;br /&gt;
# чтобы продолжить выделение лексем из строки s1.&lt;br /&gt;
# После вывода последней лексемы, все последующие вызовы будут выводить на stdout&lt;br /&gt;
# пустое значение. Строка-разделитель может изменяться от вызова к вызову.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoloa&lt;br /&gt;
dfunction strtok ()&lt;br /&gt;
{&lt;br /&gt;
 :&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#:docstring strtrunc:&lt;br /&gt;
# Порядок использования: strtrunc $n $s1 {$s2} {$...}&lt;br /&gt;
#&lt;br /&gt;
# Используется многими функциями, такими как strncmp, чтобы отсечь &amp;quot;лишние&amp;quot; символы.&lt;br /&gt;
# Выводит первые n символов в каждой из строк s1 s2 ... на stdout.&lt;br /&gt;
#:end docstring:&lt;br /&gt;
&lt;br /&gt;
###;;;autoload&lt;br /&gt;
function strtrunc ()&lt;br /&gt;
{&lt;br /&gt;
 n=$1 ; shift&lt;br /&gt;
 for z; do&lt;br /&gt;
  echo &amp;quot;${z:0:$n}&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# provide string&lt;br /&gt;
# string.bash конец библиотеки&lt;br /&gt;
&lt;br /&gt;
# ========================================================================== #&lt;br /&gt;
# ==&amp;gt; Все, что находится ниже, добавлено автором документа.&lt;br /&gt;
# ==&amp;gt; Чтобы этот сценарий можно было использовать как &amp;quot;библиотеку&amp;quot;, необходимо&lt;br /&gt;
# ==&amp;gt; удалить все, что находится ниже и &amp;quot;source&amp;quot; этот файл в вашем сценарии.&lt;br /&gt;
&lt;br /&gt;
# strcat&lt;br /&gt;
string0=one&lt;br /&gt;
string1=two&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверка функции \&amp;quot;strcat\&amp;quot; :&amp;quot;&lt;br /&gt;
echo &amp;quot;Изначально \&amp;quot;string0\&amp;quot; = $string0&amp;quot;&lt;br /&gt;
echo &amp;quot;\&amp;quot;string1\&amp;quot; = $string1&amp;quot;&lt;br /&gt;
strcat string0 string1&lt;br /&gt;
echo &amp;quot;Теперь \&amp;quot;string0\&amp;quot; = $string0&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# strlen&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;Проверка функции \&amp;quot;strlen\&amp;quot; :&amp;quot;&lt;br /&gt;
str=123456789&lt;br /&gt;
echo &amp;quot;\&amp;quot;str\&amp;quot; = $str&amp;quot;&lt;br /&gt;
echo -n &amp;quot;Длина строки \&amp;quot;str\&amp;quot; = &amp;quot;&lt;br /&gt;
strlen str&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Упражнение:&lt;br /&gt;
# ---------&lt;br /&gt;
# Добавьте проверку остальных функций.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Michael Zick'' предоставил очень сложный пример работы с массивами и утилитой '''''md5sum''''', используемой для кодирования сведений о каталоге.&lt;br /&gt;
''От переводчика'':&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''К своему стыду вынужден признаться, что перевод комментариев оказался мне не &amp;quot;по зубам&amp;quot;,поэтому оставляю этот сценарий без перевода'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-21. Directory information.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# directory-info.sh&lt;br /&gt;
# Parses and lists directory information.&lt;br /&gt;
&lt;br /&gt;
# NOTE: Change lines 273 and 353 per &amp;quot;README&amp;quot; file.&lt;br /&gt;
&lt;br /&gt;
# Michael Zick is the author of this script.&lt;br /&gt;
# Used here with his permission.&lt;br /&gt;
&lt;br /&gt;
# Controls&lt;br /&gt;
# If overridden by command arguments, they must be in the order:&lt;br /&gt;
# Arg1: &amp;quot;Descriptor Directory&amp;quot;&lt;br /&gt;
# Arg2: &amp;quot;Exclude Paths&amp;quot;&lt;br /&gt;
# Arg3: &amp;quot;Exclude Directories&amp;quot;&lt;br /&gt;
# &lt;br /&gt;
# Environment Settings override Defaults.&lt;br /&gt;
# Command arguments override Environment Settings.&lt;br /&gt;
&lt;br /&gt;
# Default location for content addressed file descriptors.&lt;br /&gt;
MD5UCFS=${1:-${MD5UCFS:-'/tmpfs/ucfs'}}&lt;br /&gt;
&lt;br /&gt;
# Directory paths never to list or enter&lt;br /&gt;
declare -a \&lt;br /&gt;
 EXCLUDE_PATHS=${2:-${EXCLUDE_PATHS:-'(/proc /dev /devfs /tmpfs)'}}&lt;br /&gt;
&lt;br /&gt;
# Directories never to list or enter&lt;br /&gt;
declare -a \&lt;br /&gt;
 EXCLUDE_DIRS=${3:-${EXCLUDE_DIRS:-'(ucfs lost+found tmp wtmp)'}}&lt;br /&gt;
&lt;br /&gt;
# Files never to list or enter&lt;br /&gt;
declare -a \&lt;br /&gt;
 EXCLUDE_FILES=${3:-${EXCLUDE_FILES:-'(core &amp;quot;Name with Spaces&amp;quot;)'}}&lt;br /&gt;
&lt;br /&gt;
# Here document used as a comment block.&lt;br /&gt;
: &amp;lt;&amp;lt; LSfieldsDoc&lt;br /&gt;
# # # # # List Filesystem Directory Information # # # # #&lt;br /&gt;
#&lt;br /&gt;
#  ListDirectory &amp;quot;FileGlob&amp;quot; &amp;quot;Field-Array-Name&amp;quot;&lt;br /&gt;
# or&lt;br /&gt;
# ListDirectory -of &amp;quot;FileGlob&amp;quot; &amp;quot;Field-Array-Filename&amp;quot;&lt;br /&gt;
# '-of' meaning 'output to filename'&lt;br /&gt;
# # # # #&lt;br /&gt;
&lt;br /&gt;
String format description based on: ls (GNU fileutils) version 4.0.36&lt;br /&gt;
&lt;br /&gt;
Produces a line (or more) formatted:&lt;br /&gt;
inode permissions hard-links owner group ...&lt;br /&gt;
32736 -rw------- 1 mszick mszick&lt;br /&gt;
size day month date hh:mm:ss year path&lt;br /&gt;
2756608 Sun Apr 20 08:53:06 2003 /home/mszick/core&lt;br /&gt;
&lt;br /&gt;
Unless it is formatted:&lt;br /&gt;
inode permissions hard-links owner group ...&lt;br /&gt;
266705 crw-rw---- 1 root uucp&lt;br /&gt;
major minor day month date hh:mm:ss year path&lt;br /&gt;
4, 68 Sun Apr 20 09:27:33 2003 /dev/ttyS4&lt;br /&gt;
NOTE: that pesky comma after the major number&lt;br /&gt;
NOTE: the 'path' may be multiple fields:&lt;br /&gt;
/home/mszick/core&lt;br /&gt;
/proc/982/fd/0 -&amp;gt; /dev/null&lt;br /&gt;
/proc/982/fd/1 -&amp;gt; /home/mszick/.xsession-errors&lt;br /&gt;
/proc/982/fd/13 -&amp;gt; /tmp/tmpfZVVOCs (deleted)&lt;br /&gt;
/proc/982/fd/7 -&amp;gt; /tmp/kde-mszick/ksycoca&lt;br /&gt;
/proc/982/fd/8 -&amp;gt; socket:[11586]&lt;br /&gt;
/proc/982/fd/9 -&amp;gt; pipe:[11588]&lt;br /&gt;
&lt;br /&gt;
If that isn't enough to keep your parser guessing,&lt;br /&gt;
either or both of the path components may be relative:&lt;br /&gt;
../Built-Shared -&amp;gt; Built-Static&lt;br /&gt;
../linux-2.4.20.tar.bz2 -&amp;gt; ../../../SRCS/linux-2.4.20.tar.bz2&lt;br /&gt;
&lt;br /&gt;
The first character of the 11 (10?) character permissions field:&lt;br /&gt;
's' Socket&lt;br /&gt;
'd' Directory&lt;br /&gt;
'b' Block device&lt;br /&gt;
'c' Character device&lt;br /&gt;
'l' Symbolic link&lt;br /&gt;
NOTE: Hard links not marked - test for identical inode numbers on identical filesystems.&lt;br /&gt;
All information about hard linked files are shared, except&lt;br /&gt;
for the names and the name's location in the directory system.&lt;br /&gt;
NOTE: A &amp;quot;Hard link&amp;quot; is known as a &amp;quot;File Alias&amp;quot; on some systems.&lt;br /&gt;
'-' An undistingushed fileFollowed by three groups of letters for: User, Group, Others&lt;br /&gt;
Character 1: '-' Not readable; 'r' Readable&lt;br /&gt;
Character 2: '-' Not writable; 'w' Writable&lt;br /&gt;
Character 3, User and Group: Combined execute and special&lt;br /&gt;
'-' Not Executable, Not Special&lt;br /&gt;
'x' Executable, Not Special&lt;br /&gt;
's' Executable, Special&lt;br /&gt;
'S' Not Executable, Special&lt;br /&gt;
Character 3, Others: Combined execute and sticky (tacky?)&lt;br /&gt;
'-' Not Executable, Not Tacky&lt;br /&gt;
'x' Executable, Not Tacky&lt;br /&gt;
't' Executable, Tacky&lt;br /&gt;
'T' Not Executable, Tacky&lt;br /&gt;
Followed by an access indicator&lt;br /&gt;
Haven't tested this one, it may be the eleventh character&lt;br /&gt;
or it may generate another field&lt;br /&gt;
' ' No alternate access&lt;br /&gt;
'+' Alternate access&lt;br /&gt;
LSfieldsDoc&lt;br /&gt;
&lt;br /&gt;
ListDirectory()&lt;br /&gt;
{&lt;br /&gt;
 local -a T&lt;br /&gt;
 local -i of=0 # Default return in variable&lt;br /&gt;
 # OLD_IFS=$IFS # Using BASH default ' \t\n'&lt;br /&gt;
 case &amp;quot;$#&amp;quot; in&lt;br /&gt;
 3) case &amp;quot;$1&amp;quot; in&lt;br /&gt;
  -of) of=1 ; shift ;;&lt;br /&gt;
  * ) return 1 ;;&lt;br /&gt;
   esac ;;&lt;br /&gt;
 2) : ;; # Poor man's &amp;quot;continue&amp;quot;&lt;br /&gt;
 *) return 1 ;;&lt;br /&gt;
 esac&lt;br /&gt;
# NOTE: the (ls) command is NOT quoted (&amp;quot;)&lt;br /&gt;
T=( $(ls --inode --ignore-backups --almost-all --directory \&lt;br /&gt;
--full-time --color=none --time=status --sort=none \&lt;br /&gt;
--format=long $1) )&lt;br /&gt;
&lt;br /&gt;
case $of in&lt;br /&gt;
# Assign T back to the array whose name was passed as $2&lt;br /&gt;
 0) eval $2=\( \&amp;quot;\$\{T\[@\]\}\&amp;quot; \) ;;&lt;br /&gt;
# Write T into filename passed as $2&lt;br /&gt;
 1) echo &amp;quot;${T[@]}&amp;quot; &amp;gt; &amp;quot;$2&amp;quot; ;;&lt;br /&gt;
esac&lt;br /&gt;
return 0&lt;br /&gt;
}&lt;br /&gt;
# # # # # Is that string a legal number? # # # # #&lt;br /&gt;
#&lt;br /&gt;
# IsNumber &amp;quot;Var&amp;quot;&lt;br /&gt;
# # # # # There has to be a better way, sigh...&lt;br /&gt;
&lt;br /&gt;
IsNumber()&lt;br /&gt;
{&lt;br /&gt;
 local -i int&lt;br /&gt;
 if [ $# -eq 0 ]&lt;br /&gt;
 then&lt;br /&gt;
  return 1&lt;br /&gt;
 else&lt;br /&gt;
  (let int=$1) 2&amp;gt;/dev/null&lt;br /&gt;
  return $? # Exit status of the let thread&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# # # # # Index Filesystem Directory Information # # # # #&lt;br /&gt;
#&lt;br /&gt;
# IndexList &amp;quot;Field-Array-Name&amp;quot; &amp;quot;Index-Array-Name&amp;quot;&lt;br /&gt;
# or&lt;br /&gt;
# IndexList -if Field-Array-Filename Index-Array-Name&lt;br /&gt;
# IndexList -of Field-Array-Name Index-Array-Filename&lt;br /&gt;
# IndexList -if -of Field-Array-Filename Index-Array-Filename&lt;br /&gt;
# &lt;br /&gt;
# # # #&lt;br /&gt;
: &amp;lt;&amp;lt; IndexListDoc&lt;br /&gt;
Walk an array of directory fields produced by ListDirectory&lt;br /&gt;
Having suppressed the line breaks in an otherwise line oriented&lt;br /&gt;
report, build an index to the array element which starts each line.&lt;br /&gt;
&lt;br /&gt;
Each line gets two index entries, the first element of each line&lt;br /&gt;
(inode) and the element that holds the pathname of the file.&lt;br /&gt;
&lt;br /&gt;
The first index entry pair (Line-Number==0) are informational:&lt;br /&gt;
Index-Array-Name[0] : Number of &amp;quot;Lines&amp;quot; indexed&lt;br /&gt;
Index-Array-Name[1] : &amp;quot;Current Line&amp;quot; pointer into Index-Array-Name&lt;br /&gt;
The following index pairs (if any) hold element indexes into&lt;br /&gt;
the Field-Array-Name per:&lt;br /&gt;
Index-Array-Name[Line-Number * 2] : The &amp;quot;inode&amp;quot; field element.&lt;br /&gt;
NOTE: This distance may be either +11 or +12 elements.&lt;br /&gt;
Index-Array-Name[(Line-Number * 2) + 1] : The &amp;quot;pathname&amp;quot; element.&lt;br /&gt;
NOTE: This distance may be a variable number of elements.&lt;br /&gt;
Next line index pair for Line-Number+1.&lt;br /&gt;
IndexListDoc&lt;br /&gt;
&lt;br /&gt;
IndexList()&lt;br /&gt;
{&lt;br /&gt;
 local -a LIST # Local of listname passed&lt;br /&gt;
 local -a -i INDEX=( 0 0 ) # Local of index to return&lt;br /&gt;
 local -i Lidx Lcnt&lt;br /&gt;
 local -i if=0 of=0 # Default to variable names&lt;br /&gt;
&lt;br /&gt;
 case &amp;quot;$#&amp;quot; in # Simplistic option testing&lt;br /&gt;
  0) return 1 ;;&lt;br /&gt;
  1) return 1 ;;&lt;br /&gt;
  2) : ;; # Poor man's continue&lt;br /&gt;
  3) case &amp;quot;$1&amp;quot; in&lt;br /&gt;
    -if) if=1 ;;&lt;br /&gt;
    -of) of=1 ;;&lt;br /&gt;
    * ) return 1 ;;&lt;br /&gt;
    esac ; shift ;;&lt;br /&gt;
   4) if=1 ; of=1 ; shift ; shift ;;&lt;br /&gt;
   *) return 1&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 # Make local copy of list&lt;br /&gt;
 case &amp;quot;$if&amp;quot; in&lt;br /&gt;
  0) eval LIST=\( \&amp;quot;\$\{$1\[@\]\}\&amp;quot; \) ;;&lt;br /&gt;
  1) LIST=( $(cat $1) ) ;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 # Grok (grope?) the array&lt;br /&gt;
 Lcnt=${#LIST[@]}&lt;br /&gt;
 Lidx=0&lt;br /&gt;
 until (( Lidx &amp;gt;= Lcnt ))&lt;br /&gt;
 do&lt;br /&gt;
  if IsNumber ${LIST[$Lidx]}&lt;br /&gt;
  then&lt;br /&gt;
   local -i inode name&lt;br /&gt;
   local ft&lt;br /&gt;
   inode=Lidx&lt;br /&gt;
   local m=${LIST[$Lidx+2]} # Hard Links field&lt;br /&gt;
   ft=${LIST[$Lidx+1]:0:1} # Fast-Stat&lt;br /&gt;
   case $ft in&lt;br /&gt;
    b) ((Lidx+=12)) ;; # Block device&lt;br /&gt;
    c) ((Lidx+=12)) ;; # Character device&lt;br /&gt;
    *) ((Lidx+=11)) ;; # Anything else&lt;br /&gt;
   esac&lt;br /&gt;
   name=Lidx&lt;br /&gt;
   case $ft in&lt;br /&gt;
    -) ((Lidx+=1)) ;; # The easy one&lt;br /&gt;
    b) ((Lidx+=1)) ;; # Block device&lt;br /&gt;
    c) ((Lidx+=1)) ;; # Character device&lt;br /&gt;
    d) ((Lidx+=1)) ;; # The other easy one&lt;br /&gt;
    l) ((Lidx+=3)) ;; # At LEAST two more fields&lt;br /&gt;
# A little more elegance here would handle pipes,&lt;br /&gt;
# sockets, deleted files - later.&lt;br /&gt;
    *) until IsNumber ${LIST[$Lidx]} || ((Lidx &amp;gt;= Lcnt))&lt;br /&gt;
       do&lt;br /&gt;
        ((Lidx+=1))&lt;br /&gt;
       done&lt;br /&gt;
       ;; # Not required&lt;br /&gt;
     esac&lt;br /&gt;
     INDEX[${#INDEX[*]}]=$inode&lt;br /&gt;
     INDEX[${#INDEX[*]}]=$name&lt;br /&gt;
     INDEX[0]=${INDEX[0]}+1 # One more &amp;quot;line&amp;quot; found&lt;br /&gt;
# echo &amp;quot;Line: ${INDEX[0]} Type: $ft Links: $m Inode: \&lt;br /&gt;
# ${LIST[$inode]} Name: ${LIST[$name]}&amp;quot;&lt;br /&gt;
 else&lt;br /&gt;
  ((Lidx+=1))&lt;br /&gt;
 fi&lt;br /&gt;
 done&lt;br /&gt;
 case &amp;quot;$of&amp;quot; in&lt;br /&gt;
  0) eval $2=\( \&amp;quot;\$\{INDEX\[@\]\}\&amp;quot; \) ;;&lt;br /&gt;
  1) echo &amp;quot;${INDEX[@]}&amp;quot; &amp;gt; &amp;quot;$2&amp;quot; ;;&lt;br /&gt;
 esac&lt;br /&gt;
 return 0 # What could go wrong?&lt;br /&gt;
}&lt;br /&gt;
# # # # # Content Identify File # # # # #&lt;br /&gt;
#&lt;br /&gt;
# DigestFile Input-Array-Name Digest-Array-Name&lt;br /&gt;
# or&lt;br /&gt;
# DigestFile -if Input-FileName Digest-Array-Name&lt;br /&gt;
# # # # #&lt;br /&gt;
&lt;br /&gt;
# Here document used as a comment block.&lt;br /&gt;
: &amp;lt;&amp;lt;DigestFilesDoc&lt;br /&gt;
&lt;br /&gt;
The key (no pun intended) to a Unified Content File System (UCFS)&lt;br /&gt;
is to distinguish the files in the system based on their content.&lt;br /&gt;
Distinguishing files by their name is just, so, 20th Century.&lt;br /&gt;
&lt;br /&gt;
The content is distinguished by computing a checksum of that content.&lt;br /&gt;
This version uses the md5sum program to generate a 128 bit checksum&lt;br /&gt;
representative of the file's contents.&lt;br /&gt;
There is a chance that two files having different content might&lt;br /&gt;
generate the same checksum using md5sum (or any checksum). Should&lt;br /&gt;
that become a problem, then the use of md5sum can be replace by a&lt;br /&gt;
cyrptographic signature. But until then...&lt;br /&gt;
&lt;br /&gt;
The md5sum program is documented as outputting three fields (and it&lt;br /&gt;
does), but when read it appears as two fields (array elements). This&lt;br /&gt;
is caused by the lack of whitespace between the second and third field.&lt;br /&gt;
So this function gropes the md5sum output and returns:&lt;br /&gt;
 [0] 32 character checksum in hexidecimal (UCFS filename)&lt;br /&gt;
 [1] Single character: ' ' text file, '*' binary file&lt;br /&gt;
 [2] Filesystem (20th Century Style) name&lt;br /&gt;
 Note: That name may be the character '-' indicating STDIN read.&lt;br /&gt;
DigestFilesDoc&lt;br /&gt;
&lt;br /&gt;
DigestFile()&lt;br /&gt;
{&lt;br /&gt;
 local if=0 # Default, variable name&lt;br /&gt;
 local -a T1 T2&lt;br /&gt;
 case &amp;quot;$#&amp;quot; in&lt;br /&gt;
 3) case &amp;quot;$1&amp;quot; in&lt;br /&gt;
    -if) if=1 ; shift ;;&lt;br /&gt;
    * ) return 1 ;;&lt;br /&gt;
    esac ;;&lt;br /&gt;
 2) : ;; # Poor man's &amp;quot;continue&amp;quot;&lt;br /&gt;
 *) return 1 ;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 case $if in&lt;br /&gt;
 0) eval T1=\( \&amp;quot;\$\{$1\[@\]\}\&amp;quot; \)&lt;br /&gt;
    T2=( $(echo ${T1[@]} | md5sum -) )&lt;br /&gt;
    ;;&lt;br /&gt;
 1) T2=( $(md5sum $1) )&lt;br /&gt;
    ;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 case ${#T2[@]} in&lt;br /&gt;
 0) return 1 ;;&lt;br /&gt;
 1) return 1 ;;&lt;br /&gt;
 2) case ${T2[1]:0:1} in # SanScrit-2.0.5&lt;br /&gt;
     \*) T2[${#T2[@]}]=${T2[1]:1}&lt;br /&gt;
         T2[1]=\*&lt;br /&gt;
         ;;&lt;br /&gt;
      *) T2[${#T2[@]}]=${T2[1]}&lt;br /&gt;
         T2[1]=&amp;quot; &amp;quot;&lt;br /&gt;
         ;;&lt;br /&gt;
    esac&lt;br /&gt;
    ;;&lt;br /&gt;
 3) : ;; # Assume it worked&lt;br /&gt;
 *) return 1 ;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 local -i len=${#T2[0]}&lt;br /&gt;
 if [ $len -ne 32 ] ; then return 1 ; fi&lt;br /&gt;
 eval $2=\( \&amp;quot;\$\{T2\[@\]\}\&amp;quot; \)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# # # # # Locate File # # # # #&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
# LocateFile [-l] FileName Location-Array-Name&lt;br /&gt;
# or&lt;br /&gt;
# LocateFile [-l] -of FileName Location-Array-FileName&lt;br /&gt;
# # # # #&lt;br /&gt;
&lt;br /&gt;
# A file location is Filesystem-id and inode-number&lt;br /&gt;
# Here document used as a comment block.&lt;br /&gt;
: &amp;lt;&amp;lt;StatFieldsDoc&lt;br /&gt;
  Based on stat, version 2.2&lt;br /&gt;
  stat -t and stat -lt fields&lt;br /&gt;
  [0] name&lt;br /&gt;
  [1] Total size&lt;br /&gt;
      File - number of bytes&lt;br /&gt;
      Symbolic link - string length of pathname&lt;br /&gt;
  [2] Number of (512 byte) blocks allocated&lt;br /&gt;
  [3] File type and Access rights (hex)&lt;br /&gt;
  [4] User ID of owner&lt;br /&gt;
  [5] Group ID of owner&lt;br /&gt;
  [6] Device number&lt;br /&gt;
  [7] Inode number&lt;br /&gt;
  [8] Number of hard links&lt;br /&gt;
  [9] Device type (if inode device) Major&lt;br /&gt;
  [10] Device type (if inode device) Minor&lt;br /&gt;
  [11] Time of last access&lt;br /&gt;
       May be disabled in 'mount' with noatime&lt;br /&gt;
       atime of files changed by exec, read, pipe, utime, mknod (mmap?)&lt;br /&gt;
       atime of directories changed by addition/deletion of files&lt;br /&gt;
  [12] Time of last modification&lt;br /&gt;
       mtime of files changed by write, truncate, utime, mknod&lt;br /&gt;
       mtime of directories changed by addtition/deletion of files&lt;br /&gt;
  [13] Time of last change&lt;br /&gt;
       ctime reflects time of changed inode information (owner, group&lt;br /&gt;
       permissions, link count&lt;br /&gt;
-*-*- Per:&lt;br /&gt;
       Return code: 0&lt;br /&gt;
       Size of array: 14&lt;br /&gt;
       Contents of array&lt;br /&gt;
       Element 0: /home/mszick&lt;br /&gt;
       Element 1: 4096&lt;br /&gt;
       Element 2: 8&lt;br /&gt;
       Element 3: 41e8&lt;br /&gt;
       Element 4: 500&lt;br /&gt;
       Element 5: 500&lt;br /&gt;
       Element 6: 303&lt;br /&gt;
       Element 7: 32385&lt;br /&gt;
       Element 8: 22&lt;br /&gt;
       Element 9: 0&lt;br /&gt;
       Element 10: 0&lt;br /&gt;
       Element 11: 1051221030&lt;br /&gt;
       Element 12: 1051214068&lt;br /&gt;
       Element 13: 1051214068&lt;br /&gt;
&lt;br /&gt;
       For a link in the form of linkname -&amp;gt; realname&lt;br /&gt;
       stat -t linkname returns the linkname (link) information&lt;br /&gt;
       stat -lt linkname returns the realname information&lt;br /&gt;
&lt;br /&gt;
       stat -tf and stat -ltf fields&lt;br /&gt;
       [0] name&lt;br /&gt;
       [1] ID-0? # Maybe someday, but Linux stat structure&lt;br /&gt;
       [2] ID-0? # does not have either LABEL nor UUID&lt;br /&gt;
                 # fields, currently information must come&lt;br /&gt;
                 # from file-system specific utilities&lt;br /&gt;
       These will be munged into:&lt;br /&gt;
       [1] UUID if possible&lt;br /&gt;
       [2] Volume Label if possible&lt;br /&gt;
       Note: 'mount -l' does return the label and could return the UUID&lt;br /&gt;
&lt;br /&gt;
       [3] Maximum length of filenames&lt;br /&gt;
       [4] Filesystem type&lt;br /&gt;
       [5] Total blocks in the filesystem&lt;br /&gt;
       [6] Free blocks&lt;br /&gt;
       [7] Free blocks for non-root user(s)&lt;br /&gt;
       [8] Block size of the filesystem&lt;br /&gt;
       [9] Total inodes&lt;br /&gt;
       [10] Free inodes&lt;br /&gt;
-*-*- Per:&lt;br /&gt;
       Return code: 0&lt;br /&gt;
       Size of array: 11&lt;br /&gt;
       Contents of array&lt;br /&gt;
       Element 0: /home/mszick&lt;br /&gt;
       Element 1: 0&lt;br /&gt;
       Element 2: 0&lt;br /&gt;
       Element 3: 255&lt;br /&gt;
       Element 4: ef53&lt;br /&gt;
       Element 5: 2581445&lt;br /&gt;
       Element 6: 2277180&lt;br /&gt;
       Element 7: 2146050&lt;br /&gt;
       Element 8: 4096&lt;br /&gt;
       Element 9: 1311552&lt;br /&gt;
       Element 10: 1276425&lt;br /&gt;
&lt;br /&gt;
StatFieldsDoc&lt;br /&gt;
&lt;br /&gt;
# LocateFile [-l] FileName Location-Array-Name&lt;br /&gt;
# LocateFile [-l] -of FileName Location-Array-FileName&lt;br /&gt;
&lt;br /&gt;
LocateFile()&lt;br /&gt;
{&lt;br /&gt;
 local -a LOC LOC1 LOC2&lt;br /&gt;
 local lk=&amp;quot;&amp;quot; of=0&lt;br /&gt;
&lt;br /&gt;
 case &amp;quot;$#&amp;quot; in&lt;br /&gt;
 0) return 1 ;;&lt;br /&gt;
 1) return 1 ;;&lt;br /&gt;
 2) : ;;&lt;br /&gt;
 *) while (( &amp;quot;$#&amp;quot; &amp;gt; 2 ))&lt;br /&gt;
    do&lt;br /&gt;
     case &amp;quot;$1&amp;quot; in&lt;br /&gt;
     -l) lk=-1 ;;&lt;br /&gt;
     -of) of=1 ;;&lt;br /&gt;
     *) return 1 ;;&lt;br /&gt;
     esac&lt;br /&gt;
     shift&lt;br /&gt;
    done ;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 # More Sanscrit-2.0.5&lt;br /&gt;
 # LOC1=( $(stat -t $lk $1) )&lt;br /&gt;
 # LOC2=( $(stat -tf $lk $1) )&lt;br /&gt;
 # Uncomment above two lines if system has &amp;quot;stat&amp;quot; command installed.&lt;br /&gt;
&lt;br /&gt;
 LOC=( ${LOC1[@]:0:1} ${LOC1[@]:3:11}&lt;br /&gt;
       ${LOC2[@]:1:2} ${LOC2[@]:4:1} )&lt;br /&gt;
&lt;br /&gt;
 case &amp;quot;$of&amp;quot; in&lt;br /&gt;
  0) eval $2=\( \&amp;quot;\$\{LOC\[@\]\}\&amp;quot; \) ;;&lt;br /&gt;
  1) echo &amp;quot;${LOC[@]}&amp;quot; &amp;gt; &amp;quot;$2&amp;quot; ;;&lt;br /&gt;
 esac&lt;br /&gt;
 return 0&lt;br /&gt;
&lt;br /&gt;
# Which yields (if you are lucky, and have &amp;quot;stat&amp;quot; installed)&lt;br /&gt;
# -*-*- Location Discriptor -*-*-&lt;br /&gt;
# Return code: 0&lt;br /&gt;
# Size of array: 15&lt;br /&gt;
# Contents of array&lt;br /&gt;
# Element 0: /home/mszick 20th Century name&lt;br /&gt;
# Element 1: 41e8 Type and Permissions&lt;br /&gt;
# Element 2: 500 User&lt;br /&gt;
# Element 3: 500 Group&lt;br /&gt;
# Element 4: 303 Device&lt;br /&gt;
# Element 5: 32385 inode&lt;br /&gt;
# Element 6: 22 Link count&lt;br /&gt;
# Element 7: 0 Device Major&lt;br /&gt;
# Element 8: 0 Device Minor&lt;br /&gt;
# Element 9: 1051224608 Last Access&lt;br /&gt;
# Element 10: 1051214068 Last Modify&lt;br /&gt;
# Element 11: 1051214068 Last Status&lt;br /&gt;
# Element 12: 0 UUID (to be)&lt;br /&gt;
# Element 13: 0 Volume Label (to be)&lt;br /&gt;
# Element 14: ef53 Filesystem type&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# And then there was some test &lt;br /&gt;
codeListArray() # ListArray Name&lt;br /&gt;
{&lt;br /&gt;
 local -a Ta&lt;br /&gt;
&lt;br /&gt;
 eval Ta=\( \&amp;quot;\$\{$1\[@\]\}\&amp;quot; \)&lt;br /&gt;
 echo&lt;br /&gt;
 echo &amp;quot;-*-*- List of Array -*-*-&amp;quot;&lt;br /&gt;
 echo &amp;quot;Size of array $1: ${#Ta[*]}&amp;quot;&lt;br /&gt;
 echo &amp;quot;Contents of array $1:&amp;quot;&lt;br /&gt;
 for (( i=0 ; i&amp;lt;${#Ta[*]} ; i++ ))&lt;br /&gt;
 do&lt;br /&gt;
  echo -e &amp;quot;\tElement $i: ${Ta[$i]}&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
 return 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
declare -a CUR_DIR&lt;br /&gt;
# For small arrays&lt;br /&gt;
ListDirectory &amp;quot;${PWD}&amp;quot; CUR_DIR&lt;br /&gt;
ListArray CUR_DIR&lt;br /&gt;
&lt;br /&gt;
declare -a DIR_DIG&lt;br /&gt;
DigestFile CUR_DIR DIR_DIG&lt;br /&gt;
echo &amp;quot;The new \&amp;quot;name\&amp;quot; (checksum) for ${CUR_DIR[9]} is ${DIR_DIG[0]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
declare -a DIR_ENT&lt;br /&gt;
# BIG_DIR # For really big arrays - use a temporary file in ramdisk&lt;br /&gt;
# BIG-DIR # ListDirectory -of &amp;quot;${CUR_DIR[11]}/*&amp;quot; &amp;quot;/tmpfs/junk2&amp;quot;&lt;br /&gt;
&lt;br /&gt;
ListDirectory &amp;quot;${CUR_DIR[11]}/*&amp;quot; DIR_ENT&lt;br /&gt;
&lt;br /&gt;
declare -a DIR_IDX# BIG-DIR # IndexList -if &amp;quot;/tmpfs/junk2&amp;quot; DIR_IDX&lt;br /&gt;
IndexList DIR_ENT DIR_IDX&lt;br /&gt;
declare -a IDX_DIG# BIG-DIR # DIR_ENT=( $(cat /tmpfs/junk2) )&lt;br /&gt;
# BIG-DIR # DigestFile -if /tmpfs/junk2 IDX_DIG&lt;br /&gt;
DigestFile DIR_ENT IDX_DIG&lt;br /&gt;
# Small (should) be able to parallize IndexList &amp;amp; DigestFile&lt;br /&gt;
# Large (should) be able to parallize IndexList &amp;amp; DigestFile &amp;amp; the assignment&lt;br /&gt;
echo &amp;quot;The \&amp;quot;name\&amp;quot; (checksum) for the contents of ${PWD} is ${IDX_DIG[0]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
declare -a FILE_LOC&lt;br /&gt;
LocateFile ${PWD} FILE_LOC&lt;br /&gt;
ListArray FILELOC&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Stephane Chazelas'' демонстрирует возможность объектно-ориентированного подхода к программированию в Bash-сценариях.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-22. Объектно-ориентированная база данных.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# obj-oriented.sh: Объектно-ориентрованный подход к программированию в сценариях.&lt;br /&gt;
# Автор: Stephane Chazelas.&lt;br /&gt;
&lt;br /&gt;
person.new() # Очень похоже на объявление класса в C++.&lt;br /&gt;
{&lt;br /&gt;
 local obj_name=$1 name=$2 firstname=$3 birthdate=$4&lt;br /&gt;
&lt;br /&gt;
 eval &amp;quot;$obj_name.set_name() {&lt;br /&gt;
  eval \&amp;quot;$obj_name.get_name() {&lt;br /&gt;
            echo \$1&lt;br /&gt;
         }\&amp;quot;&lt;br /&gt;
      }&amp;quot;&lt;br /&gt;
 eval &amp;quot;$obj_name.set_firstname() {&lt;br /&gt;
  eval \&amp;quot;$obj_name.get_firstname() {&lt;br /&gt;
            echo \$1&lt;br /&gt;
         }\&amp;quot;&lt;br /&gt;
       }&amp;quot;&lt;br /&gt;
 eval &amp;quot;$obj_name.set_birthdate() {&lt;br /&gt;
  eval \&amp;quot;$obj_name.get_birthdate() {&lt;br /&gt;
            echo \$1&lt;br /&gt;
          }\&amp;quot;&lt;br /&gt;
         eval \&amp;quot;$obj_name.show_birthdate() {&lt;br /&gt;
         echo \$(date -d \&amp;quot;1/1/1970 0:0:\$1 GMT\&amp;quot;)&lt;br /&gt;
          }\&amp;quot;&lt;br /&gt;
         eval \&amp;quot;$obj_name.get_age() {&lt;br /&gt;
          echo \$(( (\$(date +%s) - \$1) / 3600 / 24 / 365 ))&lt;br /&gt;
         }\&amp;quot;&lt;br /&gt;
       }&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 $obj_name.set_name $name&lt;br /&gt;
 $obj_name.set_firstname $firstname&lt;br /&gt;
 $obj_name.set_birthdate $birthdate&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
person.new self Bozeman Bozo 101272413&lt;br /&gt;
# Создаётся экземпляр класса &amp;quot;person.new&amp;quot; (фактически — вызов функции с аргументами).&lt;br /&gt;
self.get_firstname # Bozo&lt;br /&gt;
self.get_name # Bozeman&lt;br /&gt;
self.get_age # 28&lt;br /&gt;
self.get_birthdate # 101272413&lt;br /&gt;
self.show_birthdate # Sat Mar 17 20:13:33 MST 1973&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# typeset -f # чтобы просмотреть перечень созданных функций.&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Пример сценария, имеющего практическую ценность: установка и монтирование USB-устройств&amp;quot;жёстких дисков&amp;quot;.'''&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-23. Монтирование USB-устройств флэш-памяти.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# ==&amp;gt; usb.sh&lt;br /&gt;
# ==&amp;gt; Сценарий монтирует и устанавливает USB-устройства флэш-памяти.&lt;br /&gt;
# ==&amp;gt; Запускается с правами root во время загрузки системы (см. ниже).&lt;br /&gt;
&lt;br /&gt;
# Этот сценарий распространяется на условиях GNU GPL license версии 2 или выше.&lt;br /&gt;
# Полный текст лицензии вы найдете на http://www.gnu.org/.&lt;br /&gt;
#&lt;br /&gt;
# Часть кода заимствована из сценария usb-mount, автор Michael Hamilton (LGPL)&lt;br /&gt;
# см. http://users.actrix.co.nz/michael/usbmount.html#&lt;br /&gt;
#&lt;br /&gt;
# УСТАНОВКА&lt;br /&gt;
# ---------&lt;br /&gt;
# Поместите сценарий в каталог /etc/hotplug/usb/diskonkey.&lt;br /&gt;
# Затем скопируйте все описания устройств usb-storage из /etc/hotplug/usb.distmap&lt;br /&gt;
# в /etc/hotplug/usb.usermap, заменяя &amp;quot;usb-storage&amp;quot; на &amp;quot;diskonkey&amp;quot;.&lt;br /&gt;
#&lt;br /&gt;
# TODO&lt;br /&gt;
# ----&lt;br /&gt;
# Обслуживание более одного устройства diskonkey (например /dev/diskonkey1&lt;br /&gt;
# и /mnt/diskonkey1), и т.д. Наибольшая проблема здесь состоит в работе с&lt;br /&gt;
# devlabel.&lt;br /&gt;
#&lt;br /&gt;
# АВТОР и ПОДДЕРЖКА&lt;br /&gt;
# -------------------&lt;br /&gt;
# Konstantin Riabitsev, &amp;lt;icon linux duke edu&amp;gt;.&lt;br /&gt;
# Сообщения об обнаруженных ошибках отправляйте мне на электронный адрес.&lt;br /&gt;
#&lt;br /&gt;
# ==&amp;gt; Комментарии добавленные автором книги.&lt;br /&gt;
&lt;br /&gt;
SYMLINKDEV=/dev/diskonkey&lt;br /&gt;
MOUNTPOINT=/mnt/diskonkey&lt;br /&gt;
DEVLABEL=/sbin/devlabel&lt;br /&gt;
DEVLABELCONFIG=/etc/sysconfig/devlabel&lt;br /&gt;
IAM=$0&lt;br /&gt;
&lt;br /&gt;
##&lt;br /&gt;
# Функция заимствована из usb-mount.&lt;br /&gt;
#&lt;br /&gt;
&lt;br /&gt;
function allAttachedScsiUsb {&lt;br /&gt;
 find /proc/scsi/ -path '/proc/scsi/usb-storage*' -type f | xargs grep -l 'Attached: Yes'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function scsiDevFromScsiUsb {&lt;br /&gt;
 echo $1 | awk -F&amp;quot;[-/]&amp;quot; '{ n=$(NF-1); print &amp;quot;/dev/sd&amp;quot; substr(&amp;quot;abcdefghijklmnopqrstuvwxyz&amp;quot;, n+1, 1) }'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;${ACTION}&amp;quot; = &amp;quot;add&amp;quot; ] &amp;amp;&amp;amp; [ -f &amp;quot;${DEVICE}&amp;quot; ]; then&lt;br /&gt;
##&lt;br /&gt;
# заимствовано из usbcam.&lt;br /&gt;
#&lt;br /&gt;
 if [ -f /var/run/console.lock ]; then&lt;br /&gt;
  CONSOLEOWNER=`cat /var/run/console.lock`&lt;br /&gt;
 elif [ -f /var/lock/console.lock ]; then&lt;br /&gt;
  CONSOLEOWNER=`cat /var/lock/console.lock`&lt;br /&gt;
 else&lt;br /&gt;
  CONSOLEOWNER=&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 for procEntry in $(allAttachedScsiUsb); do&lt;br /&gt;
  scsiDev=$(scsiDevFromScsiUsb $procEntry)&lt;br /&gt;
  # Это ошибка в usb-storage?&lt;br /&gt;
  # Разделы не появляются в /proc/partitions до тех пор&lt;br /&gt;
  # пока к ним не было хотя бы одного обращения.&lt;br /&gt;
  /sbin/fdisk -l $scsiDev &amp;gt;/dev/null&lt;br /&gt;
  ##&lt;br /&gt;
  # Большинство устройств имеет информацию о разделах, например&lt;br /&gt;
  # /dev/sd?1. Однако, некоторые устройства не имеют разделов&lt;br /&gt;
  # выделяя под данные весь объем памяти. Здесь делается&lt;br /&gt;
  # попытка определить такие устройства, т.е. имеется ли /dev/sd?1&lt;br /&gt;
  # или нет.&lt;br /&gt;
  #&lt;br /&gt;
  if grep -q `basename $scsiDev`1 /proc/partitions; then&lt;br /&gt;
   part=&amp;quot;$scsiDev&amp;quot;&amp;quot;1&amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
   part=$scsiDev&lt;br /&gt;
  fi&lt;br /&gt;
  ##&lt;br /&gt;
  # Изменение владельца устройства, чтобы пользователь&lt;br /&gt;
  # мог смонтировать его.&lt;br /&gt;
  #&lt;br /&gt;
  if [ ! -z &amp;quot;$CONSOLEOWNER&amp;quot; ]; then&lt;br /&gt;
   chown $CONSOLEOWNER:disk $part&lt;br /&gt;
  fi&lt;br /&gt;
  ##&lt;br /&gt;
  # Здесь проверяется — зарегистрирован ли UUID с помощью devlabel.&lt;br /&gt;
  # Если нет, то устройство добавляется в список.&lt;br /&gt;
  #&lt;br /&gt;
  prodid=`$DEVLABEL printid -d $part`&lt;br /&gt;
  if ! grep -q $prodid $DEVLABELCONFIG; then&lt;br /&gt;
   # скрестим пальцы, надеюсь это поможет&lt;br /&gt;
   $DEVLABEL add -d $part -s $SYMLINKDEV 2&amp;gt;/dev/null&lt;br /&gt;
  fi&lt;br /&gt;
  ##&lt;br /&gt;
  # Если точка монтирования отсутствует, то она создается.&lt;br /&gt;
  #&lt;br /&gt;
  if [ ! -e $MOUNTPOINT ]; then&lt;br /&gt;
   mkdir -p $MOUNTPOINT&lt;br /&gt;
  fi&lt;br /&gt;
  ##&lt;br /&gt;
  # Позаботиться о создании соответствующей записи в /etc/fstab.&lt;br /&gt;
  #&lt;br /&gt;
  if ! grep -q &amp;quot;^$SYMLINKDEV&amp;quot; /etc/fstab; then&lt;br /&gt;
   # Добавить запись в fstab&lt;br /&gt;
   echo -e \&lt;br /&gt;
   &amp;quot;$SYMLINKDEV\t\t$MOUNTPOINT\t\tauto\tnoauto,owner,kudzu 0 0&amp;quot; \&lt;br /&gt;
   &amp;gt;&amp;gt; /etc/fstab&lt;br /&gt;
  fi&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
 if [ ! -z &amp;quot;$REMOVER&amp;quot; ]; then&lt;br /&gt;
  ##&lt;br /&gt;
  # Обеспечить запуск сценария при извлечении устройства.&lt;br /&gt;
  #&lt;br /&gt;
  mkdir -p `dirname $REMOVER`&lt;br /&gt;
  ln -s $IAM $REMOVER&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
elif [ &amp;quot;${ACTION}&amp;quot; = &amp;quot;remove&amp;quot; ]; then&lt;br /&gt;
 ##&lt;br /&gt;
 # Если устройство смонтировано — отмонтировать его.&lt;br /&gt;
 #&lt;br /&gt;
 if grep -q &amp;quot;$MOUNTPOINT&amp;quot; /etc/mtab; then&lt;br /&gt;
  # отмонтировать&lt;br /&gt;
  umount -l $MOUNTPOINT&lt;br /&gt;
 fi&lt;br /&gt;
 ##&lt;br /&gt;
 # Удалить запись из /etc/fstab, если она там имеется.&lt;br /&gt;
 #&lt;br /&gt;
 if grep -q &amp;quot;^$SYMLINKDEV&amp;quot; /etc/fstab; then&lt;br /&gt;
  grep -v &amp;quot;^$SYMLINKDEV&amp;quot; /etc/fstab &amp;gt; /etc/.fstab.new&lt;br /&gt;
  mv -f /etc/.fstab.new /etc/fstab&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''А этот сценарий согреет душу и сердце и веб-мастера, и владельца сайта: он создаёт резервную копию файлов журналов WEB-сервера'''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-24. Резервное копирование файлов журналов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# archiveweblogs.sh v1.0&lt;br /&gt;
&lt;br /&gt;
# Troy Engel &amp;lt;tengel@fluid.com&amp;gt;&lt;br /&gt;
# С небольшими изменениями, внесёнными автором документа.&lt;br /&gt;
# Используется с разрешения автора.&lt;br /&gt;
#&lt;br /&gt;
# Этот сценарий выполняет резервное копирование&lt;br /&gt;
# файлов журналов из стандартного каталога установки RedHat/Apache.&lt;br /&gt;
# Вставляет дату создания копии в имя файла-архива,&lt;br /&gt;
# сжимает (bzip), и помещает сжатые файлы в заданный каталог.&lt;br /&gt;
#&lt;br /&gt;
# Запускается из crontab ночью в 00 часов,&lt;br /&gt;
# так как bzip2 потребляет значительную часть ресурсов процессора,&lt;br /&gt;
# если журналы достаточно велики:&lt;br /&gt;
# 0 2 * * * /opt/sbin/archiveweblogs.sh&lt;br /&gt;
&lt;br /&gt;
PROBLEM=66&lt;br /&gt;
# Здесь укажите ваш каталог для архивации.&lt;br /&gt;
BKP_DIR=/opt/backups/weblogs&lt;br /&gt;
&lt;br /&gt;
# Настройки Apache/RedHat по-умолчанию&lt;br /&gt;
LOG_DAYS=&amp;quot;4 3 2 1&amp;quot;&lt;br /&gt;
LOG_DIR=/var/log/httpd&lt;br /&gt;
LOG_FILES=&amp;quot;access_log error_log&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Расположение программ в RedHat по-умолчанию&lt;br /&gt;
LS=/bin/ls&lt;br /&gt;
MV=/bin/mv&lt;br /&gt;
ID=/usr/bin/id&lt;br /&gt;
CUT=/bin/cut&lt;br /&gt;
COL=/usr/bin/column&lt;br /&gt;
BZ2=/usr/bin/bzip2&lt;br /&gt;
&lt;br /&gt;
# Проверка прав пользователя?&lt;br /&gt;
USER=`$ID -u`&lt;br /&gt;
if [ &amp;quot;X$USER&amp;quot; != &amp;quot;X0&amp;quot; ]; then&lt;br /&gt;
 echo &amp;quot;PANIC: Только root может запускать этот сценарий!&amp;quot;&lt;br /&gt;
 exit $PROBLEM&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Каталог для резервной копии существует и доступен на запись?&lt;br /&gt;
if [ ! -x $BKP_DIR ]; then&lt;br /&gt;
 echo &amp;quot;PANIC: Каталог $BKP_DIR не найден или не доступен для записи!&amp;quot;&lt;br /&gt;
 exit $PROBLEM&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
# Переместить, переименовать и сжать&lt;br /&gt;
for logday in $LOG_DAYS; do&lt;br /&gt;
 for logfile in $LOG_FILES; do&lt;br /&gt;
  MYFILE=&amp;quot;$LOG_DIR/$logfile.$logday&amp;quot;&lt;br /&gt;
  if [ -w $MYFILE ]; then&lt;br /&gt;
   DTS=`$LS -lgo --time-style=+%Y%m%d $MYFILE | $COL -t | $CUT -d ' ' -f7`&lt;br /&gt;
   $MV $MYFILE $BKP_DIR/$logfile.$DTS&lt;br /&gt;
   $BZ2 $BKP_DIR/$logfile.$DTS&lt;br /&gt;
  else&lt;br /&gt;
   # Выдать сообщение об ошибке, если файл недоступен на запись.&lt;br /&gt;
   if [ -f $MYFILE ]; then&lt;br /&gt;
    echo &amp;quot;ERROR: $MYFILE not writable. Skipping.&amp;quot;&lt;br /&gt;
   fi&lt;br /&gt;
  fi&lt;br /&gt;
 done&lt;br /&gt;
done&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Как предотвратить интерпретацию строки в сценарии'''?&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-25. Предотвращение интерпретации строк символов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
# protect_literal.sh&lt;br /&gt;
# set -vx&lt;br /&gt;
:&amp;lt;&amp;lt;-'_Protect_Literal_String_Doc'&lt;br /&gt;
 Copyright (c) Michael S. Zick, 2003; All Rights Reserved&lt;br /&gt;
 Ограничения: Допускается использовать без каких либо ограничений в любой форме.&lt;br /&gt;
 Гарантии: Никаких&lt;br /&gt;
 Издание: $ID$&lt;br /&gt;
&lt;br /&gt;
 Этот встроенный документ Bash отправит на устройство '/dev/null'.&lt;br /&gt;
 (Раскомментарьте команду set, стоящую выше, чтобы убедиться в этом.)&lt;br /&gt;
 &lt;br /&gt;
 Удалите первую строку (Sha-Bang), если вы собираетесь использовать этот сценарий&lt;br /&gt;
 в качестве библиотеки. Не забудьте при этом закомментарить примеры&lt;br /&gt;
 использования процедур (там где это указано).&lt;br /&gt;
&lt;br /&gt;
 Порядок использования:&lt;br /&gt;
  _protect_literal_str 'Whatever string meets your ${fancy}'&lt;br /&gt;
  Какая бы строка ни была передана функции,&lt;br /&gt;
  она просто будет выведена на stdout,&lt;br /&gt;
  включая &amp;quot;строгие&amp;quot; кавычки.&lt;br /&gt;
&lt;br /&gt;
  $(_protect_literal_str 'Whatever string meets your ${fancy}')&lt;br /&gt;
  как правосторонняя часть операции присваивания.&lt;br /&gt;
&lt;br /&gt;
 Назначение:&lt;br /&gt;
  В операциях присваивания, предотвращают дополнительную&lt;br /&gt;
  интерпретацию содержимого строки, путем добавления &amp;quot;строгих&amp;quot; кавычек.&lt;br /&gt;
&lt;br /&gt;
 Примечание:&lt;br /&gt;
  Имена функций (_*) выбраны таким образом, чтобы избежать&lt;br /&gt;
  конфликтов имён, при подключении данного сценария&lt;br /&gt;
  к пользовательским сценариям, в качестве библиотеки.&lt;br /&gt;
&lt;br /&gt;
_Protect_Literal_String_Doc&lt;br /&gt;
&lt;br /&gt;
_protect_literal_str() {&lt;br /&gt;
 # Выберем неиспользуемый, непечатный символ в качестве разделителя полей для IFS.&lt;br /&gt;
 # В этом нет необходимости, но делается это для демонстрации&lt;br /&gt;
 # того, что разделитель полей игнорируется.&lt;br /&gt;
 local IFS=$'\x1B' # Символ \ESC&lt;br /&gt;
 # Заключим Все-Элементы в &amp;quot;строгие&amp;quot; кавычки.&lt;br /&gt;
 local tmp=$'\x27'$@$'\x27'&lt;br /&gt;
&lt;br /&gt;
 local len=${#tmp} # Исключительно для демонстрации.&lt;br /&gt;
 echo $tmp, длина:$len. # Вывод строки и дополнительной информации.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Версия с более коротким именем.&lt;br /&gt;
_pls() {&lt;br /&gt;
 local IFS=$'x1B'      # Символ \ESC (не обязательно)&lt;br /&gt;
 echo $'\x27'$@$'\x27' # Заключить в &amp;quot;строгие&amp;quot; кавычки&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# :&amp;lt;&amp;lt;-'_Protect_Literal_String_Test'&lt;br /&gt;
# # # Раскомментарьте вышестоящую строку, чтобы запретить исполнение нижеследующего кода. # # #&lt;br /&gt;
&lt;br /&gt;
# Посмотрим как выглядит простой вывод.&lt;br /&gt;
echo&lt;br /&gt;
echo &amp;quot;- - Тест #1 - -&amp;quot;&lt;br /&gt;
&lt;br /&gt;
_protect_literal_str 'Hello $user'&lt;br /&gt;
_protect_literal_str 'Hello &amp;quot;${username}&amp;quot;'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# В результате должно получиться:&lt;br /&gt;
# - - Тест #1 - -&lt;br /&gt;
# 'Hello $user', длина: 13.&lt;br /&gt;
# 'Hello &amp;quot;${username}&amp;quot;', длина: 21.&lt;br /&gt;
&lt;br /&gt;
# Собственно получили то, что и ожидали, тогда в чем проблема?&lt;br /&gt;
# Проблема скрыта внутри Bash, в порядке выполнения операций.&lt;br /&gt;
# Она проявляется, когда функции участвуют в операциях присваивания.&lt;br /&gt;
&lt;br /&gt;
# Объявим массив тестовых значений.&lt;br /&gt;
declare -a arrayZ&lt;br /&gt;
&lt;br /&gt;
# Запишем в массив элементы с разного рода кавычками и экранирующими символами.&lt;br /&gt;
arrayZ=( zero &amp;quot;$(_pls 'Hello ${Me}')&amp;quot; 'Hello ${You}' &amp;quot;\'Pass: ${pw}\'&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
# Теперь выведем массив на экран и посмотрим, что там лежит.&lt;br /&gt;
echo &amp;quot;- - Тест #2 - -&amp;quot;&lt;br /&gt;
for (( i=0 ; i&amp;lt;${#arrayZ[*]} ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo Элемент $i: ${arrayZ[$i]}, длина: ${#arrayZ[$i]}.&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# В результате должно получиться:&lt;br /&gt;
# - - Тест #2 - -&lt;br /&gt;
# Элемент 0: zero, длина: 4. &lt;br /&gt;
# Маркировочный (ничем не примечательный) элемент&lt;br /&gt;
# Элемент 1: 'Hello ${Me}', длина: 13. # Результат &amp;quot;$(_pls '...' )&amp;quot;&lt;br /&gt;
# Элемент 2: Hello ${You}, длина: 12. # Кавычки исчезли&lt;br /&gt;
# Элемент 3: \'Pass: \', длина: 10. # ${pw} -- была интерпретирована,&lt;br /&gt;
#                                   # а на её место подставлена пустая строка&lt;br /&gt;
&lt;br /&gt;
# Выполним присвоение одного массива другому.&lt;br /&gt;
declare -a array2=( ${arrayZ[@]} )&lt;br /&gt;
&lt;br /&gt;
# И выведем его содержимое.&lt;br /&gt;
echo &amp;quot;- - Тест #3 - -&amp;quot;&lt;br /&gt;
for (( i=0 ; i&amp;lt;${#array2[*]} ; i++ ))&lt;br /&gt;
do&lt;br /&gt;
 echo Элемент $i: ${array2[$i]}, длина: ${#array2[$i]}.&lt;br /&gt;
done&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# В результате должно получиться:&lt;br /&gt;
# - - Тест #3 - -&lt;br /&gt;
# Элемент 0: zero, длина: 4.         # Наш маркер.&lt;br /&gt;
# Элемент 1: Hello ${Me}, длина: 11. # Вполне предсказуемый результат.&lt;br /&gt;
# Элемент 2: Hello, длина: 5.        # ${You} -- была интерпретирована.&lt;br /&gt;
#                                    # а на её место подставлена пустая строка&lt;br /&gt;
# Элемент 3: 'Pass:, длина: 6.       # Элемент был &amp;quot;разбит&amp;quot; на два по пробелу.&lt;br /&gt;
# Элемент 4: ', длина: 1.            # Завершающая кавычка попала в отдельный элемент.&lt;br /&gt;
&lt;br /&gt;
# В Элементе 1 были удалены начальная и завершающая &amp;quot;строгие&amp;quot; кавычки.&lt;br /&gt;
# Хотя здесь и не показано, но начальные и завершающие пробелы также удаляются.&lt;br /&gt;
# Теперь, когда содержимое строки установлено, Bash всегда, внутри, будет&lt;br /&gt;
# &amp;quot;строго&amp;quot; окавычивать содержимое строки, на протяжении всей операции&lt;br /&gt;
&lt;br /&gt;
# Зачем это нужно?&lt;br /&gt;
# В нашем случае, в конструкции &amp;quot;$(_pls 'Hello ${Me}')&amp;quot;:&lt;br /&gt;
# &amp;quot; ... &amp;quot; -&amp;gt; Требуется интерпретация (экспансия), кавычки удаляются.&lt;br /&gt;
# $( ... ) -&amp;gt; Замещается результатом выполнения ..., пустая строка.&lt;br /&gt;
# _pls ' ... ' -&amp;gt; вызов функции со строковым аргументом, кавычки удаляются.&lt;br /&gt;
# Возвращаемый результат включает в себя &amp;quot;строгие&amp;quot; кавычки; НО обработка команды&lt;br /&gt;
# уже была завершена выше, так что теперь они становятся частью присваиваемого значения.&lt;br /&gt;
#&lt;br /&gt;
# Таким образом, ${Me} оказывается частью результата&lt;br /&gt;
# и сохраняется в первоначальном виде&lt;br /&gt;
# (До тех пор, пока явно не будет указано на необходимость ее интерпретации).&lt;br /&gt;
&lt;br /&gt;
# Дополнительно: Взгляните, что произойдет, если в этих функциях&lt;br /&gt;
# &amp;quot;строгие&amp;quot; кавычки ($'\x27') заменить на &amp;quot;мягкие&amp;quot; ($'\x22').&lt;br /&gt;
# Интересный результат получится если вообще убрать кавычки.&lt;br /&gt;
&lt;br /&gt;
# _Protect_Literal_String_Test&lt;br /&gt;
# # # Раскомментарьте вышестоящую строку, чтобы запретить исполнение вышестоящего кода. # # #&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''А что делать, если необходимо заставить командный интерпретатор интерпретировать строку'''?&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-26. Принудительная интерпретация строк.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/bash&lt;br /&gt;
# unprotect_literal.sh&lt;br /&gt;
&lt;br /&gt;
# set -vx&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;&amp;lt;-'_UnProtect_Literal_String_Doc'&lt;br /&gt;
 Copyright (c) Michael S. Zick, 2003; All Rights Reserved&lt;br /&gt;
 Ограничения: Допускается использовать без каких либо ограничений в любой форме.&lt;br /&gt;
 Гарантии: Никаких&lt;br /&gt;
 Издание: $ID$&lt;br /&gt;
&lt;br /&gt;
 Этот встроенный документ Bash отправит на устройство '/dev/null'.&lt;br /&gt;
 (Раскомментарьте команду set, стоящую выше, чтобы убедиться в этом.)&lt;br /&gt;
&lt;br /&gt;
 Удалите первую строку (Sha-Bang), если вы собираетесь использовать этот сценарий&lt;br /&gt;
 в качестве библиотеки. Не забудьте при этом закомментарить примеры&lt;br /&gt;
 использования процедур (там где это указано).&lt;br /&gt;
&lt;br /&gt;
 Порядок использования:&lt;br /&gt;
  Противоположная по смыслу функции &amp;quot;$(_pls 'Literal String')&amp;quot;.&lt;br /&gt;
  (см. пример protect_literal.sh)&lt;br /&gt;
&lt;br /&gt;
  StringVar=$(_upls ProtectedSringVariable)&lt;br /&gt;
 &lt;br /&gt;
 Назначение:&lt;br /&gt;
  Выполняет подстановку (интерпретацию) строк в операциях присваивания.&lt;br /&gt;
&lt;br /&gt;
 Примечание:&lt;br /&gt;
  Имена функций (_*) выбраны таким образом, чтобы избежать&lt;br /&gt;
  конфликтов имен, при подключении данного сценария&lt;br /&gt;
  к пользовательским сценариям, в качестве библиотеки.&lt;br /&gt;
&lt;br /&gt;
_UnProtect_Literal_String_Doc&lt;br /&gt;
&lt;br /&gt;
_upls() {&lt;br /&gt;
 local IFS=$'x1B'                 # Символ \ESC character (не обязательно)&lt;br /&gt;
 eval echo $@                     # Принудительная интерпретация.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# :&amp;lt;&amp;lt;-'_UnProtect_Literal_String_Test'&lt;br /&gt;
# # # Раскомментарьте вышестоящую строку, чтобы запретить исполнение нижеследующего кода. # # #&lt;br /&gt;
&lt;br /&gt;
_pls() {&lt;br /&gt;
 local IFS=$'x1B' # Символ \ESC character (не обязательно)&lt;br /&gt;
 echo $'\x27'$@$'\x27' # Заключить в &amp;quot;строгие&amp;quot; кавычки&lt;br /&gt;
}&lt;br /&gt;
# Объявим массив тестовых значений.&lt;br /&gt;
declare -a arrayZ&lt;br /&gt;
&lt;br /&gt;
# Запишем в массив элементы с разного рода кавычками и экранирующими символами.&lt;br /&gt;
arrayZ=( zero &amp;quot;$(_pls 'Hello ${Me}')&amp;quot; 'Hello ${You}' &amp;quot;\'Pass: ${pw}\'&amp;quot; )&lt;br /&gt;
&lt;br /&gt;
# Выполним присвоение одного массива другому.&lt;br /&gt;
declare -a array2=( ${arrayZ[@]} )&lt;br /&gt;
&lt;br /&gt;
# В результате должно получиться:&lt;br /&gt;
# - - Тест #3 - -&lt;br /&gt;
# Элемент 0: zero, длина: 4.          # Наш маркер.&lt;br /&gt;
# Элемент 1: Hello ${Me}, длина: 11.  # Вполне предсказуемый результат.&lt;br /&gt;
# Элемент 2: Hello, длина: 5.         # ${You} — была интерпретирована.&lt;br /&gt;
#                                     # а на её место подставлена пустая строка&lt;br /&gt;
# Элемент 3: 'Pass:, длина: 6.        # Элемент был &amp;quot;разбит&amp;quot; на два по пробелу.&lt;br /&gt;
# Элемент 4: ', длина: 1.             # Завершающая кавычка попала в отдельный элемент.&lt;br /&gt;
&lt;br /&gt;
# set -vx&lt;br /&gt;
&lt;br /&gt;
# Инициализируем переменную 'Me' каким-нибудь значением&lt;br /&gt;
# чтобы увидеть последующую её интерпретацию.&lt;br /&gt;
&lt;br /&gt;
Me=&amp;quot;to the array guy.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Присвоим результат принудительной интерпретации другой переменной.&lt;br /&gt;
newVar=$(_upls ${array2[1]})&lt;br /&gt;
&lt;br /&gt;
# И посмотрим, что получилось.&lt;br /&gt;
echo $newVar&lt;br /&gt;
&lt;br /&gt;
# Так ли необходима эта функция?&lt;br /&gt;
newerVar=$(eval echo ${array2[1]})&lt;br /&gt;
echo $newerVar&lt;br /&gt;
&lt;br /&gt;
# Оказывается совсем не обязательно, но функция _upls делает сценарий&lt;br /&gt;
# более понятным.&lt;br /&gt;
&lt;br /&gt;
# Она поможет в том случае, если вдруг забудется смысл конструкции&lt;br /&gt;
# $(eval echo ... ).&lt;br /&gt;
&lt;br /&gt;
# Что произойдет, если часть строки,&lt;br /&gt;
# которая требует дополнительной интерпретации, окажется неинициализированной?&lt;br /&gt;
unset Me&lt;br /&gt;
newestVar=$(_upls ${array2[1]})&lt;br /&gt;
echo $newestVar&lt;br /&gt;
&lt;br /&gt;
# Просто и со вкусом! Никаких сообщений, никаких предупреждений, никаких ошибок.&lt;br /&gt;
&lt;br /&gt;
# Для чего все это?&lt;br /&gt;
# Одна из основных проблем в Bash — невозможность записать в переменные&lt;br /&gt;
# некоторые последовательности символов&lt;br /&gt;
#&lt;br /&gt;
# Теперь эта проблема разрешается восемью строчками кода&lt;br /&gt;
# (и четырьмя страницами описания).&lt;br /&gt;
&lt;br /&gt;
# Где это можно использовать?&lt;br /&gt;
# Для динамической генерации содержимого Web-страниц,&lt;br /&gt;
# в виде массивов строк.&lt;br /&gt;
&lt;br /&gt;
# Содержимое таких страниц может генерироваться командой Bash 'eval'&lt;br /&gt;
# Я совсем не призываю заменить PHP, просто высказал интересную мысль.&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
# UnProtectLiteralStringTest&lt;br /&gt;
&lt;br /&gt;
# # # Раскомментарьте вышестоящую строку, чтобы запретить исполнение вышестоящего кода. # # #&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''В завершение этого раздела, бросим краткий взгляд назад'''... &lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''A-27. Повторение основ.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# basics-reviewed.bash&lt;br /&gt;
&lt;br /&gt;
# Расширение файла == *.bash == сценарий, использующий особенности Bash&lt;br /&gt;
&lt;br /&gt;
# Copyright (c) Michael S. Zick, 2003; All rights reserved.&lt;br /&gt;
# License: Use in any form, for any purpose.&lt;br /&gt;
# Издание: $ID$&lt;br /&gt;
#&lt;br /&gt;
# Правка, с целью улучшения оформления, выполнена автором книги.&lt;br /&gt;
# (&amp;quot;Advanced Bash Scripting Guide&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
# Этот сценарий тестировался в Bash версий 2.04, 2.05a и 2.05b.&lt;br /&gt;
# Он может не работать в более ранних версиях.&lt;br /&gt;
# Этот сценарий умышленно генерирует ошибку&lt;br /&gt;
# &amp;quot;command not found&amp;quot;. См. строку 394.&lt;br /&gt;
&lt;br /&gt;
# Ведущий разработчик Bash, Chet Ramey, обязался исправить эту проблему&lt;br /&gt;
# в следующих версиях Bash.&lt;br /&gt;
&lt;br /&gt;
###-------------------------------------------###&lt;br /&gt;
### Сценарий выводит много информации на      ###&lt;br /&gt;
### экран, поэтому запускайте его в конвейере ###&lt;br /&gt;
### с командой more                           ###&lt;br /&gt;
###                                           ###&lt;br /&gt;
### Кроме того, вы можете перенаправить       ###&lt;br /&gt;
### вывод в файл, с целью последующего        ###&lt;br /&gt;
### изучения                                  ###&lt;br /&gt;
###-------------------------------------------###&lt;br /&gt;
&lt;br /&gt;
# Большая часть из приводимых здесь моментов описывается&lt;br /&gt;
# в вышеупомянутой книге &amp;quot;Advanced Bash Scripting Guide.&amp;quot;&lt;br /&gt;
# Этот сценарий, по сути можно расценивать как своего рода презентацию.&lt;br /&gt;
# -- msz&lt;br /&gt;
&lt;br /&gt;
# Переменные не типизированы, если не указано обратное.&lt;br /&gt;
&lt;br /&gt;
# Соглашения по именованию переменных.&lt;br /&gt;
# Имена переменных не должны начинаться с цифровых символов.&lt;br /&gt;
# Имена дескрипторов файлов (как например: 2&amp;gt;&amp;amp;1)&lt;br /&gt;
# должны содержать ТОЛЬКО цифры.&lt;br /&gt;
&lt;br /&gt;
# Параметры и элементы массивов Bash — пронумерованы.&lt;br /&gt;
# (Параметры, в этом смысле, очень похожи на массивы.)&lt;br /&gt;
&lt;br /&gt;
# Переменные в Bash могут иметь неопределенное значение.&lt;br /&gt;
unset VarNull&lt;br /&gt;
&lt;br /&gt;
# Переменные в Bash могут быть определены, но содержать &amp;quot;пустое&amp;quot; (null) значение.&lt;br /&gt;
VarEmpty=''&lt;br /&gt;
&lt;br /&gt;
# Переменные могут быть определены и содержать некоторое, непустое значение&lt;br /&gt;
VarSomething='Literal'&lt;br /&gt;
&lt;br /&gt;
# Переменные могут хранить:&lt;br /&gt;
# * Целое 32-битовое число со знаком&lt;br /&gt;
# * Строку символов&lt;br /&gt;
# Переменные могут быть массивом.&lt;br /&gt;
&lt;br /&gt;
# Строки могут содержать пробелы и интерпретироваться&lt;br /&gt;
# как вызов функции с аргументами.&lt;br /&gt;
&lt;br /&gt;
# Имена переменных и имена функций&lt;br /&gt;
# находятся в разных пространствах имен (namespaces).&lt;br /&gt;
&lt;br /&gt;
# Переменные могут быть объявлены массивами как явно, так и неявно&lt;br /&gt;
# в зависимости от семантики операции присваивания.&lt;br /&gt;
# Явно:&lt;br /&gt;
declare -a ArrayVar&lt;br /&gt;
# Команда echo — внутренняя команда.&lt;br /&gt;
&lt;br /&gt;
echo $VarSomething&lt;br /&gt;
# Команда printf — внутренняя команда.&lt;br /&gt;
&lt;br /&gt;
# здесь %s интерпретируется как строка формата&lt;br /&gt;
printf %s $VarSomething # Перевод строки отсутствует, ничего не выводится.&lt;br /&gt;
echo # Выводит только перевод строки.&lt;br /&gt;
&lt;br /&gt;
# Интерпретатор Bash различает отдельные слова по символу пробела между ними.&lt;br /&gt;
# Поэтому наличие или отсутствие пробела — очень важный признак.&lt;br /&gt;
# (В общем случае это так, но есть и исключения из правил.)&lt;br /&gt;
&lt;br /&gt;
# Символ &amp;quot;доллара&amp;quot; ($) интерпретируется как: Content-Of (содержимое для ...).&lt;br /&gt;
&lt;br /&gt;
# Расширенный синтаксис, с использованием символа &amp;quot;доллара&amp;quot;:&lt;br /&gt;
echo ${VarSomething}&lt;br /&gt;
&lt;br /&gt;
# Здесь, конструкция ${ ... }, позволяет указывать&lt;br /&gt;
# не только имена переменных.&lt;br /&gt;
# Как правило, запись $VarSomething&lt;br /&gt;
# всегда может быть представлена в виде : ${VarSomething}.&lt;br /&gt;
&lt;br /&gt;
# Чтобы увидеть следующие операции в действии — вызовите сценарий&lt;br /&gt;
# с несколькими входными аргументами.&lt;br /&gt;
&lt;br /&gt;
# За пределами двойных кавычек, специальные символы @ и *&lt;br /&gt;
# имеют идентичное назначение.&lt;br /&gt;
# Может произноситься как: All-Elements-Of (Все-Элементы-Для).&lt;br /&gt;
&lt;br /&gt;
# Если имя переменной не указано, то эти специальные символы&lt;br /&gt;
# применяются к предопределенным переменным Bash.&lt;br /&gt;
&lt;br /&gt;
echo $* # Все входные параметры сценария или функции&lt;br /&gt;
echo ${*} # То же самое&lt;br /&gt;
# Bash запрещает подстановку имён файлов в вышеупомянутых конструкциях.&lt;br /&gt;
&lt;br /&gt;
# Ссылка на Все-Элементы-Для&lt;br /&gt;
echo $@ # то же самое, что и выше&lt;br /&gt;
echo ${@} # то же самое&lt;br /&gt;
&lt;br /&gt;
# Внутри двойных кавычек, поведение символов @ и *&lt;br /&gt;
# зависит от установки переменной IFS (Input Field Separator — Разделитель Полей).&lt;br /&gt;
# Ссылка на Все-Элементы-Для, внутри двойных кавычек, работает точно так же.&lt;br /&gt;
&lt;br /&gt;
# Обращение к имени переменной означает получение&lt;br /&gt;
# всех элементов (символов) строки.&lt;br /&gt;
&lt;br /&gt;
# Для обращения к отдельным элементам (символам) строки,&lt;br /&gt;
# может использоваться расширенный синтаксис (см. ниже).&lt;br /&gt;
&lt;br /&gt;
# Обращение к имени переменной-массива в Bash&lt;br /&gt;
# означает обращение к нулевому элементу массива,&lt;br /&gt;
# а НЕ к ПЕРВОМУ ОПРЕДЕЛЕННОМУ или к ПЕРВОМУ ИНИЦИАЛИЗИРОВАННОМУ элементу.&lt;br /&gt;
&lt;br /&gt;
# Для обращения к другим элементам массива, необходимо явное указание элемента,&lt;br /&gt;
# это означает, что ДОЛЖЕН использоваться расширенный синтаксис.&lt;br /&gt;
# В общем случае: ${name[subscript]}.&lt;br /&gt;
&lt;br /&gt;
# Для строк может использоваться такая форма записи: ${name:subscript},&lt;br /&gt;
# а также для обращения к нулевому элементу массива.&lt;br /&gt;
&lt;br /&gt;
# Массивы в Bash реализованы как связанные списки,&lt;br /&gt;
# а не как фиксированная область памяти, что характерно для некоторых &lt;br /&gt;
# языков программирования.&lt;br /&gt;
&lt;br /&gt;
# Характеристики массивов в Bash:&lt;br /&gt;
# -------------------------------&lt;br /&gt;
&lt;br /&gt;
# Если не определено иначе, индексация массивов в Bash&lt;br /&gt;
# начинается с нуля: [0]&lt;br /&gt;
# Это называется &amp;quot;индексация с нуля&amp;quot;.&lt;br /&gt;
###&lt;br /&gt;
# Если не указано иначе, массивы в Bash являются упакованными&lt;br /&gt;
# (т.е. массивы просто не содержат элементов с отсутствующими индексами).&lt;br /&gt;
###&lt;br /&gt;
# Отрицательные индексы недопустимы.&lt;br /&gt;
###&lt;br /&gt;
# Элементы массива не обязательно должны быть одного и того же типа.&lt;br /&gt;
###&lt;br /&gt;
# Элементы массива могут быть неинициализированы.&lt;br /&gt;
# Т.е. массив может быть &amp;quot;разреженным&amp;quot;&lt;br /&gt;
###&lt;br /&gt;
# Элементы массива могут быть инициализированы пустым значением.&lt;br /&gt;
###&lt;br /&gt;
# Элементы массива могут содержать:&lt;br /&gt;
# * Целое 32-битовое число со знаком&lt;br /&gt;
# * Строку&lt;br /&gt;
# * Форматированную строку, которая выглядит&lt;br /&gt;
#   как вызов к функции с параметрами&lt;br /&gt;
###&lt;br /&gt;
# Инициализированные элементы массива могут быть деинициализированы (unset).&lt;br /&gt;
# Т.е. массив может быть переупакован так,&lt;br /&gt;
# что он не будет содержать элемента с данным индексом.&lt;br /&gt;
###&lt;br /&gt;
# К массиву могут добавляться дополнительные элементы,&lt;br /&gt;
# не определенные ранее.&lt;br /&gt;
###&lt;br /&gt;
# По этим причинам я называю массивы Bash — &amp;quot;Bash-массивами&amp;quot; (&amp;quot;Bash-Arrays&amp;quot;).&lt;br /&gt;
#&lt;br /&gt;
# -- msz&lt;br /&gt;
&lt;br /&gt;
# Демонстрация вышесказанного — инициализируем ранее объявленный массив ArrayVar&lt;br /&gt;
# как &amp;quot;разреженный&amp;quot; массив.&lt;br /&gt;
# (команда 'unset ... ' используется для демонстрации вышесказанного.)&lt;br /&gt;
&lt;br /&gt;
unset ArrayVar[0]                  # Для демонстрации&lt;br /&gt;
ArrayVar[1]=one                    # Без кавычек&lt;br /&gt;
ArrayVar[2]=''                     # Инициализация пустым значением&lt;br /&gt;
unset ArrayVar[3]                  # Для демонстрации&lt;br /&gt;
ArrayVar[4]='four'                 # В кавычках&lt;br /&gt;
&lt;br /&gt;
# Строка формата %q — трактуется как: Quoted-Respecting-IFS-Rules&lt;br /&gt;
# (в соответствии с установками IFS).&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Вне двойных кавычек - -'&lt;br /&gt;
###&lt;br /&gt;
printf %q ${ArrayVar[*]}           # Шаблон &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'${ArrayVar[*]}&lt;br /&gt;
###&lt;br /&gt;
printf %q ${ArrayVar[@]}           # &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'${ArrayVar[@]}&lt;br /&gt;
&lt;br /&gt;
# Двойные кавычки используются для разрешения операции подстановки&lt;br /&gt;
# внутри кавычек.&lt;br /&gt;
# Существует пять самых распространенных случаев,&lt;br /&gt;
# зависящих от установок переменной IFS.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo '- - В двойных кавычках - По-умолчанию IFS содержит пробел-табуляцию-перевод строки- -'&lt;br /&gt;
IFS=$'\x20'$'\x09'$'\x0A'           # Три байта, и именно в таком порядке.&lt;br /&gt;
&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[*]}&amp;quot;          # Шаблон &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[*]}&amp;quot;&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[@]}&amp;quot;          # &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - В двойных кавычках - Первый символ в IFS: ^ - -'&lt;br /&gt;
# Любой печатаемый, непробельный символ, дает тот же эффект.&lt;br /&gt;
IFS='^'$IFS                         # ^ + пробел табуляция перевод строки###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[*]}&amp;quot;          # Шаблон &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[*]}&amp;quot;&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[@]}&amp;quot;          # &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - В двойных кавычках - IFS не содержит пробела - -'&lt;br /&gt;
IFS='^:%!'&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[*]}&amp;quot;          # Шаблон &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[*]}&amp;quot;&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[@]}&amp;quot;          # &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - В двойных кавычках - переменная IFS пуста - -'&lt;br /&gt;
IFS=''&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[*]}&amp;quot;           # Шаблон &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[*]}&amp;quot;&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[@]}&amp;quot;           # &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - В двойных кавычках - переменная IFS не определена - -'&lt;br /&gt;
unset IFS&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[*]}&amp;quot;           # Шаблон &amp;quot;Все-Элементы-Для&amp;quot; All-Elements-Of&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[*]}&amp;quot;&lt;br /&gt;
###&lt;br /&gt;
printf %q &amp;quot;${ArrayVar[@]}&amp;quot;           # &amp;quot;Все-Элементы-Для&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
echo 'команда echo:'&amp;quot;${ArrayVar[@]}&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# Вернём переменную IFS в первоначальное состояние,&lt;br /&gt;
# записав в неё значение по-умолчанию.&lt;br /&gt;
&lt;br /&gt;
IFS=$'\x20'$'\x09'$'\x0A'             # точно в таком порядке.&lt;br /&gt;
&lt;br /&gt;
# Интерпретация результатов, полученных выше:&lt;br /&gt;
# Форма ввода по шаблону &amp;quot;Все-Элементы-Для&amp;quot; зависит от содержимого переменной&lt;br /&gt;
###&lt;br /&gt;
# Простой вывод &amp;quot;Всех-Элементов-Для&amp;quot; не зависит от содержимого переменной IFS.&lt;br /&gt;
###&lt;br /&gt;
# Обратите внимание на различия, имеющиеся в выводе         &lt;br /&gt;
# от команд echo и printf с форматом %q.&lt;br /&gt;
&lt;br /&gt;
# Давайте вспомним:&lt;br /&gt;
# Параметры очень похожи на массивы и имеют сходное поведение.&lt;br /&gt;
###&lt;br /&gt;
# Примеры выше показывают, что для того, чтобы вывести разреженный&lt;br /&gt;
# массив полностью, необходимо писать дополнительный код.&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
# Длина строки равна количеству ненулевых элементов (символов):&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Имя переменной употребляется вне кавычек - -'&lt;br /&gt;
echo 'Количество ненулевых символов: '${#VarSomething}'.'&lt;br /&gt;
&lt;br /&gt;
# test='Lit'$'\x00''eral'             # $'\x00' — нулевой (null) символ.&lt;br /&gt;
# echo ${#test}                       # Что получится?&lt;br /&gt;
&lt;br /&gt;
# Длина массива равна количеству инициализированных элементов,&lt;br /&gt;
# включая элементы, инициализированные пустыми значениями.&lt;br /&gt;
echo&lt;br /&gt;
echo 'Количество инициализированных элементов в массиве: '${#ArrayVar[@]}'.'&lt;br /&gt;
# Это НЕ максимальный индекс массива (4).&lt;br /&gt;
# Это НЕ ширина диапазона (1 . . 4 включительно).&lt;br /&gt;
# Это длина связного списка.&lt;br /&gt;
###&lt;br /&gt;
# Максимальный номер индекса массива и диапазон индексов&lt;br /&gt;
# могут быть найдены, но для этого потребуется дополнительный код.&lt;br /&gt;
&lt;br /&gt;
# Длина строки равна количеству ненулевых элементов (символов):&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Имя переменной употребляется в кавычках - -'&lt;br /&gt;
echo 'Количество непустых символов: '&amp;quot;${#VarSomething}&amp;quot;'.'&lt;br /&gt;
&lt;br /&gt;
# Длина массива равна количеству инициализированных элементов,&lt;br /&gt;
# включая элементы, инициализированные пустыми значениями.&lt;br /&gt;
echo&lt;br /&gt;
echo 'Количество инициализированных элементов в массиве: '&amp;quot;${#ArrayVar[*]}&amp;quot;'.'&lt;br /&gt;
&lt;br /&gt;
# Вывод: Конструкция ${# ... } не производит подстановку.&lt;br /&gt;
# Совет:&lt;br /&gt;
# Всегда используйте символ All-Elements-Of (Все-Элементы-Для)&lt;br /&gt;
# если желаете получить результат, не зависящий от содержимого переменной IFS.&lt;br /&gt;
&lt;br /&gt;
# Определим простую функцию.&lt;br /&gt;
# Я включил в имя функции символ подчеркивания&lt;br /&gt;
# чтобы как-то обозначить, что это функция, а не переменная.&lt;br /&gt;
###&lt;br /&gt;
# Bash различает имена функций и переменных,&lt;br /&gt;
# размещая из в различных пространствах имён.&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
_simple() {&lt;br /&gt;
 echo -n 'SimpleFunc'$@                 # Символ перевода строки в любом случае&lt;br /&gt;
}                                       # будет &amp;quot;съеден&amp;quot;.&lt;br /&gt;
# Конструкция ( ... ) вызывает команду или функцию.&lt;br /&gt;
# Форма записи $( ... ) произносится как: Result-Of (Результат-Выполнения).&lt;br /&gt;
&lt;br /&gt;
# Вызовем функцию _simple&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Результат работы функции _simple - -'&lt;br /&gt;
&lt;br /&gt;
_simple                                 # Попробуйте передать несколько аргументов.&lt;br /&gt;
echo&lt;br /&gt;
# или&lt;br /&gt;
(_simple)                               # Попробуйте передать несколько аргументов.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo '- Существует ли переменная с таким именем? -'&lt;br /&gt;
echo $_simple not defined # Нет переменной с таким именем.&lt;br /&gt;
&lt;br /&gt;
# Обращение к результату выполнения функции _simple&lt;br /&gt;
# (будет получено сообщение об ошибке)&lt;br /&gt;
###&lt;br /&gt;
$(_simple)                              # Генерирует сообщение об ошибке:&lt;br /&gt;
# line 394: SimpleFunc: command not found&lt;br /&gt;
# ---------------------------------------&lt;br /&gt;
echo&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
# Причина ошибки вполне очевидна: результат работы функции _simple не есть&lt;br /&gt;
# ни команда Bash, ни имя определенной ранее функции.&lt;br /&gt;
###&lt;br /&gt;
# Этот пример показывает, что вывод от функции _simple подвергается&lt;br /&gt;
# дополнительной интерпретации.&lt;br /&gt;
###&lt;br /&gt;
# Вывод:&lt;br /&gt;
# Функция может использоваться для генерации команд Bash.&lt;br /&gt;
&lt;br /&gt;
# Простая функция, которая выводит команду bash:&lt;br /&gt;
###&lt;br /&gt;
_print() {&lt;br /&gt;
 echo -n 'printf %q '$@&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo '- - Результат работы функции _print - -'&lt;br /&gt;
_print parm1 parm2                       # Простой вывод — НЕ команда.&lt;br /&gt;
echo&lt;br /&gt;
$(_print parm1 parm2)                    # Исполняет команду printf %q parm1 parm2&lt;br /&gt;
                                         # См. пример с IFS выше&lt;br /&gt;
                                         # на предмет дополнительных возможностей.&lt;br /&gt;
echo&lt;br /&gt;
$(_print $VarSomething)                  # Вполне предсказуемый результат.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Переменные-функции&lt;br /&gt;
# ------------------&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Переменные-функции - -'&lt;br /&gt;
# Переменная может хранить целое число, строку или массив.&lt;br /&gt;
# Строка может интерпретироваться как вызов функции.&lt;br /&gt;
&lt;br /&gt;
# set -vx                               # Раскомментарьте при желании&lt;br /&gt;
&lt;br /&gt;
declare -f funcVar                      # в пространстве имён функций!&lt;br /&gt;
&lt;br /&gt;
funcVar=_print                          # Записать имя функции.&lt;br /&gt;
$funcVar parm1                          # Аналогично вызову функции _print.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
funcVar=$(_print )                      # Результат работы функции.&lt;br /&gt;
$funcVar                                # Нет ни ввода, ни вывода.&lt;br /&gt;
$funcVar $VarSomething                  # Предсказуемый результат.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
funcVar=$(_print $VarSomething)         # Здесь выполняется подстановка&lt;br /&gt;
                                        # значения переменной $VarSomething.&lt;br /&gt;
&lt;br /&gt;
$funcVar                                # Содержимое переменной $VarSomething&lt;br /&gt;
echo                                    # стало частью переменной $funcVar&lt;br /&gt;
&lt;br /&gt;
funcVar=&amp;quot;$(_print $VarSomething)&amp;quot;       # Здесь выполняется подстановка&lt;br /&gt;
                                        # значения переменной $VarSomething.&lt;br /&gt;
&lt;br /&gt;
$funcVar                                # Содержимое переменной $VarSomething&lt;br /&gt;
echo                                    # стало частью переменной $funcVar&lt;br /&gt;
&lt;br /&gt;
# Различия в применении или неприменении двойных кавычек&lt;br /&gt;
# объясняются в примере &amp;quot;protect_literal.sh&amp;quot;.&lt;br /&gt;
# В первом случае Bash обрабатывает строку как два отдельных слова,&lt;br /&gt;
# во втором — как одно слово в кавычках с пробелом внутри слова.&lt;br /&gt;
&lt;br /&gt;
# Отложенная подстановка&lt;br /&gt;
# ----------------------&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Отложенная подстановка - -'&lt;br /&gt;
funcVar=&amp;quot;$(_print '$VarSomething')&amp;quot;       # Подстановка значения переменной не производится.&lt;br /&gt;
eval $funcVar                             # Подстановка производится ЗДЕСЬ.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
VarSomething='NewThing'&lt;br /&gt;
eval $funcVar                             # Подстановка производится ЗДЕСЬ.&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Восстановим прежнее значение переменной VarSomething.&lt;br /&gt;
VarSomething=Literal&lt;br /&gt;
# В примерах &amp;quot;protect_literal.sh&amp;quot; и &amp;quot;unprotect_literal.sh&amp;quot;&lt;br /&gt;
# вы найдёте две функции, которые выполняют отложенную подстановку&lt;br /&gt;
# значений переменных.&lt;br /&gt;
&lt;br /&gt;
# ОБЗОР:&lt;br /&gt;
# -----&lt;br /&gt;
&lt;br /&gt;
# Строки могут рассматриваться как классический массив элементов-символов.&lt;br /&gt;
# Строковые операции воздействуют на все элементы (символы) строки&lt;br /&gt;
###&lt;br /&gt;
# Запись: ${array_name[@]} представляет все элементы&lt;br /&gt;
# Bash-Массива: array_name.&lt;br /&gt;
###&lt;br /&gt;
# Строковые операции, в расширенном синтаксисе, могут манипулировать&lt;br /&gt;
# всеми элементами массива сразу.&lt;br /&gt;
###&lt;br /&gt;
# Эта способность может рассматриваться как операция For-Each над вектором строк.&lt;br /&gt;
###&lt;br /&gt;
# Параметры подобны массивам.&lt;br /&gt;
# Различия в параметрах для функции и сценария касаются только параметра&lt;br /&gt;
# ${0}, который никогда не изменяется.&lt;br /&gt;
###&lt;br /&gt;
# Нулевой параметр сценария содержит имя файла сценария&lt;br /&gt;
###&lt;br /&gt;
# Нулевой параметр функции НЕ СОДЕРЖИТ имени функции.&lt;br /&gt;
# Имя функции хранится в служебной переменной $FUNCNAME.&lt;br /&gt;
###&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Тест (без изменения содержимого переменной) - -'&lt;br /&gt;
echo '- неинициализированная переменная -'&lt;br /&gt;
echo -n ${VarNull-'NotSet'}' '            # NotSet&lt;br /&gt;
echo ${VarNull}                           # только перевод строки&lt;br /&gt;
echo -n ${VarNull:-'NotSet'}' '           # NotSet&lt;br /&gt;
&lt;br /&gt;
echo ${VarNull}                           # только перевод строкиecho '- &amp;quot;пустая&amp;quot; переменная -'&lt;br /&gt;
echo -n ${VarEmpty-'Empty'}' '            # только пробел&lt;br /&gt;
echo ${VarEmpty}                          # только перевод строки&lt;br /&gt;
echo -n ${VarEmpty:-'Empty'}' '           # Empty&lt;br /&gt;
echo ${VarEmpty}                          # только перевод строки&lt;br /&gt;
&lt;br /&gt;
echo '- непустая переменная -'&lt;br /&gt;
echo ${VarSomething-'Content'}            # Literal&lt;br /&gt;
echo ${VarSomething:-'Content'}           # Literal&lt;br /&gt;
&lt;br /&gt;
echo '- Разреженный массив -'&lt;br /&gt;
echo ${ArrayVar[@]-'not set'}&lt;br /&gt;
&lt;br /&gt;
# ASCII-Art      time&lt;br /&gt;
#      State Y==yes, N==no&lt;br /&gt;
#            -       :-&lt;br /&gt;
# Unset      Y       Y        ${# ... } == 0&lt;br /&gt;
# Empty      N       Y        ${# ... } == 0&lt;br /&gt;
# Contents   N       N        ${# ... } &amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
# Либо первая, либо вторая часть операции подстановки параметра по-умолчанию&lt;br /&gt;
# может быть командой или вызовом функции.&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Тест 1, не определенная переменная - -'&lt;br /&gt;
declare -i t&lt;br /&gt;
_decT() {&lt;br /&gt;
 t=$t-1&lt;br /&gt;
}&lt;br /&gt;
# Для не определенной переменной: t == -1&lt;br /&gt;
t=${#VarNull}                  # t == 0&lt;br /&gt;
${VarNull- _decT }             # Вызов функции, теперь t == -1.&lt;br /&gt;
echo $t&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;Пустая&amp;quot; переменная: t == 0&lt;br /&gt;
t=${#VarEmpty}                 # t == 0&lt;br /&gt;
${VarEmpty- _decT }            # Функция _decT НЕ вызывается.&lt;br /&gt;
echo $t&lt;br /&gt;
&lt;br /&gt;
# Непустая переменная: t == число непустых символов&lt;br /&gt;
VarSomething='_simple'         # Записать имя функции в переменную.&lt;br /&gt;
t=${#VarSomething}             # ненулевая длина&lt;br /&gt;
${VarSomething- _decT }        # Вызывается функция _simple.&lt;br /&gt;
echo $t                        # Обратите внимание на вывод.&lt;br /&gt;
&lt;br /&gt;
# Упражнение: Разберитесь в этом примере.&lt;br /&gt;
unset t&lt;br /&gt;
unset _decT&lt;br /&gt;
VarSomething=Literal&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Тест (с изменением содержимого переменной) - -'&lt;br /&gt;
echo '- Присвоить, если переменная не определена -'&lt;br /&gt;
echo -n ${VarNull='NotSet'}' '  # NotSet NotSet&lt;br /&gt;
echo ${VarNull}&lt;br /&gt;
unset VarNull&lt;br /&gt;
&lt;br /&gt;
echo '- Присвоить, если переменная не определена -'&lt;br /&gt;
echo -n ${VarNull:='NotSet'}' ' # NotSet NotSet&lt;br /&gt;
echo ${VarNull}&lt;br /&gt;
unset VarNull&lt;br /&gt;
&lt;br /&gt;
echo '- Не присваивать, если переменная пуста -'&lt;br /&gt;
echo -n ${VarEmpty='Empty'}' '  # только пробел&lt;br /&gt;
echo ${VarEmpty}&lt;br /&gt;
VarEmpty=''&lt;br /&gt;
&lt;br /&gt;
echo '- Присвоить, если переменная пуста -'&lt;br /&gt;
echo -n ${VarEmpty:='Empty'}' ' # Empty Empty&lt;br /&gt;
echo ${VarEmpty}&lt;br /&gt;
VarEmpty=''&lt;br /&gt;
&lt;br /&gt;
echo '- Не изменять, если переменная не пуста -'&lt;br /&gt;
echo ${VarSomething='Content'}  # Literal&lt;br /&gt;
echo ${VarSomething:='Content'} # Literal&lt;br /&gt;
&lt;br /&gt;
# &amp;quot;Разреженные&amp;quot; Bash-Массивы&lt;br /&gt;
###&lt;br /&gt;
# Bash-Массивы не содержат пустых элементов, и индексация их,&lt;br /&gt;
# если не оговорено иное, начинается с нуля.&lt;br /&gt;
###&lt;br /&gt;
# Инициализируем массив ArraySparse как раз тем способом,&lt;br /&gt;
# когда &amp;quot;оговорено иное&amp;quot;. Ниже приведен один из вариантов:&lt;br /&gt;
###&lt;br /&gt;
echo&lt;br /&gt;
declare -a ArraySparse&lt;br /&gt;
ArraySparse=( [1]=one [2]='' [4]='four' )&lt;br /&gt;
# [0]=нет элемента, [2]=пустой элемент, [3]=нет элемента&lt;br /&gt;
&lt;br /&gt;
echo '- - Разреженный массив - -'&lt;br /&gt;
# В двойных кавычках, значение IFS -- по-умолчанию, Все-Элементы-Для&lt;br /&gt;
&lt;br /&gt;
IFS=$'\x20'$'\x09'$'\x0A'printf %q &amp;quot;${ArraySparse[*]}&amp;quot;&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание на отсутствие различий в том, как выводятся отсутствующий&lt;br /&gt;
# и пустой элементы массива.&lt;br /&gt;
# Оба выводятся как экранированные пробелы.&lt;br /&gt;
###&lt;br /&gt;
# Не упустите из виду и то, что все неопределенные элементы массива,&lt;br /&gt;
# предшествующие первому инициализированному элементу, не выводятся&lt;br /&gt;
###&lt;br /&gt;
# Замечание о таком &amp;quot;поведении&amp;quot; Bash, версий 2.04, 2.05a и 2.05b,&lt;br /&gt;
# было передано разработчикам has been reported&lt;br /&gt;
# и возможно будет изменено в последующих версиях Bash.&lt;br /&gt;
&lt;br /&gt;
# Чтобы вывести содержимое такого разреженного массива без изменений&lt;br /&gt;
# требуется некоторое количество усилий.&lt;br /&gt;
# Вот один из возможных вариантов вывода такого массива:&lt;br /&gt;
###&lt;br /&gt;
# local l=${#ArraySparse[@]}       # Количество инициализированных элементов&lt;br /&gt;
# local f=0                        # Количество найденных индексов&lt;br /&gt;
# local i=0                        # текущий индекс&lt;br /&gt;
&lt;br /&gt;
(                                  # Анонимная функция&lt;br /&gt;
 for (( l=${#ArraySparse[@]}, f = 0, i = 0 ; f &amp;lt; l ; i++ ))&lt;br /&gt;
 do&lt;br /&gt;
  # 'if defined then...'&lt;br /&gt;
  ${ArraySparse[$i]+ eval echo '\ ['$i']='${ArraySparse[$i]} ; (( f++ )) }&lt;br /&gt;
 done&lt;br /&gt;
)&lt;br /&gt;
&lt;br /&gt;
# Важно:&lt;br /&gt;
# Команда &amp;quot;read -a array_name&amp;quot; начинает заполнять массив&lt;br /&gt;
# array_name с нулевого элемента.&lt;br /&gt;
# ArraySparse -- не содержит нулевого элемента.&lt;br /&gt;
###&lt;br /&gt;
# Для выполнения операций над разреженными массивами,&lt;br /&gt;
# такими как чтение/запись массива из/в файла&lt;br /&gt;
# программист должен сам создать программный код, который&lt;br /&gt;
# будет удовлетворять его потребности.&lt;br /&gt;
###&lt;br /&gt;
# Упражнение: разберитесь в следующем примере самостоятельно.&lt;br /&gt;
&lt;br /&gt;
unset ArraySparse&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Замена по условию (замена не производится)- -'&lt;br /&gt;
echo '- Не изменять если переменная не определена -'&lt;br /&gt;
echo -n ${VarNull+'NotSet'}' '&lt;br /&gt;
echo ${VarNull}&lt;br /&gt;
unset VarNull&lt;br /&gt;
&lt;br /&gt;
echo '- Не изменять если переменная не определена -'&lt;br /&gt;
echo -n ${VarNull:+'NotSet'}' '&lt;br /&gt;
echo ${VarNull}&lt;br /&gt;
unset VarNull&lt;br /&gt;
&lt;br /&gt;
echo '- Изменить если переменная пуста -'&lt;br /&gt;
echo -n ${VarEmpty+'Empty'}' ' # Empty&lt;br /&gt;
echo ${VarEmpty}&lt;br /&gt;
VarEmpty=''&lt;br /&gt;
&lt;br /&gt;
echo '- Не изменять если переменная пуста -'&lt;br /&gt;
echo -n ${VarEmpty:+'Empty'}' '          # Только пробел &lt;br /&gt;
echo ${VarEmpty}&lt;br /&gt;
VarEmpty=''&lt;br /&gt;
&lt;br /&gt;
echo '- Изменить, если переменная не пуста -'&lt;br /&gt;
&lt;br /&gt;
echo -n ${VarSomething+'Content'}' '     # Content Literal&lt;br /&gt;
echo ${VarSomething}&lt;br /&gt;
&lt;br /&gt;
# Вызов функции&lt;br /&gt;
echo -n ${VarSomething:+ $(_simple) }' ' # SimpleFunc Literal&lt;br /&gt;
echo ${VarSomething}&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Разреженный массив - -'&lt;br /&gt;
echo ${ArrayVar[@]+'Empty'}              # An array of 'Empty'(ies)&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo '- - Тест 2, неопределенные переменные - -'&lt;br /&gt;
&lt;br /&gt;
declare -i t&lt;br /&gt;
_incT() {&lt;br /&gt;
 t=$t+1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Обратите внимание:&lt;br /&gt;
# Тот же самый тест, что и в случае с разреженными массивами&lt;br /&gt;
&lt;br /&gt;
# Неопределенная переменная: t == -1&lt;br /&gt;
t=${#VarNull}-1                        # t == -1&lt;br /&gt;
${VarNull+ _incT }                     # Функция не вызывается.&lt;br /&gt;
&lt;br /&gt;
echo $t' Переменная не определена'&lt;br /&gt;
&lt;br /&gt;
# Пустая переменная: t == 0&lt;br /&gt;
t=${#VarEmpty}-1                       # t == -1&lt;br /&gt;
${VarEmpty+ _incT }                    # Вызов функции.&lt;br /&gt;
echo $t' Переменная пуста'&lt;br /&gt;
# Переменная не пуста: t == (количество непустых символов)&lt;br /&gt;
t=${#VarSomething}-1                   # количество_непустых_символов минус один&lt;br /&gt;
${VarSomething+ _incT }                # Вызов функции.&lt;br /&gt;
echo $t' Переменная не пуста'&lt;br /&gt;
&lt;br /&gt;
# Операции над элементами массива&lt;br /&gt;
# -------------------------------&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Выборка элементов - -'&lt;br /&gt;
&lt;br /&gt;
# Строки, массивы и позиционные параметры&lt;br /&gt;
# Чтобы увидеть работу сценария с позиционными параметрами,&lt;br /&gt;
# вызовите его с несколькими аргументами&lt;br /&gt;
&lt;br /&gt;
echo '- Все -'&lt;br /&gt;
echo ${VarSomething:0}                  # все не пустые символы&lt;br /&gt;
echo ${ArrayVar[@]:0}                   # все не пустые элементы&lt;br /&gt;
echo ${@:0}                             # все не пустые параметры;&lt;br /&gt;
                                        # параметр [0] игнорируется&lt;br /&gt;
echo&lt;br /&gt;
echo '- Все после -'&lt;br /&gt;
echo ${VarSomething:1}                  # все не пустые символы, стоящие после [0]&lt;br /&gt;
echo ${ArrayVar[@]:1}                   # все не пустые элементы, стоящие после [0]&lt;br /&gt;
echo ${@:2}                             # все не пустые параметры, стоящие после [1]&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Диапазон символов -'&lt;br /&gt;
echo ${VarSomething:4:3}                # ral &lt;br /&gt;
                                        # Три символа, следующие за символом [3]&lt;br /&gt;
echo '- Разреженный массив -'&lt;br /&gt;
echo ${ArrayVar[@]:1:2}                 # four - Единственный непустой элемент.&lt;br /&gt;
&lt;br /&gt;
# Чтобы убедиться в том, что Bash в данной ситуации рассматривает только&lt;br /&gt;
# непустые элементы&lt;br /&gt;
&lt;br /&gt;
# printf %q &amp;quot;${ArrayVar[@]:0:3}&amp;quot;        # Попробуйте раскомментарить эту строку&lt;br /&gt;
&lt;br /&gt;
# Версии Bash 2.04, 2.05a и 2.05b,&lt;br /&gt;
# работают с разреженными массивами не так как ожидается.&lt;br /&gt;
#&lt;br /&gt;
# Chet Ramey обещал исправить это в последующих версиях Bash.&lt;br /&gt;
&lt;br /&gt;
echo '- Неразреженный массив -'&lt;br /&gt;
echo ${@:2:2}                           # За параметром [1] следуют ещё два параметра&lt;br /&gt;
&lt;br /&gt;
# Простые примеры со строками и массивами строк:&lt;br /&gt;
stringZ=abcABC123ABCabc&lt;br /&gt;
arrayZ=( abcabc ABCABC 123123 ABCABC abcabc )&lt;br /&gt;
sparseZ=( [1]='abcabc' [3]='ABCABC' [4]='' [5]='123123' )&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo ' - - Простая строка - -'$stringZ'- - '&lt;br /&gt;
echo ' - - Простой массив - -'${arrayZ[@]}'- - '&lt;br /&gt;
echo ' - - Разреженный массив - -'${sparseZ[@]}'- - '&lt;br /&gt;
echo ' - [0]==нет элемента, [2]==нет элемента, [4]==пустой элемент - '&lt;br /&gt;
echo ' - [1]=abcabc [3]=ABCABC [5]=123123 - '&lt;br /&gt;
echo ' - количество инициализированных элементов: '${#sparseZ[@]}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Префиксы - -'&lt;br /&gt;
echo '- - Шаблон должен совпадать с первым символом строки. - -'&lt;br /&gt;
echo '- - Шаблон может быть строкой или результатом работы функции. - -'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Функция, результатом работы которой является обычная строка&lt;br /&gt;
_abc() {&lt;br /&gt;
 echo -n 'abc'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo '- Кратчайший префикс -'&lt;br /&gt;
echo ${stringZ#123}                   # Без изменения — не префикс.&lt;br /&gt;
echo ${stringZ#$(abc)}                # ABC123ABCabc&lt;br /&gt;
echo ${arrayZ[@]#abc}                 # Применяется к каждому элементу массива.&lt;br /&gt;
&lt;br /&gt;
# Chet Ramey обещал исправить в последующих версиях Bash.&lt;br /&gt;
# echo ${sparseZ[@]#abc}              # В версии 2.05b — core dumps.&lt;br /&gt;
&lt;br /&gt;
# -Это было бы здорово- First-Subscript-Of (Первый-Индекс-Массива)&lt;br /&gt;
# echo ${#sparseZ[@]#*} # line 805: ${#sparseZ[@]#*}: bad substitution.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Наибольший префикс -'&lt;br /&gt;
echo ${stringZ##1*3}                  # Без изменения — не префикс.&lt;br /&gt;
echo ${stringZ##a*C}                  # abc&lt;br /&gt;
echo ${arrayZ[@]##a*c}                # ABCABC 123123 ABCABC&lt;br /&gt;
# Chet Ramey обещал исправить в последующих версиях Bash.&lt;br /&gt;
# echo ${sparseZ[@]##a*c}             # В версии 2.05b — core dumps.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Суффиксы - -'&lt;br /&gt;
echo '- - Шаблон должен совпадать с последним символом строки. - -'&lt;br /&gt;
echo '- - Шаблон может быть строкой или результатом работы функции. - -'&lt;br /&gt;
echo&lt;br /&gt;
echo '- Кратчайший суффикс -'&lt;br /&gt;
echo ${stringZ%1*3}                   # Без изменения — не суффикс.&lt;br /&gt;
echo ${stringZ%$(_abc)}               # abcABC123ABC&lt;br /&gt;
echo ${arrayZ[@]%abc}                 # Применяется к каждому элементу массива.&lt;br /&gt;
&lt;br /&gt;
# Chet Ramey обещал исправить в последующих версиях Bash.&lt;br /&gt;
# echo ${sparseZ[@]%abc}              # В версии 2.05b — core dumps.&lt;br /&gt;
&lt;br /&gt;
# -Это было бы здорово- Last-Subscript-Of (Последний-Индекс-Массива)&lt;br /&gt;
# echo ${#sparseZ[@]%*} # line 830: ${#sparseZ[@]%*}: bad substitution&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Наибольший суффикс -'&lt;br /&gt;
echo ${stringZ%%1*3}                  # Без изменения — не суффикс.&lt;br /&gt;
echo ${stringZ%%b*c}                  # a&lt;br /&gt;
echo ${arrayZ[@]%%b*c}                # a ABCABC 123123 ABCABC a&lt;br /&gt;
&lt;br /&gt;
# Chet Ramey обещал исправить в последующих версиях Bash.&lt;br /&gt;
# echo ${sparseZ[@]%%b*c}             # В версии 2.05b — core dumps.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Замена подстроки - -'&lt;br /&gt;
echo '- - Подстрока может находиться в любом месте в строке. - -'&lt;br /&gt;
echo '- - Первый описатель задает шаблон поиска - -'&lt;br /&gt;
echo '- - Шаблон может быть строкой или результатом работы функции. - -'&lt;br /&gt;
echo '- - Второй описатель может быть строкой или результатом работы функции. - -'&lt;br /&gt;
echo '- - Второй описатель может быть опущен. В результате получится:'&lt;br /&gt;
echo ' Заменить-Ничем (Удалить) - -'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
# Функция, результатом работы которой является обычная строка&lt;br /&gt;
_123() {&lt;br /&gt;
 echo -n '123'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
echo '- Замена первого вхождения -'&lt;br /&gt;
echo ${stringZ/$(_123)/999}            # Подстрока 123 заменена на 999).&lt;br /&gt;
echo ${stringZ/ABC/xyz}                # xyzABC123ABCabc&lt;br /&gt;
echo ${arrayZ[@]/ABC/xyz}              # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]/ABC/xyz}             # Работает так как и ожидается.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Удаление первого вхождения -'&lt;br /&gt;
echo ${stringZ/$(_123)/}&lt;br /&gt;
echo ${stringZ/ABC/}&lt;br /&gt;
echo ${arrayZ[@]/ABC/}&lt;br /&gt;
echo ${sparseZ[@]/ABC/}&lt;br /&gt;
&lt;br /&gt;
# Замещающий элемент необязательно должен быть строкой,&lt;br /&gt;
# допускается употреблять результат функции.&lt;br /&gt;
# Это применимо ко всем формам замены.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Замена первого вхождения результатом работы функции -'&lt;br /&gt;
echo ${stringZ/$(_123)/$(_simple)}     # Работает так как и ожидается.&lt;br /&gt;
echo ${arrayZ[@]/ca/$(_simple)}        # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]/ca/$(_simple)}       # Работает так как и ожидается.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Замена всех вхождений -'&lt;br /&gt;
echo ${stringZ//[b2]/X}                # все символы b и 2 заменяются символом X&lt;br /&gt;
echo ${stringZ//abc/xyz}               # xyzABC123ABCxyz&lt;br /&gt;
echo ${arrayZ[@]//abc/xyz}             # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]//abc/xyz}            # Работает так как и ожидается.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Удаление всех вхождений -'&lt;br /&gt;
echo ${stringZ//[b2]/}&lt;br /&gt;
echo ${stringZ//abc/}&lt;br /&gt;
echo ${arrayZ[@]//abc/}&lt;br /&gt;
echo ${sparseZ[@]//abc/}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Замена префикса - -'&lt;br /&gt;
echo '- - Шаблон должен совпадать с первым символом строки. - -'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo '- - Замена префикса - -'&lt;br /&gt;
echo ${stringZ/#[b2]/X}                 # Без изменения — не префикс.&lt;br /&gt;
echo ${stringZ/#$(_abc)/XYZ}            # XYZABC123ABCabc&lt;br /&gt;
echo ${arrayZ[@]/#abc/XYZ}              # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]/#abc/XYZ}             # Работает так как и ожидается.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Удаление префикса -'&lt;br /&gt;
echo ${stringZ/#[b2]/}&lt;br /&gt;
echo ${stringZ/#$(_abc)/}&lt;br /&gt;
echo ${arrayZ[@]/#abc/}&lt;br /&gt;
echo ${sparseZ[@]/#abc/}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Замена суффикса - -'&lt;br /&gt;
echo '- - Шаблон должен совпадать с последним символом строки. - -'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo '- - Замена суффикса - -'&lt;br /&gt;
echo ${stringZ/%[b2]/X}                 # Без изменения — не суффикс.&lt;br /&gt;
echo ${stringZ/%$(_abc)/XYZ}            # abcABC123ABCXYZ&lt;br /&gt;
echo ${arrayZ[@]/%abc/XYZ}              # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]/%abc/XYZ}             # Работает так как и ожидается.&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Удаление суффикса -'&lt;br /&gt;
echo ${stringZ/%[b2]/}&lt;br /&gt;
echo ${stringZ/%$(_abc)/}&lt;br /&gt;
echo ${arrayZ[@]/%abc/}&lt;br /&gt;
echo ${sparseZ[@]/%abc/}&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Специальный случай -- пустой шаблон поиска - -'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
echo '- Префикс -'&lt;br /&gt;
# пустой шаблон означает простую вставку в начало строки&lt;br /&gt;
echo ${stringZ/#/NEW}                   # NEWabcABC123ABCabc&lt;br /&gt;
echo ${arrayZ[@]/#/NEW}                 # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]/#/NEW}                # И к неинициализированным элементам тоже&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- Суффикс -'&lt;br /&gt;
# пустой шаблон означает простое добавление в конец строки&lt;br /&gt;
echo ${stringZ/%/NEW}                   # abcABC123ABCabcNEW&lt;br /&gt;
echo ${arrayZ[@]/%/NEW}                 # Применяется ко всем элементам массива.&lt;br /&gt;
echo ${sparseZ[@]/%/NEW}                # И к неинициализированным элементам тоже&lt;br /&gt;
&lt;br /&gt;
echo&lt;br /&gt;
echo '- - Специальный случай оператора For-Each - -'&lt;br /&gt;
echo '- - - - This is a nice-to-have dream - - - -'&lt;br /&gt;
echo&lt;br /&gt;
&lt;br /&gt;
_GenFunc() {&lt;br /&gt;
 echo -n ${0}                            # Только как иллюстрация.&lt;br /&gt;
 # Фактически здесь может стоять любое другое выражение.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Все вхождения, совпадающие с шаблоном &amp;quot;*&amp;quot;&lt;br /&gt;
# В настоящее время, шаблон //*/ не совпадает с пустыми&lt;br /&gt;
# и неинициализированными элементами.&lt;br /&gt;
# В то время как шаблоны /#/ и /%/ совпадают с пустыми и не совпадают&lt;br /&gt;
# с неинициализированными элементами.&lt;br /&gt;
&lt;br /&gt;
echo ${sparseZ[@]//*/$(_GenFunc)}&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Приложение B. Справочная информация =&lt;br /&gt;
В нижеследующем справочнике представлена информация, касающаяся отдельных моментов написания сценариев на языке командной оболочки ''Bash''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-1. Переменные специального назначения'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 365px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Переменная''''' !! '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$0''' || ''Имя файла сценария''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$1''' || ''Позиционный параметр #1 (аргумент сценария или функции)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$2 - $9''' || ''Позиционные параметры #2 - #9''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${10}''' || ''Позиционный параметр #10''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$#''' || ''Количество позиционных параметров''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''&amp;quot;$*&amp;quot;''' || ''Все позиционные параметры''(как одно слово. Необходимо'' &lt;br /&gt;
''заключать в кавычки, в противном случае будет работать как &amp;quot;$@&amp;quot;'')&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''&amp;quot;$@&amp;quot;''' || ''Все позиционные параметры(в виде отдельных строк)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${#*}''' || ''Количество позиционных параметров,''&lt;br /&gt;
''переданных из командной строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${#@}''' || ''Количество позиционных параметров,''&lt;br /&gt;
''переданных из командной строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$?''' || ''Возвращаемое значение&amp;lt;br /&amp;gt;(Код возврата последней команды)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$$''' || ''Идентификатор процесса — Process ID (PID) сценария''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$-''' || ''Флаги, переданные сценарию(командой set)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$_''' || ''Последний аргумент предыдущей команды''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''$!''' || ''Идентификатор последнего фонового процесса (PID)'''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-2. Операции проверки: Двухместные операции'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 270px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Оператор''' !! '''Значение''' !! '''----''' !! '''Оператор''' !! '''Значение'''&lt;br /&gt;
|-&lt;br /&gt;
|  ||  || || || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Арифметическое сравнение''' &amp;lt;/div&amp;gt;||  ||  || &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Сравнение строк'''&amp;lt;/div&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''-eq''''' || ''Равно'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''=''''' || ''Равно''&lt;br /&gt;
|-&lt;br /&gt;
|  ||  ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''==''''' || ''Равно''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''-ne''''' || ''Не равно'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''!=''''' || ''Не равно''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''-lt''''' || ''Меньше'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''\&amp;lt;''''' || ''Меньше(в кодах ASCII)''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''-le''''' || ''Меньше или равно'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''-gt''''' || ''Больше'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''\&amp;gt;''''' || ''Больше(в кодах ASCII)''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''-ge''''' || ''Больше или равно'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
|  ||  ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''-z''''' || ''Пустая строка''&lt;br /&gt;
|-&lt;br /&gt;
|  ||  ||  || style=&amp;quot;text-align:center;&amp;quot; | '''''-n''''' || ''Не пустая строка''&lt;br /&gt;
|-&lt;br /&gt;
|  ||  ||  || || &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Арифметическое сравнение''' &amp;lt;/div&amp;gt;|| &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''В двойных круглых скобках((... )) &amp;lt;/div&amp;gt;||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''&amp;gt;''''' || ''Больше'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''&amp;gt;=''''' || ''Больше или равно'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''&amp;lt;''''' || ''Меньше'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''''&amp;lt;=''''' || Меньше или равно||  ||  || &lt;br /&gt;
|}&lt;br /&gt;
::::::::::::: *'''При использовании двойных квадратных скобок''' ''&amp;lt;nowiki&amp;gt;[[&amp;lt;/nowiki&amp;gt;...&amp;lt;nowiki&amp;gt;]]&amp;lt;/nowiki&amp;gt;'', '''необходимо использовать экранирующий символ —''' '''\'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-3. Операции проверки: Файлы'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 140px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Оператор''''' !! '''''Что проверяется''''' !! '''''----''''' !! '''''Оператор''''' !! '''''Что проверяется'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-e''' || ''Файл существует'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-s''' || ''Файл не нулевой длины''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-f''' || ''Обычный файл'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-d''' || ''Файл является каталогом'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-r''' || ''Файл доступен для чтения''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-h''' || ''Файл является символической ссылкой'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-w''' || ''Файл доступен для записи''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-L''' || ''Файл является символической ссылкой'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-x''' || ''Файл доступен для исполнения''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-b''' || ''Файл блочного устройства'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-c''' || ''Файл символьного устройства'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-g''' || ''Установлен флаг sgid''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-p''' || ''Файл является каналом (pipe)'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-u''' || ''Установлен флаг suid''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-S''' || ''Файл является сокетом (socket)'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''-k''' || ''Установлен бит &amp;quot;sticky&amp;quot;''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-t''' || ''Файл связан с терминальным устройством'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
|  ||  ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-N''' || ''Файл был модифицирован с момента последнего чтения'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''F1 -nt F2''' || ''Файл F1 более новый, чем F2''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-O''' || ''Вы являетесь владельцем файла'' ||  || style=&amp;quot;text-align:center;&amp;quot; | '''F1 -ot F2''' || ''Файл F1 более старый, чем F2''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''-G''' || ''Вы принадлежите к той же группе, что и файл ||  || style=&amp;quot;text-align:center;&amp;quot; | '''F1 -ef F2''' || ''Файлы F1 и F2 являются жёсткими''&lt;br /&gt;
''ссылками на один тот же файл''&lt;br /&gt;
|-&lt;br /&gt;
|  ||  ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''!''' || ''&amp;quot;NOT&amp;quot; (логическое отрицание(инверсия) результатов всех вышеприведенных проверок)'' ||  ||  || &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
::::::::::::: *'''Двухместный оператор (требует наличия двух операндов)'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-4. Подстановка параметров и экспансия'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;  style=&amp;quot;margin-left: 340px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Выражение''''' !! '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var}''' || ''Значение переменной var, то же, что и $var''&lt;br /&gt;
|-&lt;br /&gt;
|  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var-DEFAULT}''' || ''Если переменная var не инициализирована, то результатом''&lt;br /&gt;
''вычисления выражения является $DEFAULT''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var:-DEFAULT}''' || ''Если переменная var не инициализирована или пуста, то''&lt;br /&gt;
''результатом вычисления выражения является $DEFAULT''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var=DEFAULT}''' || ''Если переменная var не инициализирована, то результатом''&lt;br /&gt;
''вычисления выражения является $DEFAULT''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var:=DEFAULT}''' || ''Если переменная var не инициализирована, то результатом''&lt;br /&gt;
''вычисления выражения является $DEFAULT''*&lt;br /&gt;
|-&lt;br /&gt;
|  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var+OTHER}''' || ''Если переменная var инициализирована, то результатом вычисления''&lt;br /&gt;
''выражения является $OTHER, иначе — пустая строка''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var:+OTHER}''' || ''Если переменная var инициализирована set, то результатом вычисления''&lt;br /&gt;
''выражения является $OTHER, иначе — пустая строка''&lt;br /&gt;
|-&lt;br /&gt;
|  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var?ERR_MSG}''' || ''Если переменная var не инициализирована, то выводится $ERR_MSG''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${var:?ERR_MSG}''' || ''Если переменная var не инициализирована, то выводится $ERR_MSG''*&lt;br /&gt;
|-&lt;br /&gt;
|  || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${!varprefix*}''' || ''Соответствует всем ранее объявленным переменным, чьи имена''&lt;br /&gt;
''начинаются с varprefix''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${!varprefix@}''' || ''Соответствует всем ранее объявленным переменным, чьи имена''&lt;br /&gt;
начинаются с varprefix&lt;br /&gt;
|}&lt;br /&gt;
::::::::::::: *'''Само собой разумеется, если переменная var инициализирована, то результатом выражения будет $var'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-5. Операции со строками'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 220px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Выражение''''' !! '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string:position}''' || ''Извлечение подстроки из строки $string,''&lt;br /&gt;
''начиная с позиции $position''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${#string}''' || ''Длина строки $string''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string:position:length}''' || ''Извлечение $length символов из строки''&lt;br /&gt;
''$string, начиная с позиции $position''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string#substring}''' || ''Поиск кратчайшего совпадения по шаблону $substring,''&lt;br /&gt;
''в строке $string, поиск ведётся с начала строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string##substring}''' || ''Поиск самого длинного совпадения по шаблону''&lt;br /&gt;
''$substring, в строке $string, поиск ведется с начала строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string%substring}''' || ''Поиск кратчайшего совпадения по шаблону $substring,''&lt;br /&gt;
''в строке $string, поиск ведётся с конца строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string%%substring}''' || ''Поиск самого длинного совпадения по шаблону''&lt;br /&gt;
''$substring, в строке $string, поиск ведётся с конца строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string/substring/replacement}''' || ''Замена первой, найденной по''&lt;br /&gt;
''шаблону $substring, подстроки на подстроку $replacement''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string//substring/replacement}''' || ''Замена всех, найденных по''&lt;br /&gt;
''шаблону $substring, подстрок на подстроку $replacement''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${string/#substring/replacement}''' || ''Если в строке $string найдено соответствие шаблону $substring и найденная &lt;br /&gt;
''подстрока начинает строку $string, то она заменяется подстрокой $replacement''&lt;br /&gt;
|-&lt;br /&gt;
|  || ''Если в строке $string найдено соответствие шаблону $substring и найденная подстрока''&lt;br /&gt;
''заканчивает строку $string, то она заменяется подстрокой $replacement''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr match &amp;quot;$string&amp;quot; '$substring' ''' || ''Количество совпадений с шаблоном $substring''*&lt;br /&gt;
''в строке $string, поиск начинается с начала строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr &amp;quot;$string&amp;quot; : '$substring' ''' || ''Количество совпадений с шаблоном $substring''*&lt;br /&gt;
''в строке $string, поиск начинается с начала строки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr index &amp;quot;$string&amp;quot; $substring''' || ''Позиция(номер символа), первого найденного''&lt;br /&gt;
''совпадения с шаблоном $substring, в строке $string''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr substr $string $position $length''' || ''Извлечение $length символов из строки $string,''&lt;br /&gt;
''начиная с позиции $position''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr match &amp;quot;$string&amp;quot; '\($substring\)' ''' || ''Извлечение подстроки с начала строки $string,''&lt;br /&gt;
''совпадающей с шаблоном $substring''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr &amp;quot;$string&amp;quot; : '\($substring\)' ''' || ''Извлечение подстроки с начала строки $string,''&lt;br /&gt;
''совпадающей с шаблоном $substring''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr match &amp;quot;$string&amp;quot; '.*\($substring\)' ''' || ''Извлечение подстроки с конца строки $string,''&lt;br /&gt;
''совпадающей с шаблоном $substring''*&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''expr &amp;quot;$string&amp;quot; : '.*\($substring\)' ''' || ''Извлечение подстроки с конца строки $string,''&lt;br /&gt;
''совпадающей с шаблоном $substring''*&lt;br /&gt;
|}&lt;br /&gt;
:::::::::::::::::::::: '''* Где $substring — регулярное выражение'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-6. Прочие конструкции'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 265px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Выражение''''' !!  '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt; '''Квадратные скобки'''&amp;lt;/div&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''if [ CONDITION ]''' || ''Проверка условия''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''if''' '''&amp;lt;nowiki&amp;gt;[[&amp;lt;/nowiki&amp;gt;''' '''CONDITION''' '''&amp;lt;nowiki&amp;gt;]]&amp;lt;/nowiki&amp;gt;''' || ''Расширенный синтаксис операции проверки условия''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''Array[1]=element1''' || ''Инициализация массива''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[a-z]''' || ''Диапазон символов в регулярных выражениях''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Фигурные скобки'''&amp;lt;/div&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${variable}''' || ''Подстановка параметра''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''${!variable}''' || ''Косвенная ссылка на переменную''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''{ command1; command2 }''' || ''Блок кода''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''{string1,string2,string3,...}''' || ''Подстановка''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Круглые скобки'''&amp;lt;/div&amp;gt; || &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''( command1; command2 )''' || ''Группа команд, исполняемая в подоболочке(subshell)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''Array=(element1 element2element3)''' || ''Инициализация массива''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''result=$(COMMAND)''' || ''Команда исполняется в подоболочке, результат записывается в переменную''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''&amp;gt;(COMMAND)''' || ''Подстановка процесса''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''&amp;lt;(COMMAND)''' || ''Подстановка процесса''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Двойные круглые скобки''' &amp;lt;/div&amp;gt;|| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''(( var = 78 ))''' || ''Целочисленная арифметика''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''var=$(( 20 + 5 ))''' || ''Арифметическое выражение, результат записывается в переменную''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Кавычки''' &amp;lt;div&amp;gt;|| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''&amp;quot;$variable&amp;quot;''' || ''&amp;quot;Мягкие&amp;quot;, или &amp;quot;нестрогие&amp;quot; кавычки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | ''' 'string' ''' || ''&amp;quot;Строгие&amp;quot;, или &amp;quot;полные&amp;quot; кавычки''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | &amp;lt;div style=&amp;quot;color:blue&amp;quot;&amp;gt;'''Обратные кавычки''' &amp;lt;/div&amp;gt;|| &lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''result=`COMMAND`''' || ''Команда исполняется в подоболочке, результат записывается в переменную''&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица B-7. Выражения, используемые в инструкции if'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: auto; margin-right: auto;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Первичное выражение''''' !! '''''Значение''''' !! '''''Первичное выражение''''' !! '''''Значение'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -a FILE ]''' || Истина, если FILE существует. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -b FILE ]''' || Истина, если FILE существует и является блочным файлом.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -c FILE ]''' || Истина, если FILE существует и является строковым файлом. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -d FILE ]''' || Истина, если FILE существует и является директорией.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -e FILE ]''' || Истина, если FILE существует. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -f FILE ]''' || Истина, если FILE существует и является обычным файлом.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -g FILE ]''' || Истина, если FILE существует и у него установлен бит SGID. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -h FILE ]''' || Истина, если FILE существует и является символической ссылкой.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -k FILE ]''' || Истина, если FILE существует и у него установлен промежуточный бит округления. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -p FILE ]''' || Истина, если FILE существует и является именованным конвейером (FIFO).&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -r FILE ]''' || Истина, если FILE существует и доступен для чтения. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -s FILE ]''' || Истина, если FILE существует и его размер больше нуля.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -t FD ]''' || Истина, если дескриптор файла FD открыт и ссылается на терминал. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -u FILE ]''' || Истина, если FILE существует и у него&amp;lt;br /&amp;gt; установлен бит SUID (установлен идентификатор пользователя ID)&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -w FILE ]''' || Истина, если FILE существует и доступен для записи. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -x FILE ]''' || Истина, если FILE существует и является исполняемым.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -O FILE ]''' || Истина, если FILE существует и его владельцем является действующий пользователь. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -G FILE ]''' || Истина, если FILE существует и его владелец принадлежит к действующей группе.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -L FILE ]''' || Истина, если FILE существует и является символической ссылкой. || style=&amp;quot;text-align:center;&amp;quot; |  '''[ -N FILE ]''' || Истина, если FILE существует и был модифицирован после последнего чтения.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -S FILE ]''' || Истина, если FILE существует и является сокетом. || style=&amp;quot;text-align:center;&amp;quot; | '''[ FILE1 -nt FILE2 ]''' || Истина, если FILE1 был изменен раньше, чем FILE2,&amp;lt;br /&amp;gt; либо если FILE1 существует, а FILE2 не существует.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ FILE1 -ot FILE2 ]''' || Истина, если FILE1 изменен позже, чем FILE2, либо если FILE2 существует, а FILE1 не существует. || style=&amp;quot;text-align:center;&amp;quot; | '''[ FILE1 -ef FILE2 ]''' || Истина, если FILE1 и FILE2 ссылаются на одно и то же устройство или на одинаковые номера inode.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -o OPTIONNAME ]''' || Истина, если установлен параметр командной оболочки &amp;quot;OPTIONNAME&amp;quot;. || style=&amp;quot;text-align:center;&amp;quot; | '''[ -z &amp;quot;STRING&amp;quot; ]''' || Истина, если длина строки &amp;quot;STRING&amp;quot; равна нулю.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ -n &amp;quot;STRING&amp;quot; ]'''&amp;lt;br/&amp;gt;или&amp;lt;br/&amp;gt;'''[ &amp;quot;STRING&amp;quot; ]''' || Истина, если длина строки &amp;quot;STRING&amp;quot; ненулевая. || style=&amp;quot;text-align:center;&amp;quot; | '''[ &amp;quot;STRING1&amp;quot; == &amp;quot;STRING2&amp;quot; ]''' || Истина, если строки равны. Для более строгого&amp;lt;br /&amp;gt;соответствия POSIX вместо &amp;quot;==&amp;quot; можно использовать &amp;quot;=&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ &amp;quot;STRING1&amp;quot; != &amp;quot;STRING2&amp;quot; ]''' || Истина, если строки не равны || style=&amp;quot;text-align:center;&amp;quot; | '''[ &amp;quot;STRING1&amp;quot; &amp;lt; &amp;quot;STRING2&amp;quot; ]''' || Истина, если в текущей локали при лексикографической&amp;lt;br /&amp;gt; сортировке &amp;quot;STRING1&amp;quot; оказывается перед &amp;quot;STRING2&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; width=&amp;quot;15%&amp;quot;| '''[ &amp;quot;STRING1&amp;quot; &amp;gt; &amp;quot;STRING2&amp;quot; ]''' || Истина, если в текущей локали при лексикографической&amp;lt;br /&amp;gt; сортировке &amp;quot;STRING1&amp;quot; оказывается после &amp;quot;STRING2&amp;quot;. || style=&amp;quot;text-align:center;&amp;quot; | '''[ ARG1 OP ARG2 ]''' || &amp;quot;OP&amp;quot; — один из операторов -eq, -ne, -lt, -le, -gt или -ge(см. &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;Таблица B-2. Операции проверки: Двухместные операции&amp;lt;/span&amp;gt;).&amp;quot;ARG1&amp;quot; и &amp;quot;ARG2&amp;quot; являются целыми числами.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ ! EXPR ]''' || Истина, если EXPR ложно. || style=&amp;quot;text-align:center;&amp;quot;  width=&amp;quot;15%&amp;quot;| '''[ ( EXPR ) ]''' || Возвращает значение EXPR. Используется для&amp;lt;br /&amp;gt; изменения нормального предшествования операторов.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[ EXPR1 -a EXPR2 ]''' || Истина, если оба EXPR1 и EXPR2 являются истинными. || style=&amp;quot;text-align:center;&amp;quot; | '''[ EXPR1 -o EXPR2 ]''' || Истина, если либо EXPR1, либо EXPR2 истинно.&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Приложение C. Маленький учебник по Sed и Awk =&lt;br /&gt;
В этом приложении содержится очень краткое описание приемов работы с утилитами обработки текста [[sed]] и [[awk]]. Здесь будут рассмотрены лишь несколько базовых команд, которых, в принципе, будет достаточно, чтобы научиться понимать простейшие конструкции [[sed]] и [[awk]] внутри сценариев на языке командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''[[sed]]''': неинтерактивный редактор текстовых файлов&amp;lt;br /&amp;gt;&lt;br /&gt;
'''[[awk]]''': язык обработки шаблонов с C-подобным синтаксисом&amp;lt;br /&amp;gt;&lt;br /&gt;
При всех своих различиях, эти две утилиты обладают похожим синтаксисом, они обе умеют работать с &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;регулярными выражениями&amp;lt;/span&amp;gt;, обе, по-умолчанию, читают данные с устройства ''stdin'' и обе выводят результат обработки на устройство ''stdout''. Обе являются утилитами Unix-систем, и прекрасно могут взаимодействовать между собой. Вывод от одной может быть перенаправлен, по конвейеру, на вход другой. Их комбинирование придаёт сценариям, на языке командной оболочки, мощь и гибкость языка '''''Perl'''''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Одно важное отличие состоит в том, что в случае с [[sed]], сценарий легко может передавать дополнительные аргументы этой утилите, в то время, как в случае с [[awk]] это более сложная задача.&lt;br /&gt;
== C 1. Sed ==&lt;br /&gt;
'''Sed''' — это неинтерактивный строчный редактор. Он принимает текст либо с устройства ''stdin'', либо из текстового файла, выполняет некоторые операции над строками и затем выводит результат на устройство ''stdout'' или в файл. Как правило, в сценариях, [[sed]] используется в конвейерной обработке данных, совместно с другими командами и утилитами. Sed определяет, по заданному адресному пространству, над какими строками следует выполнить операции. Адресное пространство строк задаётся либо их порядковыми номерами, либо шаблоном. Например, команда ''3d'' заставит [[sed]] удалить третью строку, а команда ''/windows/d'' означает, что все строки, содержащие &amp;quot;''windows''&amp;quot;, должны быть удалены. Из всего разнообразия операций, мы остановимся на трёх, используемых наиболее часто. Это ''p'' — печать (на ''stdout''), ''d'' — удаление и ''s'' — замена.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица C-1. Основные операции sed'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 365px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Операция''''' !! '''''Название''''' !! '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[диапазон строк]/p''' || ''print'' || ''Печать [указанного диапазона строк]''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[диапазон строк]/d''' || ''delete'' || ''Удалить [указанный диапазон строк]''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s/pattern1/pattern2/''' || ''substitute'' || ''Заменить первое встреченное соответствие''&lt;br /&gt;
''шаблону pattern1, в строке, на pattern2''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[диапазон строк]/s/pattern1/pattern2/''' || ''substitute'' || ''Заменить первое встреченное соответствие шаблону''&lt;br /&gt;
''pattern1, на pattern2, в указанном диапазоне строк''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''[диапазон строк]/y/pattern1/pattern2/''' || ''transform'' || ''заменить любые символы из шаблона pattern1 на соответствующие символы''&lt;br /&gt;
''из pattern2, в указанном диапазоне строк(эквивалент команды tr)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''g''' || ''global'' || ''Операция выполняется над всеми найденными соответствиями''&lt;br /&gt;
''внутри каждой из заданных строк''&lt;br /&gt;
|}&amp;lt;br /&amp;gt;&lt;br /&gt;
Без оператора ''g'' (''global''), операция замены будет производиться только для первого найденного совпадения, с заданным шаблоном, в каждой строке.&amp;lt;br /&amp;gt;&lt;br /&gt;
В отдельных случаях, операции [[sed]] необходимо заключать в кавычки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed -e '/^$/d' $filename&lt;br /&gt;
# Ключ -e говорит о том, что далее следует строка, которая должна интерпретироваться&lt;br /&gt;
# как набор инструкций редактирования.&lt;br /&gt;
# (При передаче одной инструкции, ключ &amp;quot;-e&amp;quot; является необязательным.)&lt;br /&gt;
# &amp;quot;Строгие&amp;quot; кавычки ('') предотвращают интерпретацию символов регулярного выражения,&lt;br /&gt;
# как специальных символов, командным интерпретатором.&lt;br /&gt;
#&lt;br /&gt;
# Действия производятся над строками, содержащимися в файле $filename.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В отдельных случаях, команды редактирования не работают в одиночных кавычках.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
filename=file1.txt&lt;br /&gt;
pattern=BEGIN&lt;br /&gt;
&lt;br /&gt;
sed &amp;quot;/^$pattern/d&amp;quot; &amp;quot;$filename&amp;quot;      # Результат вполне предсказуем.&lt;br /&gt;
# sed '/^$pattern/d' &amp;quot;$filename&amp;quot; даёт иной результат.&lt;br /&gt;
# В данном случае, в &amp;quot;строгих&amp;quot; кавычках (' ... '),&lt;br /&gt;
# не происходит подстановки значения переменной &amp;quot;$pattern&amp;quot;.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Sed использует ключ ''-e'' для того, чтобы определить, что следующая строка является инструкцией, или набором инструкций, редактирования. Если инструкция является единственной, то использование этого ключа не является обязательным.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sed -n '/xzy/p' $filename&lt;br /&gt;
# Ключ -n заставляет sed вывести только те строки, которые совпадают с указанным шаблоном.&lt;br /&gt;
# В противном случае (без ключа -n), будут выведены все строки.&lt;br /&gt;
# Здесь, ключ -e не является обязательным, поскольку здесь стоит единственная команда.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица C-2. Примеры операций в sed'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 365px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Операция''''' !! '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''8d''' || ''Удалить 8-ю строку''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''/^$/d''' || ''Удалить все пустые строки''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''1,/^$/d''' || ''Удалить все строки до первой пустой строки, включительно''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''/Jones/p''' || ''Вывести строки, содержащие &amp;quot;Jones&amp;quot;(с ключом -n)''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s/Windows/Linux/''' || ''В каждой строке, заменить первое встретившееся слово &amp;quot;Windows&amp;quot; на слово &amp;quot;Linux&amp;quot;''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s/BSOD/stability/g''' || ''В каждой строке, заменить все встретившиеся слова &amp;quot;BSOD&amp;quot; на &amp;quot;stability&amp;quot;''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s/ *$//''' || ''Удалить все пробелы в конце каждой строки''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s/00*/0/g''' || ''Заменить все последовательности ведущих нулей одним символом &amp;quot;0&amp;quot;''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''/GUI/d''' || ''Удалить все строки, содержащие &amp;quot;GUI&amp;quot;''.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''s/GUI//g''' || ''Удалить все найденные &amp;quot;GUI&amp;quot;, оставляя остальную часть строки без изменений''.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Замена строки пустой строкой, эквивалентна удалению части строки, совпадающей с шаблоном. Остальная часть строки остается без изменений. Например, ''s/GUI//'', изменит следующую строку&amp;lt;br /&amp;gt;&lt;br /&gt;
''The most important parts of any application are its GUI and sound effects''&amp;lt;br /&amp;gt;&lt;br /&gt;
на&amp;lt;br /&amp;gt;&lt;br /&gt;
''The most important parts of any application are its and sound effects''&amp;lt;br /&amp;gt;&lt;br /&gt;
Символ обратного слэша представляет символ перевода строки, как символ замены. В этом случае, замещающее выражение продолжается на следующей строке.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
s/^ */\&lt;br /&gt;
/g&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта инструкция заменит начальные пробелы в строке на символ перевода строки. Ожидаемый результат — замена отступов в начале параграфа пустыми строками.&amp;lt;br /&amp;gt;&lt;br /&gt;
Указание диапазона строк, предшествующее одной, или более, инструкции может потребовать заключения инструкций в фигурные скобки, с соответствующими символами перевода строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/[0-9A-Za-z]/,/^$/{&lt;br /&gt;
/^$/d&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
В этом случае будут удалены только первые из нескольких, идущих подряд, пустых строк. Это может использоваться для установки однострочных интервалов в файле, оставляя, при этом, пустые строки между параграфами.&amp;lt;br /&amp;gt;&lt;br /&gt;
Быстрый способ установки двойных межстрочных интервалов в текстовых файлах — &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;sed G filename&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;.&lt;br /&gt;
Ссылки на дополнительные сведения о [[sed]], вы найдёте в разделе Библиография данной книги.&lt;br /&gt;
== C 2. Awk ==&lt;br /&gt;
'''''Awk''''' — это полноценный язык обработки текстовой информации с синтаксисом, напоминающим синтаксис языка ''C''. Он обладает довольно широким набором возможностей, однако, мы рассмотрим лишь некоторые из них — наиболее употребимые в сценариях командной оболочки. '''''Awk''''' &amp;quot;разбивает&amp;quot; каждую строку на отдельные поля. По-умолчанию, поля — это последовательности символов, отделённые друг от друга &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;пробелами&amp;lt;/span&amp;gt;, однако имеется возможность назначения других символов, в качестве разделителя полей. '''''Awk''''' анализирует и обрабатывает каждое поле в отдельности. Это делает его идеальным инструментом для работы со структурированными текстовыми файлами — особенно с таблицами.&amp;lt;br /&amp;gt;&lt;br /&gt;
Внутри сценариев командной оболочки, код [[awk]], заключается в &amp;quot;строгие&amp;quot; (одиночные) кавычки и фигурные скобки.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
awk '{print $3}' $filename&lt;br /&gt;
# Выводит содержимое 3-го поля из файла $filename на устройство stdout.&lt;br /&gt;
&lt;br /&gt;
awk '{print $1 $5 $6}' $filename&lt;br /&gt;
# Выводит содержимое 1-го, 5-го и 6-го полей из файла $filename.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Только что, мы рассмотрели действие команды ''print''. Ещё, на чём мы остановимся — это переменные. '''''Awk''''' работает с переменными подобно сценариям командной оболочки, но более гибко.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
{ total += ${column_number} }&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Эта команда добавит содержимое переменной ''column_number'' к переменной ''total''. Чтобы, в завершение вывести ''total'', можно использовать команду '''END''', которая открывает блок кода, отрабатывающий после того, как будут обработаны все входные данные.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
END { print total }&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команде '''END''', соответствует команда '''BEGIN''', которая открывает блок кода, отрабатывающий перед началом обработки входных данных. Следующий пример демонстрирует применение [[awk]] для разбора текста в сценариях командной оболочки.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''C-1. Подсчёт количества символов.'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /bin/sh&lt;br /&gt;
# letter-count.sh: Counting letter occurrences in a text file.&lt;br /&gt;
#&lt;br /&gt;
# Автор: nyal (nyal@voila.fr).&lt;br /&gt;
# Используется с разрешения автора сценария.&lt;br /&gt;
# Комментарии добавлены автором документа.&lt;br /&gt;
&lt;br /&gt;
INIT_TAB_AWK=&amp;quot;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
count_case=0&lt;br /&gt;
FILE_PARSE=$1&lt;br /&gt;
E_PARAMERR=65&lt;br /&gt;
&lt;br /&gt;
usage()&lt;br /&gt;
{&lt;br /&gt;
 echo &amp;quot;Порядок использования: letter-count.sh имя_файла символы&amp;quot; 2&amp;gt;&amp;amp;1&lt;br /&gt;
 # Например: ./letter-count.sh filename.txt a b c&lt;br /&gt;
 exit $E_PARAMERR # Вызов сценария без аргументов.&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if [ ! -f &amp;quot;$1&amp;quot; ] ; then&lt;br /&gt;
 echo &amp;quot;Файл $1 не найден.&amp;quot; 2&amp;gt;&amp;amp;1&lt;br /&gt;
 usage                   # Вывод сообщения и выход.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
if [ -z &amp;quot;$2&amp;quot; ] ; then&lt;br /&gt;
 echo &amp;quot;$2: Не заданы символы для поиска.&amp;quot; 2&amp;gt;&amp;amp;1&lt;br /&gt;
 usage&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
shift                    # Символы заданы.&lt;br /&gt;
for letter in `echo $@`  # Для каждого из них . . .&lt;br /&gt;
do&lt;br /&gt;
 INIT_TAB_AWK=&amp;quot;$INIT_TAB_AWK tab_search[${count_case}] = \&amp;quot;$letter\&amp;quot;; final_tab[${count_case}] = 0;&amp;quot;&lt;br /&gt;
 # Передаётся как параметр в сценарий awk ниже.&lt;br /&gt;
 count_case=`expr $count_case + 1`&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
# DEBUG:&lt;br /&gt;
# echo $INIT_TAB_AWK;&lt;br /&gt;
cat $FILE_PARSE |&lt;br /&gt;
# Передать заданный файл по конвейеру в сценарий awk.&lt;br /&gt;
&lt;br /&gt;
# --------------------------------------------------------------------------------&lt;br /&gt;
# От переводчика:&lt;br /&gt;
# В оригинальном тексте сценария стоит следующая строка:&lt;br /&gt;
#awk -v tab_search=0 -v final_tab=0 -v tab=0 -v nb_letter=0 -v chara=0 -v chara2=0 \&lt;br /&gt;
#&lt;br /&gt;
# с моим gawk 3.1.3 сценарий делается неработоспособным&lt;br /&gt;
# поэтому я взял на себя смелость несколько подправить эту строку,&lt;br /&gt;
# в результате она получилась такой:&lt;br /&gt;
awk -v nb_letter=0 -v chara=0 -v chara2=0 \&lt;br /&gt;
&amp;quot;BEGIN { $INIT_TAB_AWK } \&lt;br /&gt;
{ split(\$0, tab, \&amp;quot;\&amp;quot;); \&lt;br /&gt;
for (chara in tab) \&lt;br /&gt;
{ for (chara2 in tab_search) \&lt;br /&gt;
{ if (tab_search[chara2] == tab[chara]) { final_tab[chara2]++ } } } } \&lt;br /&gt;
END { for (chara in final_tab) \&lt;br /&gt;
{ print tab_search[chara] \&amp;quot; =&amp;gt; \&amp;quot; final_tab[chara] } }&amp;quot;&lt;br /&gt;
# --------------------------------------------------------------------------------&lt;br /&gt;
# Ничего сложного...&lt;br /&gt;
# Циклы for, проверка условия if, и пара специфических функций.&lt;br /&gt;
&lt;br /&gt;
exit $?&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Это всё, что я хотел рассказать об [[awk]]. Дополнительные ссылки на информацию об [[awk]], вы найдёте в разделе &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Библиография&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
= Приложение D. Коды завершения, имеющие предопределённый смысл =&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица D-1. &amp;quot;Зарезервированные&amp;quot; коды завершения'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 180px; margin-right: 100px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Код завершения !! Смысл !! Пример !! Примечание&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''1''' || ''Разнообразные ошибки'' || ''let &amp;quot;var1= 1/0&amp;quot; '' || ''Различные ошибки, такие&amp;lt;br /&amp;gt;как &amp;quot;деление на ноль&amp;quot; и пр. ''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''2''' || ''Согласно документации к Bash'' — &amp;lt;br /&amp;gt;''неверное использование встроенных команд'' || || ''Встречаются довольно редко, обычно&amp;lt;br /&amp;gt;код завершения возвращается равным 1''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''126''' || ''Вызываемая команда не может быть выполнена'' ||  || ''Возникает из-за проблем с правами доступа'' &amp;lt;br /&amp;gt; ''или когда вызван на исполнение неисполняемый файл''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''127''' || ''&amp;quot;Команда не найдена&amp;quot;'' ||  || ''Проблема связана либо с переменной окружения $PATH, либо&amp;lt;br /&amp;gt;с неверным написанием имени команды''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''128''' || ''Неверный аргумент команды exit'' || ''exit 3.14159'' || ''Команда exit может принимать только целочисленные&amp;lt;br /&amp;gt;значения, в диапазоне 0-255''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''128+n''' || ''Фатальная ошибка по сигналу &amp;quot;n&amp;quot;'' || ''kill -9 $PPID сценария'' || ''$? вернёт 137 (128 + 9)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; |  '''130''' || ''Завершение по Control-C'' ||  || ''&amp;quot;Control-C&amp;quot; это выход по&amp;lt;br /&amp;gt;сигналу 2, (130 =128 + 2, см.выше)''&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | '''255''' || ''Код завершения вне допустимого диапазона || ''exit -1'' || ''exit может принимать только целочисленные&amp;lt;br /&amp;gt;значения, в диапазоне 0-255''&lt;br /&gt;
|}&lt;br /&gt;
Согласно этой таблице, коды завершения '''1'''-'''2''', '''126'''-'''165''' и '''255''' имеют предопределённое значение, поэтому вам следует избегать употребления этих кодов для своих нужд. Завершение сценария с кодом возврата ''exit 127'', может привести в замешательство при поиске ошибок в сценарии (действительно ли он означает ошибку &amp;quot;команда не найдена&amp;quot;? Или это предусмотренный программистом код завершения?). В большинстве случаев, программисты вставляют ''exit 1'', в качестве реакции на ошибку. Так как код завершения '''1''' подразумевает целый &amp;quot;букет&amp;quot; ошибок, то в данном случае трудно говорить о какой-либо двусмысленности, хотя и об информативности — тоже.&amp;lt;br /&amp;gt;&lt;br /&gt;
Не раз предпринимались попытки систематизировать коды завершения (см. /usr/include/sysexits.h), но эта систематизация предназначена для программистов, пишущих на языках ''C'' и ''C++''. Автор документа предлагает ограничить коды завершения, определяемые пользователем, диапазоном '''64'''-'''113''' (и, само собой разумеется — '''0''', для обозначения успешного завершения), в соответствии со стандартом ''C/C++''. Это сделало бы поиск ошибок более простым. Все сценарии, прилагаемые к данному документу, приведены в соответствие с этим стандартом, за исключением случаев, когда существуют отменяющие обстоятельства.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''!'''&amp;lt;/big&amp;gt;Обращение к переменной '''$?''', из командной строки, после завершения работы сценария, даёт результат, в соответствии с таблицей, приведенной выше, но только для Bash или sh. Под управлением csh или tcsh значения могут в некоторых случаях отличаться.&lt;br /&gt;
&lt;br /&gt;
= Приложение E. Подробное введение в операции ввода-вывода и перенаправление ввода-вывода =&lt;br /&gt;
:::''Написано Stephane Chazelas и дополнено автором документа''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Практически любая команда предполагает доступность 3-х &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;файловых дескрипторов&amp;lt;/span&amp;gt;. Первый — '''0'''(стандартный ввод, ''stdin''), доступный для чтения. И два других — ''1'' (стандартный вывод, ''stdout'') и '''2''' (поток ошибок, ''stderr''), доступные для записи. &amp;lt;br /&amp;gt;&lt;br /&gt;
Запись, типа '''ls 2&amp;gt;&amp;amp;1''', означает временное перенаправление вывода, с устройства ''stderr'' на устройство ''stdout''. В соответствии с соглашениями, команды принимают ввод из файла с дескриптором '''0''' (''stdin''), выводят результат работы в файл с дескриптором '''1''' ('''stdout'''), а сообщения об ошибках — в файл с дескриптором '''2''' (''stderr''). Если какой-либо из этих трёх дескрипторов окажется закрытым, то могут возникнуть определенные проблемы:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ cat /etc/passwd &amp;gt;&amp;amp;-&lt;br /&gt;
cat: standard output: Bad file descriptor&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
К примеру, когда пользователь запускает '''xterm''', то он сначала выполняет процедуру инициализации, а затем, перед запуском командной оболочки, '''xterm''' трижды открывает терминальные устройства (/dev/pts/&amp;lt;n&amp;gt;, или нечто подобное). После этого, командная оболочка наследует эти три дескриптора, и любая команда, запускаемая в этой оболочке, так же наследует их. Термин &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;перенаправление&amp;lt;/span&amp;gt; — означает переназначение одного файлового дескриптора на другой (канал(конвейер) или что-то другое). Переназначение может быть выполнено локально (для отдельной команды, для группы команд, для подоболочки, для операторов ''while'', ''if'', ''case'', ''for''...) или глобально (с помощью '''exec''').&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ls &amp;gt; /dev/null&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Команда выше означает запуск команды [[ls]] с файловым дескриптором '''1''', присоединённым к устройству ''/dev/null''.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ lsof -a -p $$ -d0,1,2&lt;br /&gt;
COMMAND PID USER FD  TYPE DEVICE   SIZE NODE    NAME&lt;br /&gt;
bash    363 bozo 0u  CHR   136,1             3 /dev/pts/1&lt;br /&gt;
bash    363 bozo 1u  CHR   136,1             3 /dev/pts/1&lt;br /&gt;
bash    363 bozo 2u  CHR   136,1             3 /dev/pts/1&lt;br /&gt;
&lt;br /&gt;
bash$ exec 2&amp;gt; /dev/null&lt;br /&gt;
bash$ lsof -a -p $$ -d0,1,2&lt;br /&gt;
COMMAND PID USER FD  TYPE DEVICE   SIZE NODE    NAME&lt;br /&gt;
bash    371 bozo 0u  CHR  136,1              3 /dev/pts/1&lt;br /&gt;
bash    371 bozo 1u  CHR  136,1              3 /dev/pts/1&lt;br /&gt;
bash    371 bozo 2w  CHR   1,3              120 /dev/null&lt;br /&gt;
&lt;br /&gt;
bash$ bash -c 'lsof -a -p $$ -d0,1,2' | cat&lt;br /&gt;
COMMAND PID USER FD  TYPE DEVICE   SIZE NODE    NAME&lt;br /&gt;
lsof    379 root 0u  CHR  136,1              3 /dev/pts/1&lt;br /&gt;
lsof    379 root 1w  FIFO 0,0                7118 pipe&lt;br /&gt;
lsof    379 root 2u  CHR  136,1              3 /dev/pts/1&lt;br /&gt;
&lt;br /&gt;
bash$ echo &amp;quot;$(bash -c 'lsof -a -p $$ -d0,1,2' 2&amp;gt;&amp;amp;1)&amp;quot;&lt;br /&gt;
COMMAND PID USER FD  TYPE DEVICE   SIZE NODE    NAME&lt;br /&gt;
lsof    426 root 0u  CHR  136,1              3 /dev/pts/1&lt;br /&gt;
lsof    426 root 1w  FIFO 0,0                7520 pipe&lt;br /&gt;
lsof    426 root 2w  FIFO 0,0                7520 pipe&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;Упражнение&amp;lt;/span&amp;gt;: Проанализируйте следующий сценарий.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#! /usr/bin/env bash&lt;br /&gt;
&lt;br /&gt;
mkfifo /tmp/fifo1 /tmp/fifo2&lt;br /&gt;
&lt;br /&gt;
while read a; do echo &amp;quot;FIFO1: $a&amp;quot;; done &amp;lt; /tmp/fifo1 &amp;amp;&lt;br /&gt;
exec 7&amp;gt; /tmp/fifo1&lt;br /&gt;
exec 8&amp;gt; &amp;gt;(while read a; do echo &amp;quot;FD8: $a, to fd7&amp;quot;; done &amp;gt;&amp;amp;7)&lt;br /&gt;
&lt;br /&gt;
exec 3&amp;gt;&amp;amp;1(&lt;br /&gt;
(&lt;br /&gt;
 (&lt;br /&gt;
  ( while read a; do echo &amp;quot;FIFO2: $a&amp;quot;; done &amp;lt; /tmp/fifo2 | tee /dev/stderr | tee /dev/fd/4 | tee /dev/fd/5 | tee /dev/fd/6 &amp;gt;&amp;amp;7 &amp;amp; exec 3&amp;gt; /tmp/fifo2&lt;br /&gt;
    echo 1st, to stdout&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 2nd, to stderr &amp;gt;&amp;amp;2&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 3rd, to fd 3 &amp;gt;&amp;amp;3&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 4th, to fd 4 &amp;gt;&amp;amp;4&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 5th, to fd 5 &amp;gt;&amp;amp;5&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 6th, through a pipe | sed 's/.*/PIPE: &amp;amp;, to fd 5/' &amp;gt;&amp;amp;5&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 7th, to fd 6 &amp;gt;&amp;amp;6&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 8th, to fd 7 &amp;gt;&amp;amp;7&lt;br /&gt;
    sleep 1&lt;br /&gt;
    echo 9th, to fd 8 &amp;gt;&amp;amp;8&lt;br /&gt;
  ) 4&amp;gt;&amp;amp;1 &amp;gt;&amp;amp;3 3&amp;gt;&amp;amp;- | while read a; do echo &amp;quot;FD4: $a&amp;quot;; done 1&amp;gt;&amp;amp;3 5&amp;gt;&amp;amp;- 6&amp;gt;&amp;amp;-&lt;br /&gt;
 ) 5&amp;gt;&amp;amp;1 &amp;gt;&amp;amp;3 | while read a; do echo &amp;quot;FD5: $a&amp;quot;; done 1&amp;gt;&amp;amp;3 6&amp;gt;&amp;amp;-&lt;br /&gt;
) 6&amp;gt;&amp;amp;1 &amp;gt;&amp;amp;3 | while read a; do echo &amp;quot;FD6: $a&amp;quot;; done 3&amp;gt;&amp;amp;-&lt;br /&gt;
&lt;br /&gt;
rm -f /tmp/fifo1 /tmp/fifo2&lt;br /&gt;
# Выясните, куда переназначены файловые дескрипторы каждой команды и подоболочки.&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Приложение F. Системные каталоги =&lt;br /&gt;
Системный администратор, да и любой другой, кто занимается созданием сценариев для обслуживания системы должен чётко знать о существовании следующих системных каталогов.&amp;lt;br /&amp;gt;&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/bin'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Каталог с программами. В этом каталоге размещаются основные системные программы и утилиты (например '''bash''').&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/usr/bin'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Дополнительные системные каталоги.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/usr/local/bin'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Программы разного рода.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/sbin'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Superuser binaries'' — программы суперпользователя. Основные программы и утилиты административного назначения (например '''fsck''').&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/usr/sbin'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Дополнительные программы суперпользователя.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/etc'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Et cetera''. Конфигурационные системные скрипты.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/etc/rc.d'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Сценарии начальной загрузки системы, для дистрибутива Red Hat и его клонов.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/usr/share/doc'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Документация к установленным пакетам.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/tmp'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Временный каталог системы.&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/var/log'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Каталог для хранения системных журналов (логов).&lt;br /&gt;
* &amp;lt;big&amp;gt;'''/var/spool/mail'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
:Буфер для электронной почты.&lt;br /&gt;
&lt;br /&gt;
= Приложение G. Локализация =&lt;br /&gt;
Возможность локализации сценариев Bash нигде в документации не описана.&amp;lt;br /&amp;gt;&lt;br /&gt;
Локализованные сценарии выводят текст на том языке, который используется системой, в соответствии с настройками. Пользователь Linux, живущий в Берлине(Германия), будет видеть сообщения на немецком языке, в то время как другой пользователь, проживающий в Берлине штата Мэриленд (США) — на английском.&amp;lt;br /&amp;gt;&lt;br /&gt;
Для создания локализованных сценариев можно использовать следующий шаблон, предусматривающий вывод всех сообщений на языке пользователя (сообщения об ошибках, приглашения к вводу и т.п.).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# localized.sh&lt;br /&gt;
# Автор Stephane Chazelas, дополнил Bruno Haible&lt;br /&gt;
&lt;br /&gt;
. gettext.sh&lt;br /&gt;
&lt;br /&gt;
E_CDERROR=65&lt;br /&gt;
&lt;br /&gt;
error()&lt;br /&gt;
{&lt;br /&gt;
 printf &amp;quot;$@&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
 exit $E_CDERROR&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
cd $var || error &amp;quot;`eval_gettext \&amp;quot;Can't cd to \$var.\&amp;quot;`&amp;quot;&lt;br /&gt;
read -p &amp;quot;`gettext \&amp;quot;Enter the value: \&amp;quot;`&amp;quot; var&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ bash -D localized.sh&lt;br /&gt;
&amp;quot;Can't cd to %s.&amp;quot;&lt;br /&gt;
&amp;quot;Enter the value: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Это список всех текстовых сообщений, которые подлежат локализации(Ключ ''-D'' выводит список строк в двойных кавычках, которым предшествует символ '''$''', без запуска сценария на исполнение).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ bash --dump-po-strings localized.sh&lt;br /&gt;
#: a:6&lt;br /&gt;
 msgid &amp;quot;Can't cd to %s.&amp;quot;&lt;br /&gt;
 msgstr &amp;quot;&amp;quot;&lt;br /&gt;
 #: a:7&lt;br /&gt;
 msgid &amp;quot;Enter the value: &amp;quot;&lt;br /&gt;
 msgstr &amp;quot;&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Ключ ''--dump-po-strings'' в Bash напоминает ключ ''-D'', но выводит строки в формате &amp;quot;po&amp;quot;, с помощью утилиты '''gettext'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''!'''&amp;lt;/big&amp;gt;''Bruno Haible'' отмечает, что:&amp;lt;br /&amp;gt;&lt;br /&gt;
:Начиная с версии '''gettext-0.12.2''', вместо '''bash --dump-po-strings localized.sh''', рекомендуется использовать '''xgettext -o - localized.sh''', потому что '''xgettext'''...&lt;br /&gt;
::'''1'''. понимает команды '''gettext''' и '''eval_gettext''' (тогда как '''bash --dump-po-strings''' только свой синтаксис в виде $&amp;quot;...&amp;quot; )&lt;br /&gt;
::'''2'''. может извлекать комментарии программиста, предназначенные для переводчика.&amp;lt;br /&amp;gt;&lt;br /&gt;
Такой код не привязан к определенной версии Bash и может быть исполнен в Bash 1.x или других реализациях /bin/sh.&amp;lt;br /&amp;gt;&lt;br /&gt;
Теперь построим файл ''language.po'', для каждого языка, на которые предполагается перевести сообщения сценария. Например:&amp;lt;br /&amp;gt;&lt;br /&gt;
Файл ''ru.po'' сделан переводчиком, в оригинальном документе локализация выполнена на примере французского языка. &amp;lt;br /&amp;gt;&lt;br /&gt;
:'''ru.po''':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#: a:6&lt;br /&gt;
msgid &amp;quot;Can't cd to %s.&amp;quot;&lt;br /&gt;
msgstr &amp;quot;Невозможно перейти в каталог %s.&amp;quot;&lt;br /&gt;
#: a:7&lt;br /&gt;
msgid &amp;quot;Enter the value: &amp;quot;&lt;br /&gt;
msgstr &amp;quot;Введите число: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Затем запустите '''msgfmt'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;msgfmt -o localized.sh.mo ru.po&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Перепишите получившийся файл '''localized.sh.mo''' в каталог ''/usr/share/locale/ru/LC_MESSAGES'' и добавьте в начало сценария строки:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
TEXTDOMAINDIR=/usr/share/locale&lt;br /&gt;
TEXTDOMAIN=localized.sh&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Если система корректно настроена на русскую локаль, то пользователь, запустивший сценарий, будет видеть сообщения на русском языке.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;big&amp;gt;'''!'''&amp;lt;/big&amp;gt; В старых версиях Bash или в других командных оболочках, потребуется воспользоваться услугами утилиты '''gettext''', с ключом ''-s''. В этом случае наш сценарий будет выглядеть так:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# localized.sh&lt;br /&gt;
&lt;br /&gt;
E_CDERROR=65&lt;br /&gt;
error() {&lt;br /&gt;
 local format=$1&lt;br /&gt;
 shift&lt;br /&gt;
 printf &amp;quot;$(gettext -s &amp;quot;$format&amp;quot;)&amp;quot; &amp;quot;$@&amp;quot; &amp;gt;&amp;amp;2&lt;br /&gt;
 exit $E_CDERROR&lt;br /&gt;
}&lt;br /&gt;
cd $var || error &amp;quot;Can't cd to %s.&amp;quot; &amp;quot;$var&amp;quot;&lt;br /&gt;
read -p &amp;quot;$(gettext -s &amp;quot;Enter the value: &amp;quot;)&amp;quot; var&lt;br /&gt;
# ...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
А переменные ''TEXTDOMAIN'' и ''TEXTDOMAINDIR'', необходимо будет экспортировать в окружение.&amp;lt;br /&amp;gt;&lt;br /&gt;
Это приложение написано ''Stephane Chazelas'', и дополнено ''Bruno Haible'', ведущим разработчиком GNU '''gettext'''.&lt;br /&gt;
&lt;br /&gt;
= Приложение H. История команд =&lt;br /&gt;
Командная оболочка Bash предоставляет в распоряжение пользователя инструментарий командной строки, позволяющий управлять ''историей'' команд. История команд — это, прежде всего, очень удобный инструмент, сокращающий ручной ввод.&amp;lt;br /&amp;gt;&lt;br /&gt;
:История команд Bash:&amp;lt;br /&amp;gt;&lt;br /&gt;
:# '''history'''&lt;br /&gt;
:# '''fc'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ history&lt;br /&gt;
1 mount /mnt/cdrom&lt;br /&gt;
2 cd /mnt/cdrom&lt;br /&gt;
3 ls&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
''Внутренние переменные Bash'', связанные с историей команд:&amp;lt;br /&amp;gt;&lt;br /&gt;
:# '''$HISTCMD'''&lt;br /&gt;
:# '''$HISTCONTROL'''&lt;br /&gt;
:# '''$HISTIGNORE'''&lt;br /&gt;
:# '''$HISTFILESIZE'''&lt;br /&gt;
:# '''$HISTSIZE'''&lt;br /&gt;
:# '''!!'''&lt;br /&gt;
:# '''!$'''&lt;br /&gt;
:# '''!#'''&lt;br /&gt;
:# '''!N'''&lt;br /&gt;
:# '''!-N'''&lt;br /&gt;
:# '''!STRING'''&lt;br /&gt;
:# '''!?STRING?'''&lt;br /&gt;
:# '''^STRING^string^'''&lt;br /&gt;
К сожалению, инструменты истории команд, в Bash, совершенно бесполезны в сценариях!&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# history.sh&lt;br /&gt;
# Попытка воспользоваться 'историей' команд в сценарии.&lt;br /&gt;
&lt;br /&gt;
history&lt;br /&gt;
# На экран ничего не выводится.&lt;br /&gt;
# История команд не работает в сценариях.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
bash$ ./history.sh&lt;br /&gt;
(ничего не выводится)&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Приложение I. Пример файла .bashrc =&lt;br /&gt;
Файл ''~/.bashrc'' определяет поведение командной оболочки. Внимательное изучение этого примера поможет вам значительно продвинуться в понимании Bash. &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Emmanuel Rouat&amp;lt;/span&amp;gt; представил следующий, очень сложный, файл ''.bashrc'', написанный для операционной системы Linux. Предложения и замечания приветствуются.&amp;lt;br /&amp;gt;&lt;br /&gt;
Внимательно изучите этот файл. Отдельные участки этого файла вы свободно можете использовать в своём собственном ''.bashrc'' или, даже в своих сценариях!&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример I-1. Пример файла .bashrc'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#===============================================================&lt;br /&gt;
#&lt;br /&gt;
# ЛИЧНЫЙ ФАЙЛ $HOME/.bashrc для bash-2.05a (или выше)&lt;br /&gt;
#&lt;br /&gt;
# Время последней модификации: Втр Апр 15 20:32:34 CEST 2003&lt;br /&gt;
#&lt;br /&gt;
# Этот файл содержит настройки интерактивной командной оболочки.&lt;br /&gt;
# Здесь размещены определения псевдонимов, функций&lt;br /&gt;
# и других элементов Bash, таких как prompt (приглашение к вводу).&lt;br /&gt;
#&lt;br /&gt;
# Изначально, этот файл был создан в операционной системе Solaris,&lt;br /&gt;
# но позднее был переделан под Redhat&lt;br /&gt;
# --&amp;gt; Модифицирован под Linux.&lt;br /&gt;
# Большая часть кода, который находится здесь, была взята из&lt;br /&gt;
# Usenet (или Интернет).&lt;br /&gt;
# Этот файл содержит слишком много определений — помните, это всего лишь пример.&lt;br /&gt;
#&lt;br /&gt;
#&lt;br /&gt;
#===============================================================&lt;br /&gt;
&lt;br /&gt;
# --&amp;gt; Комментарии, добавленные автором HOWTO.&lt;br /&gt;
# --&amp;gt; И дополнены автором сценария Emmanuel Rouat :-)&lt;br /&gt;
&lt;br /&gt;
#-----------------------------------&lt;br /&gt;
# Глобальные определения&lt;br /&gt;
#-----------------------------------&lt;br /&gt;
&lt;br /&gt;
if [ -f /etc/bashrc ]; then&lt;br /&gt;
 . /etc/bashrc # --&amp;gt; Прочитать настройки из /etc/bashrc, если таковой имеется.&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
#-------------------------------------------------------------&lt;br /&gt;
# Настройка переменной $DISPLAY (если еще не установлена)&lt;br /&gt;
# Это срабатывает под linux - в вашем случае все может быть по другому....&lt;br /&gt;
# Проблема в том, что различные типы терминалов&lt;br /&gt;
# дают разные ответы на запрос 'who am i'......&lt;br /&gt;
# я не нашёл 'универсального' метода&lt;br /&gt;
#-------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
function get_xserver ()&lt;br /&gt;
{&lt;br /&gt;
 case $TERM in&lt;br /&gt;
  xterm )&lt;br /&gt;
   XSERVER=$(who am i | awk '{print $NF}' | tr -d ')''(' )&lt;br /&gt;
   XSERVER=${XSERVER%%:*}&lt;br /&gt;
   ;;&lt;br /&gt;
  aterm | rxvt)&lt;br /&gt;
   # добавьте здесь свой код.....&lt;br /&gt;
   ;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if [ -z ${DISPLAY:=&amp;quot;&amp;quot;} ]; then&lt;br /&gt;
 get_xserver&lt;br /&gt;
 if [[ -z ${XSERVER} || ${XSERVER} == $(hostname) || ${XSERVER} == &amp;quot;unix&amp;quot; ]]; then&lt;br /&gt;
  DISPLAY=&amp;quot;:0.0&amp;quot; # для локального хоста&lt;br /&gt;
 else&lt;br /&gt;
  DISPLAY=${XSERVER}:0.0 # для удалённого хоста&lt;br /&gt;
 fi&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
export DISPLAY&lt;br /&gt;
&lt;br /&gt;
#---------------&lt;br /&gt;
# Некоторые настройки&lt;br /&gt;
#---------------&lt;br /&gt;
&lt;br /&gt;
ulimit -S -c 0 # Запрет на создание файлов coredump&lt;br /&gt;
set -o notify&lt;br /&gt;
set -o noclobber&lt;br /&gt;
set -o ignoreeof&lt;br /&gt;
set -o nounset&lt;br /&gt;
#set -o xtrace # полезно для отладки&lt;br /&gt;
&lt;br /&gt;
# Разрешающие настройки:&lt;br /&gt;
shopt -s cdspell&lt;br /&gt;
shopt -s cdable_vars&lt;br /&gt;
shopt -s checkhash&lt;br /&gt;
shopt -s checkwinsize&lt;br /&gt;
shopt -s mailwarn&lt;br /&gt;
shopt -s sourcepath&lt;br /&gt;
shopt -s no_empty_cmd_completion # только для bash&amp;gt;=2.04&lt;br /&gt;
shopt -s cmdhist&lt;br /&gt;
shopt -s histappend histreedit histverify&lt;br /&gt;
shopt -s extglob&lt;br /&gt;
&lt;br /&gt;
# Запрещающие настройки:&lt;br /&gt;
shopt -u mailwarn&lt;br /&gt;
unset MAILCHECK # Я не желаю, чтобы командная оболочка сообщала мне о прибытии почты&lt;br /&gt;
&lt;br /&gt;
export TIMEFORMAT=$'\nreal %3R\tuser %3U\tsys %3S\tpcpu %P\n'&lt;br /&gt;
export HISTIGNORE=&amp;quot;&amp;amp;:bg:fg:ll:h&amp;quot;&lt;br /&gt;
export HOSTFILE=$HOME/.hosts &lt;br /&gt;
# Поместить список удаленных хостов в файл ~/.hosts&lt;br /&gt;
&lt;br /&gt;
#-----------------------&lt;br /&gt;
# Greeting, motd etc...&lt;br /&gt;
#-----------------------&lt;br /&gt;
&lt;br /&gt;
# Для начала определить некоторые цвета:&lt;br /&gt;
red='\e[0;31m'&lt;br /&gt;
RED='\e[1;31m'&lt;br /&gt;
blue='\e[0;34m'&lt;br /&gt;
BLUE='\e[1;34m'&lt;br /&gt;
cyan='\e[0;36m'&lt;br /&gt;
CYAN='\e[1;36m'&lt;br /&gt;
NC='\e[0m' # No Color (нет цвета)&lt;br /&gt;
# --&amp;gt; Прекрасно. Имеет тот же эффект, что и &amp;quot;ansi.sys&amp;quot; в DOS.&lt;br /&gt;
&lt;br /&gt;
# Лучше выглядит на черном фоне.....&lt;br /&gt;
echo -e &amp;quot;${CYAN}This is BASH ${RED}${BASH_VERSION%.*}${CYAN} - DISPLAY on ${RED}$DISPLAY${NC}\n&amp;quot;&lt;br /&gt;
date&lt;br /&gt;
if [ -x /usr/games/fortune ]; then&lt;br /&gt;
 /usr/games/fortune -s # сделает наш день более интересным.... :-)&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
function _exit() # функция, запускающаяся при выходе из оболочки&lt;br /&gt;
{&lt;br /&gt;
 echo -e &amp;quot;${RED}Аста ла виста, бэби ${NC}&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
trap _exit EXIT&lt;br /&gt;
&lt;br /&gt;
#---------------&lt;br /&gt;
# Prompt&lt;br /&gt;
#---------------&lt;br /&gt;
&lt;br /&gt;
if [[ &amp;quot;${DISPLAY#$HOST}&amp;quot; != &amp;quot;:0.0&amp;quot; &amp;amp;&amp;amp; &amp;quot;${DISPLAY}&amp;quot; != &amp;quot;:0&amp;quot; ]]; then&lt;br /&gt;
 HILIT=${red} # на удаленной системе: prompt будет частично красным&lt;br /&gt;
else&lt;br /&gt;
 HILIT=${cyan} # на локальной системе: prompt будет частично циановым&lt;br /&gt;
fi&lt;br /&gt;
# --&amp;gt; Замените \W на \w в функциях ниже&lt;br /&gt;
# --&amp;gt; чтобы видеть в оболочке полный путь к текущему каталогу.&lt;br /&gt;
&lt;br /&gt;
function fastprompt()&lt;br /&gt;
{&lt;br /&gt;
 unset PROMPT_COMMAND&lt;br /&gt;
 case $TERM in&lt;br /&gt;
  *term | rxvt )&lt;br /&gt;
    PS1=&amp;quot;${HILIT}[\h]$NC \W &amp;gt; \[\033]0;\${TERM} [\u@\h] \w\007\]&amp;quot; ;;&lt;br /&gt;
  linux )&lt;br /&gt;
    PS1=&amp;quot;${HILIT}[\h]$NC \W &amp;gt; &amp;quot; ;;&lt;br /&gt;
  *)&lt;br /&gt;
    PS1=&amp;quot;[\h] \W &amp;gt; &amp;quot; ;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function powerprompt()&lt;br /&gt;
{&lt;br /&gt;
 _powerprompt()&lt;br /&gt;
  {&lt;br /&gt;
    LOAD=$(uptime|sed -e &amp;quot;s/.*: \([^,]*\).*/\1/&amp;quot; -e &amp;quot;s/ //g&amp;quot;)&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  PROMPT_COMMAND=_powerprompt&lt;br /&gt;
  case $TERM in&lt;br /&gt;
    *term | rxvt )&lt;br /&gt;
      PS1=&amp;quot;${HILIT}[\A \$LOAD]$NC\n[\h \#] \W &amp;gt; \[\033]0;\${TERM} [\u@\h] \w\007\]&amp;quot; ;;&lt;br /&gt;
    linux )&lt;br /&gt;
      PS1=&amp;quot;${HILIT}[\A - \$LOAD]$NC\n[\h \#] \w &amp;gt; &amp;quot; ;;&lt;br /&gt;
    * )&lt;br /&gt;
      PS1=&amp;quot;[\A - \$LOAD]\n[\h \#] \w &amp;gt; &amp;quot; ;;&lt;br /&gt;
  esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
powerprompt # это prompt по-умолчанию - может работать довольно медленно&lt;br /&gt;
            # Если это так, то используйте fastprompt....&lt;br /&gt;
&lt;br /&gt;
#===============================================================&lt;br /&gt;
#&lt;br /&gt;
# ПСЕВДОНИМЫ И ФУНКЦИИ&lt;br /&gt;
#&lt;br /&gt;
# Возможно некоторые из функций, приведенных здесь, окажутся для вас слишком большими,&lt;br /&gt;
# но на моей рабочей станции установлено 512Mb ОЗУ, так что.....&lt;br /&gt;
# Если пожелаете уменьшить размер этого файла, то можете оформить эти функции&lt;br /&gt;
# в виде отдельных сценариев.&lt;br /&gt;
#&lt;br /&gt;
# Большинство функций были взяты, почти без переделки, из примеров&lt;br /&gt;
# к bash-2.04.&lt;br /&gt;
#&lt;br /&gt;
#===============================================================&lt;br /&gt;
&lt;br /&gt;
#-------------------&lt;br /&gt;
# Псевдонимы&lt;br /&gt;
#-------------------&lt;br /&gt;
&lt;br /&gt;
alias rm='rm -i'&lt;br /&gt;
alias cp='cp -i'&lt;br /&gt;
alias mv='mv -i'&lt;br /&gt;
# -&amp;gt; Предотвращает случайное удаление файлов.&lt;br /&gt;
&lt;br /&gt;
alias mkdir='mkdir -p'&lt;br /&gt;
alias h='history'&lt;br /&gt;
alias j='jobs -l'&lt;br /&gt;
alias r='rlogin'&lt;br /&gt;
alias which='type -all'&lt;br /&gt;
alias ..='cd ..'&lt;br /&gt;
alias path='echo -e ${PATH//:/\\n}'&lt;br /&gt;
alias print='/usr/bin/lp -o nobanner -d $LPDEST' # Предполагается, что LPDEST определён&lt;br /&gt;
alias pjet='enscript -h -G -fCourier9 -d $LPDEST' # Печать через enscript&lt;br /&gt;
alias background='xv -root -quit -max -rmode 5' # Положить картинку в качестве фона&lt;br /&gt;
alias du='du -kh'&lt;br /&gt;
alias df='df -kTh'&lt;br /&gt;
&lt;br /&gt;
# Различные варианты 'ls' (предполагается, что установлена GNU-версия ls)&lt;br /&gt;
alias la='ls -Al' # показать скрытые файлы&lt;br /&gt;
alias ls='ls -hF --color' # выделить различные типы файлов цветом&lt;br /&gt;
alias lx='ls -lXB' # сортировка по расширению&lt;br /&gt;
alias lk='ls -lSr' # сортировка по размеру&lt;br /&gt;
alias lc='ls -lcr' # сортировка по времени изменения&lt;br /&gt;
alias lu='ls -lur' # сортировка по времени последнего обращения&lt;br /&gt;
alias lr='ls -lR' # рекурсивный обход подкаталогов&lt;br /&gt;
alias lt='ls -ltr' # сортировка по дате&lt;br /&gt;
alias lm='ls -al |more' # вывод через 'more'&lt;br /&gt;
alias tree='tree -Csu' # альтернатива 'ls'&lt;br /&gt;
&lt;br /&gt;
# подготовка 'less'&lt;br /&gt;
alias more='less'&lt;br /&gt;
export PAGER=less&lt;br /&gt;
export LESSCHARSET='latin1'&lt;br /&gt;
export LESSOPEN='|/usr/bin/lesspipe.sh %s 2&amp;gt;&amp;amp;-' # если существует lesspipe.sh&lt;br /&gt;
export LESS='-i -N -w -z-4 -g -e -M -X -F -R -P%t?f%f \&lt;br /&gt;
:stdin .?pb%pb\%:?lbLine %lb:?bbByte %bb:-...'&lt;br /&gt;
&lt;br /&gt;
# проверка правописания - настоятельно рекомендую :-)&lt;br /&gt;
alias xs='cd'&lt;br /&gt;
alias vf='cd'&lt;br /&gt;
alias moer='more'&lt;br /&gt;
alias moew='more'&lt;br /&gt;
alias kk='ll'&lt;br /&gt;
&lt;br /&gt;
#----------------&lt;br /&gt;
# добавим немножко &amp;quot;приятностей&amp;quot;&lt;br /&gt;
#----------------&lt;br /&gt;
&lt;br /&gt;
function xtitle ()&lt;br /&gt;
{&lt;br /&gt;
 case &amp;quot;$TERM&amp;quot; in&lt;br /&gt;
   *term | rxvt)&lt;br /&gt;
     echo -n -e &amp;quot;\033]0;$*\007&amp;quot; ;;&lt;br /&gt;
   *)&lt;br /&gt;
     ;;&lt;br /&gt;
 esac&lt;br /&gt;
} &lt;br /&gt;
&lt;br /&gt;
# псевдонимы...&lt;br /&gt;
alias top='xtitle Processes on $HOST &amp;amp;&amp;amp; top'&lt;br /&gt;
alias make='xtitle Making $(basename $PWD) ; make'&lt;br /&gt;
alias ncftp=&amp;quot;xtitle ncFTP ; ncftp&amp;quot;&lt;br /&gt;
&lt;br /&gt;
# .. и функции&lt;br /&gt;
function man ()&lt;br /&gt;
{&lt;br /&gt;
 for i ; do&lt;br /&gt;
  xtitle The $(basename $1|tr -d .[:digit:]) manual&lt;br /&gt;
  command man -F -a &amp;quot;$i&amp;quot;&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function ll(){ ls -l &amp;quot;$@&amp;quot;| egrep &amp;quot;^d&amp;quot; ; ls -lXB &amp;quot;$@&amp;quot; 2&amp;gt;&amp;amp;-| egrep -v &amp;quot;^d|total &amp;quot;; }&lt;br /&gt;
function te() # &amp;quot;обертка&amp;quot; вокруг xemacs/gnuserv&lt;br /&gt;
{&lt;br /&gt;
 if [ &amp;quot;$(gnuclient -batch -eval t 2&amp;gt;&amp;amp;-)&amp;quot; == &amp;quot;t&amp;quot; ]; then&lt;br /&gt;
  gnuclient -q &amp;quot;$@&amp;quot;;&lt;br /&gt;
 else&lt;br /&gt;
  ( xemacs &amp;quot;$@&amp;quot; &amp;amp;);&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#-----------------------------------&lt;br /&gt;
# Функции для работы с файлами и строками:&lt;br /&gt;
#-----------------------------------&lt;br /&gt;
&lt;br /&gt;
# Поиск файла по шаблону:&lt;br /&gt;
function ff() { find . -type f -iname '*'$*'*' -ls ; }&lt;br /&gt;
# Поиск файла по шаблону в $1 и запуск команды в $2 с ним:&lt;br /&gt;
function fe() { find . -type f -iname '*'$1'*' -exec &amp;quot;${2:-file}&amp;quot; {} \; ; }&lt;br /&gt;
# поиск строки по файлам:&lt;br /&gt;
&lt;br /&gt;
function fstr()&lt;br /&gt;
{&lt;br /&gt;
 OPTIND=1&lt;br /&gt;
 local case=&amp;quot;&amp;quot;&lt;br /&gt;
 local usage=&amp;quot;fstr: поиск строки в файлах.&lt;br /&gt;
 Порядок использования: fstr [-i] \&amp;quot;шаблон\&amp;quot; [\&amp;quot;шаблон_имени_файла\&amp;quot;] &amp;quot;&lt;br /&gt;
 while getopts :it opt&lt;br /&gt;
 do&lt;br /&gt;
  case &amp;quot;$opt&amp;quot; in&lt;br /&gt;
   i) case=&amp;quot;-i &amp;quot; ;;&lt;br /&gt;
   *) echo &amp;quot;$usage&amp;quot;; return;;&lt;br /&gt;
  esac&lt;br /&gt;
 done&lt;br /&gt;
 shift $(( $OPTIND - 1 ))&lt;br /&gt;
 if [ &amp;quot;$#&amp;quot; -lt 1 ]; then&lt;br /&gt;
  echo &amp;quot;$usage&amp;quot;&lt;br /&gt;
  return;&lt;br /&gt;
 fi&lt;br /&gt;
 local SMSO=$(tput smso)&lt;br /&gt;
 local RMSO=$(tput rmso)&lt;br /&gt;
 find . -type f -name &amp;quot;${2:-*}&amp;quot; -print0 | xargs -0 grep -sn ${case} &amp;quot;$1&amp;quot; 2&amp;gt;&amp;amp;- | \&lt;br /&gt;
 sed &amp;quot;s/$1/${SMSO}\0${RMSO}/gI&amp;quot; | more&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function cuttail() # удалить последние n строк в файле, по-умолчанию 10&lt;br /&gt;
{&lt;br /&gt;
 nlines=${2:-10}&lt;br /&gt;
 sed -n -e :a -e &amp;quot;1,${nlines}!{P;N;D;};N;ba&amp;quot; $1&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function lowercase() # перевести имя файла в нижний регистр&lt;br /&gt;
{&lt;br /&gt;
 for file ; do&lt;br /&gt;
  filename=${file##*/}&lt;br /&gt;
  case &amp;quot;$filename&amp;quot; in&lt;br /&gt;
   */*) dirname==${file%/*} ;;&lt;br /&gt;
   *) dirname=.;;&lt;br /&gt;
  esac&lt;br /&gt;
  nf=$(echo $filename | tr A-Z a-z)&lt;br /&gt;
  newname=&amp;quot;${dirname}/${nf}&amp;quot;&lt;br /&gt;
  if [ &amp;quot;$nf&amp;quot; != &amp;quot;$filename&amp;quot; ]; then&lt;br /&gt;
   mv &amp;quot;$file&amp;quot; &amp;quot;$newname&amp;quot;&lt;br /&gt;
   echo &amp;quot;lowercase: $file --&amp;gt; $newname&amp;quot;&lt;br /&gt;
  else&lt;br /&gt;
   echo &amp;quot;lowercase: имя файла $file не было изменено.&amp;quot;&lt;br /&gt;
  fi&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function swap() # меняет 2 файла местами&lt;br /&gt;
{&lt;br /&gt;
 local TMPFILE=tmp.$$&lt;br /&gt;
 mv &amp;quot;$1&amp;quot; $TMPFILE&lt;br /&gt;
 mv &amp;quot;$2&amp;quot; &amp;quot;$1&amp;quot;&lt;br /&gt;
 mv $TMPFILE &amp;quot;$2&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#-----------------------------------&lt;br /&gt;
# Функции для работы с процессами/системой:&lt;br /&gt;
#-----------------------------------&lt;br /&gt;
&lt;br /&gt;
function my_ps() { ps $@ -u $USER -o pid,%cpu,%mem,bsdtime,command ; }&lt;br /&gt;
function pp() { my_ps f | awk '!/awk/ &amp;amp;&amp;amp; $0~var' var=${1:-&amp;quot;.*&amp;quot;} ; }&lt;br /&gt;
&lt;br /&gt;
# Эта функция является грубым аналогом 'killall' в linux&lt;br /&gt;
# но не эквивалентна (насколько я знаю) 'killall' в Solaris&lt;br /&gt;
function killps() # &amp;quot;Прибить&amp;quot; процесс по его имени&lt;br /&gt;
{&lt;br /&gt;
 local pid pname sig=&amp;quot;-TERM&amp;quot; # сигнал, рассылаемый по-умолчанию&lt;br /&gt;
 if [ &amp;quot;$#&amp;quot; -lt 1 ] || [ &amp;quot;$#&amp;quot; -gt 2 ]; then&lt;br /&gt;
  echo &amp;quot;Порядок использования: killps [-SIGNAL] шаблон_имени_процесса&amp;quot;&lt;br /&gt;
  return;&lt;br /&gt;
 fi&lt;br /&gt;
 &lt;br /&gt;
 if [ $# = 2 ]; then sig=$1 ; fi&lt;br /&gt;
 for pid in $(my_ps| awk '!/awk/ &amp;amp;&amp;amp; $0~pat { print $1 }' pat=${!#} ) ; do&lt;br /&gt;
   pname=$(my_ps | awk '$1~var { print $5 }' var=$pid )&lt;br /&gt;
   if ask &amp;quot;Послать сигнал $sig процессу $pid &amp;lt;$pname&amp;gt;?&amp;quot;&lt;br /&gt;
    then kill $sig $pid&lt;br /&gt;
   fi&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function my_ip() # IP адрес&lt;br /&gt;
{&lt;br /&gt;
 MY_IP=$(/sbin/ifconfig ppp0 | awk '/inet/ { print $2 } ' | sed -e s/addr://)&lt;br /&gt;
 MY_ISP=$(/sbin/ifconfig ppp0 | awk '/P-t-P/ { print $3 } ' | sed -e s/P-t-P://)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function ii() # Дополнительные сведения о системе&lt;br /&gt;
{&lt;br /&gt;
 echo -e &amp;quot;\nВы находитесь на ${RED}$HOST&amp;quot;&lt;br /&gt;
 echo -e &amp;quot;\nДополнительная информация:$NC &amp;quot; ; uname -a&lt;br /&gt;
 echo -e &amp;quot;\n${RED}В системе работают пользователи:$NC &amp;quot; ; w -h&lt;br /&gt;
 echo -e &amp;quot;\n${RED}Дата:$NC &amp;quot; ; date&lt;br /&gt;
 echo -e &amp;quot;\n${RED}Время, прошедшее с момента последней перезагрузки :$NC &amp;quot; ; uptime&lt;br /&gt;
 echo -e &amp;quot;\n${RED}Память :$NC &amp;quot; ; free&lt;br /&gt;
 my_ip 2&amp;gt;&amp;amp;- ;&lt;br /&gt;
 echo -e &amp;quot;\n${RED}IP адрес:$NC&amp;quot; ; echo ${MY_IP:-&amp;quot;Соединение не установлено&amp;quot;}&lt;br /&gt;
 echo -e &amp;quot;\n${RED}Адрес провайдера (ISP):$NC&amp;quot; ; echo ${MY_ISP:-&amp;quot;Соединение не установлено&amp;quot;}&lt;br /&gt;
 echo&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
# Разные утилиты:&lt;br /&gt;
function repeat() # повторить команду n раз&lt;br /&gt;
{&lt;br /&gt;
 local i max&lt;br /&gt;
 max=$1; shift;&lt;br /&gt;
 for ((i=1; i &amp;lt;= max ; i++)); do # --&amp;gt; C-подобный синтаксис&lt;br /&gt;
  eval &amp;quot;$@&amp;quot;;&lt;br /&gt;
 done&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function ask()&lt;br /&gt;
{&lt;br /&gt;
 echo -n &amp;quot;$@&amp;quot; '[y/n] ' ; read ans&lt;br /&gt;
 case &amp;quot;$ans&amp;quot; in&lt;br /&gt;
   y*|Y*) return 0 ;;&lt;br /&gt;
   *) return 1 ;;&lt;br /&gt;
 esac&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
#=========================================================================&lt;br /&gt;
#&lt;br /&gt;
# ПРОГРАММНЫЕ ДОПОЛНЕНИЯ - ТОЛЬКО НАЧИНАЯ С ВЕРСИИ BASH-2.04&lt;br /&gt;
# Большая часть дополнений взята из документации к bash 2.05 и из&lt;br /&gt;
# пакета 'Bash completion' (http://www.caliban.org/bash/index.shtml#completion)&lt;br /&gt;
# автор — Ian McDonalds# Фактически, у вас должен стоять bash-2.05a&lt;br /&gt;
#&lt;br /&gt;
#=========================================================================&lt;br /&gt;
&lt;br /&gt;
if [ &amp;quot;${BASH_VERSION%.*}&amp;quot; \&amp;lt; &amp;quot;2.05&amp;quot; ]; then&lt;br /&gt;
 echo &amp;quot;Вам необходимо обновиться до версии 2.05&amp;quot;&lt;br /&gt;
 return&lt;br /&gt;
fi&lt;br /&gt;
shopt -s extglob # необходимо&lt;br /&gt;
set +o nounset   # иначе некоторые дополнения не будут работать&lt;br /&gt;
complete -A hostname rsh rcp telnet rlogin r ftp ping disk&lt;br /&gt;
complete -A export printenv&lt;br /&gt;
complete -A variable export local readonly unset&lt;br /&gt;
complete -A enabled builtin&lt;br /&gt;
complete -A alias alias unalias&lt;br /&gt;
complete -A function function&lt;br /&gt;
complete -A user su mail finger&lt;br /&gt;
&lt;br /&gt;
complete -A helptopic help&lt;br /&gt;
complete -A shopt shopt&lt;br /&gt;
complete -A stopped -P '%' bg&lt;br /&gt;
complete -A job -P '%' fg jobs disown&lt;br /&gt;
&lt;br /&gt;
complete -A directory mkdir rmdir&lt;br /&gt;
complete -A directory -o default cd&lt;br /&gt;
&lt;br /&gt;
# Архивация&lt;br /&gt;
complete -f -o default -X '*.+(zip|ZIP)' zip&lt;br /&gt;
complete -f -o default -X '!*.+(zip|ZIP)' unzip&lt;br /&gt;
complete -f -o default -X '*.+(z|Z)' compress&lt;br /&gt;
complete -f -o default -X '!*.+(z|Z)' uncompress&lt;br /&gt;
complete -f -o default -X '*.+(gz|GZ)' gzip&lt;br /&gt;
complete -f -o default -X '!*.+(gz|GZ)' gunzip&lt;br /&gt;
complete -f -o default -X '*.+(bz2|BZ2)' bzip2&lt;br /&gt;
complete -f -o default -X '!*.+(bz2|BZ2)' bunzip2&lt;br /&gt;
# Postscript,pdf,dvi.....&lt;br /&gt;
complete -f -o default -X '!*.ps' gs ghostview ps2pdf ps2ascii&lt;br /&gt;
complete -f -o default -X '!*.dvi' dvips dvipdf xdvi dviselect dvitype&lt;br /&gt;
complete -f -o default -X '!*.pdf' acroread pdf2ps&lt;br /&gt;
complete -f -o default -X '!*.+(pdf|ps)' gv&lt;br /&gt;
complete -f -o default -X '!*.texi*' makeinfo texi2dvi texi2html texi2pdf&lt;br /&gt;
complete -f -o default -X '!*.tex' tex latex slitex&lt;br /&gt;
complete -f -o default -X '!*.lyx' lyx&lt;br /&gt;
complete -f -o default -X '!*.+(htm*|HTM*)' lynx html2ps# Multimedia&lt;br /&gt;
complete -f -o default -X '!*.+(jp*g|gif|xpm|png|bmp)' xv gimp&lt;br /&gt;
complete -f -o default -X '!*.+(mp3|MP3)' mpg123 mpg321&lt;br /&gt;
complete -f -o default -X '!*.+(ogg|OGG)' ogg123&lt;br /&gt;
&lt;br /&gt;
complete -f -o default -X '!*.pl' perl perl5&lt;br /&gt;
&lt;br /&gt;
# Эти 'универсальные' дополнения работают тогда, когда команды вызываются&lt;br /&gt;
# с, так называемыми, 'длинными ключами', например: 'ls --all' вместо 'ls -a'&lt;br /&gt;
&lt;br /&gt;
_get_longopts ()&lt;br /&gt;
{&lt;br /&gt;
 $1 --help | sed -e '/--/!d' -e 's/.*--\([^[:space:].,]*\).*/--\1/'| \&lt;br /&gt;
 grep ^&amp;quot;$2&amp;quot; |sort -u ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
_longopts_func ()&lt;br /&gt;
{&lt;br /&gt;
 case &amp;quot;${2:-*}&amp;quot; in&lt;br /&gt;
   -*) ;;&lt;br /&gt;
   *) return ;;&lt;br /&gt;
 esac&lt;br /&gt;
&lt;br /&gt;
 case &amp;quot;$1&amp;quot; in&lt;br /&gt;
   \~*) eval cmd=&amp;quot;$1&amp;quot; ;;&lt;br /&gt;
   *) cmd=&amp;quot;$1&amp;quot; ;;&lt;br /&gt;
 esac&lt;br /&gt;
 COMPREPLY=( $(_get_longopts ${1} ${2} ) )&lt;br /&gt;
}&lt;br /&gt;
complete -o default -F _longopts_func configure bash&lt;br /&gt;
complete -o default -F _longopts_func wget id info a2ps ls recode&lt;br /&gt;
&lt;br /&gt;
_make_targets ()&lt;br /&gt;
{&lt;br /&gt;
 local mdef makef gcmd cur prev i&lt;br /&gt;
&lt;br /&gt;
 COMPREPLY=()&lt;br /&gt;
 cur=${COMP_WORDS[COMP_CWORD]}&lt;br /&gt;
 prev=${COMP_WORDS[COMP_CWORD-1]}&lt;br /&gt;
&lt;br /&gt;
 # Если аргумент prev это -f, то вернуть возможные варианты имен файлов.&lt;br /&gt;
 # будем великодушны и вернем несколько вариантов&lt;br /&gt;
 # `makefile Makefile *.mk'&lt;br /&gt;
 case &amp;quot;$prev&amp;quot; in&lt;br /&gt;
   -*f) COMPREPLY=( $(compgen -f $cur ) ); return 0;;&lt;br /&gt;
 esac&lt;br /&gt;
 &lt;br /&gt;
 # Если запрошены возможные ключи, то вернуть ключи posix&lt;br /&gt;
 case &amp;quot;$cur&amp;quot; in&lt;br /&gt;
   -) COMPREPLY=(-e -f -i -k -n -p -q -r -S -s -t); return 0;;&lt;br /&gt;
 esac&lt;br /&gt;
 &lt;br /&gt;
 # попробовать передать make `makefile' перед тем как попробовать передать `Makefile'&lt;br /&gt;
 if [ -f makefile ]; then&lt;br /&gt;
  mdef=makefile&lt;br /&gt;
 elif [ -f Makefile ]; then&lt;br /&gt;
  mdef=Makefile&lt;br /&gt;
 else&lt;br /&gt;
  mdef=*.mk&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 # прежде чем просмотреть &amp;quot;цели&amp;quot;, убедиться, что имя makefile было задано&lt;br /&gt;
 # ключом -f&lt;br /&gt;
 for (( i=0; i &amp;lt; ${#COMP_WORDS[@]}; i++ )); do&lt;br /&gt;
  if [[ ${COMP_WORDS[i]} == -*f ]]; then&lt;br /&gt;
    eval makef=${COMP_WORDS[i+1]}&lt;br /&gt;
    break&lt;br /&gt;
  fi&lt;br /&gt;
 done&lt;br /&gt;
&lt;br /&gt;
  [ -z &amp;quot;$makef&amp;quot; ] &amp;amp;&amp;amp; makef=$mdef&lt;br /&gt;
  # Если задан шаблон поиска, то ограничиться&lt;br /&gt;
  # этим шаблоном&lt;br /&gt;
  if [ -n &amp;quot;$2&amp;quot; ]; then gcmd='grep &amp;quot;^$2&amp;quot;' ; else gcmd=cat ; fi&lt;br /&gt;
  # если мы не желаем использовать *.mk, то необходимо убрать cat и использовать&lt;br /&gt;
  # test -f $makef с перенаправлением ввода&lt;br /&gt;
  COMPREPLY=( $(cat $makef 2&amp;gt;/dev/null | awk 'BEGIN {FS=&amp;quot;:&amp;quot;} /^[^.# ][^=]*:/ {print $1}' | tr -s ' ' '\012' | sort -u | eval $gcmd ) )&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
complete -F _make_targets -X '+($*|*.[cho])' make gmake pmake&lt;br /&gt;
# cvs(1) completion_cvs ()&lt;br /&gt;
_cvs ()&lt;br /&gt;
{&lt;br /&gt;
 local cur prev&lt;br /&gt;
 COMPREPLY=()&lt;br /&gt;
 cur=${COMP_WORDS[COMP_CWORD]}&lt;br /&gt;
 prev=${COMP_WORDS[COMP_CWORD-1]}&lt;br /&gt;
&lt;br /&gt;
 if [ $COMP_CWORD -eq 1 ] || [ &amp;quot;${prev:0:1}&amp;quot; = &amp;quot;-&amp;quot; ]; then&lt;br /&gt;
  COMPREPLY=( $( compgen -W 'add admin checkout commit diff \&lt;br /&gt;
  export history import log rdiff release remove rtag status \&lt;br /&gt;
  tag update' $cur ))&lt;br /&gt;
 else&lt;br /&gt;
  COMPREPLY=( $( compgen -f $cur ))&lt;br /&gt;
 fi&lt;br /&gt;
 return 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
complete -F _cvs cvs&lt;br /&gt;
&lt;br /&gt;
_killall ()&lt;br /&gt;
{&lt;br /&gt;
 local cur prev&lt;br /&gt;
 COMPREPLY=()&lt;br /&gt;
 cur=${COMP_WORDS[COMP_CWORD]}&lt;br /&gt;
&lt;br /&gt;
 # получить список процессов&lt;br /&gt;
 COMPREPLY=( $( /usr/bin/ps -u $USER -o comm | \&lt;br /&gt;
   sed -e '1,1d' -e 's#[]\[]##g' -e 's#^.*/##'| \&lt;br /&gt;
   awk '{if ($0 ~ /^'$cur'/) print $0}' ))&lt;br /&gt;
 return 0&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
complete -F _killall killall killps&lt;br /&gt;
# Функция обработки мета-команд&lt;br /&gt;
# В настоящее время недостаточно отказоустойчива (например, mount и umount&lt;br /&gt;
# обрабатываются некорректно), но все еще актуальна. Автор Ian McDonald, изменена мной.&lt;br /&gt;
&lt;br /&gt;
_my_command()&lt;br /&gt;
{&lt;br /&gt;
 local cur func cline cspec&lt;br /&gt;
&lt;br /&gt;
 COMPREPLY=()&lt;br /&gt;
 cur=${COMP_WORDS[COMP_CWORD]}&lt;br /&gt;
&lt;br /&gt;
 if [ $COMP_CWORD = 1 ]; then&lt;br /&gt;
   COMPREPLY=( $( compgen -c $cur ) )&lt;br /&gt;
 elif complete -p ${COMP_WORDS[1]} &amp;amp;&amp;gt;/dev/null; then&lt;br /&gt;
   cspec=$( complete -p ${COMP_WORDS[1]} )&lt;br /&gt;
   if [ &amp;quot;${cspec%%-F *}&amp;quot; != &amp;quot;${cspec}&amp;quot; ]; then&lt;br /&gt;
     # complete -F &amp;lt;function&amp;gt;&lt;br /&gt;
     #&lt;br /&gt;
     # COMP_CWORD and COMP_WORDS() доступны на запись,&lt;br /&gt;
     # так что мы можем установить их перед тем,&lt;br /&gt;
     # как передать их дальше&lt;br /&gt;
&lt;br /&gt;
     # уменьшить на 1 текущий номер лексемы&lt;br /&gt;
     COMP_CWORD=$(( $COMP_CWORD - 1 ))&lt;br /&gt;
     # получить имя функции&lt;br /&gt;
     func=${cspec#*-F }&lt;br /&gt;
     func=${func%% *}&lt;br /&gt;
     # получить командную строку, исключив первую команду&lt;br /&gt;
     cline=&amp;quot;${COMP_LINE#$1 }&amp;quot;&lt;br /&gt;
     # разбить на лексемы и поместить в массив&lt;br /&gt;
     COMP_WORDS=( $cline )&lt;br /&gt;
     $func $cline&lt;br /&gt;
   elif [ &amp;quot;${cspec#*-[abcdefgjkvu]}&amp;quot; != &amp;quot;&amp;quot; ]; then&lt;br /&gt;
     # complete -[abcdefgjkvu]&lt;br /&gt;
     #func=$( echo $cspec | sed -e 's/^.*\(-[abcdefgjkvu]\).*$/\1/' )&lt;br /&gt;
     func=$( echo $cspec | sed -e 's/^complete//' -e 's/[^ ]*$//' )&lt;br /&gt;
     COMPREPLY=( $( eval compgen $func $cur ) )&lt;br /&gt;
   elif [ &amp;quot;${cspec#*-A}&amp;quot; != &amp;quot;$cspec&amp;quot; ]; then&lt;br /&gt;
     # complete -A &amp;lt;type&amp;gt;&lt;br /&gt;
     func=${cspec#*-A }&lt;br /&gt;
     func=${func%% *}&lt;br /&gt;
     COMPREPLY=( $( compgen -A $func $cur ) )&lt;br /&gt;
   fi&lt;br /&gt;
 else&lt;br /&gt;
  COMPREPLY=( $( compgen -f $cur ) )&lt;br /&gt;
 fi&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
complete -o default -F _my_command nohup exec eval trace truss strace sotruss gdb&lt;br /&gt;
complete -o default -F _my_command command type which man nice&lt;br /&gt;
&lt;br /&gt;
# Локальные переменные:&lt;br /&gt;
# mode:shell-script&lt;br /&gt;
# sh-shell:bash&lt;br /&gt;
# Конец:&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Приложение J. Преобразование пакетных (*.bat) файлов DOS в сценарии командной оболочки =&lt;br /&gt;
Большое число программистов начинало изучать скриптовые языки на PC, работающих под управлением ''DOS''. Даже на этом &amp;quot;калеке&amp;quot; удавалось создавать неплохие сценарии, хотя это и требовало значительных усилий. Иногда ещё возникает потребность в переносе пакетных файлов ''DOS'' на платформу ''Unix'', в виде сценариев командной оболочки. Обычно это не сложно, поскольку набор операторов, доступных в ''DOS'', представляет из себя ограниченное подмножество эквивалентных команд, доступных в командной оболочке.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица J-1. Ключевые слова/переменные/операторы пакетных файлов DOS и их аналоги командной оболочки'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 365px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Операторы&amp;lt;br /&amp;gt;пакетных файлов !! Эквивалентные команды в&amp;lt;br /&amp;gt;Unix !! Описание&lt;br /&gt;
|-&lt;br /&gt;
| '''%''' || '''&amp;amp;''' || ''Префикс аргументов командной строки''&lt;br /&gt;
|-&lt;br /&gt;
| '''/''' || '''-''' || ''Признак ключа(опции)''&lt;br /&gt;
|-&lt;br /&gt;
| '''\''' || '''/''' || ''Разделитель имен каталогов в пути''&lt;br /&gt;
|-&lt;br /&gt;
| '''==''' || '''=''' || ''(Равно)сравнение строк''&lt;br /&gt;
|-&lt;br /&gt;
| '''!==!''' || '''!=''' || ''(Не равно) сравнение строк&lt;br /&gt;
|-&lt;br /&gt;
| '''|''' || '''|''' || ''конвейер(канал)''&lt;br /&gt;
|-&lt;br /&gt;
| '''@''' || '''set +v''' || ''Не выводить текущую команду''&lt;br /&gt;
|-&lt;br /&gt;
| '''*''' || '''*''' || ''&amp;quot;Шаблонный символ&amp;quot; в имени файла''&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;gt;''' || '''&amp;gt;''' || ''Перенаправление(с удалением&amp;lt;br /&amp;gt;существующего файла)&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;gt;&amp;gt;''' || '''&amp;gt;&amp;gt;''' || ''Перенаправление(с добавлением&amp;lt;br /&amp;gt; в конец существующего файла)&lt;br /&gt;
|-&lt;br /&gt;
| '''&amp;lt;''' || '''&amp;lt;''' || ''Перенаправление ввода stdin''&lt;br /&gt;
|-&lt;br /&gt;
| '''%VAR%''' || '''$VAR''' || ''Переменная окружения''&lt;br /&gt;
|-&lt;br /&gt;
| '''REM''' || '''#''' || ''Комментарий''&lt;br /&gt;
|-&lt;br /&gt;
| '''NOT''' || '''!''' || ''Отрицание последующего условия''&lt;br /&gt;
|-&lt;br /&gt;
| '''NUL''' || '''/dev/null''' || ''&amp;quot;Чёрная дыра&amp;quot; для того,&amp;lt;br /&amp;gt;чтобы &amp;quot;спрятать&amp;quot; вывод команды&lt;br /&gt;
|-&lt;br /&gt;
| '''ECHO''' || '''echo''' || ''Вывод(в Bash имеет большое&amp;lt;br /&amp;gt;число опций)&lt;br /&gt;
|-&lt;br /&gt;
| '''ECHO.''' || '''echo''' || ''Вывод пустой строки''&lt;br /&gt;
|-&lt;br /&gt;
| '''ECHO OFF''' || '''set +v''' || ''Не выводить последующие команды''&lt;br /&gt;
|-&lt;br /&gt;
| '''FOR %%VAR IN (LIST)&amp;lt;br /&amp;gt;DO''' || '''for var in [list]; do''' || ''Цикл &amp;quot;for&amp;quot;''&lt;br /&gt;
|-&lt;br /&gt;
| ''':LABEL''' || '''Эквивалент отсутствует&amp;lt;br /&amp;gt;(нет необходимости) || ''Метка''&lt;br /&gt;
|-&lt;br /&gt;
| '''GOTO''' || '''Эквивалент отсутствует&amp;lt;br /&amp;gt;(используйте функции) || ''Переход по заданной метке''&lt;br /&gt;
|-&lt;br /&gt;
| '''PAUSE''' || '''sleep''' || ''Пауза, или ожидание, &amp;lt;br /&amp;gt;в течение заданного времени''&lt;br /&gt;
|-&lt;br /&gt;
| '''CHOICE''' || '''case''' или '''select''' || ''Выбор из меню''&lt;br /&gt;
|-&lt;br /&gt;
| '''IF''' || '''if''' || ''Условный оператор if''&lt;br /&gt;
|-&lt;br /&gt;
| '''IF EXIST FILENAME''' || '''if [ -e filename ]''' || ''Проверка существования файла''&lt;br /&gt;
|-&lt;br /&gt;
| '''IF !%N==!''' || '''if [ -z &amp;quot;$N&amp;quot; ]''' || ''Проверка: параметр &amp;quot;N&amp;quot; отсутствует''&lt;br /&gt;
|-&lt;br /&gt;
| '''CALL''' || '''source''' или &amp;lt;big&amp;gt;'''.'''&amp;lt;/big&amp;gt;(оператор &amp;quot;точка&amp;quot;) || ''&amp;quot;Подключение&amp;quot; другого сценария''&lt;br /&gt;
|-&lt;br /&gt;
| '''COMMAND /C''' || '''source''' или &amp;lt;big&amp;gt;'''.'''&amp;lt;/big&amp;gt;(оператор &amp;quot;точка&amp;quot;) || ''&amp;quot;Подключение&amp;quot; другого сценария&amp;lt;br /&amp;gt;(то же, что и CALL)&lt;br /&gt;
|-&lt;br /&gt;
| '''SET''' || '''export''' || ''Установить переменную окружения''&lt;br /&gt;
|-&lt;br /&gt;
| '''SHIFT''' || '''shift''' || ''Cдвиг списка аргументов&amp;lt;br /&amp;gt;командной строки влево''&lt;br /&gt;
|-&lt;br /&gt;
| '''SGN''' || '''-lt''' или '''-gt''' || ''Знак (целого числа)''&lt;br /&gt;
|-&lt;br /&gt;
| '''ERRORLEVEL''' || '''$?''' || ''Код завершения''&lt;br /&gt;
|-&lt;br /&gt;
| '''CON''' || '''stdin''' || ''&amp;quot;Консоль&amp;quot; (stdin)''&lt;br /&gt;
|-&lt;br /&gt;
| '''PRN''' || '''/dev/lp0''' || ''Устройство принтера''&lt;br /&gt;
|-&lt;br /&gt;
| '''LPT1''' || '''/dev/lp0''' || ''Устройство принтера''&lt;br /&gt;
|-&lt;br /&gt;
| '''COM1''' || '''/dev/ttyS0''' || ''Первый последовательный порт''&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Пакетные файлы обычно содержат вызовы команд ''DOS''. Они должны быть заменены эквивалентными командами Unix.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица J-2. Команды DOS и их эквиваленты в Unix'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 385px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''''Команды DOS''''' !! '''''Эквивалент в Unix''''' !! '''''Описание'''''&lt;br /&gt;
|-&lt;br /&gt;
| '''ASSIGN''' || '''ln''' || ''Ссылка на файл или каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''ATTRIB''' || '''chmod''' || ''изменить атрибуты файла&amp;lt;br /&amp;gt;(права доступа)''&lt;br /&gt;
|-&lt;br /&gt;
| '''CD''' || '''cd''' || ''Сменить каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''CHDIR''' || '''cd''' || ''Сменить каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''CLS''' || '''clear''' || ''Очистить экран''&lt;br /&gt;
|-&lt;br /&gt;
| '''COMP''' || '''diff, comm, cmp''' || ''Сравнить файлы''&lt;br /&gt;
|-&lt;br /&gt;
| '''COPY''' || '''cp''' || ''Скопировать файл''&lt;br /&gt;
|-&lt;br /&gt;
| '''Ctl-C''' || '''Ctl-C''' || ''Прервать исполнение сценария''&lt;br /&gt;
|-&lt;br /&gt;
| '''Ctl-Z''' || '''Ctl-D''' || ''EOF (конец файла)''&lt;br /&gt;
|-&lt;br /&gt;
| '''DEL''' || '''rm''' || ''Удалить файл(ы)''&lt;br /&gt;
|-&lt;br /&gt;
| '''DELTREE''' || '''rm -rf''' || ''Удалить каталог с подкаталогами''&lt;br /&gt;
|-&lt;br /&gt;
| '''DIR''' || '''ls -l''' || ''Вывести содержимое каталога''&lt;br /&gt;
|-&lt;br /&gt;
| '''ERASE''' || '''rm''' || ''Удалить файл(ы)''&lt;br /&gt;
|-&lt;br /&gt;
| '''EXIT''' || '''exit''' || ''Завершить текущий процесс''&lt;br /&gt;
|-&lt;br /&gt;
| '''FC''' || '''comm, cmp''' || ''Сравнить файлы''&lt;br /&gt;
|-&lt;br /&gt;
| '''FIND''' || '''grep''' || ''Найти строку в файлах''&lt;br /&gt;
|-&lt;br /&gt;
| '''MD''' || '''mkdir''' || ''Создать каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''MKDIR''' || '''mkdir''' || ''Создать каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''MORE''' || '''more''' || ''Постраничный вывод''&lt;br /&gt;
|-&lt;br /&gt;
| '''MOVE''' || '''mv''' || ''Переместить''&lt;br /&gt;
|-&lt;br /&gt;
| '''PATH''' || '''$PATH''' || ''Путь поиска исполняемых файлов''&lt;br /&gt;
|-&lt;br /&gt;
| '''REN''' || '''mv''' || ''Переименовать (переместить)''&lt;br /&gt;
|-&lt;br /&gt;
| '''RENAME''' || '''mv''' || ''Переименовать (переместить)''&lt;br /&gt;
|-&lt;br /&gt;
| '''RD''' || '''rmdir''' || ''Удалить каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''RMDIR''' || '''rmdir''' || ''Удалить каталог''&lt;br /&gt;
|-&lt;br /&gt;
| '''SORT''' || '''sort''' || ''Отсортировать файл''&lt;br /&gt;
|-&lt;br /&gt;
| '''TIME''' || '''date''' || ''Вывести системное время''&lt;br /&gt;
|-&lt;br /&gt;
| '''TYPE''' || '''cat''' || ''вывести содержимое&amp;lt;br /&amp;gt;файла на stdout''&lt;br /&gt;
|-&lt;br /&gt;
| '''XCOPY''' || '''cp''' || ''Скопировать файл(расширенная команда)''&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;big&amp;gt;'''!'''&amp;lt;/big&amp;gt;Фактически, команды и операторы командной оболочки Unix имеют огромное количество дополнительных опций, расширяющих их функциональность, по сравнению с их эквивалентами в ''DOS''. В большинстве своём, пакетные файлы ''DOS'' предполагают наличие вспомогательных утилит, таких как '''ask.com''' (&amp;quot;увечный&amp;quot; аналог Unix-вого '''''read'''''). &amp;lt;br /&amp;gt;&lt;br /&gt;
''DOS'' поддерживает крайне ограниченный набор шаблонных символов, участвующих в операциях подстановки имён файлов, распознавая только два символа — &amp;lt;big&amp;gt;'''*'''&amp;lt;/big&amp;gt; и &amp;lt;big&amp;gt;'''?'''&amp;lt;/big&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Преобразование пакетных файлов ''DOS'' в сценарии командной оболочки, обычно не вызывает затруднений, а результат такого преобразования читается гораздо лучше, чем оригинал.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример J-1. VIEWDATA.BAT: пакетный файл DOS'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;dos&amp;quot;&amp;gt;&lt;br /&gt;
REM VIEWDATA&lt;br /&gt;
&lt;br /&gt;
REM INSPIRED BY AN EXAMPLE IN &amp;quot;DOS POWERTOOLS&amp;quot;&lt;br /&gt;
REM BY PAUL SOMERSON&lt;br /&gt;
&lt;br /&gt;
@ECHO OFF&lt;br /&gt;
&lt;br /&gt;
IF !%1==! GOTO VIEWDATA&lt;br /&gt;
REM IF NO COMMAND-LINE ARG...&lt;br /&gt;
&lt;br /&gt;
FIND &amp;quot;%1&amp;quot; C:\BOZO\BOOKLIST.TXT&lt;br /&gt;
GOTO EXIT0&lt;br /&gt;
REM PRINT LINE WITH STRING MATCH, THEN EXIT.&lt;br /&gt;
&lt;br /&gt;
:VIEWDATA&lt;br /&gt;
TYPE C:\BOZO\BOOKLIST.TXT | MORE&lt;br /&gt;
REM SHOW ENTIRE FILE, 1 PAGE AT A TIME.&lt;br /&gt;
&lt;br /&gt;
:EXIT0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Результат преобразования в сценарий командной оболочки, немного улучшенный.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Пример J-2. viewdata.sh: Результат преобразования VIEWDATA.BAT в сценарий командной оболочки'''''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
# Результат преобразования пакетного файла VIEWDATA.BAT в сценарий командной оболочки.&lt;br /&gt;
&lt;br /&gt;
DATAFILE=/home/bozo/datafiles/book-collection.data&lt;br /&gt;
ARGNO=1&lt;br /&gt;
&lt;br /&gt;
# @ECHO OFF Эта команда здесь не нужна.&lt;br /&gt;
&lt;br /&gt;
if [ $# -lt &amp;quot;$ARGNO&amp;quot; ] # IF !%1==! GOTO VIEWDATA&lt;br /&gt;
then&lt;br /&gt;
 less $DATAFILE # TYPE C:\MYDIR\BOOKLIST.TXT | MORE&lt;br /&gt;
else&lt;br /&gt;
 grep &amp;quot;$1&amp;quot; $DATAFILE # FIND &amp;quot;%1&amp;quot; C:\MYDIR\BOOKLIST.TXT&lt;br /&gt;
fi&lt;br /&gt;
&lt;br /&gt;
exit 0 # :EXIT0&lt;br /&gt;
&lt;br /&gt;
# Операторы перехода GOTO, метки и прочий &amp;quot;мусор&amp;quot; больше не нужны.&lt;br /&gt;
# Результат преобразования стал короче, чище и понятнее.&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
На сайте ''Тэда Дэвиса''(''Ted Davis'') [http://www.maem.umr.edu/~batch/ Shell Scripts on the PC], вы найдёте большое число руководств по созданию пакетных файлов в ''DOS''. Определённо, его изобретательность будет вам полезна, при создании ваших сценариев.&lt;br /&gt;
&lt;br /&gt;
= Приложение K. Упражнения =&lt;br /&gt;
== K1. Анализ сценариев ==&lt;br /&gt;
Просмотрите следующие сценарии. Попробуйте запустить их, затем объясните — что они делают. Расставьте комментарии и попробуйте записать сценарии в более компактном виде.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#!/bin/bash&lt;br /&gt;
&lt;br /&gt;
MAX=10000&lt;br /&gt;
&lt;br /&gt;
for((nr=1; nr&amp;lt;$MAX; nr++))&lt;br /&gt;
do&lt;br /&gt;
 let &amp;quot;t1 = nr % 5&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$t1&amp;quot; -ne 3 ]&lt;br /&gt;
 then&lt;br /&gt;
  continue&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;t2 = nr % 7&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$t2&amp;quot; -ne 4 ]&lt;br /&gt;
 then&lt;br /&gt;
  continue&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
 let &amp;quot;t3 = nr % 9&amp;quot;&lt;br /&gt;
 if [ &amp;quot;$t3&amp;quot; -ne 5 ]&lt;br /&gt;
 then&lt;br /&gt;
  continue&lt;br /&gt;
 fi&lt;br /&gt;
&lt;br /&gt;
break # Что произойдёт, если закомментировать эту строку? Почему?&lt;br /&gt;
done&lt;br /&gt;
&lt;br /&gt;
echo &amp;quot;Число = $nr&amp;quot;&lt;br /&gt;
&lt;br /&gt;
exit 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Читатель прислал следующий кусок кода:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
while read LINE&lt;br /&gt;
do&lt;br /&gt;
 echo $LINE&lt;br /&gt;
done &amp;lt; `tail -f /var/log/messages`&lt;br /&gt;
&amp;lt;/source&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
Он предполагал написать сценарий, который отслеживал бы изменения в системном журнале ''/var/log/messages''. К сожалению, этот код &amp;quot;зависает&amp;quot; и не делает ничего полезного. Почему? Найдите ошибку и исправьте её (подсказка: вместо операции перенаправления stdin в цикл, попробуйте использовать конвейерную обработку).&amp;lt;br /&amp;gt;&lt;br /&gt;
Просмотрите сценарий &amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;Пример A-11&amp;lt;/span&amp;gt;, попробуйте изменить его таким образом, чтобы он выглядел проще и логичнее. Удалите всё &amp;quot;лишние&amp;quot; переменные и попытайтесь оптимизировать сценарий по скорости исполнения. Измените сценарий таким образом, чтобы он мог принимать начальную установку &amp;quot;поколения 0&amp;quot; из любого текстового файла. Сценарий должен считать первые $ROW*$COL символов, и на место гласных вставлять &amp;quot;живые особи&amp;quot;. Подсказка: не забудьте преобразовать пробелы в символы подчеркивания.&lt;br /&gt;
&lt;br /&gt;
== K2. Создание сценариев ==&lt;br /&gt;
Напишите сценарии для выполнения повседневных задач.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Простые задания'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Содержимое домашнего каталога'''&lt;br /&gt;
:Выполните рекурсивный обход домашнего каталога и сохраните информацию в файл. Сожмите файл. Попросите пользователя вставить дискету и нажать клавишу ''ENTER''. Запишите сжатый файл на дискету.&lt;br /&gt;
'''Замена цикла for циклами while и until'''&lt;br /&gt;
:Замените циклы ''for'' в &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Простой цикл for'''''&amp;lt;/span&amp;gt; (из главы ''Циклы и ветвления'') на ''while''. Подсказка: запишите данные в массив и пройдите в цикле по элементам массива. &amp;lt;br /&amp;gt;&lt;br /&gt;
:Выполнив эту &amp;quot;тяжёлую работу&amp;quot;, замените циклы, в этом примере, на циклы ''until''.&lt;br /&gt;
'''Изменение межстрочного интервала в текстовом файле'''&lt;br /&gt;
:Напишите сценарий, который будет читать текст из заданного файла, и выводить, построчно, на ''stdout'', добавляя при этом дополнительные пустые строки так, чтобы в результате получился вывод с двойным ''межстрочным интервалом''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Добавьте код, который будет выполнять проверку наличия файла, передаваемого как аргумент.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Когда сценарий будет отлажен, измените его так, чтобы он выводил текстовый файл с тройным ''межстрочным интервалом''.&amp;lt;br /&amp;gt;&lt;br /&gt;
:И наконец, напишите сценарий, который будет удалять пустые строки из заданного файла.&lt;br /&gt;
'''Вывод &amp;quot;задом-на-перёд&amp;quot;'''&lt;br /&gt;
:Напишите сценарий, который будет выводить себя на ''stdout'', но в обратном порядке.&lt;br /&gt;
'''Автоматическое разархивирование'''&lt;br /&gt;
:Для каждого файла, из заданного списка, сценарий должен определить тип архиватора, которым был создан тот или иной файл (с помощью утилиты '''file'''). Затем сценарий должен выполнить соответствующую команду разархивации ('''gunzip''', '''bunzip2''', '''unzip''', '''uncompress''' или что-то иное). Если файл не является архивом, то сценарий должен оповестить пользователя об этом и ничего не делать с этим файлом.&lt;br /&gt;
'''Уникальный идентификатор системы'''&lt;br /&gt;
:Сценарий должен сгенерировать &amp;quot;уникальный&amp;quot; 6-ти разрядный шестнадцатиричный идентификатор системы. Не пользуйтесь дефектной утилитой '''hostid''. Подсказка: '''md5sum /etc/passwd''', затем отберите первые 6 цифр.&lt;br /&gt;
'''Резервное копирование'''&lt;br /&gt;
:Сценарий должен создать архив (*.tar.gz) всех файлов в домашнем каталоге пользователя(/home/user-name), которые изменялись в течение последних 24 часов. Подсказка: воспользуйтесь утилитой '''find'''.&lt;br /&gt;
'''Простые числа'''&lt;br /&gt;
:Сценарий должен вывести (на ''stdout'') все простые числа, в диапазоне от 60000 до 63000. Вывод должен быть отформатирован по столбцам (подсказка: воспользуйтесь командой '''printf''').&lt;br /&gt;
'''Лототрон'''&lt;br /&gt;
:Сценарий должен имитировать работу лототрона — извлекать 5 случайных неповторяющихся чисел в диапазоне 1-50. Сценарий должен предусматривать как вывод на ''stdout'', так и запись чисел в файл, кроме того, вместе с числами должны выводиться дата и время генерации данного набора.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Задания повышенной сложности'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Управление дисковым пространством'''&lt;br /&gt;
:Сценарий должен отыскать в домашнем каталоге пользователя ''/home/username'' файлы, имеющие размер больше 100K. Каждый раз предоставляя пользователю возможность удалить или сжать этот файл, затем переходить к поиску следующего файла.&lt;br /&gt;
'''Безопасное удаление'''&lt;br /&gt;
:Напишите сценарий &amp;quot;безопасного&amp;quot; удаления файлов — srm.sh. Файлы, с именами, передаваемыми этому сценарию, не должны удаляться, вместо этого, файлы следует сжать утилитой [[gzip]], если они ещё не сжаты (не забывайте про утилиту '''file'''), и переместить в каталог ''/home/username/trash''. При старте, сценарий должен удалять из каталога &amp;quot;trash&amp;quot; файлы, которые были созданы более 48 часов тому назад.&lt;br /&gt;
'''Размен монет'''&lt;br /&gt;
:Как более рационально собрать сумму в $1.68, используя только монеты, с номиналом не выше 25c? Это будет шесть 25-ти центовых монет, одна десятицентовая, одна пятицентовая и три монеты достоинством в 1 цент.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Учитывая возможность произвольного ввода суммы в долларах и центах ($*.??), найдите такую комбинацию, которая требовала бы наименьшее число монет. Если вы проживаете не в США, то можете использовать свою денежную единицу и номиналы монет. Подсказка: взгляните на &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Преобразование чисел в римскую форму записи'''''&amp;lt;/span&amp;gt;.&lt;br /&gt;
'''Корни квадратного уравнения'''&lt;br /&gt;
:Напишите сценарий, который находил бы корни &amp;quot;квадратного &amp;quot; уравнения, вида: ''Ax^2+Bx+C=0''. Сценарий должен получать коэффициенты уравнения A, B и C, как аргументы командной строки, и находить корни, с точностью до четвёртого знака после запятой.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Подсказка: воспользуйтесь '''bc''', для нахождения решения по хорошо известной формуле: ''x = ( -B+/- sqrt( B^2 - 4AC ) ) / 2A''.&lt;br /&gt;
'''Сумма чисел'''&lt;br /&gt;
:Найдите сумму всех пятизначных чисел (в диапазоне 10000-99999), которые содержат точно две цифры из следующего набора: {4, 5, 6}.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Примеры чисел, удовлетворяющих данному условию: 42057, 74638 и 89515.&lt;br /&gt;
'''Счастливый билет'''&lt;br /&gt;
:&amp;quot;Счастливым&amp;quot; считается такой билет, в котором последовательное сложение цифр номера даёт число 7. Например, 62431 — номер &amp;quot;счастливого&amp;quot; билета (6+2+4+3+1=16, 1+6 = 7). Найдите все &amp;quot;счастливые&amp;quot; номера, располагающиеся в диапазоне 1000-10000.&lt;br /&gt;
'''Синтаксический анализ'''&lt;br /&gt;
:Проанализируйте файл ''/etc/passwd'' и выведите его содержимое в табличном виде.&lt;br /&gt;
'''Контроль входов в систему'''&lt;br /&gt;
:Проанализируйте файл ''/var/log/messages'' и выведите в отформатированном виде сведения по каждому пользователю — когда он входил в систему. Возможно, что для работы сценарию потребуются права root. (Подсказка: Ищите строки, содержащие текст &amp;quot;LOGIN&amp;quot;)&lt;br /&gt;
'''Просмотр файла с данными'''&lt;br /&gt;
:Некоторые базы данных и электронные таблицы используют формат CSV (''comma-separated values'' — значения, разделённые запятыми), для хранения данных в файлах. Зачастую, эти файлы должны анализироваться другими приложениями.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Пусть файл содержит следующие данные:&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Jones,Bill,235 S. Williams St.,Denver,CO,80221,(303) 244-7989&amp;lt;br /&amp;gt;Smith,Tom,404 Polk Ave.,Los Angeles,CA,90003,(213) 879-5612...''&lt;br /&gt;
:Прочитайте данные и выведите их на ''stdout'' в виде колонок с заголовками.&lt;br /&gt;
'''Выравнивание'''&lt;br /&gt;
:Текст вводится с устройства ''stdin'' или из файла. Его необходимо вывести на ''stdout'', с выравниванием по ширине, используя задаваемую пользователем ширину строк.&lt;br /&gt;
'''Список рассылки'''&lt;br /&gt;
:Напишите сценарий, который использовал бы команду '''mail''', для управления простым списком рассылки. Сценарий должен брать текст ежемесячного информационного бюллетеня из заданного файла, список адресатов из другого файла и выполнять рассылку новостей по электронной почте.&lt;br /&gt;
'''Генерация паролей'''&lt;br /&gt;
:Сгенерируйте псевдослучайные 8-ми символьные пароли, используя символы из диапазона [0-9], [A-Z], [a-z]. Каждый пароль должен содержать не менее 2-х цифр.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;big&amp;gt;'''Сложные задания'''&amp;lt;/big&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Проверка паролей'''&lt;br /&gt;
:Напишите сценарий проверки простоты раскрытия заданного пароля.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Исследуемый пароль должен передаваться сценарию как аргумент командной строки. Пароль должен отвечать следующим минимальным требованиям:&amp;lt;br /&amp;gt;&lt;br /&gt;
:* Минимальная длина — 8 символов&lt;br /&gt;
:* Должен содержать хотя бы одну цифру&lt;br /&gt;
:* Должен содержать хотя бы один из следующих символов: @, #, $, %, &amp;amp;, *, +, -, =&lt;br /&gt;
:''Необязательно'':&lt;br /&gt;
:*Проверка возможности подбора по словарю каждой последовательной четвёрки алфавитных символов. Это исключит вхождение &amp;quot;словарных словwords&amp;quot; в пароль.&lt;br /&gt;
:*Проверьте с помощью этого сценария все пароли в вашей системе, которые могут располагаться в ''/etc/passwd'' (или в другом месте).&lt;br /&gt;
:Для создания такого сценария вам потребуется умение работать с ''регулярными выражениями''.&lt;br /&gt;
'''Регистрация обращений к файлам'''&lt;br /&gt;
:Попробуйте отследить все попытки обращения к файлам в каталоге ''/etc'', в течение дня. Сведения, которые включают в себя время обращения, имя файла, имя пользователя (если имели место какие-либо изменения в файлах, то они тоже должны быть отмечены), запишите в виде аккуратно отформатированных записей в лог-файл.&lt;br /&gt;
'''Мониторинг процессов'''&lt;br /&gt;
:Напишите сценарий, который производит непрерывный мониторинг запускаемых процессов и отслеживает количество дочерних процессов для каждого &amp;quot;родителя&amp;quot;. Как только процесс порождает более 5 дочерних процессов, сценарий должен послать уведомление системному администратору (или root-у) с соответствующей информацией. В письме необходимо указать время, PID &amp;quot;родителя&amp;quot;, PID каждого &amp;quot;потомка&amp;quot; и пр.. Сценарий должен писать отчет в системный журнал один раз в 10 минут.&lt;br /&gt;
'''Удаление комментариев'''&lt;br /&gt;
:Удалите все комментарии из сценария, имя которого задается с командной строки. При этом, строка &amp;quot;''#! /bin/bash''&amp;quot; не должна удаляться.&lt;br /&gt;
'''Преобразование в HTML'''&lt;br /&gt;
Преобразуйте заданный текстовый файл в HTML формат. Этот сценарий должен автоматически вставлять необходимые теги HTML в тело файла.&lt;br /&gt;
'''Удаление тегов HTML'''&lt;br /&gt;
:Удалите все теги HTML из заданного HTML файла, затем переформатируйте его так, чтобы строки не были короче 60 и длиннее 75 символов. Предусмотрите оформление параграфов. Преобразуйте таблицы HTML в их приблизительный текстовый эквивалент.&lt;br /&gt;
'''Преобразование XML файлов'''&lt;br /&gt;
:Преобразуйте файл из формата XML в формат HTML и в простой текстовый файл.&lt;br /&gt;
'''Борьба со спамом'''&lt;br /&gt;
:Напишите сценарий, который анализировал бы входящие почтовые сообщения на принадлежность к спаму и отыскивал бы в DNS имена узлов сети, по IP адресам из заголовка письма. Сценарий должен отправлять найденные спамерские сообщения ответственным за спам-провайдерам (ISP). Естественно, вы должны отфильтровать свой собственный IP-адрес, чтобы не случилось так, что вы жалуетесь на самого себя.&amp;lt;br /&amp;gt;&lt;br /&gt;
:По мере необходимости, используйте соответствующие команды для работы с сетью.&lt;br /&gt;
'''Азбука Морзе'''&lt;br /&gt;
:Преобразуйте текстовый файл в код Морзе. Символы из файла должны быть представлены в виде, соответствующих им, кодов Морзе, состоящих из точек и тире, и разделённых пробелами. Например, &amp;quot;'''script'''&amp;quot; ===&amp;gt; &amp;quot;'''... _._. ._. .. .__. _'''&amp;quot;.&lt;br /&gt;
'''Шестнадцатиричный дамп'''&lt;br /&gt;
:Выведите, в виде шестнадцатиричного дампа, содержимое бинарного файла, передаваемого в сценарий, как аргумент командной строки. Вывод должен производиться в четкой табличной форме, первое поле таблицы — адрес, далее должны следовать 8 полей, содержащие 4-хбайтовые шестнадцатиричные числа, а завершать строку должно поле, содержащее эквивалентное отображение 8-ми предшествующих полей, в виде ASCII-символов.&lt;br /&gt;
'''Эмуляция сдвигового регистра'''&lt;br /&gt;
:Используя &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Эмуляция структуры &amp;quot;СТЕК&amp;quot; (&amp;quot;первый вошёл — последний вышел&amp;quot;)'''''&amp;lt;/span&amp;gt;, как образец, напишите сценарий, который эмулировал бы 64-х битный сдвиговый регистр в виде массива. Реализуйте функции загрузки значения в регистр, сдвиг влево и сдвиг вправо. В заключение, напишите функцию, которая интерпретировала бы содержимое &amp;quot;регистра&amp;quot; как восемь 8-ми битных символов ''ASCII''.&lt;br /&gt;
'''Детерминант (определитель)'''&lt;br /&gt;
:Найдите детерминант (определитель) матрицы 4x4.&lt;br /&gt;
'''Анаграммы'''&lt;br /&gt;
:Сценарий должен запросить у пользователя 4-х символьное слово, и найти анаграммы для этого слова. Например, анаграммы к слову word: do or rod row word. Для поиска анаграмм можете использовать файл ''/usr/share/dict/linux.words''.&lt;br /&gt;
'''Индекс сложности текста'''&lt;br /&gt;
:&amp;quot;Индекс сложности текста&amp;quot; оценивает трудность понимания текста, как некое число, которое грубо соответствует количеству лет обучения в общеобразовательной школе. Например, индекс равный 8-ми говорит о том, что текст доступен для понимания человеку, окончившему 8-й класс общеобразовательной школы.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Вычисление индекса ведется по следующему алгоритму:&lt;br /&gt;
:# Выберите кусок текста, длиной не менее 100 слов.&lt;br /&gt;
:# Сосчитайте количество предложений.&lt;br /&gt;
:# Найдите среднее число слов в предложении — '''СРЕДНЕЕ_ЧИСЛО_СЛОВ'''=''ОБЩЕЕ_ЧИСЛО_СЛОВ/ЧИСЛО_ПРЕДЛОЖЕНИЙ''&lt;br /&gt;
:# Сосчитайте количество &amp;quot;трудных&amp;quot; слов — которые содержат не менее 3-х слогов. Разделите это число на общее количество слов, в результате вы получите пропорцию сложных слов — '''ПРОПОРЦИЯ_СЛОЖНЫХ_СЛОВ'''=''ЧИСЛО_ДЛИННЫХ_СЛОВ/ОБЩЕЕ_ЧИСЛО_СЛОВ''&lt;br /&gt;
:# Индекс сложности текста рассчитывается как сумма двух этих чисел, умноженная на 0.4 и округлённая до ближайшего целого — '''ИНДЕКС_СЛОЖНОСТИ'''=''int (0.4*( СРЕДНЕЕ_ЧИСЛО_СЛОВ +ПРОПОРЦИЯ_СЛОЖНЫХ_СЛОВ))'' &amp;lt;br /&amp;gt;&lt;br /&gt;
:4-й пункт — самый сложный. Существуют различные алгоритмы подсчета слогов в словах. В данном же случае, вы можете ограничиться подсчетом сочетаний &amp;quot;гласный-согласный&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Строго говоря, при расчете индекса сложности не следует считать составные слова и имена собственные как &amp;quot;сложные&amp;quot; слова, но это слишком усложнит сценарий.&lt;br /&gt;
'''Вычисление числа пи по алгоритму &amp;quot;Игла Баффона&amp;quot;'''&lt;br /&gt;
:В 18 веке, французский математик де Баффон (de Buffon) проделывал эксперимент, который заключался в бросании иглы, длиной &amp;quot;n&amp;quot;, на деревянный пол, собранный из длинных и узких досок. Ширина всех досок пола одинакова и равна &amp;quot;d&amp;quot;. Оказалось, что отношение общего числа бросков, к числу бросков, когда игла ложилась на щель, кратно числу пи.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Пользуясь &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Пример'''&amp;lt;/span&amp;gt;: &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''''Вычисление числа &amp;quot;пи&amp;quot;'''''&amp;lt;/span&amp;gt;, напишите сценарий, который использовал бы метод Монте Карло для эмуляции &amp;quot;Иглы Баффона&amp;quot;. Для простоты примите длину иглы раной ширине досок, n = d.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''Подсказка'': особое значение здесь имеют переменные, которые будут вычисляться как расстояние от центра иглы до ближайшей щели и величина угла между иглой и щелью. Для выполнения расчётов можно воспользоваться утилитой '''bc'''.&lt;br /&gt;
'''Шифрование по алгоритму Playfair (Wheatstone)'''&lt;br /&gt;
:Напишите сценарий, реализующий алгоритм шифрования Playfair (Wheatstone). В соответствии с этим алгоритмом, текст шифруется путем замены каждой 2-х символьной последовательности — &amp;quot;диграммы&amp;quot;. Традиционно, в качестве ключа, используется матрица символов алфавита 5x5.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''C O D E S''&lt;br /&gt;
:''A B F G H''&lt;br /&gt;
:''I K L M N''&lt;br /&gt;
:''P Q R T U''&lt;br /&gt;
:''V W X Y Z''&lt;br /&gt;
:Матрица содержит все символы алфавита, за исключением символа &amp;quot;J&amp;quot;, который представляет символ &amp;quot;I&amp;quot;. Первая строка матрицы — произвольно выбранное слово, в данном случае — &amp;quot;CODES&amp;quot;, далее следуют символы алфавита, в порядке слева-направо, исключая те, которые входят в состав первой строки.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Шифрование производится по следующему алгоритму: для начала, текст сообщения разбивается на диграммы (группы по 2 символа). Если в диграмму попадают два одинаковых символа, то второй символ удаляется, и формируется новая диграмма. Если в последней группе остаётся один символ, то такая &amp;quot;неполная&amp;quot; диграмма дополняется &amp;quot;пустым&amp;quot; символом, обычно &amp;quot;X&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''THIS IS A TOP SECRET MESSAGE''&lt;br /&gt;
:''TH IS IS AT OP SE CR ET ME SA''&lt;br /&gt;
:Каждая диграмма может подпадать под одно из следующих определений:&amp;lt;br /&amp;gt;&lt;br /&gt;
:# Оба символа находятся в одной строке ключа. Тогда, каждый из них заменяется символом,стоящим справа в той же строке. Если это последний символ строки ключа, то он заменяется первым символом в той же строке ключа.&lt;br /&gt;
:# Оба символа находятся в одном столбце ключа. Тогда каждый из них заменяется на символ,стоящий ниже, в этом же столбце. Если это последний символ в столбце ключа, то он заменяется первым символом в том же столбце ключа.&lt;br /&gt;
:# Символы диграммы стоят в вершинах прямоугольника. Тогда каждый из них заменяетсясимволом из соседнего, по горизонтали, угла. Диграмма &amp;quot;TH&amp;quot; соответствует 3-му определению.&amp;lt;br /&amp;gt;&lt;br /&gt;
:''G H''&lt;br /&gt;
:''M N''&lt;br /&gt;
:T U (Прямоугольник с вершинами &amp;quot;T&amp;quot; и &amp;quot;H&amp;quot;)&lt;br /&gt;
:''T'' --&amp;gt; ''U''&lt;br /&gt;
:''H'' --&amp;gt; ''G''&lt;br /&gt;
:Диграмма &amp;quot;SE&amp;quot; соответствует 1-му определению.&lt;br /&gt;
:''C O D E S'' (Строка содержит оба символа &amp;quot;S&amp;quot; и &amp;quot;E&amp;quot;)&lt;br /&gt;
:''S'' --&amp;gt; ''C'' (замена на первый символ в строке ключа)&lt;br /&gt;
:''E'' --&amp;gt; ''S''&lt;br /&gt;
:Дешифрация выполняется обратной процедурой, для случаев 1 и 2 — замена символом стоящим левее/выше. Для случая 3 — аналогично шифрации, т.е. заменяется символом из соседнего, по горизонтали, угла. ''Helen Fouche Gaines'', в своей классической работе &amp;quot;Elementary Cryptoanalysis&amp;quot;(1939), приводит подробное описание алгоритма ''Playfair'' и методы его реализации.&amp;lt;br /&amp;gt;&lt;br /&gt;
:Этот сценарий должен иметь три основных раздела:&lt;br /&gt;
:# Генерация &amp;quot;ключевой матрицы&amp;quot;, основывающейся на слове, которое вводит пользователь.&lt;br /&gt;
:# Шифрование &amp;quot;плоского&amp;quot; текста сообщения.&lt;br /&gt;
:# Дешифрование зашифрованного текста.&lt;br /&gt;
:Широкое применение, в этом сценарии, найдут массивы и функции.&lt;br /&gt;
&lt;br /&gt;
'''Пожалуйста, не присылайте автору свои варианты решения упражнений. Если вы хотите впечатлить его своим умом и сообразительностью — присылайте обнаруженные вами ошибки и предложения по улучшению этой книги!'''&lt;br /&gt;
&lt;br /&gt;
= Приложение L. Хронология =&lt;br /&gt;
Впервые этот документ вышел как ''HOWTO'' весной 2000 года. С тех пор он претерпел множество изменений и дополнений. Эта книга вряд ли появилась бы на свет без помощи всего Linux-сообщества, и особенно без помощи [http://www.tldp.org/ Linux Documentation Project].&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt; '''Таблица L-1. Хронология'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin-left: 365px; margin-right: 0px;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Редакция !! Дата !! Примечания&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 0.1 || 14 Июня 2000 || Первая редакция.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 0.2 || 30 Октября 2000 || Исправление ошибок, сделаны добавления&amp;lt;br /&amp;gt;в тексте, добавлены примеры сценариев.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 0.3 || 12 Февраля 2001 || Добавления&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 0.4 || 08 Июля 2001 || Полная переработка книги.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 0.5 || 03 Сентября 2001 || Исправления ошибок, дополнительный&amp;lt;br /&amp;gt;материал, реорганизация структуры книги.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.0 || 14 Октября 2001 || Стабильная редакция: исправления ошибок,&amp;lt;br /&amp;gt;реорганизация структуры, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.1 || 06 Января 2002 || Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.2 || 31 Марта 2002 || Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.3 || 02 Июня 2002 || Редакция &amp;quot;Мандарин&amp;quot; (TANGERINE):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.4 || 16 Июня 2002 || Редакция &amp;quot;Манго&amp;quot; (MANGO):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.5 || 13 Июля 2002 || Редакция &amp;quot;Папайя&amp;quot; (PAPAYA):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.6 || 29 Сентября 2002 || Редакция &amp;quot;Гранат&amp;quot; (POMEGRANATE):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.7 || 05 Января 2003 || Редакция &amp;quot;Кокос&amp;quot; (COCONUT):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.8 || 10 Мая 2003 || Редакция &amp;quot;Плод хлебного дерева&amp;quot; (BREADFRUIT):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 1.9 || 21 Июня 2003 || Редакция &amp;quot;Хурма&amp;quot; (PERSIMMON):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 2.0 || 24 Августа 2003 || Редакция &amp;quot;Крыжовник&amp;quot; (GOOSEBERRY):&amp;lt;br /&amp;gt;Дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 2.1 || 14 Сентября 2003 || Редакция &amp;quot;Черника&amp;quot; (HUCKLEBERRY):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 2.2 || 31 Октября 2003 || Редакция &amp;quot;Клюква&amp;quot; (CRANBERRY):&amp;lt;br /&amp;gt;Дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 2.3 || 03 Января 2004 || Редакция &amp;quot;Земляника&amp;quot; (STRAWBERRY):&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 2.4 || 25 Января 2004 || Редакция &amp;quot;Дыня&amp;quot; (MUSKMELON):&amp;lt;br /&amp;gt;Исправления ошибок.&lt;br /&gt;
|-&lt;br /&gt;
| style=&amp;quot;text-align:center;&amp;quot; | 2.5 || 15 Февраля 2004 || Редакция STARFRUIT:&amp;lt;br /&amp;gt;Исправления ошибок, дополнительный материал.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Приложение M. Авторские права =&lt;br /&gt;
Авторские права на книгу &amp;quot;Advanced Bash-Scripting Guide&amp;quot;, принадлежат '''Менделю Куперу''' (MendelCooper). Автор так же заявляет о своих правах на все предыдущие версии этого документа. Этим соглашением признаются и охраняются авторские права третьих лиц, предоставивших свои материалы для данной книги. Этот документ может распространяться исключительно на условиях Open Publication License (версия 1.0 или выше), [http://www.opencontent.org/openpub/]. Соблюдение следующих пунктов лицензии обязательно:&amp;lt;br /&amp;gt;&lt;br /&gt;
# Распространение существенно измененных версий этого документа, запрещено без явного разрешения держателя прав.&lt;br /&gt;
# Запрещено распространение твёрдых (бумажных) копий книги, или её производных, без явного согласия держателя прав.&amp;lt;br /&amp;gt;&lt;br /&gt;
''Пункт 1'', выше, явно запрещает вставлять логотипы компаний или навигационные элементы в титульную страницу или в текст документа, за исключением:&amp;lt;br /&amp;gt;&lt;br /&gt;
# Некоммерческих организаций, таких как [http://www.tldp.org/ Linux Documentation Project] и [https://www.ibiblio.org/ Sunsite].&lt;br /&gt;
# Не &amp;quot;запятнавших&amp;quot; себя дистрибутивостроителей Linux, таких как '''''Debian''''', '''''Red Hat''''', '''''Mandrake''''' и других.&amp;lt;br /&amp;gt;&lt;br /&gt;
Распространителям и издателям (включая электронные издания) запрещается наложение каких-либо ограничений, условий на данный документ, и все предыдущие его версии, без явного письменного разрешения автора. Начиная с этой версии, автор утверждает, что он ''НЕ'' связан какими-либо договорными отношениями, которые отменяли бы вышеизложенные высказывания.&amp;lt;br /&amp;gt;&lt;br /&gt;
Практически, вы можете свободно распространять неизмененную электронную версию этой книги. Вы должны получить явное разрешение автора на распространение изменённых версий книги или её производных. Цель этого ограничения состоит в том, чтобы сохранить художественную целостность данного документа и предотвратить появление побочных &amp;quot;ветвей&amp;quot;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Если вы выкладываете или распространяете этот документ, или какую-либо его предыдущую версию, на основе лицензии, иной, кроме перечисленных выше, тогда вы обязаны получить письменное разрешение автора книги, в противном случае ваши права на распространение документа являются незаконными.&amp;lt;br /&amp;gt;&lt;br /&gt;
Это очень либеральные условия и они не должны препятствовать законному распространению и использованию этой книги. Автор особенно поощряет использование этой книги в учебных целях.&lt;br /&gt;
Права на коммерческое распространение книги могут быть получены у автора(thegrendel@theriver.com).&amp;lt;br /&amp;gt;&lt;br /&gt;
Автор произвёл этот документ в соответствии с буквой и духом [http://www.tldp.org/manifesto.html LDP Manifesto].&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| '''Linux''' — это торговая марка, принадлежащая ''Линусу Торвальдсу'' (''Linus Torvalds'').&amp;lt;br /&amp;gt;&lt;br /&gt;
'''UNIX''' и '''Unix''' — это торговая марка, принадлежащая Open Group.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''MS Windows''' — это торговая марка, принадлежащая Microsoft Corp.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Pentium''' — это торговая марка, принадлежащая Intel, Inc.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''Scrabble''' — это торговая марка, принадлежащая Hasbro, Inc.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''''Все другие коммерческие торговые марки, упомянутые в данном документе, принадлежат их владельцам'''''.&lt;br /&gt;
|}&lt;br /&gt;
'''Hyun Jin Cha''' завершил перевод на Корейский язык версию 1.0.11 этой книги. Переводы на Испанский, Португальский, Французский, Немецкий, Итальянский, [http://gazette.linux.ru.net/rus/articles/index-abs-guide.html Русский] и Китайский языки находятся на стадии реализации. Если вы изъявите желание перевести этот документ на другой язык, то можете свободно выполнить этот перевод, основываясь на условиях, заявленных выше. В этом случае, автор хотел бы, чтобы его поставили в известность.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Gzip</id>
		<title>Gzip</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Gzip"/>
				<updated>2017-06-02T11:18:24Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''gzip, gunzip, gzcat''' — утилиты(команды) сжатия(упаковки) и распаковки файлов.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;    [[gzip]] [ -acdfhlLnNrtvV19 ] [-S суффикс] [ имя ... ]&lt;br /&gt;
    gunzip [ -acfhlLnNrtvV ] [-S суффикс] [ имя ... ]&lt;br /&gt;
    gzcat [ -fhLV ] [ имя ... ] &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
&lt;br /&gt;
Утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; уменьшает размер указанных файлов за счет кодирования по алгоритму Лемпела-Зива (Lempel-Ziv coding - LZ77). По возможности каждый файл заменяется одноименным файлом с расширением &amp;lt;code&amp;gt;.gz&amp;lt;/code&amp;gt;, с сохранением тех же прав доступа, владельца и времени изменения. (Стандартное расширение - &amp;lt;code&amp;gt;-gz&amp;lt;/code&amp;gt; для ОС ''VMS'', &amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt; для ''MSDOS'', ''OS/2 FAT'', ''Windows NT FAT'' и ''Atari''.) Если файлы не указаны или в качестве имени файла указан дефис (-), содержимое стандартного входного потока сжимается и направляется в стандартный выходной поток. Утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; будет пытаться сжимать только обычные файлы. В частности, она будет '''''игнорировать символические связи'''''.&lt;br /&gt;
&lt;br /&gt;
Если имя сжатого файла - слишком длинное для соответствующей файловой системы, утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; его усекает. Утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; пытается усечь только те части имени файла, которые длиннее 3 символов. (Часть имени ограничивается точками.) Если имя состоит только из коротких частей, усекаются самые длинные части. Например, если имена файлов должны быть не длиннее 14 символов, файл gzip.msdos.exe после сжатия получает имя gzi.msd.exe.gz. Имена '''''не усекаются''''' в системах, не имеющих ограничений на длину имени файла.&lt;br /&gt;
&lt;br /&gt;
По умолчанию, утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; сохраняет имя и время изменения сжимаемого файла. Они используются при разжатии файла с использованием опции -N. Это удобно, когда имя сжатого файла было усечено или когда после переноса не сохранилась временная отметка файла.&lt;br /&gt;
&lt;br /&gt;
Сжатые файлы могут быть восстановлены в исходный вид с помощью &amp;lt;code&amp;gt;[[gzip]] -d&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;gzcat&amp;lt;/code&amp;gt;. Если исходное имя файла до сжатия не подходит для текущей файловой системы, на основе исходного имени конструируется новое, допустимое.&lt;br /&gt;
&lt;br /&gt;
Утилита &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; принимает список файлов в командной строке и заменяет каждый файл, имя которого заканчивается суффиксом &amp;lt;code&amp;gt;.gz&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;-gz&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.z&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;-z&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;_z&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;.Z&amp;lt;/code&amp;gt; и который начинается с соответствующей сигнатуры распакованным файлом без расширения. Утилита &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; также распознает специальные расширения &amp;lt;code&amp;gt;.tgz&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;.taz&amp;lt;/code&amp;gt; в качестве сокращений для &amp;lt;code&amp;gt;.tar.gz&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;.tar.Z&amp;lt;/code&amp;gt;, соответственно. При сжатии утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;code&amp;gt;, при необходимости, использует расширение &amp;lt;code&amp;gt;.tgz&amp;lt;/code&amp;gt; вместо усечения имени файла с расширением &amp;lt;code&amp;gt;.tar&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Утилита &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; в настоящее время может разжимать файлы, созданные утилитами &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;zip&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;compress -H&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;pack&amp;lt;/code&amp;gt;. Формат входных данных определяется автоматически. При использовании первых двух форматов, &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; проверяет 32-битовую контрольную сумму CRC. Для формата &amp;lt;code&amp;gt;pack&amp;lt;code&amp;gt;, &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; проверяет длину распакованного файла. Стандартный формат &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt; не предполагает возможности проверки согласованности. Однако, утилита &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; иногда способна выявить сбойный файл с расширением &amp;lt;code&amp;gt;.Z&amp;lt;/code&amp;gt;. Если при разжатии файла с расширением &amp;lt;code&amp;gt;.Z&amp;lt;/code&amp;gt; вы получаете сообщение об ошибке, не думайте, что этот файл корректен только потому, что стандартная утилита &amp;lt;code&amp;gt;uncompress&amp;lt;/code&amp;gt; не сообщает об ошибках. Это просто означает, что стандартная утилита &amp;lt;code&amp;gt;uncompress&amp;lt;/code&amp;gt; не проверяет входные данные и молча генерирует &amp;quot;мусорные&amp;quot; результаты. Формат &amp;lt;code&amp;gt;compress -H&amp;lt;/code&amp;gt; в SCO (метод сжатия lzh) не включает контрольной суммы CRC, но позволяет выполнять определенные проверки согласованности.&lt;br /&gt;
&lt;br /&gt;
Файлы, сжатые с помощью утилиты &amp;lt;code&amp;gt;zip&amp;lt;/code&amp;gt; могут быть распакованы с помощью &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; только если они имеют один компонент, сжатый по методу 'deflation'. Эта возможность предназначена для упрощения преобразования файлов &amp;lt;code&amp;gt;tar.zip&amp;lt;/code&amp;gt; в формат &amp;lt;code&amp;gt;tar.gz&amp;lt;/code&amp;gt;. Для распаковки zip-файлов из нескольких компонентов используйте вместо &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; утилиту &amp;lt;code&amp;gt;unzip&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Команда &amp;lt;code&amp;gt;gzcat&amp;lt;/code&amp;gt; идентична &amp;lt;code&amp;gt;gunzip -c&amp;lt;/code&amp;gt;. (В некоторых системах утилита &amp;lt;code&amp;gt;zcat&amp;lt;/code&amp;gt; может устанавливаться как &amp;lt;code&amp;gt;gzcat&amp;lt;/code&amp;gt;, чтобы сохранилась исходная связь с &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt;.) Утилита &amp;lt;code&amp;gt;gzcat&amp;lt;/code&amp;gt; распаковывает либо список файлов, заданный в командной строке, либо стандартный входной поток, и записывает распакованные данные в стандартный выходной поток. Утилита &amp;lt;code&amp;gt;gzcat&amp;lt;/code&amp;gt; будет распаковывать файлы, имеющие соответствующую сигнатуру, независимо от наличия суффикса &amp;lt;code&amp;gt;.gz&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; использует алгоритм Лемпела-Зива (Lempel-Ziv), как и утилиты &amp;lt;code&amp;gt;zip&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;PKZIP&amp;lt;/code&amp;gt;. Степень сжатия зависит от размера входного файла и распределения типичных подстрок. Обычно файлы типа исходных кодов программ или текстов на английском языке упаковываются на 60-70%. Степень сжатия обычно намного лучше, чем достигаемая алгоритмом LZW (который используется в &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt;), кодированием Хафмана (Huffman coding, используемым утилитой &amp;lt;code&amp;gt;pack&amp;lt;/code&amp;gt;), или адаптивным кодированием Хафмана (как в утилите &amp;lt;code&amp;gt;compact&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Сжатие выполняется всегда, даже если сжатый файл несколько больше исходного. В худшем случае файл увеличивается на несколько байтов заголовка файла &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; плюс 5 байтов на каждый блок размером 32 Кбайта, что означает рост порядка 0.015% для больших файлов. Учтите, что фактическое количество блоков диска, занимаемых файлом, практически никогда не увеличивается. Утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; сохраняет права доступа, владельца и временные отметки файлов при сжатии и распаковке.&lt;br /&gt;
&lt;br /&gt;
== Опции ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Опции !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| '''-a --ascii''' || Текстовый режим ascii: преобразует символы конца строки на базе локальных установок. Эта опция поддерживается только на некоторых системах, отличных от Unix. Для MSDOS, &amp;lt;code&amp;gt;CR LF&amp;lt;/code&amp;gt; преобразуется при сжатии в &amp;lt;code&amp;gt;LF&amp;lt;/code&amp;gt;, а &amp;lt;code&amp;gt;LF&amp;lt;/code&amp;gt; преобразуется в &amp;lt;code&amp;gt;CR LF&amp;lt;/code&amp;gt; при распаковке.&lt;br /&gt;
|-&lt;br /&gt;
| '''-c --stdout --to-stdout''' || Выдаёт результат в стандартный выходной поток; исходные файлы не изменяются. Если имеется несколько входных файлов, результат состоит из последовательности независимо сжатых компопнентов. Для получения большей степени сжатия, конкатенируйте все входные файлы перед сжатием.&lt;br /&gt;
|-&lt;br /&gt;
| '''-d --decompress --uncompress''' || Распаковка.&lt;br /&gt;
|-&lt;br /&gt;
| '''-f --force''' || Принудительно упаковывает или распаковывает файл даже если он имеет несколько связей или результирующий файл уже существует, или если сжатые данные читаются с терминала или записываются на терминал. Если входные данные не соответствуют формату, распознаваемому утилитой &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; и если указана также опция &amp;lt;code&amp;gt;--stdout&amp;lt;/code&amp;gt;, копирует входные данные в стандартный выходной поток без изменений, что позволяет утилите &amp;lt;code&amp;gt;gzcat&amp;lt;/code&amp;gt; работать как &amp;lt;code&amp;gt;cat&amp;lt;/code&amp;gt;. Если опция &amp;lt;code&amp;gt;-f&amp;lt;/code&amp;gt; не задана, и утилита не работает в фоновом режиме, &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; запрашивает у пользователя, надо ли перезаписывать существующий файл.&lt;br /&gt;
|-&lt;br /&gt;
| '''-h --help''' || Выдаёт справочную информацию и завершает работу.&lt;br /&gt;
|-&lt;br /&gt;
| '''-l --list''' || Для каждого сжатого файла выдаёт следующие поля:&lt;br /&gt;
        compressed size: размер сжатого файла&lt;br /&gt;
        uncompressed size: размер исходного файла&lt;br /&gt;
        ratio: коэффициент сжатия (0.0% если неизвестен)&lt;br /&gt;
        uncompressed_name: имя файла до сжатия &lt;br /&gt;
Размер разжатого файла имеет значение -1 для файлов, формат которых не поддерживается утилитой &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;, например, для сжатых файлов с расширением &amp;lt;code&amp;gt;.Z&amp;lt;/code&amp;gt;. Для получения исходного размера файла, можно использовать команду:&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;gzcat file.Z | wc -c&amp;lt;/source&amp;gt;&lt;br /&gt;
В сочетании с опцией --verbose выдаются также следующие поля:&lt;br /&gt;
        method: метод сжатия&lt;br /&gt;
        crc: 32-битовая контрольная сумма (CRC) не сжатых данных&lt;br /&gt;
        date &amp;amp; time: временная отметка исходного файла &lt;br /&gt;
В настоящее время поддерживаются следующие методы сжатия: &amp;lt;code&amp;gt;deflate&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;lzh&amp;lt;/code&amp;gt; (аналог &amp;lt;code&amp;gt;compress -H&amp;lt;/code&amp;gt; в SCO) и &amp;lt;code&amp;gt;pack&amp;lt;/code&amp;gt;. Для файлов не в формате &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; в качестве контрольной суммы crc выдаётся значение ffffffff.&lt;br /&gt;
Если указана опция &amp;lt;code&amp;gt;--name&amp;lt;/code&amp;gt;, в качестве имени, даты и времени изменения исходного несжатого файла выдаются значения, хранящиеся в сжатом файле, если они доступны.&lt;br /&gt;
Если указана опция &amp;lt;code&amp;gt;--verbose&amp;lt;/code&amp;gt; для всех файлов выдаются также общие размеры и коэффициенты сжатия, за исключением случаев, когда размеры не известны. Если указана опция &amp;lt;code&amp;gt;--quiet&amp;lt;/code&amp;gt;, заголовки и общие значения не выдаются.&lt;br /&gt;
|-&lt;br /&gt;
| '''-L --license''' || Выдаёт лицензию &amp;lt;code&amp;gt;gzip&amp;lt;/code&amp;gt; и завершает работу.&lt;br /&gt;
|-&lt;br /&gt;
| '''-n --no-name''' || При сжатии по умолчанию не сохраняет имя и временную отметку исходного файла. (Исходное имя всегда сохраняется, если имя после сжатия придётся усекать.) При распаковке не восстанавливает исходное имя файла, если оно есть (просто удаляет суффикс &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; у имени сжатого файла) и не восстанавливает исходную временную отметку, если она есть (она просто копируется из сжатого файла). Эта опция является стандартной при распаковке.&lt;br /&gt;
|-&lt;br /&gt;
| '''-N --name''' || При сжатии всегда сохраняет исходное имя файла и временную отметку; так и происходит по умолчанию. При распаковке восстанавливает исходное имя и временную отметку файла, если они доступны. Эта опция полезна в системах с ограничениями на длину имени файла или когда после переноса файлов была потеряна временная отметка.&lt;br /&gt;
|-&lt;br /&gt;
| '''-q --quiet''' || Подавляет выдачу любых предупреждений.&lt;br /&gt;
|-&lt;br /&gt;
| '''-r --recursive''' || Рекурсивно проходит по структуре каталогов. Если любое из имён файлов, указанных в командной строке, представляет собой каталог, утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; перейдёт в этот каталог и сожмёт все находящиеся в нём файлы (или разожмёт их в случае &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt;).&lt;br /&gt;
|-&lt;br /&gt;
| '''-S .suf --suffix .suf''' || Использует суффикс .suf вместо .gz. Можно задать любой суффикс, но не стоит использовать другие суффиксы, кроме .z и .gz, чтобы избежать недоразумений при переносе файлов на другие системы. Пустой суффикс вынуждает программу gunzip попытаться распаковать все указанные файлы, независимо от суффикса, как в следующем примере:&lt;br /&gt;
        &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;gunzip -S &amp;quot;&amp;quot; * (*.* for MSDOS)&amp;lt;/source&amp;gt; &lt;br /&gt;
В прежних версиях &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; использовался суффикс &amp;lt;code&amp;gt;.z&amp;lt;/code&amp;gt;. Этот суффикс был изменен, чтобы избежать конфликтов с программой &amp;lt;code&amp;gt;pack&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| '''-t --test''' || Проверка. Проверяет целостность сжатого файла.&lt;br /&gt;
|-&lt;br /&gt;
| '''-v --verbose''' || Подробная выдача. Выдаёт имя и процент сжатия для каждого сжимаемого или разжимаемого файла.&lt;br /&gt;
|-&lt;br /&gt;
| '''-V --version''' || Версия. Выдаёт номер версии и использованные опции компиляции и завершает работу.&lt;br /&gt;
|-&lt;br /&gt;
| '''-# --fast --best''' || Управляет скоростью сжатия, задавая её указанной цифрой #, причем опция -1 или --fast задаёт самый быстрый метод (с наименьшим коэффициентом сжатия), а -9 или --best задаёт самый медленный метод (с наибольшим коэффициентом сжатия). Стандартный уровень сжатия — -6 (т.е. имеется определённое смещение в сторону повышения коэффициента сжатия за счёт снижения скорости).&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Расширенные варианты использования ==&lt;br /&gt;
Можно конкатенировать несколько сжатых файлов. В этом случае утилита &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; будет извлекать все файлы сразу. Например:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    gzip -c file1 &amp;gt; foo.gz&lt;br /&gt;
    gzip -c file2 &amp;gt;&amp;gt; foo.gz &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
После этого команда:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    gunzip -c foo &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет эквивалентна команде:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    cat file1 file2 &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В случае повреждения одного из компонентов файла &amp;lt;code&amp;gt;.gz&amp;lt;/code&amp;gt;, другие компоненты можно восстановить (если удалить поврежденный компонент). Однако большей степени сжатия можно достичь, сжимая все компоненты сразу:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    cat file1 file2 | gzip &amp;gt; foo.gz &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
сжимается лучше, чем:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    gzip -c file1 file2 &amp;gt; foo.gz &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если необходимо переупаковать конкатенированые файлы для получения большей степени сжатия, используйте команду следующего вида:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    gzip -cd old.gz | gzip &amp;gt; new.gz &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если сжатый файл состоит из нескольких компонентов, размер исходного файла и контрольная сумма CRC, выдаваемые опцией &amp;lt;code&amp;gt;--list&amp;lt;/code&amp;gt;, относятся только к последнему компоненту. Если необходимо узнать исходный размер всех компонентов, можно использовать команду:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    gzip -cd file.gz | wc -c &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если необходимо создать единый архивынй файл с несколькими компонентами так, чтобы можно было извлекать независимо друг от друга, используйте архиватор типа tar или zip. Утилита GNU &amp;lt;code&amp;gt;tar&amp;lt;code&amp;gt; поддерживает опцию &amp;lt;code&amp;gt;-z&amp;lt;/code&amp;gt; для прозрачного вызова утилиты &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;. Утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; дополняет программу &amp;lt;code&amp;gt;[[tar]]&amp;lt;/code&amp;gt;, но не заменяет её.&lt;br /&gt;
&lt;br /&gt;
== Среда ==&lt;br /&gt;
&lt;br /&gt;
Переменная среды GZIP может задавать набор стандартных опций для &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;. Эти опции интерпретируются первыми и могут переопределяться явными параметрами командной строки. Например:&lt;br /&gt;
&lt;br /&gt;
    для sh: &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;GZIP=&amp;quot;-8v --name&amp;quot;; export GZIP&amp;lt;/source&amp;gt;&lt;br /&gt;
    для csh: &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;setenv GZIP &amp;quot;-8v --name&amp;quot;&amp;lt;/source&amp;gt;&lt;br /&gt;
    для MSDOS: &amp;lt;source lang=&amp;quot;dos&amp;quot;&amp;gt;set GZIP=-8v --name&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
В ОС Vax/VMS соответствующая переменная среды называется GZIP_OPT, чтобы избежать конфликта с именем программы.&lt;br /&gt;
&lt;br /&gt;
== Диагностика ==&lt;br /&gt;
&lt;br /&gt;
Статус выхода обычно имеет значение '''''0;''''' если возникает ошибка, статус выхода имеет значение '''''1'''''. Если выдавались предупреждения, статус выхода имеет значение '''''2'''''.&lt;br /&gt;
&lt;br /&gt;
Usage: gzip [-cdfhlLnNrtvV19] [-S suffix] [file ...]&lt;br /&gt;
    В командной строке заданы недопустимые опции.&lt;br /&gt;
&lt;br /&gt;
'''''file: not in gzip format'''''&lt;br /&gt;
    Указанный программе &amp;lt;code&amp;gt;gunzip&amp;lt;/code&amp;gt; файл не был сжат утилитой &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
'''''file: Corrupt input. Use gzcat to recover some data.'''''&lt;br /&gt;
    Сжатый файл был поврежден. Данные до точки сбоя могут быть восстановлены с помощью команды&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
        gzcat file &amp;gt; recover &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''''file: compressed with xx bits, can only handle yy bits'''''&lt;br /&gt;
    Файл был сжат (с помощью алгоритма LZW) программой, способной работать с большим количеством битов, чем код распаковки на данной машине. Сожмите файл заново с помощью утилиты &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;, сжимающей лучше и использующей меньше памяти.&lt;br /&gt;
'''''file: already has .gz suffix -- no change'''''&lt;br /&gt;
    Предполагается, что файл уже сжат. Переименуйте файл и попробуйте ещё раз.&lt;br /&gt;
'''''file already exists; do you wish to overwrite (y or n)?'''''&lt;br /&gt;
    Ответьте утвердительно (y), если хотите заменить существующий файл, или отрицательно (n), если не хотите.&lt;br /&gt;
'''''gunzip: corrupt input'''''&lt;br /&gt;
    Был получен сигнал SIGSEGV, что обычно вызвано повреждением входного файла.&lt;br /&gt;
'''''xx.x%'''''&lt;br /&gt;
    Процент входного файла, сэкономленный за счет сжатия. (Только для опций -v и -l.)&lt;br /&gt;
'''''-- not a regular file or directory: ignored'''''&lt;br /&gt;
    Если входной файл не является обычным файлом или каталогом, (т.е. это символическая связь, сокет, именованный канал FIFO или специальный файл устройства, он не изменяется.&lt;br /&gt;
'''''-- has xx other links: unchanged'''''&lt;br /&gt;
    Входной файл имеет несколько связей; он не изменняется. Поробнее о связях см. на странице справочного руководства ln(1). Для принудительного сжатия файлов с несколькими связями используйте флаг -f.&lt;br /&gt;
&lt;br /&gt;
== Потенциальные проблемы ==&lt;br /&gt;
При записи сжатых данных на ленту обычно необходимо дополнять результат нулями до границы блока. При чтении данных и передаче их для распаковки утилите gunzip, она выявляет дополнительный &amp;quot;мусор&amp;quot; после сжатых данных и, по умолчанию, выдает предупреждение. Чтобы подавить выдачу этого предупреждения, используйте опцию --quiet. Эту опцию можно задать в переменной среды GZIP, как в следующем примере:&lt;br /&gt;
&lt;br /&gt;
    для sh: &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;GZIP=&amp;quot;-q&amp;quot;; tar -xfz --block-compress /dev/rst0&amp;lt;/source&amp;gt;&lt;br /&gt;
    для csh: &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;(setenv GZIP -q; tar -xfz --block-compr /dev/rst0)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В примере выше утилита &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; вызывается неявно опцией &amp;lt;code&amp;gt;-z&amp;lt;/code&amp;gt; утилиты &amp;lt;code&amp;gt;GNU [[tar]]&amp;lt;/code&amp;gt;. Проверьте, что при чтении и записи сжатых данных на ленты используется один и тот же размер блока (опция -b программы &amp;lt;code&amp;gt;[[tar]]&amp;lt;/code&amp;gt;). (В этом примере предполагается использование GNU-версии программы &amp;lt;code&amp;gt;[[tar]]&amp;lt;/code&amp;gt;.)&lt;br /&gt;
&lt;br /&gt;
== Ошибки ==&lt;br /&gt;
&lt;br /&gt;
Опция &amp;lt;code&amp;gt;--list&amp;lt;/code&amp;gt; выдаёт некорректные размеры, если они превышают 2 Гбайта. Опция &amp;lt;code&amp;gt;--list&amp;lt;/code&amp;gt; выдает значение размера &amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt; и контрольной суммы crc - ffffffff, если сжатый файл находится на носителе, не допускающем произвольную адресацию (non seekable media).&lt;br /&gt;
&lt;br /&gt;
В некоторых редких случаях опция &amp;lt;code&amp;gt;--best&amp;lt;/code&amp;gt; даёт худшее сжатие, чем стандартный уровень сжатия (-6). Некоторые особо избыточные файлы сжимаются утилитой &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt; лучше, чем утилитой &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&lt;br /&gt;
Исходные коды для утилиты &amp;lt;code&amp;gt;[[gzip]]&amp;lt;/code&amp;gt; доступны в пакете SUNWgzipS.&lt;br /&gt;
== Авторские права == &lt;br /&gt;
Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 Free Software Foundation, Inc.&lt;br /&gt;
&lt;br /&gt;
Эта программа является свободно распространяемым программным обеспечением; вы можете распространять и/или изменять ее в соответствии с условиями Генеральной общественной лицензии GNU (GNU General Public License), опубликованной Фондом свободно распространяемого программного обеспечения (Free Software Foundation); либо версии 2, либо (по вашему выбору) любой более поздней версии.&lt;br /&gt;
&lt;br /&gt;
Эта программа распространяется в надежде, что она окажется полезной, но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без подразумеваемой гарантии ТОВАРНОЙ ПРИГОДНОСТИ или ПРИГОДНОСТИ ДЛЯ КОНКРЕТНОЙ ЦЕЛИ. Подробнее см. в Генеральной общественной лицензии GNU.&lt;br /&gt;
&lt;br /&gt;
Вы должны были получить экземпляр Генеральной общественной лицензии GNU вместе с этой программой; если же нет, обратитесь за ней по адресу Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Bzip2</id>
		<title>Bzip2</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Bzip2"/>
				<updated>2017-06-02T06:40:18Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''bzip2''' — бесплатная свободная утилита командной строки с открытым исходным кодом для сж…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''bzip2''' — бесплатная свободная утилита командной строки с открытым исходным кодом для сжатия данных, реализация алгоритма Барроуза — Уилера.&lt;br /&gt;
&lt;br /&gt;
Разработана и впервые опубликована Джулианом Сюардом (Julian Seward) в июле 1996 года (версия 0.15). Стабильность и популярность компрессора росли в течение нескольких лет, и версия 1.0 была опубликована в конце 2000 года.&lt;br /&gt;
&lt;br /&gt;
== Эффективность ==&lt;br /&gt;
&lt;br /&gt;
В соответствии с традициями UNIX, &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; единовременно может выполнять только одну операцию: либо сжатие, либо распаковку и только для одного файла. При сжатии &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; добавляет к имени файла расширение «&amp;lt;code&amp;gt;.bz2&amp;lt;/code&amp;gt;». Для упаковки нескольких файлов их сперва архивируют в один файл утилитой &amp;lt;code&amp;gt;[[tar]]&amp;lt;/code&amp;gt;, а затем сжимают при помощи &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt;. Такие архивы обычно имеют расширение «&amp;lt;code&amp;gt;.tar.bz2&amp;lt;/code&amp;gt;».&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; сжимает большинство файлов эффективнее, но медленнее, чем более традиционные утилиты &amp;lt;code&amp;gt;gzip&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;zip&amp;lt;/code&amp;gt;. В этом отношении он похож на другие современные алгоритмы сжатия.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; выполняет сжатие данных с существенной нагрузкой на CPU (что обусловлено его математическим аппаратом). &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; применяют, если нет ограничений на время сжатия и на нагрузку на CPU, например, для разовой упаковки большого объёма данных.&lt;br /&gt;
&lt;br /&gt;
В некоторых случаях &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; уступает по эффективности сжатия архиваторам &amp;lt;code&amp;gt;7-Zip&amp;lt;/code&amp;gt; (метод сжатия LZMA) и &amp;lt;code&amp;gt;rar&amp;lt;/code&amp;gt;. Согласно данным автора программы от 2005 года, метод сжатия &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; уступает по эффективности сжатия на 10‑15% наилучшим методом, известным на тот момент (PPM). На данный момент наиболее эффективно сжимают различные реализации метода PAQ. Однако, использование данного метода крайне затруднено по причине низкой производительности (сжатие требует больших временных затрат), но при этом в 2 раза быстрее при сжатии и в 6 раз быстрее при распаковке.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
&lt;br /&gt;
Метод сжатия &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; работает следующим образом:&lt;br /&gt;
* несжатые данные делятся на блоки фиксированного размера;&lt;br /&gt;
* выполняется преобразование Барроуза — Уилера для превращения последовательностей многократно чередующихся символов в строки одинаковых символов;&lt;br /&gt;
* применяет преобразование Move-To-Front(MTF);&lt;br /&gt;
* используется кодирование Хаффмана.&lt;br /&gt;
&lt;br /&gt;
Приблизительный размер блока можно выбрать при помощи аргументов командной строки («&amp;lt;code&amp;gt;-1&amp;lt;/code&amp;gt;» для 100 килобайт, «&amp;lt;code&amp;gt;-2&amp;lt;/code&amp;gt;» для 200 КБ, …, «&amp;lt;code&amp;gt;-9&amp;lt;/code&amp;gt;» для 900 КБ). Каждый блок сжимается независимо, сжатые блоки записываются последовательно друг за другом, в начале каждого используется 48-битная последовательность — магическое число 0x314159265359 (в кодировке ASCII при выравнивании на границу байта отображается как «1AY&amp;amp;SY»), то есть запись первых десятичных цифр числа Пи в формате BCD. Конец файла помечается 48-битной константой 0x177245385090, представляющей собой корень из числа Пи.&lt;br /&gt;
&lt;br /&gt;
Предшественник &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt;, программа &amp;lt;code&amp;gt;bzip&amp;lt;/code&amp;gt;, вместо кодирования Хаффмана использовала арифметическое кодирование. Из‑за патентных ограничений от этого алгоритма отказались.&lt;br /&gt;
&lt;br /&gt;
== Использование ==&lt;br /&gt;
&lt;br /&gt;
Примеры использования &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Команда для сжатия файла «file»&lt;br /&gt;
bzip2 file&lt;br /&gt;
# или&lt;br /&gt;
bzip2 --compress file&lt;br /&gt;
&lt;br /&gt;
# Команда для распаковки файла «file.bz2»&lt;br /&gt;
bzip2 -d file.bz2&lt;br /&gt;
# или&lt;br /&gt;
bzip2 --decompress file.bz2&lt;br /&gt;
# или&lt;br /&gt;
bunzip2 file.bz2&lt;br /&gt;
# bunzip2 - копия bzip2 или ссылка на bzip2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Аргументы командной строки &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt; в основном такие же, как и у утилиты &amp;lt;code&amp;gt;gzip&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Команда для распаковки архива tar, сжатого bzip2&lt;br /&gt;
bzip2 -cd file.tar.bz2 | tar -xvf -&lt;br /&gt;
# или&lt;br /&gt;
bzip2 --stdout --decompress file.tar.bz2 \&lt;br /&gt;
| tar --extract --verbose --file -&lt;br /&gt;
&lt;br /&gt;
# Команда для создания архива tar, сжатого bzip2&lt;br /&gt;
tar -cvf - files | bzip2 -9 &amp;gt; file.tar.bz2&lt;br /&gt;
# или&lt;br /&gt;
tar --create --verbose --file - files \&lt;br /&gt;
| bzip2 -9 &amp;gt; file.tar.bz2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Версия GNU &amp;lt;code&amp;gt;[[tar]]&amp;lt;/code&amp;gt; поддерживает флаг «&amp;lt;code&amp;gt;-j&amp;lt;/code&amp;gt;» («&amp;lt;code&amp;gt;--bzip2&amp;lt;/code&amp;gt;»), который позволяет создавать и распаковывать файлы «&amp;lt;tt&amp;gt;tar.bz2&amp;lt;/tt&amp;gt;» без использования перенаправлений ввода-вывода (pipeline). Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Упаковка данных в архив tar и сжатие bzip2 при помощи GNU tar&lt;br /&gt;
tar -cvjf file.tar.bz2 list_of_files&lt;br /&gt;
# или&lt;br /&gt;
tar --create --verbose --bzip2 --file file.tar.bz2 list_of_files&lt;br /&gt;
&lt;br /&gt;
# Распаковка архива tar, сжатого bzip2 при помощи GNU tar&lt;br /&gt;
tar -xvjf file.tar.bz2&lt;br /&gt;
# или&lt;br /&gt;
tar --extract --verbose --bzip2 --file file.tar.bz2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Современные версии GNU &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; могут автоматически определить метод сжатия данных, и поэтому флаг «&amp;lt;code&amp;gt;-j&amp;lt;/code&amp;gt;» («&amp;lt;code&amp;gt;--bzip2&amp;lt;/code&amp;gt;») можно не использовать. Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -xvf file.tar.bz2&lt;br /&gt;
# или&lt;br /&gt;
tar --extract --verbose --file file.tar.bz2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Кроме того, существует набор утилит для выполнения поиска, вывода, восстановления и сравнения данных в формате &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt;:&lt;br /&gt;
* &amp;lt;code&amp;gt;bzcat&amp;lt;/code&amp;gt; — распаковка данных и вывод на терминал;&lt;br /&gt;
* &amp;lt;code&amp;gt;bzmore&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bzless&amp;lt;/code&amp;gt; — распаковка данных и постраничный вывод на терминал;&lt;br /&gt;
* &amp;lt;code&amp;gt;bzcmp&amp;lt;/code&amp;gt; — распаковка двух файлов, сравнение содержимого и сообщение результата: «равно» или «не равно»;&lt;br /&gt;
* &amp;lt;code&amp;gt;bzdiff&amp;lt;/code&amp;gt; — распаковка двух файлов, сравнение содержимого и вывод различий;&lt;br /&gt;
* &amp;lt;code&amp;gt;bzgrep&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bzegrep&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;bzfgrep&amp;lt;/code&amp;gt; — распаковка данных и поиск в распакованном;&lt;br /&gt;
* &amp;lt;code&amp;gt;bzip2recover&amp;lt;/code&amp;gt; — распаковка любых блоков, которые только можно распаковать.&lt;br /&gt;
&lt;br /&gt;
== Формат файла ==&lt;br /&gt;
&lt;br /&gt;
Архив «&amp;lt;code&amp;gt;.bz2&amp;lt;/code&amp;gt;» содержит поток (stream) сжатых данных. Слово «поток» употребляется, так как данные нельзя разделить логически и блоки данных сжимаются независимо друг от друга. Сжатые данные состоят из следующих полей:&lt;br /&gt;
* заголовок размером 4 байта;&lt;br /&gt;
* ноль или более блоков сжатых данных различного размера;&lt;br /&gt;
* маркер, обозначающий конец сжатых данных и контрольная сумма(CRC) размером 32 бита, вычисленная для всего потока;&lt;br /&gt;
* несколько неиспользуемых бит для дополнения размера потока до целого количества байт.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Название поля || Размер поля в битах || Описание&lt;br /&gt;
|-&lt;br /&gt;
| .magic || 16 || &amp;lt;code&amp;gt;BZ&amp;lt;/code&amp;gt; — константа, сигнатура, магическое число.&lt;br /&gt;
|-&lt;br /&gt;
| .version || 8 || Байт, кодирующий номер версии.&lt;br /&gt;
; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; : Версия 1 (bzip1). Deprecated.&lt;br /&gt;
; &amp;lt;code&amp;gt;h&amp;lt;/code&amp;gt; : Версия 2 (bzip2). «h» от англ. '''H'''uffman coding}}.&lt;br /&gt;
|-&lt;br /&gt;
| .hundred_k_blocksize || 8 || Размер блока несжатых данных в сотнях kB.&lt;br /&gt;
; &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; : Одна сотня kB (100 kB).&lt;br /&gt;
; &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt; : Две сотни kB (200 kB).&lt;br /&gt;
; … : И так далее&lt;br /&gt;
; &amp;lt;code&amp;gt;9&amp;lt;/code&amp;gt; : Девять сотен kB (900 kB).&lt;br /&gt;
|- &lt;br /&gt;
| .compressed_magic || 48 || &amp;lt;code&amp;gt;0x314159265359&amp;lt;/code&amp;gt; — константа, число Пи, записанное в двоично-десятичном коде(BCD).&lt;br /&gt;
|-&lt;br /&gt;
|| .crc || 32 || Контрольная сумма, рассчитанная для текущего блока.&lt;br /&gt;
|-&lt;br /&gt;
| .randomised || 1 ||&lt;br /&gt;
; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; : normal&lt;br /&gt;
; &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; : randomised (deprecated)&lt;br /&gt;
|-&lt;br /&gt;
| .origPtr || 24 || starting pointer into Преобразование Барроуза — Уилера(BWT) for after untransform&lt;br /&gt;
|-&lt;br /&gt;
| .huffman_used_map || 16 || bitmap, of ranges of 16 bytes, «имеется»/«отсутствует»&lt;br /&gt;
|-&lt;br /&gt;
|| .huffman_used_bitmaps || 0..256 || bitmap, of symbols used, «имеется»/«отсутствует» (кратно 16)&lt;br /&gt;
|-&lt;br /&gt;
| .huffman_groups || 3 || Число от 2 до 6, количество используемых таблиц Хаффмана.&lt;br /&gt;
|-&lt;br /&gt;
| .selectors_used || 15 || Число, показывающее сколько раз выполнялась смена таблицы Хаффмана (каждые 50 байт).&lt;br /&gt;
|-&lt;br /&gt;
| *.selector_list || 1..6 || zero-terminated bit runs (0..62) of Move-To-Front(MTF)'ed Huffman table (*selectors_used)&lt;br /&gt;
|-&lt;br /&gt;
| .start_huffman_length || 5 || 0..20 starting bit length for Huffman deltas&lt;br /&gt;
|-&lt;br /&gt;
| *.delta_bit_length || 1..40 ||&lt;br /&gt;
; &amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt; : next symbol&lt;br /&gt;
; &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt; : alter length&lt;br /&gt;
{ 1=&amp;gt;decrement length; 0=&amp;gt;increment length } (*(symbols+2)*groups)&lt;br /&gt;
|-&lt;br /&gt;
| .contents || 2..∞ || Huffman encoded data stream. Продолжается до конца блока. Максимальная длина равна formatnum:7372800 бит.&lt;br /&gt;
|-&lt;br /&gt;
| .eos_magic || 48 || &amp;lt;code&amp;gt;0x177245385090&amp;lt;/code&amp;gt; — константа, квадратный корень из числа Пи (sqrt(pi)) в двоично-десятичном коде(BCD).&lt;br /&gt;
|-&lt;br /&gt;
| .crc || 32 || Контрольная сумма, рассчитанная для всего потока.&lt;br /&gt;
|-&lt;br /&gt;
| .padding || 0..7 || Неиспользуемые биты (от 0 до 7). Назначение: увеличение размера архива до размера, кратного одному байту (8 битам) (выравнивание данных).&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Максимальный размер не сжатого блока равен 900 kB. Если блок состоит из одного повторяющегося символа, после кодирования RLE блок займёт около 46 MB (45899236 байт), а после выполнения всех операций размер файла &amp;lt;code&amp;gt;.bz2&amp;lt;/code&amp;gt; составит 46 байт. Если повторяющийся символ будет иметь код 251, размер файла &amp;lt;code&amp;gt;.bz2&amp;lt;/code&amp;gt; составит 40 байт, а коэффициент сжатия (compression ratio) будет равен 1147480.9:1.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.bzip.org/ Официальный сайт bzip.org]&lt;br /&gt;
* [http://faqs.lomonline.de/introdution-to-bzip2/ Введение в bzip2]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Tar</id>
		<title>Tar</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Tar"/>
				<updated>2017-06-02T06:18:41Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''tar''' (от англ. '''t'''ape '''ar'''chive) — формат битового потока или файла архива, а также название традиционной для Unix программы для работы с такими архивами. Программа &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; была стандартизирована в POSIX.1-1998, а также позднее в POSIX.1-2001. Первоначально программа &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; использовалась для создания архивов на магнитной ленте, а в настоящее время &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; используется для хранения нескольких файлов внутри одного файла, для распространения программного обеспечения, а также по прямому назначению — для создания архива файловой системы. Одним из преимуществ формата &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; при создании архивов является то, что в архив записывается информация о структуре каталогов, о владельце и группе отдельных файлов, а также временны́е метки файлов.&lt;br /&gt;
&lt;br /&gt;
Как и другие утилиты Unix, &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; — специализированная программа, которая следует философии Unix «делать только одну вещь» (в данном случае — работать с архивами формата &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt;), «но делать её хорошо». Поэтому &amp;lt;code&amp;gt;tar&amp;lt;/code&amp;gt; не создаёт сжатых архивов, а использует для сжатия внешние утилиты, такие, как &amp;lt;code&amp;gt;gzip&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;bzip2&amp;lt;/code&amp;gt;. Ранее для сжатия использовалась также утилита &amp;lt;code&amp;gt;compress&amp;lt;/code&amp;gt;, которая практически вышла из употребления.&lt;br /&gt;
&lt;br /&gt;
== Примечание ==&lt;br /&gt;
Из-за достаточно поздней стандартизации существует несколько похожих, но не до конца совместимых форматов. В частности, различие между ''GNU tar'' и ''SUN Solaris tar'' наблюдается при длине имени файла, включаемого в архив, более 100 символов или размере включаемого в архив файла более 8 ГБ.&lt;br /&gt;
&lt;br /&gt;
== Расширения имён файлов ==&lt;br /&gt;
Для файлов, содержащих архивы tar, традиционно применяется расширение имени файла &amp;lt;code&amp;gt;.tar&amp;lt;/code&amp;gt;. В случае дополнительного сжатия другими программами применяются следующие расширения:&lt;br /&gt;
&lt;br /&gt;
* gzip: &amp;lt;code&amp;gt;.tar.gz&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tgz&amp;lt;/code&amp;gt; (в случае ограничений файловой системы на длину расширения), &amp;lt;code&amp;gt;.tar.gzip&amp;lt;/code&amp;gt;&lt;br /&gt;
* bzip2: &amp;lt;code&amp;gt;.tar.bz2&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tar.bzip2&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tbz2&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tb2&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tbz&amp;lt;/code&amp;gt;&lt;br /&gt;
* compress: &amp;lt;code&amp;gt;.tar.Z&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.taz&amp;lt;/code&amp;gt;&lt;br /&gt;
* LZMA: &amp;lt;code&amp;gt;.tar.lzma&amp;lt;/code&amp;gt;&lt;br /&gt;
* XZ: &amp;lt;code&amp;gt;.tar.xz&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.txz&amp;lt;/code&amp;gt;&lt;br /&gt;
* lzop: &amp;lt;code&amp;gt;.tar.lzo&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tzo&amp;lt;/code&amp;gt;&lt;br /&gt;
* lzip: &amp;lt;code&amp;gt;.tar.lz&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;.tlz&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
 tar [-опции] &amp;lt;имя файла tar&amp;gt; [файлы, которые необходимо поместить в архив при сжатии]&lt;br /&gt;
Опции:&lt;br /&gt;
* -c, --create создать архив&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
Создание bar.tar из файла или каталога foo:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -cvf bar.tar foo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Извлечение содержимого bar.tar в текущий каталог:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -xvf bar.tar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Tarpipe ==&lt;br /&gt;
Tarpipe — процесс создания tar-архива в stdout и последующего извлечения содержания архива в другом каталоге из stdin. Это очень удобный метод копирования содержания одной файловой системы в другую, так как происходит полное копирование, включая атрибуты файлов, символические ссылки, файлы устройств.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -C &amp;quot;каталог_источника&amp;quot; -cf - . | tar -C &amp;quot;каталог_назначения&amp;quot; -xvf -&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;!-- Кто-нить пробовал? И сделайте команду минимальной.&lt;br /&gt;
Пробовали :) Работает) --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Tar over SSH&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar -C каталог_источника -czpvf - . | ssh user@host &amp;quot;cat &amp;gt; каталог_назначения/backup.tgz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Tar &amp;amp; 7-zip&lt;br /&gt;
Чтобы сделать резервную копию каталога:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
tar cf - directory | 7za a -si directory.tar.7z&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Чтобы восстановить из резервной копии:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
7za x -so directory.tar.7z | tar xf -&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.gnu.org/software/tar/ Официальная страница] на сайте GNU&lt;br /&gt;
* [http://savannah.gnu.org/cgi-bin/viewcvs/*checkout*/tar/tar/src/tar.h?content-type=text/plain Файл 'tar.h' из исходных текстов GNU tar]&lt;br /&gt;
* [http://www.mkssoftware.com/docs/man4/tar.4.asp Подробная информация о заголовках архивов tar и USTAR]&lt;br /&gt;
* [http://www.openbsd.org/cgi-bin/man.cgi?query=tar man-страница tar(1)] из OpenBSD&lt;br /&gt;
* [http://www.freebsd.org/cgi/man.cgi?query=tar&amp;amp;apropos=0&amp;amp;sektion=0&amp;amp;manpath=FreeBSD+8-current&amp;amp;format=html man-страница tar(1)] из FreeBSD&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Rsync_%E2%80%94_C%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%B8_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2_%D0%B2_%D0%B4%D0%B2%D1%83%D1%85_%D0%BC%D0%B5%D1%81%D1%82%D0%B0%D1%85</id>
		<title>Rsync — Cинхронизация файлов и каталогов в двух местах</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Rsync_%E2%80%94_C%D0%B8%D0%BD%D1%85%D1%80%D0%BE%D0%BD%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%B8_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2_%D0%B2_%D0%B4%D0%B2%D1%83%D1%85_%D0%BC%D0%B5%D1%81%D1%82%D0%B0%D1%85"/>
				<updated>2017-06-01T07:45:33Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «[http://rsync.samba.org/ rsync] (англ. Remote Synchronization) — программа для UNIX-подобных систем, которая выполня…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://rsync.samba.org/ rsync] (англ. Remote Synchronization) — программа для UNIX-подобных систем, которая выполняет синхронизацию файлов и каталогов в двух местах с минимизированием трафика, используя кодировку данных при необходимости.&lt;br /&gt;
&lt;br /&gt;
__TOC__&lt;br /&gt;
&lt;br /&gt;
==Примеры работы с данными на локальной машине==&lt;br /&gt;
&lt;br /&gt;
===Простое копирование файлов===&lt;br /&gt;
В принципе, команда ''ср'' отлично выполняет свою функцию, за исключением небольшой прихоти -- при копировании больших файлов хотелось бы знать сколько времени осталось до завершения операции (т.е. всего-навсего нужно вывести прогресс операции копирования). &lt;br /&gt;
&lt;br /&gt;
Данную задачу можно решить несколькими способами:&lt;br /&gt;
&lt;br /&gt;
1) Использовать команду [[Scp — Команда безопасного сетевого копирования файлов|scp]] (потребует ввода пароля пользователя, а также ввода полного пути к каталогам): &lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp -r &amp;lt;что копировать&amp;gt; localhost:&amp;lt;куда копировать&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2) Использовать команду rsync с ключом --progress:&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --progress -av &amp;lt;что копировать&amp;gt; &amp;lt;куда копировать&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При копировании каталогов (а не файлов) в последнем случае следует обратить внимание на знак &amp;quot;/&amp;quot; замыкающий имя каталога-источника, т.к. команда rsync будет интерпретировать результат по-разному:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --progress -av &amp;lt;каталог-источник&amp;gt; &amp;lt;каталог-назначения/&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --progress -av &amp;lt;каталог-источник/&amp;gt; &amp;lt;каталог-назначения/&amp;gt;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Наличие завершающих слешей &amp;quot;/&amp;quot; обязательно, иначе результат копирования будет содержать корневую папку  &amp;lt;каталог-источник&amp;gt; внутри &amp;lt;каталога-назначения&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Копирование файла ''а'' из ''dir1'' в ''dir2'':&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp  /home/dir1/a   localhost:/home/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Копирование каталога из ''dir1'' в ''dir2'':&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp  -r  /home/dir1/     localhost:/home/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Копирование файла ''а'' из ''dir1'' в ''dir2'':&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --progress -av ~/dir1/a ~/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Копирование файлов из ''dir1'' в ''dir2'':&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --progress -av ~/dir1/ ~/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Копирование самой директории ''dir1'' (со всем содержимым) в ''dir2'':&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --progress -av ~/dir1 ~/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Синхронизация каталогов===&lt;br /&gt;
&lt;br /&gt;
Точная копия каталогов (удаление всех файлов из ''dir2'', которых нет в ''dir1''):&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync --delete -av ~/dir1/ ~/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Исключить каталоги, синхронизация которых не требуется (например, каталог ''dir3'' находящийся в ''dir1'' при копировании последнего в ''dir2'' будет пропущен):&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync -av ~/dir1/ --exclude=&amp;quot;./~dir3/&amp;quot; ~/dir2/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Двусторонняя синхронизация (объединить содержимое ''dir1'' и ''dir2'')&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync -av ~/dir1/ ~/dir2/ &amp;amp;&amp;amp; rsync -av ~/dir2/ ~/dir1/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Как копировать большие файлы и докопировать их в случае обрыва связи? ===&lt;br /&gt;
&lt;br /&gt;
Нужно использовать ключи &amp;lt;tt&amp;gt;--partial&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;-P&amp;lt;/tt&amp;gt;) и &amp;lt;tt&amp;gt;--append-verify&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ключ &amp;lt;tt&amp;gt;--partial&amp;lt;/tt&amp;gt; говорит о том, что нужно оставлять даже не полностью скопированные файлы,&lt;br /&gt;
а &amp;lt;tt&amp;gt;--append-verify&amp;lt;/tt&amp;gt; говорит о том, что если файл уже есть нужно проверить, возможно он не полностью синхронизирован,&lt;br /&gt;
и синхронизировать остаток.&lt;br /&gt;
Пример команды, которая поможет докачать файл в случае разрыва соединения с удалённым сервером hostname:&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync -av --partial --rsh=ssh username@hostname:filename./&amp;lt;/source&amp;gt;&lt;br /&gt;
Подробнее:&lt;br /&gt;
&lt;br /&gt;
* http://unix.stackexchange.com/questions/48298/can-rsync-resume-after-being-interrupted&lt;br /&gt;
&lt;br /&gt;
==Работа с удалённой машиной==&lt;br /&gt;
&lt;br /&gt;
Копирование через SSH (аналог scp)&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;rsync -av --rsh=ssh user@host:dir1/ ~/dir1/&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
По умолчанию, в случае разрыва соединения частично переданные файлы будут удалены. Чтобы изменить это поведение необходимо указать ключ ''--partial''. Так же можно использовать ''--partial-dir=DIR'' чтобы в место назначения попадали только полностью переданные файлы.&lt;br /&gt;
Очень полезно при использовании плохих каналах связи.&lt;br /&gt;
&lt;br /&gt;
==Дополнительная информация==&lt;br /&gt;
* [http://alexandr.sysoev.ru/node/66 10 примеров удаленного копирования файлов]&lt;br /&gt;
* [http://unixstuff.ru/files/74875f10c5ff1a33eecb0d86c5f98f9b-8.html Перевод документации]&lt;br /&gt;
* [http://cworld.org.ua/news/rsync-backup-debian/ Синхронизация файлов с помощью rsync (Debian)]&lt;br /&gt;
* [http://wiki.enchtex.info/tools/console/rsync rsync - синхронизация файлов]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Setfacl</id>
		<title>Setfacl</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Setfacl"/>
				<updated>2017-05-18T12:11:22Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Введение==&lt;br /&gt;
'''A'''ccess '''C'''ontrol '''L'''ist предоставляет расширенный и более гибкий механизм распределения прав файловых систем. Он предназначен для расширения прав доступа к файлам &amp;lt;code&amp;gt;UNIX&amp;lt;/code&amp;gt;. ACL позволяет устанавливать разрешения любым пользователям или группам для различных файловых ресурсов.&lt;br /&gt;
&lt;br /&gt;
==Установка==&lt;br /&gt;
Установка ACL доступна из репозитория rhel-server-eus-rpms или rhel-server-rpms пакетов:&amp;lt;br /&amp;gt;&lt;br /&gt;
 # yum install -y acl&lt;br /&gt;
&lt;br /&gt;
==Настройка==&lt;br /&gt;
&lt;br /&gt;
===Включение ACL===&lt;br /&gt;
Для включения ACL - отредактируйте файл '''/etc/fstab''' и добавьте атрибут '''acl''' к опциям раздела, где полагается использование ACL:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# &lt;br /&gt;
# /etc/fstab: static file system information&lt;br /&gt;
#&lt;br /&gt;
# &amp;lt;file system&amp;gt;        &amp;lt;dir&amp;gt;         &amp;lt;type&amp;gt;    &amp;lt;options&amp;gt;          &amp;lt;dump&amp;gt; &amp;lt;pass&amp;gt;&lt;br /&gt;
none                   /dev/pts      devpts    defaults            0      0&lt;br /&gt;
none                   /dev/shm      tmpfs     defaults            0      0&lt;br /&gt;
&lt;br /&gt;
UUID=5de01fca-7c63-49b0-9b2b-8b1790f8428e swap swap defaults 0 0&lt;br /&gt;
&lt;br /&gt;
UUID=8e5259dd-26fc-411a-88e2-f38d4dc36724 /home reiserfs defaults,acl 0 1&lt;br /&gt;
&lt;br /&gt;
UUID=c18f753e-0039-49bd-930f-587d48b7e083 / reiserfs defaults 0 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Сохраните файл. Переподключите раздел:&lt;br /&gt;
 # mount -o remount /home&lt;br /&gt;
&lt;br /&gt;
===Установка прав ACL===&lt;br /&gt;
Для изменения ACL используйте команду '''setfacl'''. Для добавления прав используйте '''setfacl -m'''.&lt;br /&gt;
&lt;br /&gt;
Добавление прав какому-нибудь пользователю:&lt;br /&gt;
 # setfacl -m &amp;quot;u:username:permissions&amp;quot;&lt;br /&gt;
или&lt;br /&gt;
 # setfacl -m &amp;quot;u:uid:permissions&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Для добавления прав какой-нибудь группе:&lt;br /&gt;
 # setfacl -m &amp;quot;g:groupname:permissions&amp;quot;&lt;br /&gt;
или&lt;br /&gt;
 # setfacl -m &amp;quot;g:gid:permissions&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Удаление всех расширений ACL:&lt;br /&gt;
 # setfacl -b&lt;br /&gt;
&lt;br /&gt;
Удаление всех записей:&lt;br /&gt;
 # setfacl -x &amp;quot;entry&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Проверка установленных разрешений:&lt;br /&gt;
 # getfacl filename&lt;br /&gt;
&lt;br /&gt;
=== Параметры ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Опции !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| '''-m, --modify=acl''' || Добавить и модифицировать существующие записи [[ACL]]&lt;br /&gt;
|-&lt;br /&gt;
| '''-M, --modify-file=file''' || Добавить и модифицировать существующие записи [[ACL]] взятые из указанного файла&lt;br /&gt;
|-&lt;br /&gt;
| '''-x, --remove=acl''' || Удалить указанные [[ACL]] права взятые из указанного файла&lt;br /&gt;
|-&lt;br /&gt;
| '''-b, --remove-all''' || Удалить все [[ACL]] права с объекта, сохраняя основные права&lt;br /&gt;
|-&lt;br /&gt;
| '''-k, --remove-default''' || Удалить с объекта [[ACL]] по умолчанию. Если таковых на объекте нет, предупреждение об этом выдаваться не будет&lt;br /&gt;
|-&lt;br /&gt;
| '''--set=acl''' || Установить новые указанные права [[ACL]], удаляя все существующие. Необходимо, чтобы наравне с задаваемыми правилами [[ACL]] были также указаны стандартные права Unix, в противном случае будет давать ошибку&lt;br /&gt;
|-&lt;br /&gt;
| '''--set-file=file''' || Установить новые указанные права [[ACL]], взятые из указанного файла, удаляя все существующие. Необходимо, чтобы наравне с задаваемыми правилами [[ACL]] были также указаны стандартные права Unix, в противном случае будет давать ошибку&lt;br /&gt;
|-&lt;br /&gt;
| '''--mask''' || Пересчитать маску действующих прав&lt;br /&gt;
|-&lt;br /&gt;
| '''-n, --no-mask''' || Не пересчитывать маску действующих прав&lt;br /&gt;
|-&lt;br /&gt;
| '''-d, --default''' || Установить [[ACL]] по умолчанию на объект&lt;br /&gt;
|-&lt;br /&gt;
| '''-R, --recursive''' || Рекурсивное назначение (удаление) прав, тобишь пройтись по всем подкаталогам&lt;br /&gt;
|-&lt;br /&gt;
| '''-L, --logical''' ||  Логический обход, следующий символическим ссылкам &lt;br /&gt;
|-&lt;br /&gt;
| '''-P, --physical''' || Физический обход, не следующий символическим ссылкам&lt;br /&gt;
|-&lt;br /&gt;
| '''--restore=file''' || Восстанавить [[ACL]] права на объекты из ранее созданного файла с правами&lt;br /&gt;
|-&lt;br /&gt;
| '''--test''' || Тестовый режим&lt;br /&gt;
|-&lt;br /&gt;
| '''-v, --version''' || Вывод версии&lt;br /&gt;
|-&lt;br /&gt;
| '''-h, --help''' || Вывод справки&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Примеры==&lt;br /&gt;
&lt;br /&gt;
Установить все разрешения на файл &amp;quot;abc&amp;quot; для пользователя johny:&lt;br /&gt;
 # setfacl -m &amp;quot;u:johny:rwx&amp;quot; abc&lt;br /&gt;
Проверить разрешения:&lt;br /&gt;
 # getfacl abc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# file: abc&lt;br /&gt;
# owner: someone&lt;br /&gt;
# group: someone&lt;br /&gt;
user::rw-&lt;br /&gt;
user:johny:rwx&lt;br /&gt;
group::r--&lt;br /&gt;
mask::rwx&lt;br /&gt;
other::r--&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Изменение разрешений для пользователя johny:&lt;br /&gt;
 # setfacl -m &amp;quot;u:johny:r-x&amp;quot; abc&lt;br /&gt;
Проверка разрешений:&lt;br /&gt;
 # getfacl abc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# file: abc&lt;br /&gt;
# owner: someone&lt;br /&gt;
# group: someone&lt;br /&gt;
user::rw-&lt;br /&gt;
user:johny:r-x&lt;br /&gt;
group::r--&lt;br /&gt;
mask::r-x&lt;br /&gt;
other::r--&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Удаление всех записей расширения ACL:&lt;br /&gt;
 # setfacl -b abc&lt;br /&gt;
Проверка разрешений:&lt;br /&gt;
 # getfacl abc&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# file: abc&lt;br /&gt;
# owner: someone&lt;br /&gt;
# group: someone&lt;br /&gt;
user::rw-&lt;br /&gt;
group::r--&lt;br /&gt;
other::r--&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Вывод команды ls===&lt;br /&gt;
При использовании команды '''ls -l''' можно заметить '''+'''(знак плюс) следующий за правами unix, предупреждающий об использовании расширений ACL для файла.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ls -l /dev/audio &lt;br /&gt;
crw-rw----+ 1 root audio 14, 4 nov.   9 12:49 /dev/audio&lt;br /&gt;
&lt;br /&gt;
$ getfacl /dev/audio&lt;br /&gt;
getfacl: Removing leading '/' from absolute path names&lt;br /&gt;
# file: dev/audio&lt;br /&gt;
# owner: root&lt;br /&gt;
# group: audio&lt;br /&gt;
user::rw-&lt;br /&gt;
user:solstice:rw-&lt;br /&gt;
group::rw-&lt;br /&gt;
mask::rw-&lt;br /&gt;
other::---&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Повышение безопасности веб-сервера==&lt;br /&gt;
&lt;br /&gt;
Для повышения безопасности веб-сервера добавьте расширенные права на домашнюю директорию и/или директорию сайта только для пользователя '''http'''.&lt;br /&gt;
&lt;br /&gt;
Перейдите в домашнюю директорию:&lt;br /&gt;
 # cd /home&lt;br /&gt;
Добавьте разрешение '''+x''' для пользователя http с помощью ACL:&lt;br /&gt;
 # setfacl -m &amp;quot;u:http:--x&amp;quot; homeusername/&lt;br /&gt;
Теперь удалите права rx разрешающие использование директории другим пользователям:&lt;br /&gt;
 # chmod o-rx homeusername/&lt;br /&gt;
Проверьте изменения:&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;pre&amp;gt;# file: username/&lt;br /&gt;
# owner: username&lt;br /&gt;
# group: users&lt;br /&gt;
user::rwx&lt;br /&gt;
user:http:--x&lt;br /&gt;
group::r-x&lt;br /&gt;
mask::r-x&lt;br /&gt;
other::---&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Как мы можем видеть, другие пользователи не имеют доступа, но для пользователя http установлен атрибут &amp;quot;x&amp;quot;, что разрешает ему просмотр пользовательской директории и дает доступ к веб-страницам пользователя. Это справедливо, если веб-сервер работает от имени пользователя http. По умолчанию пользователь http не наделён такими полномочиями.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [https://www.opennet.ru/man.shtml?topic=setfacl&amp;amp;category=1&amp;amp;russian=2 OpenNET setfacl мануал] — Мануал по setfacl&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Getfacl</id>
		<title>Getfacl</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Getfacl"/>
				<updated>2017-05-18T11:57:11Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''getfacl''' — команда с помощью которой можно посмотреть список текущих ACL.&lt;br /&gt;
&lt;br /&gt;
 getfacl [параметры] файлы&lt;br /&gt;
&lt;br /&gt;
Поскольку мы еще не определяли ACL на файлы, то в примере использования программы будут показаны права по умолчанию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$ getfacl test&lt;br /&gt;
# file: test&lt;br /&gt;
# owner: artur&lt;br /&gt;
# group: users&lt;br /&gt;
user::rw-&lt;br /&gt;
group::r--&lt;br /&gt;
other::r--&lt;br /&gt;
$&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Параметры ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Опция  !! Значение&lt;br /&gt;
|-&lt;br /&gt;
| '''-a, --access''' || Вывести только права [[ACL]]&lt;br /&gt;
|-&lt;br /&gt;
| '''-d, --default''' || Вывести только стандартные права &lt;br /&gt;
|-&lt;br /&gt;
| '''-c, --omit-header''' ||  Не выводить комментарии в заголовке&lt;br /&gt;
|-&lt;br /&gt;
| '''-e, --all-effective''' || Вывести все эффективные права&lt;br /&gt;
|-&lt;br /&gt;
| '''-E, --no-effective''' || Вывести неэффективные права&lt;br /&gt;
|-&lt;br /&gt;
| '''-s, --skip-base''' || Пропускать файлы, у которых есть только базовые записи&lt;br /&gt;
|-&lt;br /&gt;
| '''-R, --recursive''' || Отработать рекурсивно&lt;br /&gt;
|-&lt;br /&gt;
| '''-L, --logical''' || Логический обход, следующий символическим ссылкам&lt;br /&gt;
|-&lt;br /&gt;
| '''-P, --physical''' || Физический обход, не следующий символическим ссылкам&lt;br /&gt;
|-&lt;br /&gt;
| '''-t, --tabular''' || Использовать табличный формат вывода&lt;br /&gt;
|-&lt;br /&gt;
| '''-n, --numeric''' || Выводить ID пользователя/группы вместо имени&lt;br /&gt;
|-&lt;br /&gt;
| '''-p, --absolute-names''' || Оставлять ведущие '/' в именах путей&lt;br /&gt;
|-&lt;br /&gt;
| '''-v, --version''' || Вывод версии&lt;br /&gt;
|-&lt;br /&gt;
| '''-h, --help''' || Вывод справки&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
* [https://www.opennet.ru/man.shtml?topic=getfacl&amp;amp;category=1&amp;amp;russian=2 OpenNet getfacl мануал] — man-страница getfacl&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/ACL</id>
		<title>ACL</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/ACL"/>
				<updated>2017-05-18T11:38:29Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''Access Control List''' или '''ACL''' — список контроля доступа, который определяет, кто или что может…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Access Control List''' или '''ACL''' — список контроля доступа, который определяет, кто или что может получать доступ к конкретному объекту, и какие именно операции разрешено или запрещено этому субъекту проводить над объектом.&lt;br /&gt;
&lt;br /&gt;
Списки контроля доступа являются основой систем с избирательным управлением доступа.&lt;br /&gt;
&lt;br /&gt;
== Введение ==&lt;br /&gt;
В типичных ACL каждая запись определяет субъект воздействия и операцию: например, запись ''(Vasya, delete)'' в ACL для файла ''XYZ'' даёт возможность пользователю ''Vasya'' удалить файл ''XYZ''.&lt;br /&gt;
&lt;br /&gt;
В системе с моделью безопасности, основанной на ACL, когда субъект запрашивает выполнение операции над объектом, система сначала проверяет список разрешённых для этого субъекта операций, и только после этого даёт (или не даёт) доступ к запрошенному действию.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
== Модели безопасности, базирующиеся на ACL ==&lt;br /&gt;
Ключевая проблема в определении любой основанной на ACL модели безопасности — это вопрос, как будут редактироваться списки доступа. Кто может модифицировать списки ACL для каждого из объектов, и какие изменения можно вносить?&lt;br /&gt;
&lt;br /&gt;
Использующие ACL системы могут быть разделены на две категории: дискреционные (discretionary) и мандатные (mandatory). Систему можно назвать построенной на дискреционном контроле доступа, если создатель или владелец объекта может полностью контролировать доступ к объекту, включая и список тех, кому разрешено изменять права доступа к объекту. Систему можно назвать обладающей мандатным контролем доступа, если заданные пользователем ACL перекрываются системными ограничениями.&lt;br /&gt;
&lt;br /&gt;
— Примечание: возможно избирательные и мандатные системы отличаются не тем, кто правит права, а тем, как права устроены. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При централизованном хранении списков контроля доступа можно говорить о ''матрице доступа'', в которой по осям размещены объекты и субъекты, а в ячейках — соответствующие права. Однако в большом количестве систем списки контроля доступа к объектам хранятся отдельно для каждого объекта, зачастую непосредственно с самим объектом.&lt;br /&gt;
&lt;br /&gt;
Традиционные ACL системы назначают права индивидуальным пользователям, и со временем и ростом числа пользователей в системе списки доступа могут стать громоздкими. Вариантом решения этой проблемы является назначения прав группам пользователей, а не персонально. Другим вариантом решения этой проблемы является «'''Управление доступом на основе ролей'''», где функциональные подмножества прав к ряду объектов объединяются в «роли», и эти роли назначаются пользователям. Однако, в первом варианте группы пользователей также часто называются ролями.&lt;br /&gt;
&lt;br /&gt;
== Файловые системы с ACL ==&lt;br /&gt;
В файловых системах для реализации ACL используется идентификатор пользователя процесса (UID в терминах POSIX).&lt;br /&gt;
&lt;br /&gt;
Список доступа представляет собой структуру данных (обычно таблицу), содержащую записи, определяющие права индивидуального пользователя или группы на специальные системные объекты, такие как программы, процессы или файлы. Эти записи также известны как ACE (Access Control Entries) в операционных системах Microsoft Windows и OpenVMS. В операционной системе Linux и Mac OS X большинство файловых систем имеют расширенные атрибуты, выполняющие роль ACL. Каждый объект в системе содержит указатель на свой ACL. Привилегии (или полномочия) определяют специальные права доступа, разрешающие пользователю '''читать''' из (read), '''писать''' в (write), или '''исполнять''' (execute) объект. В некоторых реализациях ACE (Access Control Entries) могут определять право пользователя или группы на изменение ACL объекта.&lt;br /&gt;
&lt;br /&gt;
Концепции ACL в разных операционных системах различаются, несмотря на существующий «стандарт» POSIX. (Проекты безопасности POSIX, .1e и .2c, были отозваны, когда стало ясно что они затрагивают слишком обширную область и работа не может быть завершена, но хорошо проработанные части, определяющие ACL, были широко реализованы и известны как «POSIX ACLs».)&lt;br /&gt;
&lt;br /&gt;
== Сетевые ACL ==&lt;br /&gt;
В сетях '''ACL''' представляют список правил, определяющих порты служб или имена доменов, доступных на узле или другом устройстве третьего уровня  модели OSI, каждый со списком узлов и/или сетей, которым разрешен доступ к сервису. Сетевые ACL могут быть настроены как на обычном сервере, так и на маршрутизаторе и могут управлять как входящим, так и исходящим трафиком, в качестве межсетевого экрана.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.suse.de/~agruen/acl/linux-acls/online/ POSIX Access Control Lists on Linux]&lt;br /&gt;
* [http://www.rsbac.org/documentation/rsbac_handbook/security_models#access_control_lists_acl RSBAC Access Control Lists on Linux]&lt;br /&gt;
* [http://phpgacl.sourceforge.net/ Generic Access Control Lists for PHP/Perl]&lt;br /&gt;
* [http://www.c2.com/cgi/wiki?AccessControlList C2-Wiki Discussion and Relational Implementation]&lt;br /&gt;
* [http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci213757,00.html Information Security Definitions: ACL]&lt;br /&gt;
* [http://wiki.kaspersandberg.com/doku.php?id=howtos:acl Easy and detailed ACL howto for linux]&lt;br /&gt;
* [http://msdn.microsoft.com/msdnmag/issues/05/03/SecurityBriefs/default.aspx Security Briefs: Access Control List Editing in .NET]&lt;br /&gt;
* [http://msdn2.microsoft.com/en-us/library/ms229742.aspx MS Windows .NET ACL Technology]&lt;br /&gt;
* [http://wt.xpilot.org/publications/posix.1e/download.html What could have been IEEE 1003.1e/2c]&lt;br /&gt;
* [http://web.archive.org/web/20051102080247/http://manuals.info.apple.com/en/File_Services_v10.4.pdf Apple Mac OS X Server version 10.4+ ''File Services Administration'' Manual (see pages 16-26)]&lt;br /&gt;
* [http://aclbit.sourceforge.net/ ACLbit — ACL Backup and Inspect Tool for Linux]&lt;br /&gt;
* [http://www.u-networks.net/glavnaya/nastrojka-spiskov-dostupa-na-morshrutizatore-cisco/ Настройка и описание ACL на маршрутизаторе Cisco]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Subnetting</id>
		<title>Subnetting</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Subnetting"/>
				<updated>2017-05-18T11:18:14Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==  Введение  ==&lt;br /&gt;
&lt;br /&gt;
'''Маска подсети''' — битовая маска, определяющая, какая часть IP-адреса узла сети относится к адресу сети, а какая — к адресу самого узла в этой сети (при этом, в отличие от IP-адреса, маска подсети не является частью IP-пакета). Например, узел с IP-адресом 12.34.56.78 и маской подсети 255.255.255.0 находится в сети 12.34.56.0 с длиной префикса 24 бита. В случае адресации IPv6 адрес 2001:0DB8:1:0:6C1F:A78A:3CB5:1ADD с длиной префикса 32 бита (/32) находится в сети 2001:0DB8::/32.&lt;br /&gt;
&lt;br /&gt;
Другой вариант определения — это определение подсети IP-адресов. Например, с помощью маски подсети можно сказать, что один диапазон IP-адресов будет в одной подсети, а другой диапазон соответственно в другой подсети.&lt;br /&gt;
&lt;br /&gt;
Чтобы получить адрес сети, зная IP-адрес и маску подсети, необходимо применить к ним операцию поразрядной конъюнкции (логическое И). Например, в случае более сложной маски (битовые операции в IPv6 выглядят аналогично):&lt;br /&gt;
&lt;br /&gt;
 IP-адрес:       &amp;lt;span style=&amp;quot;background-color:Yellow&amp;quot;&amp;gt;11000000 10101000 0000000&amp;lt;/span&amp;gt;&amp;lt;span style=&amp;quot;background-color:Salmon&amp;quot;&amp;gt;1 00000010&amp;lt;/span&amp;gt; (192.168.1.2)&lt;br /&gt;
 Маска подсети:  &amp;lt;span style=&amp;quot;background-color:PaleGreen&amp;quot;&amp;gt;11111111 11111111 1111111&amp;lt;/span&amp;gt;0 00000000 (255.255.254.0)&lt;br /&gt;
 Адрес сети:     &amp;lt;span style=&amp;quot;background-color:Yellow&amp;quot;&amp;gt;11000000 10101000 0000000&amp;lt;/span&amp;gt;0 00000000 (192.168.0.0)&lt;br /&gt;
&lt;br /&gt;
Легенда:&lt;br /&gt;
*&amp;lt;span style=&amp;quot;background-color:PaleGreen&amp;quot;&amp;gt;Часть маски, определяющая адрес сети, состоящая из единиц.&amp;lt;/span&amp;gt;&lt;br /&gt;
*&amp;lt;span style=&amp;quot;background-color:Yellow&amp;quot;&amp;gt;Адрес сети, который определяется маской подсети.&amp;lt;/span&amp;gt;&lt;br /&gt;
*&amp;lt;span style=&amp;quot;background-color:Salmon&amp;quot;&amp;gt;Диапазон адресов устройств в этой сети.&amp;lt;/span&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Разбиение одной большой сети на несколько маленьких подсетей позволяет упростить маршрутизацию. Например, пусть таблица маршрутизации некоторого маршрутизатора содержит следующую запись:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;standard&amp;quot;&lt;br /&gt;
 !Сеть назначения&lt;br /&gt;
 !Маска сети&lt;br /&gt;
 !Адрес шлюза&lt;br /&gt;
 |-&lt;br /&gt;
 |192.168.1.0&lt;br /&gt;
 |255.255.255.0&lt;br /&gt;
 |10.20.30.1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть теперь маршрутизатор получает пакет данных с адресом назначения 192.168.1.2. Обрабатывая построчно таблицу маршрутизации, он обнаруживает, что при наложении на адрес 192.168.1.2 маски 255.255.255.0 получается адрес сети 192.168.1.0. В таблице маршрутизации этой сети соответствует шлюз 10.20.30.1, которому и отправляется пакет.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable sortable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! IP-адреса !! Биты(Bits) !! Префикс(Prefix) !! Маска подсети(Subnet mask)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || /32 || 255.255.255.255&lt;br /&gt;
|-&lt;br /&gt;
| 2 || 1 || /31 || 255.255.255.254&lt;br /&gt;
|-&lt;br /&gt;
| 4 || 2 || /30 || 255.255.255.252&lt;br /&gt;
|-&lt;br /&gt;
| 8 || 3 || /29 || 255.255.255.248&lt;br /&gt;
|-&lt;br /&gt;
| 16 || 4 || /28 || 255.255.255.240&lt;br /&gt;
|-&lt;br /&gt;
| 32 || 5 || /27 || 255.255.255.224&lt;br /&gt;
|-&lt;br /&gt;
| 64 || 6 || /26 || 255.255.255.192&lt;br /&gt;
|-&lt;br /&gt;
| 128 || 7 || /25 || 255.255.255.128&lt;br /&gt;
|-&lt;br /&gt;
| 256 || 8 || /24 || 255.255.255.0&lt;br /&gt;
|-&lt;br /&gt;
| 512 || 9 || /23 || 255.255.254.0&lt;br /&gt;
|-&lt;br /&gt;
| 1k || 10 || /22 || 255.255.252.0&lt;br /&gt;
|-&lt;br /&gt;
| 2k || 11 || /21 || 255.255.248.0&lt;br /&gt;
|-&lt;br /&gt;
| 4k || 12 || /20 || 255.255.240.0&lt;br /&gt;
|-&lt;br /&gt;
| 8k || 13 || /19 || 255.255.224.0&lt;br /&gt;
|-&lt;br /&gt;
| 16k || 14 || /18 || 255.255.192.0&lt;br /&gt;
|-&lt;br /&gt;
| 32k || 15 || /17 || 255.255.128.0&lt;br /&gt;
|-&lt;br /&gt;
| 64k || 16 || /16 || 255.255.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 128k || 17 || /15 || 255.254.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 256k || 18 || /14 || 255.252.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 512K || 19 || /13 || 255.248.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 1M || 20 || /12 || 255.240.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 2M || 21 || /11 || 255.224.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 4M || 22 || /10 || 255.192.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 8M || 23 || /9 || 255.128.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 16M || 24 || /8 || 255.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 32M || 25 || /7 || 254.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 64M || 26 || /6 || 252.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 128M || 27 || /5 || 248.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 256M || 28 || /4 || 240.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 512M || 29 || /3 || 224.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 1024M || 30 || /2 || 192.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 2048M || 31 || /1 || 128.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
| 4096M || 32 || /0 || 0.0.0.0&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Маски при бесклассовой маршрутизации (CIDR) ==&lt;br /&gt;
Маски подсети являются основой метода бесклассовой маршрутизации (CIDR). При этом подходе маску подсети записывают вместе с IP-адресом в формате «''IP-адрес/количество единичных бит в маске''». Число после знака дроби (так называемая ''длина префикса сети'') означает количество единичных разрядов в маске подсети.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим пример записи диапазона IP-адресов в виде 10.96.0.0/11. В этом случае маска подсети будет иметь двоичный вид 11111111 11100000 00000000 00000000, или то же самое в десятичном виде: 255.224.0.0. 11 разрядов IP-адреса отводятся под ''адрес сети'', а остальной 32-11=21 разряд полного адреса (&amp;lt;s&amp;gt;11111111 111&amp;lt;/s&amp;gt;00000 00000000 00000000) — под локальный адрес в этой сети. Итого, 10.96.0.0/11 означает диапазон адресов от 10.96.0.0 до 10.127.255.255.&lt;br /&gt;
&lt;br /&gt;
== Диапазоны адресов ==&lt;br /&gt;
IP-адрес является массивом бит. Принцип IP-адресации — выделение множества (диапазона, блока, подсети) IP-адресов, в котором некоторые битовые разряды имеют фиксированные значения, а остальные разряды пробегают все возможные значения. Блок адресов задаётся указанием начального адреса и маски подсети. Бесклассовая адресация основывается на переменной длине маски подсети (variable length subnet mask,VLSM), в то время, как в классовой (традиционной) адресации длина маски строго фиксирована 0, 1, 2 или 3 установленными октетами.&lt;br /&gt;
&lt;br /&gt;
Пример подсети 192.0.2.32/27 с применением бесклассовой адресации: &lt;br /&gt;
{| border=1 | class=&amp;quot;standard&amp;quot; | align=&amp;quot;center&amp;quot;&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Октеты IP-адреса&lt;br /&gt;
 | align=&amp;quot;center&amp;quot; colspan=8 | 192 || align=&amp;quot;center&amp;quot; colspan=8 | 0 || align=&amp;quot;center&amp;quot; colspan=8 | 2 || align=&amp;quot;center&amp;quot; colspan=8 | 32&lt;br /&gt;
 |-&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Биты IP-адреса&lt;br /&gt;
 | 1 || 1 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0  || 0 || 1 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 0 || 0&lt;br /&gt;
 |-&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Биты маски подсети&lt;br /&gt;
 | 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0&lt;br /&gt;
 |-&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Октеты маски подсети&lt;br /&gt;
 | align=&amp;quot;center&amp;quot; colspan=8 | 255 || align=&amp;quot;center&amp;quot; colspan=8 | 255 || align=&amp;quot;center&amp;quot; colspan=8 | 255 || align=&amp;quot;center&amp;quot; colspan=8 | 224&lt;br /&gt;
 |}&lt;br /&gt;
В данном примере видно, что в маске подсети 27 бит слева — единицы. В таком случае говорят о длине префикса подсети в 27 бит и указывают через косую черту (знак ''/'') после базового адреса.&lt;br /&gt;
&lt;br /&gt;
Пример записи IP-адреса 172.16.0.1/12 с применением бесклассовой адресации: &lt;br /&gt;
{| border=1 | class=&amp;quot;standard&amp;quot; | align=&amp;quot;center&amp;quot;&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Октеты IP-адреса&lt;br /&gt;
 | align=&amp;quot;center&amp;quot; colspan=8 | 172 || align=&amp;quot;center&amp;quot; colspan=8 | 16 || align=&amp;quot;center&amp;quot; colspan=8 | 0 || align=&amp;quot;center&amp;quot; colspan=8 | 1&lt;br /&gt;
 |-&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Биты IP-адреса&lt;br /&gt;
 | 1 || 0 || 1 || 0 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 1 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 1&lt;br /&gt;
 |-&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Биты маски подсети&lt;br /&gt;
 | 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 1 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0&lt;br /&gt;
 |-&lt;br /&gt;
 ! align=&amp;quot;left&amp;quot; | Октеты маски подсети&lt;br /&gt;
 | align=&amp;quot;center&amp;quot; colspan=8 | 255&lt;br /&gt;
 | align=&amp;quot;center&amp;quot; colspan=8 | 240 || align=&amp;quot;center&amp;quot; colspan=8 | 0 || align=&amp;quot;center&amp;quot; colspan=8 | 0&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Множество всех адресов соответствует нулевой маске подсети и обозначается /0, а конкретный адрес IPv4 — маске подсети с длиной префикса в 32 бита, обозначаемой /32.&lt;br /&gt;
&lt;br /&gt;
Для упрощения таблиц маршрутизации можно объединять блоки адресов, указывая один большой блок вместо ряда мелких. Например, 4 смежные сети класса C (4 × 255 адресов, маска 255.255.255.0 или /24) могут быть объединены, с точки зрения далёких от них маршрутизаторов, в одну сеть /22. И напротив, сети можно разбивать на более мелкие подсети, и так далее.&lt;br /&gt;
&lt;br /&gt;
Стандартом принята маска в виде непрерывной последовательности единиц и непрерывной последовательности нулей. Только для таких масок получающиеся множества IP-адресов будут смежными. Однако, также широко распространены обратные маски (invers mask, wildcard mask), которые не обязаны содержать подряд идущие единицы или нули. Обратная маска используется для формирования правил ''ACL''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;quot;1 кибибайт&amp;quot; адресов - приблизительно 1.8 * 10^308. Приведенные в первом столбце значения не имеют никакого отношения к реальности. Требуется заменить: &amp;quot;1 кибибайт&amp;quot; на &amp;quot;1 * 2^10&amp;quot; адресов, &amp;quot;8 мебибайт&amp;quot; на &amp;quot;8 * 2^20 адресов&amp;quot; и т.п. (слова вроде &amp;quot;кибиадресов&amp;quot; было бы использовать глупо)&lt;br /&gt;
В английской версии статьи такой ошибки не допущено; столбец &amp;quot;Hosts&amp;quot;.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ IPv4 CIDR&lt;br /&gt;
!IP/маска&lt;br /&gt;
! До последнего IP&lt;br /&gt;
в подсети&lt;br /&gt;
!Маска&lt;br /&gt;
!Количество адресов&lt;br /&gt;
!Количество хостов&lt;br /&gt;
!Класс&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/32'''&lt;br /&gt;
| +0.0.0.0&lt;br /&gt;
|255.255.255.255&lt;br /&gt;
|1&lt;br /&gt;
|1*&lt;br /&gt;
|1/256 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/31'''&lt;br /&gt;
| +0.0.0.1&lt;br /&gt;
|255.255.255.254&lt;br /&gt;
|2&lt;br /&gt;
|2*&lt;br /&gt;
|1/128 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/30'''&lt;br /&gt;
| +0.0.0.3&lt;br /&gt;
|255.255.255.252&lt;br /&gt;
|4&lt;br /&gt;
|2&lt;br /&gt;
|1/64 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/29'''&lt;br /&gt;
| +0.0.0.7&lt;br /&gt;
|255.255.255.248&lt;br /&gt;
|8&lt;br /&gt;
|6&lt;br /&gt;
|1/32 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/28'''&lt;br /&gt;
| +0.0.0.15&lt;br /&gt;
|255.255.255.240&lt;br /&gt;
|16&lt;br /&gt;
|14&lt;br /&gt;
|1/16 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/27'''&lt;br /&gt;
| +0.0.0.31&lt;br /&gt;
|255.255.255.224&lt;br /&gt;
|32&lt;br /&gt;
|30&lt;br /&gt;
|1/8 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/26'''&lt;br /&gt;
| +0.0.0.63&lt;br /&gt;
|255.255.255.192&lt;br /&gt;
|64&lt;br /&gt;
|62&lt;br /&gt;
|1/4 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.d'''/25'''&lt;br /&gt;
| +0.0.0.127&lt;br /&gt;
|255.255.255.128&lt;br /&gt;
|128&lt;br /&gt;
|126&lt;br /&gt;
|1/2 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/24'''&lt;br /&gt;
| +0.0.0.255&lt;br /&gt;
|255.255.255.000&lt;br /&gt;
|256&lt;br /&gt;
|254&lt;br /&gt;
|1 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/23'''&lt;br /&gt;
| +0.0.1.255&lt;br /&gt;
|255.255.254.000&lt;br /&gt;
|512&lt;br /&gt;
|510&lt;br /&gt;
|2 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/22'''&lt;br /&gt;
| +0.0.3.255&lt;br /&gt;
|255.255.252.000&lt;br /&gt;
|1024&lt;br /&gt;
|1022&lt;br /&gt;
|4 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/21'''&lt;br /&gt;
| +0.0.7.255&lt;br /&gt;
|255.255.248.000&lt;br /&gt;
|2048&lt;br /&gt;
|2046&lt;br /&gt;
|8 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/20'''&lt;br /&gt;
| +0.0.15.255&lt;br /&gt;
|255.255.240.000&lt;br /&gt;
|4096&lt;br /&gt;
|4094&lt;br /&gt;
|16 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/19'''&lt;br /&gt;
| +0.0.31.255&lt;br /&gt;
|255.255.224.000&lt;br /&gt;
|8192&lt;br /&gt;
|8190&lt;br /&gt;
|32 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/18'''&lt;br /&gt;
| +0.0.63.255&lt;br /&gt;
|255.255.192.000&lt;br /&gt;
|16 384&lt;br /&gt;
|16 382&lt;br /&gt;
|64 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.c.0'''/17'''&lt;br /&gt;
| +0.0.127.255&lt;br /&gt;
|255.255.128.000&lt;br /&gt;
|32 768&lt;br /&gt;
|32 766&lt;br /&gt;
|128 C&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/16'''&lt;br /&gt;
| +0.0.255.255&lt;br /&gt;
|255.255.000.000&lt;br /&gt;
|65 536&lt;br /&gt;
|65 536&lt;br /&gt;
|256 C = 1 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/15'''&lt;br /&gt;
| +0.1.255.255&lt;br /&gt;
|255.254.000.000&lt;br /&gt;
|131 072&lt;br /&gt;
|131 070&lt;br /&gt;
|2 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/14'''&lt;br /&gt;
| +0.3.255.255&lt;br /&gt;
|255.252.000.000&lt;br /&gt;
|262 144&lt;br /&gt;
|262 142&lt;br /&gt;
|4 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/13'''&lt;br /&gt;
| +0.7.255.255&lt;br /&gt;
|255.248.000.000&lt;br /&gt;
|524 288&lt;br /&gt;
|524 286&lt;br /&gt;
|8 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/12'''&lt;br /&gt;
| +0.15.255.255&lt;br /&gt;
|255.240.000.000&lt;br /&gt;
|1 048 576&lt;br /&gt;
|1 048 574&lt;br /&gt;
|16 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/11'''&lt;br /&gt;
| +0.31.255.255&lt;br /&gt;
|255.224.000.000&lt;br /&gt;
|2 097 152&lt;br /&gt;
|2 097 150&lt;br /&gt;
|32 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/10'''&lt;br /&gt;
| +0.63.255.255&lt;br /&gt;
|255.192.000.000&lt;br /&gt;
|4 194 304&lt;br /&gt;
|4 194 302&lt;br /&gt;
|64 B&lt;br /&gt;
|-&lt;br /&gt;
|a.b.0.0'''/9'''&lt;br /&gt;
| +0.127.255.255&lt;br /&gt;
|255.128.000.000&lt;br /&gt;
|8 388 608&lt;br /&gt;
|8 388 606&lt;br /&gt;
|128 B&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/8'''&lt;br /&gt;
| +0.255.255.255&lt;br /&gt;
|255.000.000.000&lt;br /&gt;
|16 777 216&lt;br /&gt;
|16 777 214&lt;br /&gt;
|256 B = 1 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/7'''&lt;br /&gt;
| +1.255.255.255&lt;br /&gt;
|254.000.000.000&lt;br /&gt;
|33 554 432&lt;br /&gt;
|33 554 430&lt;br /&gt;
|2 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/6'''&lt;br /&gt;
| +3.255.255.255&lt;br /&gt;
|252.000.000.000&lt;br /&gt;
|67 108 864&lt;br /&gt;
|67 108 862&lt;br /&gt;
|4 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/5'''&lt;br /&gt;
| +7.255.255.255&lt;br /&gt;
|248.000.000.000&lt;br /&gt;
|134 217 728&lt;br /&gt;
|134 217 726&lt;br /&gt;
|8 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/4'''&lt;br /&gt;
| +15.255.255.255&lt;br /&gt;
|240.000.000.000&lt;br /&gt;
|268 435 456&lt;br /&gt;
|268 435 454&lt;br /&gt;
|16 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/3'''&lt;br /&gt;
| +31.255.255.255&lt;br /&gt;
|224.000.000.000&lt;br /&gt;
|536 870 912&lt;br /&gt;
|536 870 910&lt;br /&gt;
|32 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/2'''&lt;br /&gt;
| +63.255.255.255&lt;br /&gt;
|192.000.000.000&lt;br /&gt;
|1 073 741 824&lt;br /&gt;
|1 073 741 822&lt;br /&gt;
|64 A&lt;br /&gt;
|-&lt;br /&gt;
|a.0.0.0'''/1'''&lt;br /&gt;
| +127.255.255.255&lt;br /&gt;
|128.000.000.000&lt;br /&gt;
|2 147 483 648&lt;br /&gt;
|2 147 483 646&lt;br /&gt;
|128 A&lt;br /&gt;
|-&lt;br /&gt;
|0.0.0.0'''/0'''&lt;br /&gt;
| +255.255.255.255&lt;br /&gt;
|000.000.000.000&lt;br /&gt;
|4 294 967 296&lt;br /&gt;
|4 294 967 294&lt;br /&gt;
|256 A&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;*&amp;lt;/nowiki&amp;gt;Чтобы в сетях с такой размерностью маски возможно было разместить хосты, отступают от правил принятых для работы в остальных сетях.&lt;br /&gt;
&lt;br /&gt;
Возможных узлов подсети меньше количества адресов на два: начальный адрес сети резервируется для идентификации подсети, последний — в качестве широковещательного адреса (возможны исключения в виде адресации в IPv4 сетей /32 и /31).&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Iptables</id>
		<title>Iptables</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Iptables"/>
				<updated>2017-05-15T07:45:17Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Iptablesfb.png|thumb|iptables]]&lt;br /&gt;
'''iptables''' — утилита командной строки, является стандартным интерфейсом управления работой межсетевого экрана(брандмауэра) '''netfilter''' для ядер Linux версий 2.4, 2.6, 3.x, 4.x . Для использования утилиты iptables требуются привилегии суперпользователя(root).&lt;br /&gt;
&lt;br /&gt;
Иногда под словом iptables имеется в виду и сам межсетевой экран netfilter.&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
Изначально разработка netfilter и iptables шла совместно, поэтому в ранней истории этих проектов есть много общего. Подробности см. в статье про netfilter.&lt;br /&gt;
&lt;br /&gt;
Предшественниками iptables были проекты ipchains (применялась для администрирования фаервола ядра Linux версии 2.2) и ipfwadm(аналогично для ядер Linux версий 2.0). Последний был основан на BSD-утилите ipfw.&lt;br /&gt;
&lt;br /&gt;
iptables сохраняет идеологию, ведущую начало от ipfwadm: функционирование фаервола определяется набором правил, каждое из которых состоит из критерия и действия, применяемого к пакетам, подпадающим под этот критерий. В ipchains появилась концепция ''цепочек'' — независимых списков правил. Были введены отдельные цепочки для фильтрации входящих (INPUT), исходящих (OUTPUT) и транзитных (FORWARD) пакетов. В продолжении этой идеи, в iptables появились ''таблицы'' — независимые группы цепочек. Каждая таблица решала свою задачу — цепочки таблицы filter отвечали за фильтрацию, цепочки таблицы nat — за преобразование сетевых адресов ('''NAT'''), к задачам таблицы mangle относились прочие модификации заголовков пакетов (например, изменение Time to live('''TTL''') или Тип обслуживания('''TOS''')). Кроме того, была слегка изменена логика работы цепочек: в ipchains все входящие пакеты, включая транзитные, проходили цепочку INPUT. В iptables через INPUT проходят только пакеты, адресованные самому хосту.&lt;br /&gt;
&lt;br /&gt;
Такое разделение функциональности позволило iptables при обработке отдельных пакетов использовать информацию о соединениях в целом (ранее это было возможно только для NAT). В этом iptables значительно превосходит ipchains, так iptables может отслеживать состояние соединения и перенаправлять, изменять или отфильтровывать пакеты, основываясь не только на данных из их заголовков (источник, получатель) или содержимом пакетов, но и на основании данных о соединении. Такая возможность фаервола называется stateful-фильтрацией, в отличие от реализованной в ipchains примитивной stateless-фильтрации (подробнее о видах фильтрации см. статью о фаерволах). Можно сказать, что iptables анализирует не только передаваемые данные, но и контекст их передачи, в отличие от ipchains, и поэтому может принимать более обоснованные решения о судьбе каждого конкретного пакета. Более подробно о stateful-фильтрации в netfilter/iptables.&lt;br /&gt;
&lt;br /&gt;
В будущем, разработчики netfilter планируют заменить iptables на '''nftables''' — инструмент нового поколения, пока находящийся в ранней стадии разработки[http://www.opennet.ru/opennews/art.shtml?num=20843 Разработчики Netfilter представили замену iptables].&lt;br /&gt;
&lt;br /&gt;
== Архитектура ==&lt;br /&gt;
&lt;br /&gt;
=== Основные понятия ===&lt;br /&gt;
&lt;br /&gt;
Ключевыми понятиями iptables являются:&lt;br /&gt;
* '''Правило''' — состоит из ''критерия'', ''действия'' и ''счетчика''. Если пакет соответствует критерию, к нему применяется действие, и он учитывается счетчиком. Критерия может и не быть — тогда неявно предполагается критерий «все пакеты». Указывать действие тоже не обязательно — в отсутствие действия правило будет работать только как счетчик.&lt;br /&gt;
** '''Критерий''' — логическое выражение, анализирующее свойства пакета и/или соединения и определяющее, подпадает ли данный конкретный пакет под действие текущего правила.&lt;br /&gt;
** '''Действие''' — описание действия, которое нужно проделать с пакетом и/или соединением в том случае, если они подпадают под критерий этого правила. О действиях более подробно будет рассказано ниже.&lt;br /&gt;
** '''Счетчик''' — компонент правила, обеспечивающий учет количества пакетов, которые попали под критерий данного правила. Также счетчик учитывает суммарный объем таких пакетов в байтах.&lt;br /&gt;
* '''Цепочка''' — упорядоченная последовательность правил. Цепочки можно разделить на ''пользовательские'' и ''базовые''.&lt;br /&gt;
** '''Базовая цепочка''' — цепочка, создаваемая по умолчанию при инициализации таблицы. Каждый пакет, в зависимости от того, предназначен ли он самому хосту, сгенерирован им или является транзитным, должен пройти положенный ему набор базовых цепочек различных таблиц. Схема следования пакетов приведена на рисунке. Кроме того, базовая цепочка отличается от пользовательской наличием «действия по умолчанию» (default policy). Это действие применяется к тем пакетам, которые не были обработаны другими правилами этой цепочки и вызванных из нее цепочек (см. переходы). Имена базовых цепочек всегда записываются в верхнем регистре (PREROUTING, INPUT, FORWARD, OUTPUT, POSTROUTING).&lt;br /&gt;
** '''Пользовательская цепочка''' — цепочка, созданная пользователем. Может использоваться только в пределах своей таблицы. Рекомендуется не использовать для таких цепочек имена в верхнем регистре, чтобы избежать путаницы с базовыми цепочками и встроенными действиями.&lt;br /&gt;
* '''Таблица''' — совокупность ''базовых'' и ''пользовательских'' цепочек, объединенных общим функциональным назначением. Имена таблиц (как и модулей критериев) записываются в нижнем регистре, так как в принципе не могут конфликтовать с именами пользовательских цепочек. При вызове команды iptables таблица указывается в формате &amp;lt;tt&amp;gt;-t имя_таблицы&amp;lt;/tt&amp;gt;. При отсутствии явного указания, используется таблица filter. Более подробно таблицы будут рассмотрены ниже.&lt;br /&gt;
&lt;br /&gt;
=== Принцип работы ===&lt;br /&gt;
&lt;br /&gt;
Все пакеты пропускаются через определенные для них последовательности цепочек (см. рис.). При прохождении пакетом цепочки, к нему последовательно применяются все правила этой цепочки в порядке их следования. Под применением правила понимается: во-первых, проверка пакета на соответствие критерию, и во-вторых, если пакет этому критерию соответствует, применение к нему указанного действия. Под действием может подразумеваться как элементарная операция (встроенное действие, например, ACCEPT, MARK), так и переход в одну из пользовательских цепочек. В свою очередь, действия могут быть как терминальными, то есть прекращающими обработку пакета в рамках данной базовой цепочки (например, ACCEPT, REJECT), так и нетерминальными, то есть не прерывающими процесса обработки пакета (MARK, TOS). Если пакет прошел через всю базовую цепочку и к нему так и не было применено ни одного терминального действия, к нему применяется действие по умолчанию для данной цепочки (обязательно терминальное). Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F # Очищаем все цепочки таблицы filter&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Ко всем пакетам, которые относятся к уже установленным&lt;br /&gt;
# соединениям, применяем терминальное действие ACCEPT — пропустить&lt;br /&gt;
iptables -P INPUT DROP # В качестве действия по умолчанию устанавливаем DROP — блокирование пакета&lt;br /&gt;
iptables -P OUTPUT ACCEPT # Разрешаем все исходящие пакеты&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь цепочка INPUT таблицы filter содержит единственное правило, которое пропускает все пакеты, относящиеся к уже установленным соединениям. Ко всем остальным входящим пакетам будет применено действие по умолчанию — DROP. Цепочка же OUTPUT вообще не содержит правил, поэтому ко всем исходящим пакетам будет применяться действие по умолчанию ACCEPT. Таким образом хост, настроенный согласно этому примеру и подключенный к Интернету, будет недоступен извне (все попытки установить соединение снаружи блокируются), однако с самого хоста доступ к Интернету будет свободный (исходящие пакеты разрешены, а ответы на них уже относятся к установленным соединениям).&lt;br /&gt;
&lt;br /&gt;
=== Основные компоненты ===&lt;br /&gt;
&lt;br /&gt;
==== netfilter ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Пока здесь будет англоязычный оригинал. Постараюсь в ближайшее время перевести — FIXED --&amp;gt;&lt;br /&gt;
[[Файл:Netfilter-components-ru.svg.png|600px|thumb|Взаимосвязь основных компонентов netfilter и conntrack]]&lt;br /&gt;
&amp;lt;!-- Поставил 600, потому что иначе нифига не разглядеть. С удовольствием приму ценные предложения по улучшению верстки для небольших экранных разрешений --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Компонент ядра '''Linux''', обеспечивающий фильтрацию и модификацию трафика. Собственно, именно он и является фаерволом. В состав netfilter входят следующие модули:&lt;br /&gt;
* '''ip_tables''' — фаервол для протокола IPv4. Обеспечивает фильтрацию пакетов, модификацию их заголовков и NAT.&lt;br /&gt;
* '''ip6_tables''' — фаервол для протокола IPv6. Обеспечивает фильтрацию пакетов и модификацию их заголовков.&lt;br /&gt;
* '''arp_tables''' — фаервол для протоколов ARP и RARP. Обеспечивает фильтрацию и модификацию пакетов.&lt;br /&gt;
* '''x_tables''' — бэкенд для ip_tables, ip6_tables и arp_tables. В этом модуле определены основные операции для работы с фаерволами «таблично-цепочечной» структуры и их компонентами.&lt;br /&gt;
* '''ebtables''' — Ethernet-фаервол (префикс eb от Ethernet Bridge). В отличие от трех перечисленных выше фаерволов, работающих с протоколами сетевого и более высоких уровней, ebtables работает на канальном уровне, выполняя фильтрацию и модификацию ethernet-кадров, проходящих через сетевые мосты, если таковые имеются на хосте.&lt;br /&gt;
&lt;br /&gt;
Принципы работы с ip_tables и ip6_tables практически идентичны, с тем небольшим отличием, что в ip6_tables отсутствует таблица nat и соответствующие действия. В то же время, принципы построения правил в arp_tables и ebtables несколько иные. В частности, arp_tables и ebtables имеют четыре базовых действия — ACCEPT (пропустить), DROP (заблокировать), CONTINUE (продолжить обработку в данной цепочке) и RETURN (прекратить обработку в данной цепочке, вернуть в цепочку уровнем выше). Эти действия могут использоваться отдельно, либо применяться к пакетам после выполнения какого-либо преобразующего действия (например, маркировки). Таким образом, после применения преобразования пакет может быть, скажем, немедленно пропущен фаерволом (ACCEPT), либо будет вынужден проследовать через последующие правила (CONTINUE). Этим arptables и ebtables отличаются от ip_tables и ip6_tables — в последних существует четкое разделение действий на терминальные и нетерминальные, которое нельзя изменить при составлении набора правил, а чтобы, например, пропустить пакет после некоторого нетерминального преобразования, необходимо добавлять дополнительное правило («&amp;lt;tt&amp;gt;iptables ... -j MARK ...; iptables ... -j ACCEPT&amp;lt;/tt&amp;gt;» вместо «&amp;lt;tt&amp;gt;ebtables ... -j mark ... --mark-target ACCEPT&amp;lt;/tt&amp;gt;»). Также, система conntrack не&amp;amp;nbsp;производит отслеживание соединений для ARP/RARP и Ethernet, поэтому возможности stateful-фильтрации в arp_tables и ebtables отсутствуют (нет критерия conntrack и таблицы raw).&lt;br /&gt;
&lt;br /&gt;
В данной статье рассматриваются только аспекты работы с ip_tables и ip6_tables. В их задачи входит:&lt;br /&gt;
* Классификация пакетов на основе различных критериев. В качестве критерия могут выступать, например, IP-адреса источника и/или назначения, состояние соединения (новое/уже установленное), порты TCP/IP источника и/или назначения (для протоколов транспортного уровня, имеющих порты), вспомогательные значения в заголовках пакетов (скажем, длина пакета,Type of Service(TOS), Time to live(TTL)) и т. п. Результаты этой классификации используются при решении других задач из данного списка.&lt;br /&gt;
* Фильтрация входящих (INPUT), исходящих (OUTPUT) и транзитных (FORWARD) пакетов, сводящуюся либо к их пропусканию (ACCEPT), либо к блокированию (DROP или REJECT). Также поддерживаются дополнительные возможности, например, блокирование попыток сканирования портов (DELUDE и CHAOS), эффективное противодействие (D)DoS-атакам (TARPIT).&lt;br /&gt;
* Модификация заголовков пакетов и связанной информации. К этому классу задач можно отнести:&lt;br /&gt;
** Трансляцию сетевых адресов (NAT), включая маскарадинг(SNAT или MASQUERADE), «проброс» адресов и портов (DNAT) и даже целых подсетей (NETMAP). Эта задача касается только модуля ip_tables. Модуль ip6_tables не&amp;amp;nbsp;производит трансляции адресов.&lt;br /&gt;
** Изменение различных вспомогательных величин в заголовках пакетов, например, TOS, TTL, TCP MSS.&lt;br /&gt;
** Установку и изменение маркировки пакетов и соединений. Впоследствии эта маркировка может быть использована системой iproute2 для маршрутизации и шейпинга трафика.&lt;br /&gt;
* Учет количества обработанных пакетов и их суммарного размера при помощи счетчиков.&lt;br /&gt;
* Занесение информации о пакетах в системный журнал syslog (LOG и LOGMARK).&lt;br /&gt;
* Передача на обработку userspace-демонам пакетов целиком (NFQUEUE) либо информации о них (NFLOG), что позволяет решать самый широкий круг задач по фильтрации, модификации и учету трафика.&lt;br /&gt;
* Внутренние задачи, связанные с обеспечением работы критериев и действий netfilter. Например, сопровождение списков IP-адресов для критериев recent и hashlimit.&lt;br /&gt;
&lt;br /&gt;
==== iptables ====&lt;br /&gt;
&lt;br /&gt;
Userspace-утилита, через которую системный администратор может управлять IPv4-фаерволом (ip tables). К ее задачам относятся:&lt;br /&gt;
* Создание и удаление пользовательских цепочек.&lt;br /&gt;
* Установка действий по умолчанию для базовых цепочек.&lt;br /&gt;
* Добавление и удаление правил.&lt;br /&gt;
* Установка и обнуление счетчиков пакетов и байт.&lt;br /&gt;
* Просмотр цепочек и правил, а также значений счетчиков.&lt;br /&gt;
* Проверка корректности задания параметров, определяющих работу критериев и действий.&lt;br /&gt;
* Вывод справки по использованию критериев (&amp;lt;tt&amp;gt;iptables -m ''критерий'' -h&amp;lt;/tt&amp;gt;) и действий (&amp;lt;tt&amp;gt;iptables -j ''действие'' -h&amp;lt;/tt&amp;gt;).&lt;br /&gt;
Также в комплект поставки вместе с iptables обычно входят вспомогательные утилиты, обеспечивающие сохранение (iptables-save) и последующее восстановление (iptables-restore) состояния фаервола, его инициализацию при запуске системы (init-скрипт) и т. п.&lt;br /&gt;
&lt;br /&gt;
Сегментом фаервола, отвечающим за фильтрацию IPv6-пакетов (ip6 tables), управляет утилита ip6tables. Так как обычно она поставляется вместе с iptables, имеет похожий синтаксис и выполняет схожие задачи, под термином «iptables» часто подразумевают сразу обе эти утилиты.&lt;br /&gt;
&lt;br /&gt;
Также в рамках данного проекта разрабатываются два набора библиотек:&lt;br /&gt;
* '''libiptc''' — содержит функции, осуществляющие вышеперечисленные операции по управлению цепочками и правилами. Именно с этими функциями и работают утилиты iptables (библиотека libip4tc) и ip6tables (библиотека libip6tc). Приложения, использующие эти библиотеки, могут обращаться к netfilter напрямую, минуя вызов утилит iptables и ip6tables. В качестве примера такого приложения можно назвать Perl-модуль [http://search.cpan.org/~hawk/IPTables-libiptc-0.18/lib/IPTables/libiptc.pm IPTables::libiptc, предоставляющий доступ к функциям этих библиотек из Perl-скриптов.&lt;br /&gt;
* '''libipq''' — содержит функции, позволяющие пользовательским приложениям принимать IP-пакеты на обработку. Отправка со стороны ядра выполняется через модуль ip queue (ip6_queue для IPv6), что соответствует действию QUEUE. В настоящее время этот механизм [http://netfilter.org/projects/libnetfilter_queue/index.html объявлен устаревшим], и вместо него рекомендуется использовать действие NFQUEUE, работа которого реализуется через модуль ядра nfnetlink_queue и библиотеку libnetfilter_queue.&lt;br /&gt;
&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
&lt;br /&gt;
Компонент netfilter, обеспечивающий отслеживание состояния соединений и классификацию пакетов с точки зрения принадлежности к соединениям, что позволяет netfilter осуществлять полноценную stateful-фильтрацию трафика. Как и netfilter, система conntrack является частью ядра '''Linux'''. К его задачам относятся:&lt;br /&gt;
* Отслеживание состояний отдельных соединений с тем, чтобы классифицировать каждый пакет либо как относящийся к уже установленному соединению, либо как открывающий новое соединение. При этом понятие &amp;quot;состояние соединения&amp;quot; искусственно вводится для протоколов, в которых оно изначально отсутствует (UDP, ICMP). При работе же с протоколами, поддерживающими состояния (например, TCP), conntrack активно использует эту возможность, тесно взаимодействуя с базовой сетевой подсистемой ядра Linux.&lt;br /&gt;
* Отслеживание связанных соединений, например, ICMP-ответов на TCP и UDP-пакеты. Более сложный вариант — протоколы, использующие несколько соединений в одной сессии, например, FTP. Для правильной обработки таких протоколов conntrack использует специальные модули (conntrack helpers), которые анализируют трафик и «выхватывают» информацию протокола о новых соединениях (например, порт, на который оно будет открыто), что позволяет обеспечить их корректную фильтрацию, маршрутизацию, шейпинг и пропускание через NAT.&lt;br /&gt;
&lt;br /&gt;
Более подробно о возможностях системы conntrack и их использовании при работе с iptables/netfilter.&lt;br /&gt;
&lt;br /&gt;
В состав conntrack входят следующие компоненты:&lt;br /&gt;
* Главный модуль nf_conntrack. Реализует базовую функциональность отслеживания соединений, интерфейсы для работы с модулями расширений, а также механизмы отслеживания протоколов TCP и UDP.&lt;br /&gt;
* Трекеры протоколов сетевого уровня: nf_conntrack_ipv4 и nf_conntrack_ipv6. Реализуют операции, специфичные для «своих» протоколов (IPv4 и IPv6 соответственно), а также механизмы отслеживания соответствующих протоколов управляющих сообщений (ICMP и ICMPv6 соответственно).&lt;br /&gt;
* Трекеры протоколов транспортного уровня (кроме TCP и UDP, реализованных в главном модуле): nf_conntrack_proto_sctp (SCTP), nf_conntrack_proto_dccp (DCCP), nf_conntrack_proto_gre (GRE), nf_conntrack_proto_udplite (UDP Lite).&lt;br /&gt;
* Вспомогательные модули (helpers), обеспечивающие отслеживание протоколов прикладного и сеансового уровней: nf_conntrack_ftp, nf_conntrack_irc, nf_conntrack_pptp, nf_conntrack_netbios_ns и т. п. Требуются далеко не&amp;amp;nbsp;для всех протоколов, а только для тех, отслеживание которых требует знания специфики протокола. Например, неоднократно упоминающийся в этой статье протокол FTP}} использует в одном сеансе два соединения (управляющее соединение и соединение передачи данных), и чтобы корректно отследить соединение передачи данных, необходимо анализировать трафик управляющего соединения и выделять в нем информацию, касающуюся открытия соединения данных.&lt;br /&gt;
* Модуль nf_nat. Реализует базовую функциональность трансляции сетевых адресов и портов с учетом информации о соединениях. Также этот модуль содержит механизмы трансляции для протоколов IPv4, TCP, UDP и ICMP (IPv6 и ICMPv6 не&amp;amp;nbsp;поддерживаются NAT-подсистемой conntrack).&lt;br /&gt;
* NAT-трекеры протоколов транспортного уровня: nf_nat_proto_sctp, nf_nat_proto_dccp, nf_nat_proto_gre, nf_nat_proto_udplite.&lt;br /&gt;
* Вспомогательные модули NAT для протоколов прикладного и сеансового уровней: nf_nat_ftp, nf_nat_irc, nf_nat_pptp и т. п.&lt;br /&gt;
* Модуль взаимодействия с userspace через протокол nfnetlink (см. следующий раздел) nf_conntrack_netlink, которому соответствует userspace-библиотека libnetfilter_conntrack.&lt;br /&gt;
* Кроме того, к conntrack можно условно отнести и модули netfilter, обеспечивающие взаимодействие этих двух подсистем: критерий conntrack (xt_conntrack), действия NOTRACK и CT (xt_NOTRACK и xt_CT), практически все действия таблицы nat, а также соответствующие модули (библиотеки iptables/ip6tables): libxt_conntrack, libxt_NOTRACK, libxt_CT и т. п.&lt;br /&gt;
&lt;br /&gt;
Для взаимодействия с системой conntrack из userspace разработан комплект [http://conntrack-tools.netfilter.org/ conntrack-tools], содержащий две утилиты:&lt;br /&gt;
* '''conntrack''' — инструмент, позволяющий системному администратору наблюдать таблицы состояний соединений и взаимодействовать с ними: очищать таблицы целиком, удалять отдельные записи, маркировать соединения вручную (аналог действия CONNMARK), устанавливать тайм-ауты соединений. Поддерживается фильтрация вывода (например, на основании адресов и/или портов источника и/или назначения), а также вывод в различных форматах, включая XML. Кроме того, данная утилита позволяет отслеживать в реальном времени события системы conntrack, например, открытие новых соединений или изменение состояния существующих.&lt;br /&gt;
* '''conntrackd''' — демон, обеспечивающий синхронизацию таблиц состояний с другими хостами, что в сочетании с возможностями демона keepalived позволяет создавать фаерволы на кластерах высокой доступности (High Availability) — при выходе из строя одного из хостов кластера его соединения будут «подхвачены» другими хостами кластера и корректно обработаны с учетом состояний. Также conntrackd можно использовать просто для удаленного сбора статистики по соединениям.&lt;br /&gt;
&lt;br /&gt;
Взаимодействие conntrack с этими программами производится посредством интерфейса nfnetlink, который будет рассмотрен в следующем разделе.&lt;br /&gt;
&lt;br /&gt;
==== nfnetlink ====&lt;br /&gt;
&lt;br /&gt;
Интерфейс, позволяющий различным userspace-приложениям взаимодействовать с netfilter и conntrack. Со стороны userspace он обеспечивается набором библиотек libnfnetlink. Ключевые библиотеки из этого набора:&lt;br /&gt;
* '''libnetfilter_conntrack''' (ранее libnfnetlink_conntrack и libctnetlink) — обеспечивает взаимодействие приложений с системой conntrack. В качестве примеров приложений, использующих эту библиотеку, можно упомянуть:&lt;br /&gt;
** Описанные выше программы '''conntrack''' и '''conntrackd''' из комплекта conntrack-tools.&lt;br /&gt;
** '''iptstate''' — в какой-то мере аналог утилиты conntrack, хотя и не&amp;amp;nbsp;имеющий таких богатых возможностей. Предназначена для непрерывного вывода таблицы состояний соединений с периодическим обновлением, в стиле широко известной утилиты top. Поддерживает различные виды сортировки (по адресам/портам источника/назначения, тайм-ауту, счетчикам и т. п.). Позволяет удалять записи из таблицы состояний. Не&amp;amp;nbsp;поддерживает работу с таблицей ожидаемых (expected) соединений.&lt;br /&gt;
* '''libnetfilter_queue''' (ранее libnfnetlink_queue) — отвечает за передачу пакетов демонам на предмет анализа. По результатам этого анализа пакет может быть заблокирован или пропущен. При пропускании пакета возможна установка или изменение его маркировки (nfmark). Идеологическим предшественником libnetfilter_queue была ныне устаревшая библиотека libipq. В качестве примеров приложений, использующих libnetfilter_queue, можно упомянуть:&lt;br /&gt;
** '''nufw''' — фаервол, выполняющий фильтрацию трафика на основе авторизации пользователей. Позволяет устанавливать ограничения на доступ к сетям, находящимся за фаерволом, для отдельных пользователей. Авторизация пользователей на фаерволе обеспечивается отдельным демоном nuauth. Например, в случае, если клиенты используют Linux, авторизация может выполняться совершенно прозрачно, благодаря возможностям PAM(модуль pam_nufw) в момент входа пользователя в систему. Особенно удобны подобные системы в корпоративных сетях, где используются системы централизованного управления аккаунтами пользователей (nufw/nuauth поддерживает LDAP и winbind).&lt;br /&gt;
** '''l7-filter-userspace''' — демон, позволяющий определить протокол 7-го (прикладного) уровня модели OSI, которому принадлежит полученный пакет, на основании анализа его содержимого при помощи регулярных выражений. Результат анализа возвращает в маркировке пакета. Полезен при фильтрации и шейпинге трафика протоколов, не&amp;amp;nbsp;имеющих фиксированных номеров портов для соединений данных, например, BitTorrent. Впрочем, в настоящее время существуют и альтернативные решения — P2P-протоколы можно выделять при помощи критерия ipp2p (из набора xtables-addons), а вспомогательные соединения в известных системе conntrack протоколах (FTP, IRC, SIP) можно выделять при помощи критерия helper и маркировки соединений.&lt;br /&gt;
** '''iplist''' — userspace-альтернатива ipset. Как и ipset, позволяет считывать большие списки IP-адресов и проверять пакеты на предмет нахождения адреса их источника/назначения в данном списке. В зависимости от результата проверки, пакет может быть пропущен или заблокирован, либо промаркирован соответствующим образом. Разумеется, ipset, работая на уровне ядра, обеспечивает более высокую скорость проверки, а также поддерживает дополнительные возможности, например, динамическое изменение списков при помощи действия SET (добавление и удаление записей), сохранение дополнительной информации (номера портов, MAC-адреса, тайм-ауты записей). Несмотря на то, что в настоящий момент ipset пока что не&amp;amp;nbsp;принят в ядро, современные дистрибутивы ipset позволяет произвести сборку и установку необходимых компонентов без необходимости наложения патчей на ядро и iptables, благодаря возможностям подгружаемых модулей (LKM) ядра Linux. Поэтому, с учетом вышесказанного, необходимость в iplist в настоящее время сомнительна.&lt;br /&gt;
* '''libnetfilter_log''' (ранее libnfnetlink_log) — предоставляет демонам интерфейс для получения служебной информации о пакетах на предмет регистрации и учета трафика. В настоящее время известен только один проект, использующий данную библиотеку — '''ulogd2''' ([netfilter] userspace logging daemon, версия&amp;amp;nbsp;2). Данный проект находится пока в бета-стадии разработки. Надо заметить, что ulogd2 может получать информацию не&amp;amp;nbsp;только через libnetfilter_log (действие NFLOG), но и через классический механизм libipulog (действие ULOG), а также через libnetfilter_conntrack (данный метод позволяет получать информацию не&amp;amp;nbsp;об отдельных пакетах, а о соединениях в целом).&lt;br /&gt;
&lt;br /&gt;
Со стороны ядра взаимодействие обеспечивается базовым модулем nfnetlink и «специализированными» модулями nf_conntrack_netlink, nfnetlink_queue и nfnetlink_log соответственно.&lt;br /&gt;
&lt;br /&gt;
Кроме того, такие программы, как nfnl_osf (передает ядру список сигнатур для критерия детекции операционной системы osf) и ipset начиная с версии 5 (см. ниже) также используют для коммуникаций ядро-userspace интерфейс nfnetlink, но эти задачи являются узкоспециализированными и поэтому реализованы без использования специальных библиотек и модулей ядра.&lt;br /&gt;
&lt;br /&gt;
==== ipset ====&lt;br /&gt;
&lt;br /&gt;
Представляет собой набор инструментов, позволяющий работать с большими списками (sets) IP-адресов и/или портов. Поддерживается возможность динамического обновления списков при прохождении пакетов через правила netfilter.&lt;br /&gt;
&lt;br /&gt;
В версии ipset&amp;amp;nbsp;4 и более ранних поддерживалась работа только с семейством адресов IPv4, однако начиная с пятой версии реализована также и поддержка IPv6.&lt;br /&gt;
&lt;br /&gt;
Стоит отметить, что долгое время проект ipset существовал вне основной ветки развития ядра Linux. В частности, в четвертой версии ipset «ядерные» компоненты приходилось собирать отдельно, используя заголовочные файлы текущего ядра. Однако, после выхода пятой версии, в которой были учтены все предыдущие замечания, началась работа по включению ipset в основную ветку. Она [http://www.spinics.net/lists/netfilter-devel/msg17027.html завершилась успехом]: поддержка ipset присутствует в Linux начиная с 2.6.39. В ходе этих работ протокол взаимодействия ядерной и userspace-частей ipset подвергся значительной переработке, и окончательная версия [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=ipset.git;a=commit;h=d6ee5bb4e5346b84efa33858091ba4add2b26de2 получила] номер 6.0. Таким образом, в современных ядрах поддержка ipset присутствует штатно, а пользователи более старых ядер могут воспользоваться реализациями ipset версий 4 и 5, включенными в набор [http://xtables-addons.sourceforge.net/ xtables-addons].&lt;br /&gt;
&lt;br /&gt;
ipset состоит из следующих элементов:&lt;br /&gt;
* Модуль ядра ip_set, обеспечивающий базовый инструментарий работы со списками записей, который используется модулями расширений.&lt;br /&gt;
* Модули расширений, определяющие конкретные структуры записей и методы работы с ними, например, ip_set_hash_ip (тип данных hash:ip), ip_set_bitmap_port (тип данных bitmap:port) и т. д.&lt;br /&gt;
* Userspace-утилита ipset, позволяющая выполнять различные операции со списками и записями в них:&lt;br /&gt;
** Создание, удаление, переименование, вывод, очистка списков.&lt;br /&gt;
** Добавление и удаление записей из списков, проверка наличия записи в списке.&lt;br /&gt;
** Вывод справочной информации по работе со списками различного типа.&lt;br /&gt;
* Модули расширений для утилиты ipset, соответствующие модулям расширений в ядре, например, ipset_hash_ip (тип данных hash:ip), ipset_bitmap_port (тип данных bitmap:port) и т. д. Каждый такой модуль отвечает за обеспечение нтерфейса между «своим» модулем ядра и конечным пользователем, в частности, проверку корректности вводимых и форматирование выводимых данных, а также вывод справочной информации по допустимым командам и параметрам. В ранних версиях ipset (до 4 включительно) такие модули выделялись в виде подгружаемых библиотек, однако в современных версиях ipset они статически включаются в основной бинарник, поэтому разделение существует лишь в исходном коде.&lt;br /&gt;
* Модуль netfilter xt_set (критерий set и действие SET), а также соответствующие модули (библиотеки) iptables (libxt_set и libxt_SET). Критерий set позволяет проверять различные параметры пакета (IP/MAC-адреса, TCP/UDP-порты источника и/или получателя) на предмет нахождения или отсутствия в списке. Действие SET позволяет добавлять или удалять записи из списка на основании указанных параметров пакета. &amp;lt;!-- Отметим, что, начиная с версии iptables 1.4.9 IPv4-специфичные модули libipt_set и libipt_SET [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=commit;h=d40f1628c3717daebc437a398a285e371b5b6f7f заменены] на более универсальные libxt_set и libxt_SET, которые могут использоваться как в iptables, так и в ip6tables. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ipset поддерживает следующие типы данных (в скобках приведены названия согласно терминологии устаревшей версии ipset&amp;amp;nbsp;4):&lt;br /&gt;
* '''bitmap:ip''' (ipmap) — полный перечень IP-адресов.&lt;br /&gt;
* '''bitmap:ip,mac''' (macipmap) — полный перечень IP-адресов, причем вместе с каждым IP-адресом может быть сохранен MAC-адрес.&lt;br /&gt;
* '''bitmap:port''' (portmap) — полный перечень портов.&lt;br /&gt;
* '''hash:ip''' (iphash) — выборочный перечень IP-адресов (либо IP-подсетей с одинаковой маской).&lt;br /&gt;
* '''hash:net''' (nethash) — выборочный перечень IP-подсетей (блоков IP-адресов). В отличие от hash:ip, в одном списке могут присутствовать подсети с различными масками.&lt;br /&gt;
* '''hash:ip,port''' (ipporthash) — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт. В версии ipset&amp;amp;nbsp;4 и более ранних существует ограничение: адреса в пределах одного перечня должны принадлежать одному блоку /16 (/255.255.0.0, максимум 65536 адресов). Начиная с версии ipset&amp;amp;nbsp;5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня.&lt;br /&gt;
* '''hash:ip,port,ip''' (ipportiphash) — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт и еще один IP-адрес. В версии ipset&amp;amp;nbsp;4 и более ранних ограничение на «первичные» адреса (первые в тройке адрес-порт-адрес) такое же, как и для ipporthash. Начиная с версии ipset&amp;amp;nbsp;5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня.&lt;br /&gt;
* '''hash:ip,port,net''' (ipportnethash) — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранен порт и IP-подсеть. В версии ipset&amp;amp;nbsp;4 и более ранних ограничение на «первичные» адреса такое же, как и у типа ipporthash. Начиная с версии ipset&amp;amp;nbsp;5, для каждого номера порта можно также сохранять идентификатор протокола транспортного уровня.&lt;br /&gt;
* '''list:set''' (setlist) — список списков. Может содержать списки любого перечисленного здесь типа, кроме list:set. При обращении к такому объекту из netfilter, включенные в него списки рассматриваются как один большой список. Поиск записей (критерий set) производится по всем вложенным спискам соответствующего типа. При добавлении записей (действие SET), вложенные списки поочередно проверяются (согласно порядку их перечисления) на соответствие типа и наличие свободного места, и запись добавляется в первый же подходящий. В то же время, при обращении к такому списку через утилиту ipset, он рассматривается именно как совокупность элементов-списков, что позволяет добавлять, удалять и проверять наличие именно вложенных списков, но не их элементов.&lt;br /&gt;
* '''hash:net,iface''' — выборочный перечень IP-подсетей, причем с каждой подсетью может быть сохранено название сетевого интерфейса. Появился в версии ipset 6.7 (входит в ядро Linux 3.1), ранние версии ipset не имеют подобных возможностей. Существует ограничение: нельзя сохранять более 64 имен интерфейсов с одним и тем же адресом подсети. Этот тип данных удобен при наличии в системе большого количества сетевых интерфейсов (например, сотен VLAN-интерфейсов).&lt;br /&gt;
&lt;br /&gt;
В четвертой версии дополнительно присутствовали два типа списков, упраздненные в более поздних версиях:&lt;br /&gt;
* '''iptree''' — выборочный перечень IP-адресов, причем с каждым адресом может быть сохранено значение тайм-аута в секундах. По истечении тайм-аута адрес удаляется из списка. Чтобы активировать возможность использование тайм-аутов для определенного списка, нужно при его создании задать тайм-аут по умолчанию (опция &amp;lt;tt&amp;gt;--timeout&amp;lt;/tt&amp;gt;). Начиная с версии ipset&amp;amp;nbsp;5, данный тип не&amp;amp;nbsp;поддерживается, при попытке его использования автоматически заменяется на hash:ip. Заметим, что начиная с пятой версии тайм-ауты реализованы для всех поддерживаемых типов данных.&lt;br /&gt;
* '''iptreemap''' — гибридный перечень, позволяющий сохранять адреса, блоки и диапазоны адресов. Начиная с версии ipset&amp;amp;nbsp;5, данный тип не&amp;amp;nbsp;поддерживается, при попытке его использования автоматически заменяется на hash:ip. Стоит отметить, что в современных версиях ipset при работе с адресами IPv4 можно указывать диапазоны адресов и подсети, которые при обращении к внутренним спискам будут автоматически преобразованы в наборы соответствующих элементов, Например, &amp;lt;tt&amp;gt;ipset create foo hash:ip; ipset add foo 192.168.0.0-192.168.0.3&amp;lt;/tt&amp;gt; добавит в список &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; адреса 192.168.0.0, 192.168.0.1, 192.168.0.2 и 192.168.0.3 (аналогичный эффект может быть достигнут и командой &amp;lt;tt&amp;gt;ipset add foo 192.168.0.0/30&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Практически для всех типов списков, реализованных в ipset, существует общее ограничение на максимальный размер: 65536 записей.&lt;br /&gt;
&lt;br /&gt;
Большинство перечисленных типов данных можно разделить на две группы: полные перечни (map, bitmap) и выборочные перечни (hash, tree). Разница между этими типами состоит в следующем: если выборочный перечень сохраняет только те элементы, которые в него входят, то полный перечень представляет собой таблицу логических значений битов для всех элементов, которые могут входить в данный перечень, и вхождение конкретного элемента в перечень определяется значением соответствующего бита. Полный перечень всегда формируется на базе ''одного непрерывного'' диапазона значений.&lt;br /&gt;
&lt;br /&gt;
Таким образом, выбор необходимого вам типа данных определяется конкретными условиями задачи, прежде всего, отношением усредненного количества элементов в списке к требуемому диапазону охвата. Например, если вы собираетесь хранить в списке блэк-листы адресов, замеченных в атаках на ваш сервер, целесообразнее использовать тип hash:ip, потому что атакующие вас ботнеты, как бы они ни&amp;amp;nbsp;были велики, все равно занимают незначительную долю адресного пространства IPv4. К тому же, как следует из сказанного в предыдущем абзаце, тип bitmap:ip все равно не&amp;amp;nbsp;может хранить адреса, выходящие за предел одной подсети префикса&amp;amp;nbsp;16. Но в том случае, если вам, например, нужно задать список хостов из вашей локальной сети, имеющих доступ к каким-либо услугам (службам вашего сервера, выходу в Интернет), и этот доступ должно иметь значительное количество хостов (а не&amp;amp;nbsp;единицы), то целесообразнее будет использовать bitmap:ip.&lt;br /&gt;
&lt;br /&gt;
По поводу хранения адресов подсетей (блоков IP-адресов) можно сказать следующее. Если вам нужно хранить большое количество блоков одного размера из ограниченного диапазона (не&amp;amp;nbsp;более 65536 возможных значений), например, блоки /24 из подсети /8, вы можете использовать тип bitmap:ip, указав маску. Если же вам нужно хранить блоки одного размера из достаточно широкого диапазона, например, /24 из всего адресного пространства IPv4, используйте тип hash:ip, также с указанием маски. При необходимости хранить в одном списке блоки ''разного'' размера, воспользуйтесь типом hash:net.&lt;br /&gt;
&lt;br /&gt;
Что касается улучшений в версиях 5 и 6 по сравнению с четвертой и более ранними, то, помимо уже упомянутых (поддержка адресов IPv6, поддержка тайм-аутов для всех типов данных, возможность сохранения идентификатора протокола транспортного уровня в типах hash:ip,port, hash:ip,port,ip и hash:ip,port,net), стоит также отметить переход на использование nfnetlink (см. выше) для связи ядра и userspace, а также более простой синтаксис. Например, те действия, которые в ipset&amp;amp;nbsp;4 выглядели бы так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ipset -N foo macipmap --network 192.168.0.0/16 # Создаем список&lt;br /&gt;
ipset -A foo 192.168.1.1,12:34:56:78:9A:BC # Добавляем запись&lt;br /&gt;
ipset -T foo 192.168.1.1,12:34:56:78:9A:BC # Проверяем ее наличие в списке&lt;br /&gt;
ipset -L foo # Выводим список на экран (точнее, на stdout)&lt;br /&gt;
ipset -F foo # Очищаем список&lt;br /&gt;
ipset -X foo # Удаляем список&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
в современных версиях ipset будут выглядеть следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ipset create foo bitmap:ip,mac range 192.168.0.0/16&lt;br /&gt;
ipset add foo 192.168.1.1,12:34:56:78:9A:BC&lt;br /&gt;
ipset test foo 192.168.1.1,12:34:56:78:9A:BC&lt;br /&gt;
ipset list foo&lt;br /&gt;
ipset flush foo&lt;br /&gt;
ipset destroy foo&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Кроме того, современные версии ipset поддерживают работу в режиме простой оболочки, принимающей команды со stdin. При этом в них обеспечивается полная обратная совместимость синтаксиса с четвертой версией, то есть синтаксис, корректно работающий для четвертой версии ipset, будет точно так же работать в пятой и шестой.&lt;br /&gt;
&lt;br /&gt;
==== ipvs ====&lt;br /&gt;
&lt;br /&gt;
Разработанный в рамках проекта [http://www.linuxvirtualserver.org/ Linux Virtual Server] инструментарий для балансировки входящих соединений на транспортном уровне, позволяющий создавать отказоустойчивые (highly available, HA) кластеры с балансировкой нагрузки. В структуру такого кластера входит один или несколько хостов-балансировщиков (front-end), а также группа хостов-обработчиков (back-end). Хост-балансировщик принимает входящие соединения и перенаправляет их на хосты-обработчики, причем выбор хоста-обработчика осуществляется по специальному алгоритму, обеспечивающему гибкое распределение нагрузки между обработчиками. В кластере также могут присутствовать дополнительные (резервные) балансировщики, которые вступают в игру в случае отказа основного балансировщика.&lt;br /&gt;
&lt;br /&gt;
Как правило, IPVS работает в связке с демоном keepalived, который обеспечивает отказоустойчивость балансировщика (с использованием протокола VRRP) и поддержку в актуальном состоянии списка обработчиков (демон периодически проверяет работоспособность обработчиков и выводит из состава кластера неработоспособные хосты). Также допускается «ручное» управление настройками кластера — через программу ipvsadm]].&lt;br /&gt;
&lt;br /&gt;
Как уже упоминалось выше, IPVS обеспечивает балансировку нагрузки на транспортном уровне, т.е. конфигурационной единицей IPVS является ''кластерная служба''. Она характеризуется адресом (IPv4 или IPv6), протоколом транспортного уровня (на данный момент IPVS поддерживает протоколы TCP,UDP и SCTP) и номером порта. Обычно для кластерных служб выделяется отдельный адрес, который присваивается активному (на данный момент) балансировщику. В случае его отказа, адрес автоматически передается резервному балансировщику, и кластер продолжает работу. Обратите внимание, что обеспечением отказоустойчивости занимается не IPVS, а keepalived. Впрочем, использование keepalived не является строго обязательным — существуют и альтернативные подходы, например, встраивание IPVS в кластерный стек [http://linux-ha.org/ Linux-HA] (см. Heartbeat). В том случае, если отказоустойчивость не критична (требуется только балансировка нагрузки), можно вообще обойтись без дополнительного демона, выполняя всю настройку через ipvsadm.&lt;br /&gt;
&lt;br /&gt;
Для перенаправления пакетов на выбранный обработчик, IPVS может использовать один из следующих методов:&lt;br /&gt;
* '''Прямая маршрутизация(gatewaying)''' — применяется в том случае, если между балансировщиком и обработчиками отсутствуют маршрутизаторы, т.е. они находятся в одном сегменте сети. В этом случае адрес назначения в заголовке пакетов сохраняется неизменным («кластерный» адрес), подменяются лишь MAC-адреса назначения при отправке кадров с этими пакетами.&lt;br /&gt;
* '''Инкапсуляция IPIP''' — модификация предыдущего метода на тот случай, когда балансировщик и обработчики находятся в разных сегментах сети. При помощи инкапсуляции IP-в-IP создаются сетевые туннели, которые объединяют балансировщик и обработчик в один сегмент виртуальной сети.&lt;br /&gt;
* '''Маскарадинг (NAT)''' — наиболее гибкое и универсальное решение: балансировщик подменяет адреса/порты назначения проходящих пакетов на реальные адреса/порты обработчиков трансляция порт-адрес). При этом обеспечивается как простота настройки (не нужно поднимать дополнительные адреса на обработчиках и туннели между балансировщиком и обработчиком), так и гибкость (целевой порт обработчика может отличаться от порта кластерной службы, что невозможно в рамках других методов). Недостатком данного метода является несколько большее потребление системных ресурсов (трансляция адресов является довольно ресурсоемкой задачей).&lt;br /&gt;
&lt;br /&gt;
В настоящее время существует довольно обширная библиотека алгоритмов балансировки нагрузки между обработчиками:&lt;br /&gt;
* '''rr (round robin)''' — классическая кольцевая схема, когда все обработчики получают новые соединения поочередно.&lt;br /&gt;
* '''wrr (weighted round robin)''' — модификация кольцевой схемы на тот случай, когда одни сервера могут обрабатывать больше соединений, чем другие. Такие сервера включаются в один проход очереди по нескольку раз, и соответственно получают больше соединений.&lt;br /&gt;
* '''lc (least-connection)''' — новое соединение передается тому серверу, который на текущий момент обрабатывает наименьшее число соединений.&lt;br /&gt;
* '''wlc (weighted least-connection)''' — модификация предыдущего метода на случай, когда возможности серверов отличаются. При выборе нового сервера сравниваются не непосредственно количества открытых соединений, а отношения количества соединений к весовому коэффициенту (весу) обработчика (который и характеризует его возможности).&lt;br /&gt;
* '''lblc (locality-based least-connection)''' — формирует привязку обработчиков к кластерному адресу назначения (их может быть несколько). В том случае, если для запрошенного адреса такой привязки еще нет, или привязанный обработчик сильно перегружен ­— выбирает (по алгоритму lc) и привязывает новый обработчик.&lt;br /&gt;
* '''lblcr (locality-based least-connection with replication)''' — несколько усложненный вариант предыдущего алгоритма. К каждому кластерному адресу привязывается группа обработчиков, которая периодически обновляется (исключаются наиболее нагруженные обработчики, вместо них включаются наименее нагруженные).&lt;br /&gt;
* '''dh (destination hashing)''' — обеспечивает жесткую, неуправляемую привязку обработчиков к кластерным адресам назначения (выбор обработчика производится исключительно на основании элементарных арифметических операций над кластерным адресом и ''никак не учитывает'' загруженности обработчиков). Может привести к перегрузкам отдельных обработчиков — в этом случае кластер просто перестает обслуживать соответствующий адрес. В такой ситуации нужно либо увеличить лимит соединений на обработчик, либо выбрать другой алгоритм.&lt;br /&gt;
* '''sh (source hashing)''' — аналогично dh, но обработчики привязываются к адресам клиентов. Как и dh, в случае перегрузки прекращает обслуживание. Отметим, что для формирования ''временных'' привязок обработчиков к адресам клиентов целесообразнее использовать механизм устойчивых соединений (persistent connections), доступный для всех алгоритмов.&lt;br /&gt;
* '''sed (shortest expected delay)''' — выбирает сервер с наименьшей ожидаемой задержкой ответа. Эта задержка определяется как отношение числа обрабатываемых соединений плюс единица к весу обработчика. Таким образом, этот метод по принципу близок к wlc (отличается лишь прибавлением единицы к числителю сравниваемой величины, что немного меняет влияние веса обработчика на выбор).&lt;br /&gt;
* '''nq (never queue)''' — пытается передать новое соединение обработчику, который в данный момент не обрабатывает других соединений. Если все обработчики уже заняты, использует предыдущий алгоритм (sed).&lt;br /&gt;
&lt;br /&gt;
Для отслеживания соединений к кластерным службам IPVS использует собственную систему трекинга соединений, более примитивную, но менее ресурсоемкую, нежели классический conntrack. При этом поддерживается экспорт информации о кластерных соединениях в conntrack, в целях обеспечения их корректной обработки фаерволом и трансляции адресов (при трансляции адресов используются штатные средства netfilter). Однако, для корректной обработки протоколов, использующих связанные соединения (например, FTP), IPVS использует возможности conntrack. Синхронизация таблицы соединений между основным и дублирующими балансировщиками полностью реализована на уровне ядра (для сравнения, в conntrack эту задачу выполняет userspace-демон conntrackd).&lt;br /&gt;
&lt;br /&gt;
=== Механизм определения состояний ===&lt;br /&gt;
&lt;br /&gt;
Важной особенностью iptables/netfilter является механизм определения состояний (connection tracking, nf_conntrack) — специальная подсистема, отслеживающая состояния соединений и позволяющая использовать эту информацию при принятии решений о судьбе отдельных пакетов. Наличие этого механизма делает netfilter полноценным stateful-фаерволом.&lt;br /&gt;
&lt;br /&gt;
Определение состояния соединения порою бывает довольно сложной задачей. Скажем, в случае TCP все относительно просто — контроль состояний реализован средствами самого протокола, установлены специальные процедуры открытия и закрытия соединения. А вот в протоколе UDP для этого специальных процедур не предусмотрено, поэтому UDP-соединением с точки зрения conntrack является поток пакетов, следующих с интервалом, не превышающим заданный тайм-аут (sysctl-параметр &amp;lt;tt&amp;gt;net.netfilter.nf_conntrack_udp_timeout&amp;lt;/tt&amp;gt;, по умолчанию 30 секунд), с одного и того же порта одного хоста, на один и тот же порт другого хоста.&lt;br /&gt;
&lt;br /&gt;
Заметим, что классификация пакетов по отношению к соединениям, реализуемая системой conntrack, во многих случаях отличается от официального описания сетевых протоколов. Например, с точки зрения критерия conntrack, TCP-пакет SYN/ACK (отвечающий на SYN) — уже часть существующего сеанса, а по определению TCP такой пакет — всего лишь элемент открытия сеанса.&lt;br /&gt;
&lt;br /&gt;
Существует также понятие «связанных соединений». Например, когда в ответ на UDP-пакет с нашего хоста удаленный хост отвечает ICMP-пакетом icmp-port-unreachable, формально этот ответ является отдельным соединением, так как использует совсем другой протокол. netfilter отслеживает подобные ситуации и присваивает таким соединениям статус «связанных» (RELATED), позволяя корректно пропускать их через фильтры фаервола.&lt;br /&gt;
&lt;br /&gt;
Более сложный вариант связанного соединения — соединение данных в пассивном режиме FTP. FTP-сервер самостоятельно выбирает порт для прослушивания из достаточно большого диапазона, и сообщает номер порта клиенту через управляющее соединение, после чего клиент подключается к этому порту и передает данные. netfilter, а точнее модуль conntrack_ftp, выделяет в потоке данных управляющего соединения нужный номер порта, что позволяет корректно определить новое соединение как связанное и, соответственно, корректно пропустить его через правила фильтрации.&lt;br /&gt;
&lt;br /&gt;
В некоторых случаях целесообразно отключить отслеживание состояния соединений. Например, если ваш сервер находится под (D)DoS-атакой типа флуд, и вам удалось локализовать ее источники, отслеживать соединения с атакующих хостов и тратить для этого ресурсы своей системы явно не имеет смысла. В подобных случаях используется действие NOTRACK, применяемое в таблице raw.&lt;br /&gt;
&lt;br /&gt;
Ниже кратко перечислены возможности, предоставляемые системой отслеживания состояний:&lt;br /&gt;
&lt;br /&gt;
==== Критерий состояния соединения ====&lt;br /&gt;
&lt;br /&gt;
При помощи критерия conntrack вы можете классифицировать пакеты на основании их отношения к соединениям. В частности, состояние NEW позволяет выделять только пакеты, открывающие новые соединения, состояние ESTABLISHED — пакеты, принадлежащие к установленным соединениям, состоянию RELATED соответствуют пакеты, открывающие новые соединения, логически связанные с уже установленными (например, соединение данных в пассивном режиме FTP). Состояние INVALID означает, что принадлежность пакета к соединению установить не удалось.&lt;br /&gt;
&lt;br /&gt;
Например, одним простым правилом&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
вы можете обеспечить корректное пропускание всех входящих пакетов, принадлежащих установленным соединениям, и сконцентрироваться только на фильтрации новых соединений.&lt;br /&gt;
&lt;br /&gt;
Заменив в предыдущем правиле &amp;lt;tt&amp;gt;ESTABLISHED&amp;lt;/tt&amp;gt; на &amp;lt;tt&amp;gt;ESTABLISHED,RELATED&amp;lt;/tt&amp;gt; и подгрузив соответствующие модули ядра, вы автоматически обеспечите корректную фильтрацию протоколов, использующих связанные соединения — FTP, SIP, IRC, H.323 и других. Такое простое (с точки зрения пользователя) решение сложной (с технической точки зрения) проблемы является безусловным достоинством фаервола netfilter и ядра Linux в целом.&lt;br /&gt;
&lt;br /&gt;
Кроме критерия conntrack, стоит упомянуть и его идеологического предшественника — критерий state. Изначально для определения состояния соединения использовался именно он, то есть вместо &amp;lt;tt&amp;gt;-m conntrack --ctstate ESTABLISHED,RELATED&amp;lt;/tt&amp;gt; использовалось &amp;lt;tt&amp;gt;-m state --state ESTABLISHED,RELATED&amp;lt;/tt&amp;gt;. Подобные формулировки до сих пор сохраняются во многих руководствах по iptables. Однако в настоящее время критерий state считается устаревшим, и разработчики iptables [http://jengelh.medozas.de/documents/Perfect_Ruleset.pdf рекомендуют] использовать вместо него критерий conntrack. Также заметим, что критерий conntrack обладает более широкими возможностями, нежели state, и позволяет использовать дополнительную информацию о соединении, в частности, состояние самого соединения (ctstatus), факт применения к нему трансляции адресов, тайм-аут для «повисших» соединений (ctexpire) и т. п.&lt;br /&gt;
&lt;br /&gt;
==== Маркировка соединений ====&lt;br /&gt;
&lt;br /&gt;
Этот прием позволяет классифицировать соединение в целом на основании информации об отдельном пакете. Выделив этот пакет, вы применяете к нему действие CONNMARK, и выбранную вами маркировку автоматически приобретают все пакеты в соединении. Впоследствии вы можете, например, модифицировать эти пакеты каким-либо образом, или использовать эту маркировку для маршрутизации или шейпинга пакетов. Таким образом, вы оперируете с соединением как с единым целым. Более того, эта маркировка автоматически копируется и на соединения, связанные с текущим.&lt;br /&gt;
&lt;br /&gt;
==== Трансляция сетевых адресов ====&lt;br /&gt;
&lt;br /&gt;
В операциях NAT, производимых с помощью iptables, отслеживание состояний используется автоматически. Вам достаточно указать критерии, под которые подпадет лишь первый пакет в соединении — и трансляция адресов будет применена ко всем пакетам в этом соединении, а также в связанных с ним соединениях.&lt;br /&gt;
&lt;br /&gt;
==== Использование статистики по соединениям ====&lt;br /&gt;
&lt;br /&gt;
Применяя критерий connbytes, вы можете контролировать количество байт или пакетов, переданных по каждому конкретному соединению. В простейшем случае этот механизм может использоваться, скажем, для назначения квот. Более сложный пример — шейпинг пакетов в зависимости от «весовой категории» соединения (ставить пониженный приоритет загрузкам больших файлов).&lt;br /&gt;
&lt;br /&gt;
Этот критерий рассмотрен ниже, в разделе лимитирующие критерии.&lt;br /&gt;
&lt;br /&gt;
==== Ограничение количества соединений ====&lt;br /&gt;
&lt;br /&gt;
Используя критерий connlimit, вы можете ограничивать количество одновременно открытых TCP-соединений с каждого хоста или подсети на ваш сервер, что позволяет обеспечить эффективную защиту от DoS-атак или просто некорректно работающего клиентского ПО.&lt;br /&gt;
&lt;br /&gt;
Этот критерий рассмотрен ниже, в разделе лимитирующие критерии.&lt;br /&gt;
&lt;br /&gt;
==== Отслеживание информации о соединениях ====&lt;br /&gt;
&lt;br /&gt;
Пользователь (точнее, системный администратор) или его процессы могут непосредственно наблюдать таблицу контроля состояний, считывать статистику по передаче данных, а также модифицировать эту таблицу (например, удалять из нее соединения). Для этого существуют специальные утилиты, такие как conntrack или iptstate. Впрочем, можно читать информацию и напрямую из псевдофайлов &amp;lt;tt&amp;gt;/proc/net/nf_conntrack&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;/proc/net/nf_conntrack_expect&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Действия ==&lt;br /&gt;
&lt;br /&gt;
=== Переходы ===&lt;br /&gt;
&lt;br /&gt;
Для организации перехода пакета из текущей цепочки в другую (определенную пользователем), просто используйте действие &amp;lt;tt&amp;gt;-j имя_цепочки&amp;lt;/tt&amp;gt;. В случае применения в этой цепочке к пакету действия RETURN (см. ниже), пакет вернется в исходную цепочку и продолжит ее прохождение начиная со следующего правила.&lt;br /&gt;
&lt;br /&gt;
Также, существует довольно редко используемое действие «безвозвратного перехода» &amp;lt;tt&amp;gt;-g имя_цепочки&amp;lt;/tt&amp;gt;. В таком случае, после прохождения пакетом этой цепочки либо при применении в этой цепочке к пакету действия RETURN, пакет вернется к месту последнего перехода по &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt;. Если таких переходов не было, к пакету сразу будет применено действие по умолчанию для базовой цепочки.&lt;br /&gt;
&lt;br /&gt;
Заметим, что не стоит пытаться перейти в базовую цепочку (например, &amp;lt;tt&amp;gt;-j OUTPUT&amp;lt;/tt&amp;gt;), в текущую цепочку (во избежание зацикливания), а также в цепочку, определенную в другой таблице.&lt;br /&gt;
&lt;br /&gt;
=== Встроенные действия ===&lt;br /&gt;
&lt;br /&gt;
Как уже было сказано выше, каждое встроенное действие реализует какую-либо одну операцию, например, ACCEPT пропускает пакет, MARK меняет его маркировку, MASQUERADE обеспечиват маскарадинг соединения. Наиболее общими действиями являются:&lt;br /&gt;
* '''ACCEPT''', '''DROP''' и '''REJECT''' — базовые операции фильтрации. Более подробно они рассмотрены ниже, при описании таблицы filter.&lt;br /&gt;
* '''RETURN''' — обеспечивает возврат из текущей цепочки. В частности, если из цепочки A правилом номер 3 пакет был направлен в цепочку B, то применение к нему в цепочке B действия RETURN приведет к его переходу обратно в цепочку A, и он продолжит ее прохождение со следующего правила (номер 4).&lt;br /&gt;
Например, предположим, что нам нужно обеспечить доступ к определенным портам нашего сервера для всех хостов из подсети 10.134.0.64/26, ''кроме'' 10.134.0.67 и 10.134.0.100.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F # Очищаем все цепочки таблицы filter&lt;br /&gt;
iptables -N our_subnet # Создаем специальную цепочку для проверки пакетов из нашей подсети&lt;br /&gt;
iptables -A our_subnet -s 10.134.0.67 -j RETURN # Запрещенный хост — выходим&lt;br /&gt;
iptables -A our_subnet -s 10.134.0.100 -j RETURN # Запрещенный хост — выходим&lt;br /&gt;
# Всем остальным разрешаем доступ к нужным портам&lt;br /&gt;
iptables -A our_subnet -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT&lt;br /&gt;
iptables -A our_subnet -p udp -m multiport --dports 53,123,137,138 -j ACCEPT&lt;br /&gt;
iptables -A our_subnet -p icmp --icmp-type 8 -j ACCEPT&lt;br /&gt;
# Разрешаем пакеты по уже установленным соединениям&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
# Все пакеты из нашей подсети отправляем на проверку&lt;br /&gt;
iptables -A INPUT -s 10.134.0.64/26 -j our_subnet&lt;br /&gt;
iptables -P INPUT DROP # Что не разрешено — то запрещено&lt;br /&gt;
iptables -P OUTPUT ACCEPT # На выход — можно все&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь все новые входящие пакеты, отправленные из нашей подсети 10.134.0.64/26, отправляются на проверку в цепочку &amp;lt;tt&amp;gt;our_subnet&amp;lt;/tt&amp;gt;. К пакетам с «запрещенных» хостов применяется операция RETURN, и они покидают эту цепочку и впоследствии блокируются действием по умолчанию цепочки INPUT. Пакеты с остальных хостов этой подсети пропускаются в том случае, если они адресованы на порты прокси (8080/tcp), SSH (22/tcp), SMB (139,445/tcp, 137,138/udp), DNS (53/tcp, udp), NTP (123/udp). Также для этих хостов разрешены ICMP-эхо-запросы (пинги). Все остальные пакеты (включая пакеты не из нашей подсети, пакеты с запрещенных хостов и пакеты на неразрешенные порты) блокируются действием по умолчанию DROP.&lt;br /&gt;
&lt;br /&gt;
Нетрудно заметить, что в нашем простом примере вместо RETURN можно было использовать и DROP. Однако, существует понятие «принципа одного запрета». При организации фильтрующих правил в рамках этого принципа, сначала следует серия разрешающих правил, исключения оформляются в виде RETURN, а все не разрешенные пакеты доходят до конца базовой цепочки и блокируются действием по умолчанию либо последним правилом. Следование этому принципу позволяет достичь гибкости в выборе и смене метода блокирования пакетов. Допустим, вы хотите сменить блокирующее действие DROP на REJECT. Нет ничего проще — просто меняете правило по умолчанию. Так же просто вводятся специфические методы блокировки для TCP, например, REJECT &amp;lt;tt&amp;gt;--reject-with tcp-reset&amp;lt;/tt&amp;gt; или DELUDE — достаточно просто добавить это действие (вместе с указанием протокола &amp;lt;tt&amp;gt;-p tcp&amp;lt;/tt&amp;gt;) в конец цепочки. Все не-TCP пакеты при этом будут по-прежнему блокироваться действием по умолчанию.&lt;br /&gt;
&lt;br /&gt;
Впрочем, изложенный принцип теряет первоначальный смысл, если в разных случаях нужно обеспечить разные способы блокирования. Рассмотрим чуть более сложный пример: допустим, наш сервер подключен к локальной сети 10.0.0.0/8. В ней есть некий «недоверенный» сегмент, скажем, 10.122.0.0/16, для которого нужно полностью заблокировать доступ к нашему серверу. Но в этом сегменте есть несколько «хороших» хостов (скажем, 10.122.72.11 и 10.122.180.91), которые блокировать не&amp;amp;nbsp;нужно. Поставленную задачу можно решить следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F # Очищаем все цепочки таблицы filter&lt;br /&gt;
iptables -N check_untrusted # Создаем специальную цепочку для проверки пакетов из нашей подсети&lt;br /&gt;
iptables -A check_untrusted -s 10.122.72.11 -j RETURN # Разрешенный хост — выходим&lt;br /&gt;
iptables -A check_untrusted -s 10.122.180.91 -j RETURN # Разрешенный хост — выходим&lt;br /&gt;
iptables -A check_untrusted -j DROP # Остальных — молча игнорируем&lt;br /&gt;
# Разрешаем пакеты по уже установленным соединениям&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
# Пакеты из недоверенной подсети проверяем по списку&lt;br /&gt;
iptables -A INPUT -s 10.122.0.0/16 -j check_untrusted&lt;br /&gt;
# Всем остальным разрешаем доступ к нужным портам&lt;br /&gt;
iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -p udp -m multiport --dports 53,123,137,138 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT&lt;br /&gt;
# «Хорошим» хостам, обращающимся на неправильные TCP-порты, вежливо сообщаем об отказе&lt;br /&gt;
iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset&lt;br /&gt;
# Для всех остальных протоколов используем стандартный REJECT с icmp-port-unreachable&lt;br /&gt;
iptables -P INPUT REJECT&lt;br /&gt;
iptables -P OUTPUT ACCEPT # На выход — можно все&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Заметим, что в данном примере хосты из недоверенного сегмента блокируются «молча» (DROP), в то время как при обращении «хороших» хостов на неправильные порты сервер вежливо сообщает им об отказе (REJECT). Этот принцип также является очень важным при построении фаерволов — чем меньше информации попадает к потенциальному злоумышленнику, тем лучше, поэтому на опасных направлениях целесообразно использовать «молчаливое» блокирование, в то время как явные сообщения для «своих» упрощают диагностику работы сети и поиск ошибок.&lt;br /&gt;
&lt;br /&gt;
: ''Примечание: следующий пример планируется к переносу в еще не написанный раздел статьи (Прочие критерии → mac)''.&lt;br /&gt;
Например, предположим, что у нас есть объединенная через один свитч подсеть 10.134.0.64/26, к которой наш компьютер подключен через интерфейс eth1. Тогда защиту от спуфинга (подделки адресов отправителя) через проверку MAC-адреса можно обеспечить следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик&lt;br /&gt;
iptables -F # Очищаем все цепочки таблицы filter&lt;br /&gt;
iptables -N check_ours_sp00f # Создаем цепочку, в которой будут проверяться MAC-адреса&lt;br /&gt;
iptables -A check_ours_sp00f -s 10.134.0.67 -m mac --mac-source 00:1D:60:2E:ED:A5 -j RETURN&lt;br /&gt;
iptables -A check_ours_sp00f -s 10.134.0.68 -m mac --mac-source 00:1D:60:2E:ED:CD -j RETURN&lt;br /&gt;
iptables -A check_ours_sp00f -s 10.134.0.69 -m mac --mac-source 00:1D:60:2E:ED:D7 -j RETURN&lt;br /&gt;
iptables -A check_ours_sp00f -s 10.134.0.70 -m mac --mac-source 00:1D:60:2E:ED:E0 -j RETURN&lt;br /&gt;
# Аналогичным образом проверяем все адреса нашей подсети&lt;br /&gt;
# И в конце обязательно добаляем правило для НЕпрошедших проверку&lt;br /&gt;
iptables -A check_ours_sp00f -j DROP&lt;br /&gt;
iptables -N check_ours # Создаем цепочку, которая будет описывать логику работы с нашей подсетью&lt;br /&gt;
iptables -A check_ours ! -i eth1 -j DROP # С других интерфейсов пакеты от них прийти не могут&lt;br /&gt;
iptables -A check_ours -j check_ours_sp00f # Прогоняем их через проверку на спуфинг&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Как обычно, пропускаем все, что идет по установленным соединениям&lt;br /&gt;
iptables -A INPUT -s 10.134.0.64/26 -j check_ours # Тех, кто претендует на звание своих, прогоняем через проверку&lt;br /&gt;
# Прошедшим проверку разрешаем пользоваться нащей проксёй и самбой, а также соединяться по ssh&lt;br /&gt;
iptables -A INPUT -s 10.134.0.64/26 -m multiport --dports 22,8080,139,445 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP # Остальных блокируем&lt;br /&gt;
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Как обычно, пропускаем все, что идет по установленным соединениям&lt;br /&gt;
iptables -A FORWARD -s 10.134.0.64/26 -j check_ours # Проверка&lt;br /&gt;
iptables -A FORWARD -s 10.134.0.64/26 -j ACCEPT # Прошедшим проверку разрешаем передавать через нас транзитный трафик&lt;br /&gt;
iptables -P FORWARD DROP # Остальных блокируем&lt;br /&gt;
iptables -P OUTPUT ACCEPT # Исходящий трафик разрешаем&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;!--В демонстрационных целях этот пример был слегка упрощён (вместо повтора правил с критерием &amp;lt;tt&amp;gt;-s 10.134.0.64/26&amp;lt;/tt&amp;gt; эти правила логичнее было бы вынести в отдельные цепочки) но, тем не менее, наглядно показывает принципы работы действия RETURN.--&amp;gt;&lt;br /&gt;
Все новые входящие пакеты с обратным адресом из подсети 10.134.0.64/26 проходят двойную проверку в цепочке &amp;lt;tt&amp;gt;check_ours&amp;lt;/tt&amp;gt;. Первый этап проверки — соответствие интерфейса. Ведь к нашей подсети, по условию задачи, мы подключены только интерфейсом eth1. Если пакет якобы из этой подсети придет с любого другого интерфейса, он будет заблокирован. Второй этап проверки заключается в последовательном чтении списка соответствующих IP- и MAC-адресов (цепочка &amp;lt;tt&amp;gt;check_ours_sp00f&amp;lt;/tt&amp;gt;). Каждое правило этой цепочки, кроме последнего, выделяет пакеты от одного конкретного хоста нашей подсети. К пакетам, прошедшим проверку, применяется операция RETURN, выводящая пакет из этой цепочки. Если же пакет не подошел ни по одному из этих правил, он считается не прошедшим проверки и блокируется последним правилом &amp;lt;tt&amp;gt;-j DROP&amp;lt;/tt&amp;gt;. Для прошедших же проверку пакетов дальнейшая судьба зависит от того, кому они адресованы. Если они идут через наш хост в другие подсети, то они пропускаются. Если же они адресованы непосредственно нашему хосту, то пропускаются только соединения на некоторые TCP-порты (прокси, SSH, SMB).&lt;br /&gt;
* '''LOG''' — позволяет записывать информацию о пакетах в журнал ядра (см. syslog).&lt;br /&gt;
Например, если в предыдущем примере перед строкой&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
мы добавим строку&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp -m multiport --dports 22,53,8080,139,445 -j LOG --log-level INFO --log-prefix &amp;quot;New connection from ours: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
то для каждого нового соединения к нашему хосту из нашей подсети в системном журнале будет появляться запись примерно такого вида:&lt;br /&gt;
 Jul 16 20:10:40 interdictor kernel: New connection from ours: IN=eth0 OUT= MAC=00:15:17:4c:89:35:00:1d:60:2e:ed:a5:08:00 SRC=10.134.0.67 &lt;br /&gt;
 DST=10.134.0.65 LEN=48 TOS=0x00 PREC=0x00 TTL=112 ID=38914 DF PROTO=TCP SPT=31521 DPT=8080 WINDOW=65535 RES=0x00 SYN URGP=0&lt;br /&gt;
Такая запись содержит очень много полезной информации. Начинается она с даты и времени получения пакета. Затем идет имя нашего хоста (interdictor) и источник сообщения (для сообщений фаервола это всегда ядро). Потом идет заданный нами префикс (&amp;lt;tt&amp;gt;New connection from ours:&amp;lt;/tt&amp;gt;), после чего следуют данные о самом пакете: входящий интерфейс (определен для цепочек PREROUTING, INPUT и FORWARD), исходящий интерфейс (определен для цепочек FORWARD, OUTPUT и POSTROUTING), далее — сцепленные вместе MAC-адреса источника и назначения (сначала идет адрес назначения, в данном случае это наш интерфейс eth1 с маком 00:15:17:4C:89:35, затем адрес источника, в нашем случае это 00:1D:60:2E:ED:A5, и в конце следует значение EtherType, 08:00 соответствует протоколу IPv4&amp;lt;ref&amp;gt;Если кратко, EtherType указывает тип протокола, инкапсулированного в Ethernet-кадр. При работе с iptables это значение будет всегда равно 08:00 (протокол IPv4), при работе с ip6tables — 86:DD (IPv6). Полный список EtherTypes доступен [http://www.iana.org/assignments/ethernet-numbers на сайте IANA], список поддерживаемых netfilter’ом — в файле /etc/ethertypes, который в большинстве дистрибутивов находится в пакете ebtables), потом IP-адреса источника (10.134.0.67) и получателя (10.134.0.65, это наш хост), а затем идет различная техническая информация. Например, протокол (TCP), порты источника и назначения (31521 и 8080 соответственно), TOS и TTL, длина пакета (48 байт), наличие флага SYN и т. д.&lt;br /&gt;
&lt;br /&gt;
Указав соответствующие параметры действия LOG, можно дополнить эту информацию номером TCP-последовательности (опция &amp;lt;tt&amp;gt;--log-tcp-sequence&amp;lt;/tt&amp;gt;), выводом включенных опций протоколов TCP (опция &amp;lt;tt&amp;gt;--log-tcp-options&amp;lt;/tt&amp;gt;) и IP (&amp;lt;tt&amp;gt;--log-ip-options&amp;lt;/tt&amp;gt;), а также идентификатором пользователя, процесс которого отправил данный пакет (&amp;lt;tt&amp;gt;--log-uid&amp;lt;/tt&amp;gt;, имеет смысл только в цепочках OUTPUT и POSTROUTING).&lt;br /&gt;
&lt;br /&gt;
Параметр &amp;lt;tt&amp;gt;--log-prefix&amp;lt;/tt&amp;gt; позволяет задать поясняющую надпись, упрощающую поиск сообщений в системных журналах. Параметр &amp;lt;tt&amp;gt;--log-level&amp;lt;/tt&amp;gt; определяет уровень важности лог-сообщения, от которого зависит, в частности, в какой именно из журналов будет записано это сообщение. За более подробными сведениями обратитесь к документации по вашему демону системного лога.&lt;br /&gt;
* '''LOGMARK''' — специальная модификация действия LOG, реализованная в комплекте xtables-addons. Отличается тем, что заносит в лог информацию, специфичную для системы conntrack, в частности, маркировку соединения (connmark aka ctmark), состояния соединения (ctstate и ctstatus) и т. п. Например:&lt;br /&gt;
  Jul 16 20:10:40 interdictor kernel: New connection from ours: iif=1 hook=INPUT nfmark=0x0 secmark=0x0 classify=0x0 ctdir=ORIGINAL &lt;br /&gt;
  ct=0xf5436bcc ctmark=0x0 ctstate=NEW ctstatus=&lt;br /&gt;
&amp;lt;tt&amp;gt;iif&amp;lt;/tt&amp;gt; показывает внутренний идентификатор интерфейса, через который прошел пакет (1 в данном случае соответствует eth0, 0 — lo), &amp;lt;tt&amp;gt;hook&amp;lt;/tt&amp;gt; — имя цепочки, из которой было вызвано действие LOGMARK, &amp;lt;tt&amp;gt;nfmark&amp;lt;/tt&amp;gt; — маркировку пакета (mark), &amp;lt;tt&amp;gt;secmark&amp;lt;/tt&amp;gt; — контекст безопасности SELinux данного пакета (secmark), &amp;lt;tt&amp;gt;classify&amp;lt;/tt&amp;gt; — класс шейпера (также известный как &amp;lt;tt&amp;gt;skb-&amp;gt;priority&amp;lt;/tt&amp;gt;, соответствует обычной для tc форме записи ''MAJOR'':''MINOR'' согласно формуле &amp;lt;tt&amp;gt;skb-&amp;gt;priority == ''MAJOR'' &amp;lt;&amp;lt; 16 | ''MINOR''&amp;lt;/tt&amp;gt;), &amp;lt;tt&amp;gt;ctdir&amp;lt;/tt&amp;gt; — направление передачи информации с точки зрения conntrack, &amp;lt;tt&amp;gt;ct&amp;lt;/tt&amp;gt; — внутренний идентификатор соединения в системе conntrack (точнее говоря, адрес в памяти, по которому расположена структура, хранящая информацию о соединении), &amp;lt;tt&amp;gt;ctmark&amp;lt;/tt&amp;gt; — маркировку соединения (connmark), &amp;lt;tt&amp;gt;ctstate&amp;lt;/tt&amp;gt; — состояние соединения, &amp;lt;tt&amp;gt;ctstatus&amp;lt;/tt&amp;gt; — статус соединения в системе cоnntrack. Более подробно о параметрах ctdir, ctstate и ctstatus вы можете прочитать  в описании критерия conntrack. Здесь же ограничимся замечаниями, что «&amp;lt;tt&amp;gt;ctstate=NEW ctstatus=&amp;lt;/tt&amp;gt;» соответствует первому пакету в соединении, «&amp;lt;tt&amp;gt;ctstate=ESTABLISHED ctstatus=SEEN_REPLY,CONFIRMED&amp;lt;/tt&amp;gt;» — второму и нескольким последующим пакетам, «&amp;lt;tt&amp;gt;ctstate=ESTABLISHED ctstatus=SEEN_REPLY,ASSURED,CONFIRMED&amp;lt;/tt&amp;gt;» — пакетам в полностью установленном соединении, «&amp;lt;tt&amp;gt;ct=NULL ctmark=NULL ctstate=INVALID ctstatus=NONE&amp;lt;/tt&amp;gt;» — пакету, который не удалось отнести к существующим соединениям, «&amp;lt;tt&amp;gt;ct=UNTRACKED ctmark=NULL ctstate=UNTRACKED ctstatus=NONE&amp;lt;/tt&amp;gt;» — пакету, для которого была отключена трассировка conntrack (обычно это выполняется действием NOTRACK в таблице raw.&lt;br /&gt;
&lt;br /&gt;
Таким образом, в сочетании с традиционным LOG, действие LOGMARK позволяет заносить в системный журнал исчерпывающую информацию о пакетах и соединениях.&lt;br /&gt;
&lt;br /&gt;
Заметим, что LOGMARK принимает описанные выше опции &amp;lt;tt&amp;gt;--log-prefix&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--log-level&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* '''ULOG''' — позволяет передавать информацию об обработанных пакетах специальным демонам, таким, как [http://www.netfilter.org/projects/ulogd/ ulogd]. Такой подход позволяет эффективно управлять информацией о трафике, в частности, заносить ее в базы данных, такие как MySQL, PostgreSQL или SQLite. Впоследствии эти данные могут быть проанализированы и визуализированы с помощью таких средств, как [http://software.inl.fr/trac/wiki/EdenWall/NuLog NuLog].&lt;br /&gt;
* '''NFLOG''' — более универсальный вариант ULOG, обеспечивающий передачу информации о пакете не напрямую в netlink-сокет (как это делает ULOG), а специальной подсистеме — logging backend. Например, бэкенд nfnetlink_log обеспечивает передачу данных в netlink-сокет, то есть с ним NFLOG работает аналогично ULOG.&lt;br /&gt;
* '''NFQUEUE''' — во многом похоже на ULOG, но передает специальному демону не информацию о пакете, а сам пакет целиком. Применяется, в частности, для организации работы l7-filter-userspace.&lt;br /&gt;
Например, если демон l7-filter был запущен командой&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
l7-filter -f /etc/l7-filter.conf -q 2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
то передать ему на обработку все входящие и локально сгенерированные пакеты можно командами&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -F # На всякий случай очищаем таблицу mangle&lt;br /&gt;
iptables -t mangle -A PREROUTING -j NFQUEUE --queue-num 2&lt;br /&gt;
iptables -t mangle -A OUTPUT -j NFQUEUE --queue-num 2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Опция &amp;lt;tt&amp;gt;--queue-num&amp;lt;/tt&amp;gt; позволяет указать номер очереди пакетов. Он должен быть совпадать с номером, указанным при запуске демона l7-filter (параметр &amp;lt;tt&amp;gt;-q&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* '''QUEUE''' — устаревшая версия NFQUEUE. Не имеет параметров, так как работает только с очередью номер 0.&lt;br /&gt;
&lt;br /&gt;
Выше были рассмотрены действия «общего назначения», то есть не привязанные по своей специфике к таблицам. Далее, при рассмотрении отдельных таблиц, будут описываться действия, специфичные для каждой таблицы. Термин «специфичные» надо понимать так: совсем не обязательно, что действие, специфичное для одной таблицы, будет в принципе недопустимо в другой, но в любом случае использование этого действия в других таблицах будет «плохим тоном» — ведь таблицы и действия четко разделены по назначению. Не стоит «забивать гвозди микроскопом».&lt;br /&gt;
&lt;br /&gt;
Порой эта разница бывает довольно тонкой. Например, если действие NFQUEUE передает пакеты демону l7-filter-userspace (который занимается маркировкой пакетов на основе анализа их содержимого), то правильнее будет разместить вызов такого действия в таблице mangle. Если же оно передает пакеты демону nufw (который обеспечивает разрешение или запрещение трафика на основе авторизации пользователя), то логичнее разместить это действие в таблице filter.&lt;br /&gt;
&lt;br /&gt;
Кроме того, существуют и ограничения, наложенные непосредственно в коде iptables. Например, действия таблицы nat жестко защищены от употребления за ее пределами. Другой пример: действие REDIRECT можно применять только в цепочках PREROUTING и OUTPUT таблицы nat, то есть ограничения могут быть не только на таблицы, но на отдельные цепочки. Данная статья ни в коем случае не претендует на полноту изложения, поэтому, перед тем как использовать какое-либо действие, обязательно ознакомьтесь с документацией, прилагающейся к вашей версии iptables.&lt;br /&gt;
&lt;br /&gt;
=== Терминальные и нетерминальные действия ===&lt;br /&gt;
&lt;br /&gt;
* ''Терминальными'' называются действия, которые прерывают прохождение пакета через текущую базовую цепочку. То есть если к пакету в рамках некоторого правила было применено терминальное действие, он уже не проверяется на соответствие всем следующим правилам в этой цепочке (и в тех цепочках, из которых она была вызвана, если это пользовательская цепочка). Терминальными являются все действия, специфичные для таблиц filter и nat. Из приведенных выше в этом разделе — ACCEPT, DROP, REJECT, NFQUEUE, QUEUE.&lt;br /&gt;
Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix &amp;quot;IN HTTP: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Второе из приведенных правил (логгирование) никогда не будет срабатывать, так как все пакеты, удовлетворяющие этому критерию (входящие TCP-пакеты на порт 80), будут пропущены по первому из этих правил, и до второго просто не дойдут.&lt;br /&gt;
&lt;br /&gt;
* ''Нетерминальными'', соответственно, являются действия, ''не'' прерывающие процесс прохождения пакета через цепочки. Нетерминальными являются действия, специфичные для таблицы mangle, а из перечисленных выше — LOG, ULOG и NFLOG.&lt;br /&gt;
Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j LOG --log-prefix &amp;quot;IN HTTP: &amp;quot;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь все входящие на TCP-порт 80 пакеты будут сначала заноситься в лог, и только потом пропускаться.&lt;br /&gt;
&lt;br /&gt;
Действие RETURN с точки зрения такой классификации занимает промежуточное положение — оно может прервать прохождение пакета через отдельную цепочку (или несколько цепочек, если для перехода в них использовалась опция &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt;, а не &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt;), но совсем не обязательно, чтобы это приводило к завершению обработки пакета в рамках текущей базовой цепочки.&lt;br /&gt;
&lt;br /&gt;
== Таблицы ==&lt;br /&gt;
[[Файл:Netfilter-diagram-rus.png|thumb|400px|Путь проверки пакета в системе netfilter]]&lt;br /&gt;
&lt;br /&gt;
=== Таблица mangle ===&lt;br /&gt;
Данная таблица предназначена для операций по классификации и маркировке пакетов и соединений, а также модификации заголовков пакетов (поля TTL и TOS).&lt;br /&gt;
&lt;br /&gt;
==== Цепочки ====&lt;br /&gt;
Таблица mangle содержит следующие цепочки:&lt;br /&gt;
* '''PREROUTING''' — позволяет модифицировать пакет ''до'' принятия решения о маршрутизации.&lt;br /&gt;
* '''INPUT''' — позволяет модифицировать пакет, предназначенный самому хосту.&lt;br /&gt;
* '''FORWARD''' — цепочка, позволяющая модифицировать транзитные пакеты.&lt;br /&gt;
* '''OUTPUT''' — позволяет модифицировать пакеты, исходящие от самого хоста.&lt;br /&gt;
* '''POSTROUTING''' — дает возможность модифицировать все исходящие пакеты, как сгенерированные самим хостом, так и транзитные.&lt;br /&gt;
&lt;br /&gt;
Заметим, что все цепочки таблицы mangle пакеты проходят раньше, чем одноименные цепочки таблиц nat и filter. Это позволяет классифицировать и маркировать пакеты и соединения в цепочках этой таблицы. Впоследствии эти маркировки могут быть использованы в цепочках двух других таблиц при принятии решений о фильтрации и трансляции адресов.&lt;br /&gt;
&lt;br /&gt;
==== Действия ====&lt;br /&gt;
Допустимыми действиями в этой таблице являются:&lt;br /&gt;
* '''TOS''' — изменяет поле TOS данного пакета. Поддерживаются опции &amp;lt;tt&amp;gt;--set-tos&amp;lt;/tt&amp;gt; (установить поле TOS в заданное значение), а также &amp;lt;tt&amp;gt;--and-tos&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--or-tos&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--xor-tos&amp;lt;/tt&amp;gt;, комбинирующие текущее значение поля TOS с заданным в правиле значением по соответствующему логическому правилу и записывающие результат как новое значения поля TOS.&lt;br /&gt;
&lt;br /&gt;
Кроме того, опция &amp;lt;tt&amp;gt;--set-tos&amp;lt;/tt&amp;gt; поддерживает расширенный синтаксис &amp;lt;tt&amp;gt;--set-tos ''значение''/''маска''&amp;lt;/tt&amp;gt;. При использовании такого синтаксиса в исходном значении TOS пакета зануляются те биты, которые установлены в маске, затем полученное число XOR’ится с указанным в параметрах значением, и полученная величина записывается в поле TOS. Используя синтаксис языка C, это можно записать так: &amp;lt;tt&amp;gt;NEW_TOS = (OLD_TOS &amp;amp; ~''маска'') ^ ''значение''&amp;lt;/tt&amp;gt;. Заметим, что в случае с IPv6 операция отрицания маски не&amp;amp;nbsp;выполняется (то есть в исходном значении зануляются те биты, которые в маске ''не&amp;amp;nbsp;установлены''), хотя это и не&amp;amp;nbsp;отражено в документации.&lt;br /&gt;
&lt;br /&gt;
Также, в случае IPv4 (iptables) в параметре &amp;lt;tt&amp;gt;--set-tos&amp;lt;/tt&amp;gt; вы можете указать одно из допустимых символьных обозначений: Minimize-Delay (TOS 16, требование минимальной задержки), Maximize-Throughput (TOS 8, требование максимальной пропускной способности), Maximize-Reliability (TOS 4, максимальная надежность доставки), Minimize-Cost (TOS 2, минимальная стоимость), Normal-Service (TOS 0, специальные требования отсутствуют). В ip6tables использование этих обозначений не&amp;amp;nbsp;запрещено, однако в этом случае более корректным будет использование действия DSCP (см. ниже).&lt;br /&gt;
&lt;br /&gt;
Практический пример использования действия TOS представлен в описании критерия connbytes.&lt;br /&gt;
&lt;br /&gt;
Отметим, что, в соответствии с современными соглашениями, поле TOS в заголовке IP-пакета разделяется на две части:DSCP (первые шесть бит кода TOS) и ECN (последние два бита TOS). Современные версии netfilter/iptables не&amp;amp;nbsp;поддерживают изменение значений ECN в IP-заголовках, поэтому фактически действие TOS работает только с полем DSCP, отличаясь от действия DSCP (см. чуть ниже) разве что интерфейсом (фактически, синтаксисом).&lt;br /&gt;
&lt;br /&gt;
* '''DSCP''' — изменяет поле DSCP (класс DiffServ) в заголовке пакета. Поддерживаются опции &amp;lt;tt&amp;gt;--set-dscp&amp;lt;/tt&amp;gt; (позволяет задать значение DSCP числом) и &amp;lt;tt&amp;gt;--set-dscp-class&amp;lt;/tt&amp;gt; (позволяет установить заданный класс DiffServ, например, EF или AF13).&lt;br /&gt;
* '''TTL''' — изменяет поле TTL данного пакета (работает только с IPv4, для IPv6 используется действие HL). Поддерживаются опции &amp;lt;tt&amp;gt;--ttl-set&amp;lt;/tt&amp;gt; (установить поле TTL в заданное значение), а также &amp;lt;tt&amp;gt;--ttl-inc&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--ttl-dec&amp;lt;/tt&amp;gt; (соответственно увеличить или уменьшить текущее значение поля TTL на заданное значение). Допустимые значения TTL — от 0 до 255. При достижении TTL=0 пакет уничтожается.&lt;br /&gt;
&lt;br /&gt;
В качестве полезного примера использования этого действия можно привести команду&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -I PREROUTING -j TTL --ttl-inc 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
делающую наш шлюз невидимым для большинства трассировщиков.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что автоматически выполняемая сетевым стеком ядра операция уменьшения TTL на единицу и проверки на равенство нулю выполняется ''после'' цепочки PREROUTING, но ''до'' цепочки FORWARD. Таким образом, переместив это правило в цепочку FORWARD, вы обеспечите «невидимость» следующего за вами шлюза.&lt;br /&gt;
&lt;br /&gt;
Другой полезный пример — выравнивание TTL на выходе в Интернет (интерфейс eth0)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -I POSTROUTING -o eth0 -j TTL --ttl-set 64&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Некоторые домашние провайдеры, пытаясь бороться с нелегальной перепродажей канала их клиентами, блокируют доступ тем клиентам, на выходе которых замечены пакеты с разными значениями TTL, потому что этот факт косвенно указывает на наличие у клиента внутренней подсети. Предложенное правило, будучи применено на шлюзе такой подсети, делает ее детекцию по TTL крайне затруднительной.&lt;br /&gt;
&lt;br /&gt;
'''Будьте очень осторожны''' с правилами, которые увеличивают или, что особенно опасно, напрямую задают значение TTL, так как, при наличии определенных ошибок маршрутизации, это может привести к появлению «бессмертных» пакетов, которые будут долго циркулировать между одними и теми же узлами, захламляя канал и затрудняя работу сетевого оборудования.&lt;br /&gt;
&lt;br /&gt;
* '''HL''' — изменяет поле Hop Limit в заголовке IPv6-пакета. Является аналогом IPv4-действия TTL и поддерживает те же операции: &amp;lt;tt&amp;gt;--hl-set&amp;lt;/tt&amp;gt; (установить поле HL в заданное значение), а также &amp;lt;tt&amp;gt;--hl-inc&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--hl-dec&amp;lt;/tt&amp;gt; (соответственно увеличить или уменьшить текущее значение поля HL на заданное значение).&lt;br /&gt;
* '''MARK''' — устанавливает или изменяет маркировку пакета. Поддерживает опции &amp;lt;tt&amp;gt;--set-mark&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--and-mark&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--or-mark&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--xor-mark&amp;lt;/tt&amp;gt;, аналогичные опциям действия TOS. Важно понимать, что маркировка пакета не хранится в его заголовке или содержимом, и поэтому действует только в пределах одного хоста. Также нужно отличать маркировку пакета от маркировки соединения. Маркировка пакетов может применяться для их дальнейшей обработки фаерволом (критерии mark и connmark), а также для классификации трафика фильтрами шейпинговой подсистемы tc (лексема handle ''mark'' fw).&lt;br /&gt;
* '''CONNMARK''' — устанавливает или изменяет маркировку соединения. Поддерживает те же опции, что и MARK, а также дополнительные опции &amp;lt;tt&amp;gt;--restore-mark&amp;lt;/tt&amp;gt; (копирует маркировку соединения в маркировку пакета) и &amp;lt;tt&amp;gt;--save-mark&amp;lt;/tt&amp;gt; (копирует маркировку пакета в маркировку соединения).&lt;br /&gt;
* '''CLASSIFY''' — устанавливает CBQ-класс пакета для его последующей обработки шейпером (опция &amp;lt;tt&amp;gt;--set-class&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* '''TCPMSS''' — устанавливает максимальный размер TCP-сегмента. Бывает крайне полезной при использовании VPN-подключения&amp;lt;ref&amp;gt;Обычно проблемы с пониженным MTU в Ethernet-сетях возникают как раз из-за VPN-туннелей&amp;lt;/ref&amp;gt; в том случае, если VPN-сервер блокирует ICMP-сообщения destination unreachable/fragmentation needed (тип 3, код 4), тем самым нарушая работу процедуры технологии Path MTU discovery.&lt;br /&gt;
&lt;br /&gt;
С точки зрения клиента, эта проблема выглядит так: пинги проходят нормально, но при попытке открыть какую-либо веб-страницу, браузер «подвисает». При этом с самого шлюза все работает нормально. В этом случае достаточно применить на шлюзе следующую команду&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
которая обеспечит автоматическую установку размера сегмента в TCP-заголовках SYN- и SYN,ACK-пакетов в соответствии с минимальным из известных нашему шлюзу значений MTU на пути следования пакета. Например, если пакет пришел с интерфейса eth0 (MTU 1500) и уходит через интерфейс ppp0 (MTU 1492), а суммарный размер заголовков сетевого и транспортного  уровней составляет 40 байт (20 байт TCP и 20 байт IP), то целесообразно установить MSS равным 1452 байтам.&lt;br /&gt;
&lt;br /&gt;
Помимо возможности автоматического выбора TCP MSS, вы можете задать необходимое значение и вручную, используя параметр &amp;lt;tt&amp;gt;--set-mss ''значение''&amp;lt;/tt&amp;gt;. Это бывает полезным в том случае, если вам заведомо известно, что дальше на маршруте встречаются участки с еще меньшим MTU, а пограничные сервера этих участков опять же блокируют ICMP destination unreachable/fragmentation needed.&lt;br /&gt;
* '''ECN''' — обеспечивает обнуление ECN-битов (флаги CWR и ECE) в TCP-заголовке (единственная опция &amp;lt;tt&amp;gt;--ecn-tcp-remove&amp;lt;/tt&amp;gt;). Может использоваться только в IPv4-модуле (iptables, но не&amp;amp;nbsp;ip6tables) для TCP-пакетов (&amp;lt;tt&amp;gt;-p tcp&amp;lt;/tt&amp;gt;). Данное действие предназначено для защиты пакетов от ECN blackholes (маршрутизаторов, которые некорректно обрабатывают пакеты с установленными в TCP-заголовке ECN-битами) — рекомендуется применять это действие ко всем пакетам, уходящим на такие маршрутизаторы. Обратите внимание, что данное действие никак не&amp;amp;nbsp;влияет на ECN-биты в IP-заголовках (последние два бита поля TOS).&lt;br /&gt;
&lt;br /&gt;
Кроме того, данное действие поддерживает три потенциально опасные опции, не отраженные в документации: &amp;lt;tt&amp;gt;--ecn-tcp-cwr&amp;lt;/tt&amp;gt; (установка значения бита CWR в TCP-заголовке, 0 или 1), &amp;lt;tt&amp;gt;--ecn-tcp-ece&amp;lt;/tt&amp;gt; (установка значения бита ECE в TCP-заголовке, 0 или 1) и &amp;lt;tt&amp;gt;--ecn-ip-ect&amp;lt;/tt&amp;gt; (установка значения ECT codepoint в IPv4-заголовке, от 0 до 3). Использование этих опций настолько опасно, что они не отражены даже во встроенной справке iptables (&amp;lt;tt&amp;gt;iptables -j ECN -h&amp;lt;/tt&amp;gt;) — их можно увидеть, только изучив [http://git.netfilter.org/cgi-bin/gitweb.cgi?p=iptables.git;a=blob;f=extensions/libipt_ECN.c исходный код]. Без крайней необходимости применять их не рекомендуется.&lt;br /&gt;
* '''TCPOPTSTRIP''' — выполняет удаление заданных TCP-опций из заголовка TCP-пакета (единственный параметр &amp;lt;tt&amp;gt;--strip-options ''значение''[,''значение''[,...]]&amp;lt;/tt&amp;gt;). Удаляемые опции могут быть указаны через их номера (согласно [http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml списку на сайте IANA]) или в виде символьных обозначений (список обозначений, поддерживаемых в вашей версии iptables можно посмотреть, выполнив команду &amp;lt;tt&amp;gt;iptables -j TCPOPTSTRIP -h&amp;lt;/tt&amp;gt;). Разумеется, данное действие допустимо только для протокола TCP (&amp;lt;tt&amp;gt;-p tcp&amp;lt;/tt&amp;gt;). Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -A POSTROUTING -p tcp -j TCPOPTSTRIP --strip-options timestamp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
обеспечит удаление штампов времени (RFC 1323). С одной стороны, такое правило будет препятствовать удаленному злоумышленнику определить аптайм нашего хоста, а также тех хостов, маршрут от которых до злоумышленника проходит через наш хост. С другой стороны, блокирование штампов времени может негативно сказаться на быстродействии сети, особенно если вы используете подключения на скорости 100&amp;amp;nbsp;МБит и выше. Заметим также, что если вам нужно управлять использованием именно штампов времени для TCP IPv4-пакетов, исходящих от вашего хоста, вы можете воспользоваться sysctl-параметром net.ipv4.tcp_timestamps (1 — штампы включены, 0 — выключены).&lt;br /&gt;
* '''TPROXY''' — реализует механизм полностью прозрачного проксирования. Такой подход отличается от традиционно используемого «прозрачного» проксирования (действие REDIRECT таблицы nat) тем, что заголовок пакета никак не&amp;amp;nbsp;модифицируется, в том числе не&amp;amp;nbsp;заменяется IP-адрес назначения (при традиционном прозрачном проксировании он заменяется на адрес проксирующего хоста). Кроме того, полностью прозрачное проксирование является прозрачным с точки зрения обеих общающихся сторон. Например, при проксировании обращений некоторой подсети клиентов к серверам из другой подсети, можно сделать так, чтобы не&amp;amp;nbsp;только клиенты считали, что обращаются напрямую к серверам, но и сервера «видели» настоящие исходные адреса клиентов и могли бы устанавливать с ними обратные соединения (например, в случае активного режима FTP). При традиционном же «прозрачном» проксировании, сервера могут видеть только адрес прокси-сервера.&lt;br /&gt;
&lt;br /&gt;
TPROXY позволяет перенаправить транзитный пакет на локальный сокет типа AF_INET (iptables) или AF_INET6 (ip6tables), заданный портом, а также может промаркировать пакет таким образом, чтобы система марушрутизации (iproute2) не&amp;amp;nbsp;позволила пакету покинуть наш хост. Разумеется, поддержка полностью прозрачного проксирования должна быть реализована и в самом прокси-сервере. В частности, прозрачное проксирование IPv4 HTTP [http://wiki.squid-cache.org/Features/Tproxy4 поддерживается] прокси-сервером Squid начиная с версии 3.1.&lt;br /&gt;
&lt;br /&gt;
В качестве примера можно привести простейший случай конфигурации iptables и iproute2 для обеспечения полностью прозрачного проксирования IPv4 HTTP.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Добавляем принудительную локальную маршрутизацию для всех адресов в таблицу 120&lt;br /&gt;
ip route add local 0.0.0.0/0 dev lo table 120&lt;br /&gt;
# Все пакеты, имеющие соответствующую маркировку, направляем в эту таблицу&lt;br /&gt;
ip rule add fwmark 120 table 120&lt;br /&gt;
# Выполняем проксирование для новых соединений&lt;br /&gt;
iptables -t mangle -I PREROUTING -p tcp --dport 80 -j TPROXY --tproxy-mark 120 --on-port 3129&lt;br /&gt;
# Перехватываем, маркируем и пропускаем пакеты, принадлежащие проксируемым соединениям&lt;br /&gt;
iptables -t mangle -N proxypackets&lt;br /&gt;
iptables -t mangle -A proxypackets -j MARK --set-mark 120&lt;br /&gt;
iptables -t mangle -A proxypackets -j ACCEPT&lt;br /&gt;
# Такие пакеты можно выделять с помощью критерия socket&lt;br /&gt;
iptables -t mangle -I PREROUTING -m socket -j proxypackets&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Таким образом, пакеты, перехваченные TPROXY-правилом, маркируются и направляются на локальный сокет (порт 3129), который должен прослушиваться специально сконфигурированным прокси-сервером (в случае Squid, в файл конфигурации &amp;lt;tt&amp;gt;squid.conf&amp;lt;/tt&amp;gt; нужно добавить строку &amp;lt;tt&amp;gt;http_port 3129 tproxy&amp;lt;/tt&amp;gt;). Все пакеты, принадлежащие уже проксируемым соединениям, перехватываются правилом с критерием socket (этот критерий позволяет определить, существует ли на нашем хосте сокет, связанный с данным пакетом), маркируются и немедленно пропускаются. Отметим, что последнее правило будет обрабатываться раньше, чем правило с TPROXY, так как параметр &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; обеспечивает вставку правил ''в начало'' цепочки, и при последовательном добавлении нескольких правил с этим параметром, порядок добавленных правил будет обратным порядку их ввода.&lt;br /&gt;
&lt;br /&gt;
=== Таблица nat ===&lt;br /&gt;
&lt;br /&gt;
Предназначена для операций stateful-преобразования сетевых адресов и портов обрабатываемых пакетов.&lt;br /&gt;
&lt;br /&gt;
==== Цепочки ====&lt;br /&gt;
&lt;br /&gt;
Таблица nat содержит следующие цепочки:&lt;br /&gt;
* '''PREROUTING''' — в эту цепочку пакеты попадают ''до'' принятия решения о маршрутизации. По сути, термин «решение о маршрутизации» подразумевает деление трафика на входящий (предназначенный самому хосту) и транзитный (идущий через этот хост на другие хосты). Именно на данном этапе нужно проводить операции проброса (DNAT, REDIRECT, NETMAP).&lt;br /&gt;
* '''OUTPUT''' — через эту цепочку проходят пакеты, сгенерированные процессами самого хоста. На данном этапе при необходимости можно повторить операции проброса, так локально сгенерированные пакеты ''не'' проходят цепочку PREROUTING и ''не'' обрабатываются ее правилами. См. пример для действия DNAT ниже.&lt;br /&gt;
* '''POSTROUTING''' — через эту цепочку проходят все исходящие пакеты, поэтому именно в ней целесообразно проводить операции маскарадинга (SNAT и MASQUERADE).&lt;br /&gt;
&lt;br /&gt;
==== Действия ====&lt;br /&gt;
&lt;br /&gt;
Допустимыми действиями в таблице nat являются:&lt;br /&gt;
* '''MASQUERADE''' — подменяет адрес источника для исходящих пакетов адресом того интерфейса, с которого они исходят, то есть осуществляет маскарадинг. Такая операция позволяет, например, предоставлять доступ в Интернет целым локальным сетям через один шлюз.&lt;br /&gt;
&lt;br /&gt;
Допустим, у нас есть локальная сеть 192.168.1.0/255.255.255.0 с несколькими компьютерами, имеющими адреса 192.168.1.2, 192.168.1.3 и т. д. Адрес 192.168.1.1 имеет внутренний (подключенный к локальной сети) сетевой интерфейс шлюза, назовем этот интерфейс eth1. Другой его интерфейс, назовем его eth0, подключен к сети Интернет и имеет адрес, допустим, 208.77.188.166. Тогда, чтобы обеспечить выход хостов из этой локальной сети в Интернет, на шлюзе достаточно выполнить следующие команды&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик&lt;br /&gt;
iptables -F FORWARD # На всякий случай очистим цепочку FORWARD&lt;br /&gt;
# Разрешаем проходить пакетам по уже установленным соединениям&lt;br /&gt;
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
# Разрешаем исходящие соединения из локальной сети к интернет-хостам&lt;br /&gt;
iptables -A FORWARD -m conntrack --ctstate NEW -i eth1 -s 192.168.1.0/24 -j ACCEPT&lt;br /&gt;
iptables -P FORWARD DROP # Весь остальной транзитный трафик — запрещаем.&lt;br /&gt;
iptables -t nat -F POSTROUTING # На всякий случай очистим цепочку POSTROUTING таблицы nat&lt;br /&gt;
# Маскарадим весь трафик, идущий через eth0&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь, если один из хостов локальной сети, например, 192.168.1.2, попытается связаться с одним из интернет-хостов, например, 199.204.44.194 (kernel.org), при проходе его пакетов через шлюз, их исходный адрес будет подменяться на внешний адрес шлюза, то есть 208.77.188.166. С точки зрения удаленного хоста (kernel.org), это будет выглядеть, как будто с ним связывается непосредственно сам шлюз. Когда же удаленный хост начнет ответную передачу данных, он будет адресовать их именно шлюзу, то есть 208.77.188.166. Однако, на шлюзе адрес назначения этих пакетов будет подменяться на 192.168.1.2, после чего пакеты будут передаваться настоящему получателю. Для такого обратного преобразования никаких дополнительных правил указывать не нужно — это будет делать все та же операция MASQUERADE. Простота трансляции сетевых адресов является одним из важнейших достоинств stateful-фильтрации.&lt;br /&gt;
&lt;br /&gt;
Если же такой трансляции не производить, удаленный хост просто не сможет ответить на адрес 192.168.1.2, так как адресные пространства локальных сетей изолировано от адресного пространства Интернета. В мире могут существовать миллионы локальных сетей 192.168.1.0/255.255.255.0, и в каждой может быть свой хост 192.168.1.2. Эти сети могут и не быть связаны с Интернетом. Но если они с ним связаны — то только благодаря механизмам трансляции сетевых адресов.&lt;br /&gt;
&lt;br /&gt;
* '''SNAT''' (Source Network Address Translation) — работает аналогично MASQUERADE, однако позволяет указать адрес «внешнего» интерфейса (опция &amp;lt;tt&amp;gt;--to-source&amp;lt;/tt&amp;gt;). Такой подход позволяет экономить процессорное время шлюза, так как в случае с MASQUERADE для каждого пакета адрес внешнего интерфейса определяется заново. Таким образом, если в предыдущем примере внешний адрес шлюза 208.77.188.166 является статическим (то есть никогда не меняется), команду&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
целесообразно заменить на&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.166&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Однако, в случае, если внешний адрес шлюза динамический, то есть меняется в начале каждой новой сессии, правильнее будет использовать именно MASQUERADE.&lt;br /&gt;
&lt;br /&gt;
Дополнительно, если на внешнем интерфейсе шлюза «висит» несколько статических адресов, например, 208.77.188.166, 208.77.188.167 и 208.77.188.168, можно использовать балансировку между этими адресами:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.166-208.77.188.168&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь для каждого нового соединения адрес для подмены будет выбираться случайным образом.&lt;br /&gt;
&lt;br /&gt;
* '''DNAT''' (Destination Network Address Translation) — подменяет адрес назначения для входящих пакетов, позволяя «пробрасывать» адреса или отдельные порты внутрь локальной сети.&lt;br /&gt;
&lt;br /&gt;
Возвращаясь к предыдущему примеру, предположим, что нам нужно «пробросить» внешний адрес шлюза 208.77.188.166 на хост 192.168.1.2, то есть все, кто будет обращаться по внешнему адресу шлюза 208.77.188.166, должны попадать на хост 192.168.1.2. Это достигается следующими командами:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Разрешаем шлюзу передавать транзитный трафик&lt;br /&gt;
sysctl net.ipv4.ip_forward=1&lt;br /&gt;
iptables -t nat -F PREROUTING # На всякий случай очистим цепочку PREROUTING таблицы nat&lt;br /&gt;
# Пробрасываем 208.77.188.166 на 192.168.1.2&lt;br /&gt;
iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2&lt;br /&gt;
iptables -F FORWARD # На всякий случай очистим цепочку FORWARD&lt;br /&gt;
# Разрешаем проходить пакетам по уже установленным соединениям&lt;br /&gt;
iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
# Разрешаем входящие соединения к 192.168.1.2&lt;br /&gt;
iptables -A FORWARD -m conntrack --ctstate NEW -d 192.168.1.2 -j ACCEPT&lt;br /&gt;
iptables -P FORWARD DROP # Весь остальной транзитный трафик — запрещаем.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В лучших традициях stateful-фаерволинга, подменяются не только адреса назначения для входящих пакетов (208.77.188.166 -&amp;gt; 192.168.1.2), но и адреса источника для исходящих пакетов (192.168.1.2 -&amp;gt; 208.77.188.166), поэтому для интернет-хостов создается полное впечатление, что они общаются именно с 208.77.188.166.&lt;br /&gt;
&lt;br /&gt;
Однако, при всей своей простоте и наглядности, этот пример имеет два недостатка. Во-первых, из нашей локальной сети 192.168.1.0/24 адрес 208.77.188.166 может быть недоступен, так как 192.168.1.2, увидев, что запрос исходит из его сети, может отправить ответ непосредственно отправителю (например, 192.168.1.3), минуя сам шлюз. Отправитель же будет ждать ответа от 208.77.188.166, и просто проигнорирует ответ от 192.168.1.2. Впрочем, эта проблема легко исправляется добавлением SNAT’а для пробрасываемых пакетов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -d 192.168.1.2 -s 192.168.1.0/24 -j SNAT --to-source 192.168.1.1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь, с точки зрения 192.168.1.2, к нему будет обращаться только сам шлюз (192.168.1.1), поэтому ответ также пойдет через шлюз, где будет корректно оттранслирован. Такое решение тоже имеет недостаток — подмена исходного адреса пакета приводит к тому, что компьютер, на который мы пробрасываем соединение, не может определить реального инициатора соединения. Чтобы уменьшить «вредность» этого правила, в него добавлена опция «-s 192.168.1.0/24», которая ограничивает применение этого правила только пакетами из локальной сети. Таким образом, соединения из локальной сети будут выглядеть как соединения, инициированные шлюзом, а соединения из внешней сети будут иметь свои оригинальные адреса.&lt;br /&gt;
&lt;br /&gt;
Вторым недостатком предложенного примера является некорректная обработка запросов с самого шлюза. Ведь пакеты, генерируемые локальными процессами, не проходят цепочку PREROUTING. Поэтому правило DNAT нужно также добавить и в цепочку OUTPUT таблицы nat:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A OUTPUT -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Разумеется, исходящие соединения к 192.168.1.2 и ответы на них должны быть разрешены соответственно в цепочках OUTPUT и INPUT таблицы filter. Самый простой способ сделать это —&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
# Разрешаем входящие пакеты по уже установленным соединениям&lt;br /&gt;
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP # Все остальные входящие пакеты — запрещаем&lt;br /&gt;
iptables -F OUTPUT # Очищаем цепочку OUTPUT&lt;br /&gt;
iptables -P OUTPUT ACCEPT # Разрешаем исходящие пакеты безо всяких ограничений&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Кроме того, при помощи действия DNAT можно пробрасывать не только сразу весь IP-адрес, но и отдельные TCP- или UDP-порты. Например, если в предыдущем примере мы в каждое из правил&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2&lt;br /&gt;
iptables -t nat -A POSTROUTING -d 192.168.1.2 -s 192.168.1.0/24 -j SNAT --to-source 192.168.1.1&lt;br /&gt;
iptables -t nat -A OUTPUT -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
добавим&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-p tcp --dport 80&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
то мы «пробросим» не сам адрес 208.77.188.166, а только его TCP-порт 80 (HTTP). Обращения на все остальные TCP- и UDP-порты, а также ICMP-пакеты, поступившие на адрес 208.77.188.166, будут обрабатываться шлюзом, и лишь входящие TCP-соединения на порт 80 будут передаваться на 192.168.1.2.&lt;br /&gt;
&lt;br /&gt;
Как и SNAT, DNAT поддерживает указание диапазонов адресов для подмены. Таким образом можно, например, балансировать нагрузку между несколькими серверами.&lt;br /&gt;
&lt;br /&gt;
* '''REDIRECT''' — подменяет номер порта в TCP- или UDP-пакете, а также подменяет адрес назначения на свой собственный. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
позволяет «завернуть» все исходящие из локальной сети TCP-соединения на порт 80, на TCP-порт 8080 шлюза. Если этот порт обслуживается специально настроенным прокси-сервером, то можно организовать «прозрачное проксирование» — клиенты из локальной сети даже не будут подозревать, что их запросы идут через прокси-сервер. Разумеется, входящие соединения из локалки на TCP-порт 8080 должны быть разрешены в таблице filter.&lt;br /&gt;
&lt;br /&gt;
Другой полезный пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -i eth0 -s 213.180.0.0/16 \&lt;br /&gt;
    -p tcp --dport 80 -j REDIRECT --to-port 8000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
«заворачивает» все входящие из Интернета, а точнее подсети 213.180.0.0/255.255.0.0 TCP-соединения на порт 80, переадресуя их на порт 8000 того же сервера (где, например, может работать специальный веб-сервер). Как обычно, входящие соединения на TCP-порт 8000 должны быть разрешены в таблице filter.&lt;br /&gt;
&lt;br /&gt;
* '''SAME''' — в зависимости от цепочки (PREROUTING или POSTROUTING) может работать как DNAT или SNAT. Однако, при указании (в параметре &amp;lt;tt&amp;gt;--to-ip&amp;lt;/tt&amp;gt;) одного или нескольких диапазонов IP-адресов, определяет для каждого нового соединения подставляемый адрес не случайно, а базируясь на IP-адресе клиента. Таким образом, адрес для подмены остается постоянным для одного и того же клиента при повторных соединениях (что ''не'' выполняется для обычных DNAT/SNAT). В некоторых случаях это бывает важным. Примечание: в соответсвии с iptables-extensions's man page действие SAME убрано и заменено на опцию --persistent для действий '''DNAT'''/'''SNAT'''.&lt;br /&gt;
* '''NETMAP''' — позволяет «пробросить» целую сеть. Например, для шлюза, стоящего между сетями 192.168.1.0/24 и 192.168.2.0/24 можно организовать следующий проброс:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -s 192.168.1.0/24 -d 192.168.3.0/24 -j NETMAP --to 192.168.2.2/24&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь, при обращении, например, хоста 192.168.1.3 на IP-адрес 192.168.3.2 он будет попадать на 192.168.2.2 (при условии, что такой транзитный трафик разрешен на шлюзе в цепочке FORWARD таблицы filter, а также на хостах сети 192.168.1.0/24 наш шлюз прописан в качестве шлюза для подсети 192.168.3.0/24).&lt;br /&gt;
&lt;br /&gt;
: ''Примечание: следующее действие планируется к переносу в еще не написанный раздел статьи (Устаревшие критерии и действия)''.&lt;br /&gt;
* '''MIRROR''' — довольно интересная игрушка. Меняет местами адрес источника и назначения и высылает пакет обратно. Создано исключительно для демонстрационных целей. Однако, может, например, применяться для защиты от сканирования портов — в результате атакующий сканирует свои собственные порты. Однако наличие двух встречных MIRROR’ов на двух хостах может повлечь бесконечное блуждание одних и тех же пакетов, забивающее канал. Поэтому применяйте это действие с осторожностью.&lt;br /&gt;
&lt;br /&gt;
=== Таблица filter ===&lt;br /&gt;
&lt;br /&gt;
Предназначена для фильтрации трафика, то есть разрешения и запрещения пакетов и соединений.&lt;br /&gt;
&lt;br /&gt;
==== Цепочки ====&lt;br /&gt;
&lt;br /&gt;
Таблица filter содержит следующие цепочки:&lt;br /&gt;
* '''INPUT''' — эта цепочка обрабатывает трафик, поступающий непосредственно самому хосту.&lt;br /&gt;
* '''FORWARD''' — позволяет фильтровать транзитный трафик.&lt;br /&gt;
* '''OUTPUT''' — эта цепочка позволяет фильтровать трафик, исходящий от самого хоста.&lt;br /&gt;
&lt;br /&gt;
==== Действия ====&lt;br /&gt;
&lt;br /&gt;
Допустимыми действиями в таблице filter являются:&lt;br /&gt;
* '''ACCEPT''' — пропуск пакета. Пакет покидает текущую базовую цепочку и следует дальше по потоковой диаграмме.&lt;br /&gt;
* '''REJECT''' — заблокировать пакет и сообщить его источнику об отказе. По умолчанию об отказе сообщается отправкой ответного ICMP-пакета «icmp-port-unreachable». Однако, это действие поддерживает опцию &amp;lt;tt&amp;gt;--reject-with&amp;lt;/tt&amp;gt;, позволяющую указать формулировку сообщения об отказе (возможные значения: &amp;lt;tt&amp;gt;icmp-net-unreachable&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;icmp-host-unreachable&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;icmp-proto-unreachable&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;icmp-net-prohibited&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;icmp-host-prohibited&amp;lt;/tt&amp;gt;). Для протокола TCP поддерживается отказ в форме отправки RST-пакета (&amp;lt;tt&amp;gt;--reject-with tcp-reset&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* '''DROP''' — заблокировать пакет, не сообщая источнику об отказе. Более предпочтительна при фильтрации трафика на интерфейсах, подключенных к интернету, так как понижает информативность сканирования портов хоста злоумышленниками.&lt;br /&gt;
&lt;br /&gt;
Также определенный интерес представляют действия, предоставляемые модулями [http://xtables-addons.sourceforge.net/ xtables-addons] (в настоящее время этот проект уже [http://packages.debian.org/squeeze/xtables-addons-common включен] в Debian testing). Некоторые из них:&lt;br /&gt;
* '''STEAL''' — аналогично DROP, но в случае использования в цепочке OUTPUT при блокировании исходящего пакета не сообщает об ошибке приложению, пытавшемуся отправить этот пакет.&lt;br /&gt;
* '''TARPIT''' — «подвесить» TCP-соединение. Используется лишь в самых крайних случаях, например, при борьбе с DoS-атаками. Отвечает на входящее соединение, после чего уменьшает размер фрейма до нуля, блокируя возможность передачи данных. Соединение будет «висеть» в таком состоянии пока не истечет тайм-аут на атакующей стороне (обычно 20—30 минут). При этом на такое соединение расходуются системные ресурсы атакующей стороны (процессорное время и оперативная память), что может быть весьма ощутимо при значительном количестве соединений. В случае правильного использования действия TARPIT ресурсы атакуемой стороны практически не расходуются.&lt;br /&gt;
Под правильным применением понимается предотвращение обработки таких соединений подсистемой conntrack, так как в противном случае будут расходоваться системные ресурсы самого атакуемого хоста. Например, перед добавлением правила блокирования порта&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p tcp --dport 25 -j TARPIT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
обязательно добавляйте в таблицу raw соответствующее правило&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t raw -I PREROUTING -p tcp --dport 25 -j NOTRACK&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
предотвращающее обработку блокируемых соединений подсистемой conntrack.&lt;br /&gt;
* '''DELUDE''' — создать видимость открытого TCP-порта. На SYN-пакеты отвечает пакетами SYN/ACK, на все прочие пакеты отвечает RST. Очень полезно для введения в заблуждение злоумышленника, сканирующего порты вашего хоста.&lt;br /&gt;
* '''CHAOS''' — для каждого нового TCP-соединения случайно выбрать одно из двух действий. Первое из них — REJECT, второе, в зависимости от выбранной опции, либо TARPIT (&amp;lt;tt&amp;gt;--tarpit&amp;lt;/tt&amp;gt;), либо DELUDE (&amp;lt;tt&amp;gt;--delude&amp;lt;/tt&amp;gt;). В частности, при использовании действия &amp;lt;tt&amp;gt;CHAOS --delude&amp;lt;/tt&amp;gt; для всех неиспользуемых портов, сканирующий ваши порты злоумышленник получит совершенно неверную информацию о состоянии ваших портов. В случае с &amp;lt;tt&amp;gt;CHAOS --tarpit&amp;lt;/tt&amp;gt; ситуация усугубится еще и «подвисающими» соединениями.&lt;br /&gt;
&lt;br /&gt;
Особо заметим, что все действия, перечисленные в качестве допустимых в таблице filter, можно применять в любой из цепочек любой из таблиц (конечно, с разумными ограничениями — например, не стоит ставить действия TARPIT, CHAOS и DELUDE для собственных исходящих пакетов). Однако эти действия предназначены именно для фильтрации, и применение их за пределами таблицы filter является дурным тоном. Как и, например, применение действий, специфичных для таблицы mangle, в таблицах filter и nat.&lt;br /&gt;
&lt;br /&gt;
=== Таблица security ===&lt;br /&gt;
&lt;br /&gt;
Предназначена для изменения маркировки безопасности (меток SELinux) пакетов и соединений.&lt;br /&gt;
&lt;br /&gt;
==== Цепочки ====&lt;br /&gt;
&lt;br /&gt;
Аналогичны цепочкам таблицы filter:&lt;br /&gt;
* '''INPUT''' — эта цепочка обрабатывает трафик, поступающий непосредственно самому хосту.&lt;br /&gt;
* '''FORWARD''' — через эту цепочку проходит транзитный трафик.&lt;br /&gt;
* '''OUTPUT''' — эта цепочка позволяет обрабатывать трафик, исходящий от самого хоста.&lt;br /&gt;
&lt;br /&gt;
Так как эта таблица появилась относительно недавно, ее редко можно увидеть на схемах следования пакетов через цепочки и таблицы netfilter'а. Поэтому стоит отметить, что все цепочки таблицы security пакеты проходят непосредственно после одноименных цепочек таблицы filter.&lt;br /&gt;
&lt;br /&gt;
==== Действия ====&lt;br /&gt;
&lt;br /&gt;
Данная таблица добавлена в ядро Linux в версии 2.6.27. Ранее операции с метками безопасности выполнялись в таблице mangle, и в целях обратной совместимости все действия, разрешенные для таблицы security, можно использовать и в таблице mangle.&lt;br /&gt;
&lt;br /&gt;
* '''SECMARK''' — устанавливает для пакета контекст безопасности SELinux (единственная допустимая опция &amp;lt;tt&amp;gt;--selctx&amp;lt;/tt&amp;gt;).&lt;br /&gt;
* '''CONNSECMARK''' — позволяет скопировать контекст безопасности SELinux с отдельного пакета на соединение в целом (опция &amp;lt;tt&amp;gt;--save&amp;lt;/tt&amp;gt;) и наоборот (опция &amp;lt;tt&amp;gt;--restore&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
=== Таблица raw ===&lt;br /&gt;
&lt;br /&gt;
Предназначена для выполнения действий с пакетами до их обработки системой conntrack.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в данной таблице не&amp;amp;nbsp;будут срабатывать критерии, которым для корректной работы необходим conntrack (это критерии conntrack, connmark, connlimit, connbytes).&lt;br /&gt;
&lt;br /&gt;
==== Цепочки ====&lt;br /&gt;
&lt;br /&gt;
* '''PREROUTING''' — в эту цепочку входящие пакеты попадают раньше, чем в любую другую из цепочек iptables, и ''до'' обработки их системой conntrack.&lt;br /&gt;
* '''OUTPUT''' — аналогично для пакетов, сгенерированных самим хостом.&lt;br /&gt;
&lt;br /&gt;
==== Действия ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- В таблице raw целесообразно применять действие '''NOTRACK''', позволяющее предотвратить обработку пакетов системой conntrack. Разумеется, применять ее стоит не ко всем пакетам подряд, а только к тем, для которых такая обработка не нужна и даже вредна. Например, к пакетам, к которым впоследствии применяется действие TARPIT (см. выше). --&amp;gt;&lt;br /&gt;
* '''NOTRACK''' — позволяет предотвратить обработку пакетов системой conntrack. Разумеется, применять его стоит не ко всем пакетам подряд, а только к тем, для которых такая обработка не нужна и даже вредна. Например, к пакетам, к которым впоследствии применяется действие TARPIT (см. выше).&lt;br /&gt;
* '''CT''' — более функциональный инструмент, добавленный в версии 2.6.34. Позволяет задать различные настройки conntrack, в соответствии с которыми будет обрабатываться соединение, открытое данным пакетом. В частности, можно:&lt;br /&gt;
:* Отключить отслеживание соединения (опция &amp;lt;tt&amp;gt;--notrack&amp;lt;/tt&amp;gt;). Таким образом, функциональность действия CT включает и функциональность NOTRACK, так что, возможно, действие NOTRACK будет объявлено устаревшим.&lt;br /&gt;
:* Задать вспомогательный модуль (conntrack helper) для данного соединения. Если раньше указать нестандартные порты для такого модуля можно было только в параметрах его загрузки (&amp;lt;tt&amp;gt;/etc/modprobe.conf&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;/etc/modprobe.d/netfilter.conf&amp;lt;/tt&amp;gt;, например, &amp;lt;tt&amp;gt;options nf_conntrack_ftp ports=2121&amp;lt;/tt&amp;gt;), то теперь это можно сделать и через правила netfilter:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t raw -I PREROUTING -p tcp --dport 2121 -j CT --helper ftp&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
:* Ограничить список событий conntrack, которые будут генерироваться для данного соединения. Например, правило&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t raw -I PREROUTING -p tcp --dport 8000 -j CT --ctevents new,destroy&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: будет предписывать для всех соединений на TCP-порт 8000 генерировать только события «открытие соединения» (NEW) и «завершение соединения» (DESTROY), игнорируя все прочие события. Полный список возможных событий: new, related, destroy, reply, assured, protoinfo, helper, mark, natseqinfo, secmark.&lt;br /&gt;
:* Задать ''зону conntrack'' для данного пакета (параметр &amp;lt;tt&amp;gt;--zone&amp;lt;/tt&amp;gt;). Механизм зон conntrack позволяет корректно отслеживать, фильтровать и NAT'ить соединения даже в том случае, если хост подключен к нескольким сетям, использующим одинаковые пространства имен, через различные интерфейсы (например, интерфейсы eth0 и eth1 подключены к двум разным сетям, но обе эти сети используют пространство 192.168.0.0/24). Традиционно, для идентификации соединений conntrack использует кортежи (tuples) — набор значений в который входят адреса и порты (в случае ICMP — типы и коды ICMP) источника и назначения при передаче данных в прямом и обратном направлении. Очевидно, что при наличии нескольких подсетей с одинаковыми адресными пространствами, возможно возникновение путаницы, когда сразу нескольким соединениям ставится в соответствие одна и та же запись в таблице соединений. Чтобы избежать такой ситуации, в кортеж был добавлен идентификатор зоны conntrack — целое число, которое можно устанавливать через специальное правило в таблице raw в зависимости от входящего/исходящего интерфейса (как уже говорилось выше, цепочки таблицы raw пакеты проходят еще до обработки их conntrack’ом). Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t raw -I PREROUTING -i eth1 -j CT --zone 1&lt;br /&gt;
iptables -t raw -I OUTPUT -o eth1 -j CT --zone 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Таким образом, пакеты, входящие или исходящие через интерфейс eth1, будут получать идентификатор зоны 1, в то время как пакеты интерфейса eth0 будут по-прежнему использовать зону по умолчанию (идентификатор 0), и путаницы не&amp;amp;nbsp;произойдет.&lt;br /&gt;
: Кроме того, идентификатор зоны можно задать для каждого интерфейса через sysfs, минуя iptables (псевдофайл &amp;lt;tt&amp;gt;/sys/class/net/имя_интерфейса/nf_ct_zone&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo 1 &amp;gt; /sys/class/net/eth1/nf_ct_zone&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Однако, стоит заметить, что iptables/netfilter позволяют реализовать более гибкую логику управления идентификатором зоны, опирающуюся на различные параметры пакетов, и поэтом данный параметр действия CT может быть полезен при решении различных сложных задач управления трафиком при использовании зон conntrack.&lt;br /&gt;
* '''RAWDNAT''' — позволяет выполнять «проброс» адресов и портов «сырым» методом — без использования системы conntrack, то есть без учета состояний соединений. Это действие реализовано в рамках проекта xtables-addons. Применять его можно только в таблице raw. Имеет единственную опцию &amp;lt;tt&amp;gt;--to-destination ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;, по смыслу аналогичную опции &amp;lt;tt&amp;gt;--to&amp;lt;/tt&amp;gt; действия NETMAP, то есть при указании маски заменяются только те биты в адресе, которые соответствуют единичным битам маски. Биты адреса, соответствующие нулевым битам маски, остаются неизменными. При отсутствии маски изменяется весь адрес.&lt;br /&gt;
&lt;br /&gt;
: Отметим, что в отличие от действий таблицы nat, которые работают только с соединениями в целом, операции «сырого» преобразования адресов работают только с отдельными пакетами, никак не&amp;amp;nbsp;учитывая контекст их передачи. Вышесказанное можно проиллюстрировать, скажем, таким простым примером: для элементарной операции «проброса» внешнего адреса на другой адрес при использовании обычных операций NAT достаточно одного правила&amp;lt;ref&amp;gt;На самом деле, для «чистого» проброса адреса, даже при использовании stateful NAT, необходимо обычно два или три правила, в частности, для проброса соединений с самого сервера в цепочке OUTPUT. Более подробно это описано при рассмотрении операции DNAT таблицы nat, и здесь, с целью упрощения понимания примера, эти аспекты опущены&amp;lt;/ref&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -i eth0 -d 212.201.100.135 -j  DNAT --to-destination 199.181.132.250&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: в то время как для той же операции при использовании «сырых» преобразований необходимо минимум два правила&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t raw -A PREROUTING -i eth0 -d 212.201.100.135 -j  RAWDNAT --to-destination 199.181.132.250&lt;br /&gt;
iptables -t rawpost -A POSTROUTING -o eth0 -s 199.181.132.250 -j RAWSNAT --to-source 212.201.100.135&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
: Как уже говорилось выше, при использовании обычной операции DNAT в ответных пакетах, приходящих с пробрасываемого адреса (199.181.132.250), производится автоматическая (без необходимости писать для этого отдельные правила) подмена исходного адреса на изначальный (212.201.100.135), и обращающиеся по адресу 212.201.100.135 хосты даже не&amp;amp;nbsp;подозревают, что общаются с кем-то другим. В случае же «сырого» преобразования такая автоматическая обработка невозможна, так как она требует возможности проверять пакеты на принадлежность соединению. С другой стороны, операции «сырого» преобразования являются более гибким инструментом, а также могут работать даже с UNTRACKED и INVALID-пакетами.&lt;br /&gt;
&lt;br /&gt;
=== Таблица rawpost ===&lt;br /&gt;
&lt;br /&gt;
Данная таблица предназначена для выполнения операций «сырого» преобразования адресов (без использования информации о соединениях), которые не&amp;amp;nbsp;могут быть реализованы в рамках таблицы raw, а именно, для операции «сырой» подмены исходного адреса (маскарадинга).&lt;br /&gt;
&lt;br /&gt;
Как и в таблице raw, в rawpost отсутствует возможность обращения к conntrack, поэтому критерии, использующие эту подсистему (conntrack, connmark, connlimit, connbytes), в этой таблице работать не&amp;amp;nbsp;будут.&lt;br /&gt;
&lt;br /&gt;
Данная таблица реализована в рамках проекта xtables-addons и отсутствует в стандартном комплекте iptables/netfilter.&lt;br /&gt;
&lt;br /&gt;
==== Цепочки ====&lt;br /&gt;
&lt;br /&gt;
* '''POSTROUTING''' — обрабатывает весь исходящий трафик.&lt;br /&gt;
&lt;br /&gt;
==== Действия ====&lt;br /&gt;
&lt;br /&gt;
В таблице rawpost можно использовать действие '''RAWSNAT''', выполняющее операцию «сырой» подмены исходного адреса. Имеет единственную опцию &amp;lt;tt&amp;gt;--to-source ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;, позволяющую задать новый исходный адрес для обрабатываемых пакетов. Как обычно, при наличии маски, в обрабатываемых адресах изменяются только те биты, которые в маске установлены в единицу, при отсутствии маски адрес изменяется целиком. Например, если по правилу&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t rawpost -A POSTROUTING -o eth0 -s 10.125.0.0/16 -d 172.18.1.100 -j RAWSNAT --to-source 192.168.0.20/16&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет обработан пакет с исходным адресом 10.125.32.28, то этот адрес будет заменен на 192.168.32.28.&lt;br /&gt;
&lt;br /&gt;
Если же при задании правила маску /16 в параметре &amp;lt;tt&amp;gt;--to-source&amp;lt;/tt&amp;gt; опустить, адрес будет заменен на 192.168.0.20. Но так лучше не&amp;amp;nbsp;делать, потому что мы выполняем трансляцию для всех пакетов из подсети 10.125.0.0/16, и без отслеживания соединений не&amp;amp;nbsp;сможем отличить, какие пакеты следует вернуть 10.125.32.28, а какие — другим хостам из этой подсети. Сама же операция «возвращения» пакетов требует отдельного RAWDNAT-правила:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t raw -A PREROUTING -i eth0 -s 172.18.1.100 -d 192.168.0.0/16 -j RAWDNAT --to-destination 10.125.0.0/16&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
которое выполняет обратную подмену, заменяя адреса назначения в пакетах-ответах. Таким образом, хост 172.18.1.100 будет считать, что к нему обращаются хосты из подести 192.168.0.0/16, а вовсе не&amp;amp;nbsp;из 10.125.0.0/16.&lt;br /&gt;
&lt;br /&gt;
Для сравнения, с использованием stateful-преобразования достаточно одного правила&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -s 10.125.0.0/16 -d 172.18.1.100 -j NETMAP --to 192.168.0.0/16&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
которое будет обеспечивать все необходимые преобразования адресов.&lt;br /&gt;
&lt;br /&gt;
Заметим, что для корректной работы обеих описанных конфигураций требуется, чтобы хост 172.18.1.100, а также маршрутизаторы на пути от нашего хоста к нему, считали наш хост шлюзом для сети 192.168.0.0/16.&lt;br /&gt;
&lt;br /&gt;
== Критерии ==&lt;br /&gt;
&lt;br /&gt;
Напоминаем, критерий — это логическое выражение, определяющее, соответствует ли пакет или соединение данному конкретному правилу.&lt;br /&gt;
&lt;br /&gt;
В одном правиле можно указать несколько критериев. Для того, чтобы пакет был обработан правилом, должны выполняться ''все'' критерии, то есть критерии неявно объединяются логическим AND.&lt;br /&gt;
&lt;br /&gt;
Также многие критерии и параметры критериев можно инвертировать, поставив перед ними восклицательный знак. В описании синтаксиса таких критериев присутствует пометка «&amp;lt;tt&amp;gt;[!]&amp;lt;/tt&amp;gt;». Инверсия меняет смысл критерия или его параметра на ровно противоположный. Например, критерию &amp;lt;tt&amp;gt;-s 127.0.0.1&amp;lt;/tt&amp;gt; соответствуют все пакеты, имеющие обратный адрес 127.0.0.1, а критерию &amp;lt;tt&amp;gt;! -s 127.0.0.1&amp;lt;/tt&amp;gt; — все пакеты, ''кроме'' имеющих обратный адрес 127.0.0.1. В ранних версиях iptables восклицательный знак можно было ставить между названием критерия и значением, например, &amp;lt;tt&amp;gt;-s ! 127.0.0.1&amp;lt;/tt&amp;gt;, однако последние версии iptables (в частности, 1.4.3.2 и выше), уже не поддерживают этот синтаксис, выдавая следующую ошибку:&lt;br /&gt;
 Using intrapositioned negation (`--option ! this`) is deprecated in favor of extrapositioned (`! --option this`).&lt;br /&gt;
&lt;br /&gt;
Далее мы кратко рассмотрим наиболее важные и интересные критерии.&lt;br /&gt;
&lt;br /&gt;
=== Универсальные критерии ===&lt;br /&gt;
&lt;br /&gt;
Под этим термином понимаются критерии, применимые ко все пакетам и соединениям, независимо от протокола транспортного уровня, и не требующие подключения внешних модулей (&amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-p'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--protocol ''протокол''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать протокол транспортного уровня. Наиболее часто употребляются &amp;lt;tt&amp;gt;tcp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;all&amp;lt;/tt&amp;gt;. Протокол также можно указать с помощью номера или названия согласно перечню, приведенному в &amp;lt;tt&amp;gt;/etc/protocols&amp;lt;/tt&amp;gt;. Значение «любой протокол» можно указать с помощью слова &amp;lt;tt&amp;gt;all&amp;lt;/tt&amp;gt; или числа 0. Если протокол не указан, подразумевается «любой протокол».&lt;br /&gt;
&lt;br /&gt;
При указании протокола становится возможным использовать специфичные для него критерии. Например, для TCP и UDP доступны критерии &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;, для ICMP — &amp;lt;tt&amp;gt;--icmp-type&amp;lt;/tt&amp;gt;. Подробнее эти критерии будут рассмотрены ниже.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-s'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--src&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source ''адрес''[/''маска''][,''адрес''[/''маска'']...]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определяет адрес отправителя. В качестве адреса может выступать IP-адрес (возможно с маской), имя хоста из /etc/hosts, или доменное имя (в последних двух случаях перед добавлением правила в цепочку имя резолвится в IP-адрес). Маска подсети может быть указана в классическом формате (например, 255.255.0.0) либо в формате CIDR (например, 16)&amp;lt;ref&amp;gt;Заметим, что для расчета масок подсетей и диапазонов адресов существует очень удобная утилита ipcalc.&amp;lt;/ref&amp;gt;. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -i eth0 -s 192.168.0.0/16 -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
(где eth0 — интерфейс, подключенный к интернету), позволяет заблокировать простейший вид спуфинга — из интернета ''не могут'' приходить пакеты с обратным адресом, принадлежащим к диапазону, зарезервированному для локальных сетей.&lt;br /&gt;
&lt;br /&gt;
Начиная с версии iptables 1.4.6, в одном параметре &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; можно указывать более одного адреса, разделяя адреса запятой. При этом для каждого адреса будет добавлено ''отдельное'' правило. Например, запись&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -i eth0 -s 192.168.0.0/16,172.16.0.0/12,10.0.0.0/8 -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
эквивалентна записи&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -i eth0 -s 192.168.0.0/16 -j DROP&lt;br /&gt;
iptables -A INPUT -i eth0 -s 172.16.0.0/12 -j DROP&lt;br /&gt;
iptables -A INPUT -i eth0 -s 10.0.0.0/8 -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
При добавлении через команду &amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt; (вставка в конец цепочки) порядок добавляемых правил будет соответствовать порядку перечисления адресов в исходной команде, при использовании команды &amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt; (вставка в начало цепочки либо после заданного правила) порядок будет обратным исходному.&lt;br /&gt;
&lt;br /&gt;
Настойчиво не рекомендуется использовать доменные имена, для разрешения (резолва) которых требуются DNS-запросы, так как на этапе конфигурирования фаервола DNS может работать некорректно. Также, заметим, имена резольвятся всего один раз — при добавлении правила в цепочку. Впоследствии соответствующий этому имени IP-адрес может измениться, но на уже записанные правила это никак не повлияет (в них останется старый адрес). Если указать доменное имя, которое резольвится в несколько IP-адресов, то для каждого адреса будет добавлено отдельное правило.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-d'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--dst&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination ''адрес''[/''маска''][,''адрес''[/''маска'']...]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определяет адрес получателя. Синтаксис аналогичен &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Заметим, что, если использовать возможность указания нескольких адресов (перечислив их явно или указав доменное имя, резольвящееся на несколько адресов) ''одновременно'' в параметрах &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, то на каждое возможное сочетание адресов будет добавлено свое правило. Например, запись&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.1,192.168.1.2 -d 192.168.1.3,192.168.1.4 -j REJECT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
эквивалентна&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.1 -d 192.168.1.3 -j REJECT&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.1 -d 192.168.1.4 -j REJECT&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.2 -d 192.168.1.3 -j REJECT&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.2 -d 192.168.1.4 -j REJECT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-i'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--in-interface ''имя_интерфейса''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определяет входящий сетевой интерфейс. Если указанное имя интерфейса заканчивается знаком «+» (например, &amp;lt;tt&amp;gt;tun+&amp;lt;/tt&amp;gt;), то критерию соответствуют все интерфейсы, чьи названия начинаются на указанное имя (для нашего примера tun0, tun1, …). Данный критерий можно использовать в цепочках PREROUTING, INPUT и FORWARD. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -i lo -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
позволит принимать весь трафик, входящий через интерфейс обратной петли.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-o'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--out-interface ''имя_интерфейса''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Определяет исходящий сетевой интерфейс. Синтаксис аналогичен &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt;. Критерий можно использовать в цепочках FORWARD, OUTPUT и POSTROUTING. Вспоминая один из наших примеров,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет маскарадить весь трафик, исходящий через интерфейс eth0.&lt;br /&gt;
&lt;br /&gt;
=== Критерии, специфичные для протоколов ===&lt;br /&gt;
&lt;br /&gt;
==== Протоколы транспортного уровня ====&lt;br /&gt;
&lt;br /&gt;
===== TCP =====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--sport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать исходящий порт (или их диапазон). Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m conntrack --ctstate NEW -p tcp --sport 0:1023 -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
заблокирует все входящие соединения с привилегированных портов (''привилегированными'' в TCP/UDP считаются порты с 0 по 1023 включительно, так как для их использования нужны привилегии суперпользователя, и обычно такие порты используются демонами только в режиме прослушивания).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--dport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать порт назначения (или их диапазон). Синтаксис аналогичен &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p tcp --dport 80 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
разрешит все входящие пакеты на 80 порт (HTTP).&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--tcp-flags''' ''маска'' ''установленные_флаги''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать список установленных и снятых TCP-флагов. В ''маске'' перечисляются (через запятую, без пробелов) все проверяемые флаги, далее, после пробела, перечисляются (также через запятую) те из них, которые должны быть установлены. Все остальные перечисленные в маске флаги должны быть сняты. Возможные флаги: SYN ACK FIN RST URG PSH. Также можно использовать псевдофлаги ALL и NONE, обозначающие «все флаги» и «ни одного флага» соответственно.&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p tcp --tcp-flags SYN,RST,ACK,FIN SYN -j LOG --log-level DEBUG --log-prefix &amp;quot;TCP SYN: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет заносить в лог все входящие TCP SYN-пакеты. У обычного SYN-пакета всегда установлен флаг SYN и сняты флаги RST, ACK и FIN.&lt;br /&gt;
&lt;br /&gt;
Другой пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m conntrack --ctstate NEW,INVALID -p tcp --tcp-flags SYN,ACK SYN,ACK -j REJECT --reject-with tcp-reset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет препятствовать спуфингу от нашего имени. Ведь если мы получаем пакет с установленными флагами SYN и ACK (такой комбинацией флагов обладает только ответ на SYN-пакет) по еще не открытому соединению, это означает, что кто-то послал другому хосту SYN-пакет от нашего имени, и ответ пришел к нам. Однако добавление такого правила в конфигурацию фаервола ''не рекомендуется'', поскольку стандартом также предусмотрено использование случайного начального номера последовательности для каждого нового TCP-соединения, как раз для предотвращения возможности спуфинг-атаки. Шансов угадать начальный номер у злоумышленника практически нет, тогда как наш ответ RST-пакетом на такой пакет может серьезно нарушить работоспособность некоторых систем защиты от DoS-атак, полагающихся на метод, называемый out-of-sequence ACK. В случае добавления этого правила в конфигурацию фаервола, системы защиты будут считать, что, раз уж мы отвечаем RST на out-of-sequence ACK, вы действительно пытались установить соединение с ресурсом, и пропустят все последующие поддельные пакеты злоумышленника, отправленные от вашего имени. В результате вы заметно облегчите злоумышленнику осуществление DoS-атаки от вашего имени, и при расследовании этого эпизода следы приведут к вам.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--syn'''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет отлавливать TCP SYN-пакеты (сокращение для &amp;lt;tt&amp;gt;--tcp-flags SYN,RST,ACK,FIN SYN&amp;lt;/tt&amp;gt;). Так что приведенный выше пример про логгирование SYN-пакетов можно записать в виде&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p tcp --syn -j LOG --log-level DEBUG --log-prefix &amp;quot;TCP SYN: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Более интересный пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m conntrack --ctstate NEW -p tcp ! --syn -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет блокировать все попытки открыть входящее TCP-соединение ''не'' SYN-пакетом. Попытка установить соединение таким образом может быть либо ошибкой, либо атакой.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--tcp-option''' ''номер''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет проверить, установлена ли в заголовке TCP-пакета соответствующая опция. Полный список опций с их номерами представлен [http://www.iana.org/assignments/tcp-parameters/tcp-parameters.xhtml на сайте IANA].&lt;br /&gt;
&lt;br /&gt;
===== UDP =====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--sport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать исходящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--dport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать входящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP.&lt;br /&gt;
&lt;br /&gt;
===== SCTP =====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--sport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать исходящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--dport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать входящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--chunk-types''' {all|any|only} ''тип_секции''[:''флаги''][,''тип_секции''[:''флаги'']...]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет анализировать набор секций (chunks), входящих в состав SCTP-пакета. Возможные типы секций: DATA INIT INIT_ACK SACK HEARTBEAT HEARTBEAT_ACK ABORT SHUTDOWN SHUTDOWN_ACK ERROR COOKIE_ECHO COOKIE_ACK ECN_ECNE ECN_CWR SHUTDOWN_COMPLETE ASCONF ASCONF_ACK. Также, для секций, имеющих флаги (DATA, ABORT и SHUTDOWN_COMPLETE) можно проверить состояние флагов, указав соответствующие буквы после названия секции (для DATA — U, B и E, для ABORT и SHUTDOWN_COMPLETE — T). Литера в верхнем регистре предполагает установленный флаг, в нижнем — снятый. Ключевое слово в начале позволяет определить логику работы: в случае &amp;lt;tt&amp;gt;all&amp;lt;/tt&amp;gt; должны присутствовать ''все'' перечисленные секции, для &amp;lt;tt&amp;gt;any&amp;lt;/tt&amp;gt; — хотя бы одна из них, для &amp;lt;tt&amp;gt;only&amp;lt;/tt&amp;gt; — пакет должен состоять только из перечисленных секций. Примеры:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p sctp --chunk-types only DATA,INIT -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
заблокирует все входящие SCTP-пакеты, состоящие только из секций DATA и INIT, а&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p sctp --chunk-types any DATA:Be -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
разрешит входящие SCTP-пакеты, содержащие секцию DATA с установленным флагом B и снятым флагом E, то есть первый фрагмент фрагментированной DATA-секции.&lt;br /&gt;
&lt;br /&gt;
===== DCCP =====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--sport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать исходящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--dport'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination-port ''порт''[:''порт'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать входящий порт (или их диапазон). Синтаксис и принцип работы аналогичен описанной выше одноименной опции TCP.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--dccp-types''' ''маска''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать тип DCCP-пакета. В ''маске'' через запятую перечисляются DCCP-типы (допустимые названия: REQUEST RESPONSE DATA ACK DATAACK CLOSEREQ CLOSE RESET SYNC SYNCACK INVALID). Пакет считается удовлетворяющим критерию, если имеет один из типов, перечисленных в маске. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p dccp --dccp-types RESET,INVALID -j LOG --log-level DEBUG --log-prefix &amp;quot;DCCP RESET or INVALID: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
занесет в лог все входящие RESET и INVALID DCCP-пакеты.&lt;br /&gt;
&lt;br /&gt;
===== UDP Lite =====&lt;br /&gt;
&lt;br /&gt;
Поддержка специфических опций протокола UDPLite (а именно, проверки портов источника и/или назначения) в netfilter реализована не вполне очевидным образом: через критерий multiport).&lt;br /&gt;
&lt;br /&gt;
Если для обычного UDP соответствие номера порта проверялось выражением вида &amp;lt;tt&amp;gt;-p udp --dport ''номер_порта''&amp;lt;/tt&amp;gt; (или &amp;lt;tt&amp;gt;-p udp --sport ''номер_порта''&amp;lt;/tt&amp;gt;), то в случае UDPLite аналогичное выражение будет выглядеть как &amp;lt;tt&amp;gt;-p udplite -m multiport --dports ''номер_порта''&amp;lt;/tt&amp;gt; (или &amp;lt;tt&amp;gt;-p udplite -m multiport --sports ''номер_порта''&amp;lt;/tt&amp;gt;). Все опции критерия multiport для UDPLite поддерживаются в полном объеме.&lt;br /&gt;
&lt;br /&gt;
==== IPv4 ====&lt;br /&gt;
&lt;br /&gt;
Ниже перечислены критерии, которые реализованы только для протокола IPv4 и, соответственно, могут быть вызваны только через iptables, но не&amp;amp;nbsp;через ip6tables.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-f'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--fragment&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Проверка фрагментации: критерию соответствуют только фрагменты пакета, начиная со второго фрагмента. Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p icmp -f -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
блокирует фрагменты ICMP-пакетов. Так как, в силу функционального назначения протокола, ICMP-пакеты должны быть очень небольшими и нормально укладываться в MTU, наличие их фрагментов обычно свидетельствует об ошибке или попытке атаки.&lt;br /&gt;
&lt;br /&gt;
У второго и последующего фрагментов нет заголовка транспортного уровня, поэтому бессмысленно пытаться использовать для них критерии номеров TCP/UDP-портов или типа ICMP.&lt;br /&gt;
&lt;br /&gt;
* '''addrtype''' — позволяет проверить тип адреса источника и/или назначения с точки зрения подсистемы маршрутизации сетевого стека ядра. Допустимые типы адресов: UNSPEC (адрес 0.0.0.0), UNICAST, LOCAL (адрес принадлежит нашему хосту), BROADCAST, ANYCAST, MULTICAST, BLACKHOLE, UNREACHABLE, PROHIBIT, THROW, NAT, XRESOLVE. Подробнее о большинстве перечисленных типов адресов и их использовании в Linux (точнее, в подсистеме iproute2) можно почитать [http://linux-ip.net/html/routing-tables.html здесь]. Данный критерий поддерживает следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --src-type ''тип''[,''тип''...]&amp;lt;/tt&amp;gt; — проверка, принадлежит ли исходный адрес пакета одному из перечисленных типов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --dst-type ''тип''[,''тип''...]&amp;lt;/tt&amp;gt; — проверка, принадлежит ли адрес назначения пакета одному из перечисленных типов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--limit-iface-in&amp;lt;/tt&amp;gt; — ограничивает проверку типа адреса только записями для интерфейса, через который пакет вошел на хост. Допускается использовать этот параметр только в цепочках PREROUTING, INPUT и FORWARD.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--limit-iface-out&amp;lt;/tt&amp;gt; — ограничивает проверку типа адреса только записями для интерфейса, через который пакет вышел с хоста. Допускается использовать этот параметр только в цепочках POSTROUTING, OUTPUT и FORWARD.&lt;br /&gt;
&lt;br /&gt;
Критерии &amp;lt;tt&amp;gt;--limit-iface-in&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--limit-iface-out&amp;lt;/tt&amp;gt; нельзя указывать одновременно.&lt;br /&gt;
&lt;br /&gt;
В качестве практического примера использования данного критерия можно привести простейшую защиту от спуфинга:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m addrtype --src-type LOCAL ! -i lo -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Это правило заблокирует пакеты, которые пришли с внешних интерфейсов, но при этом в качестве обратного адреса у них указан один из адресов, принадлежащих нашему хосту (например, 127.0.0.1).&lt;br /&gt;
&lt;br /&gt;
* '''ecn''' — позволяет проверять значения битов ECN в заголовках TCP и IPv4. Допустимые параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --ecn-tcp-cwr&amp;lt;/tt&amp;gt; — проверка флага ECN CWR (Congestion Window Received) в TCP-заголовке пакета.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --ecn-tcp-ece&amp;lt;/tt&amp;gt; — проверка флага ECN ECE (ECN Echo) в TCP-заголовке пакета.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --ecn-ip-ect ''значение''&amp;lt;/tt&amp;gt; — проверка значения, сформированного ECN-битами поля TOS (последние два бита). Возможные значения от 0 до 3.&lt;br /&gt;
&lt;br /&gt;
* '''realm''' — проверка области маршрутизации (realm) пакета. Имеет единственный параметр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --realm ''значение''[/''маска'']&amp;lt;/tt&amp;gt;, позволяющий указать численный идентификатор области. Если указана маска, то значение realm каждого проверяемого пакета сначала объединяется с маской при помощи побитового AND, а затем сравнивается со значением, указанным в правиле. Также вместо числа можно указать символьное название области согласно обозначениям в файле &amp;lt;tt&amp;gt;/etc/iproute2/rt_realms&amp;lt;/tt&amp;gt; (в этом случае маску использовать нельзя).&lt;br /&gt;
&lt;br /&gt;
* '''ttl''' — обеспечивает проверку поля TTL в заголовке пакета. Позволяет установить, является ли значение TTL проверяемого пакета большим (&amp;lt;tt&amp;gt;--ttl-gt&amp;lt;/tt&amp;gt;), меньшим (&amp;lt;tt&amp;gt;--ttl-lt&amp;lt;/tt&amp;gt;), равным или не&amp;amp;nbsp;равным (&amp;lt;tt&amp;gt;[!] --ttl-eq&amp;lt;/tt&amp;gt;) указанному значению.&lt;br /&gt;
&lt;br /&gt;
===== ICMP =====&lt;br /&gt;
&lt;br /&gt;
ICMP является протоколом контрольных сообщений IPv4. Несмотря на то, что ICMP формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), а не&amp;amp;nbsp;для вспомогательного критерия (&amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt;), де-факто этот протокол неотделим от IPv4, и поэтому соответствующий критерий может использоваться только в iptables, но не&amp;amp;nbsp;в ip6tables.&lt;br /&gt;
&lt;br /&gt;
Критерий этого протокола имеет единственный параметр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] '''--icmp-type''' ''тип''&amp;lt;/tt&amp;gt; — обеспечивает проверку типа ICMP-пакета. Список возможных типов выводится по команде &amp;lt;tt&amp;gt;iptables -p icmp -h&amp;lt;/tt&amp;gt;. Также можно указать стандартные числовые тип и, при&lt;br /&gt;
необходимости, код. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p icmp --icmp-type echo-request -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
как и аналогичное&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p icmp --icmp-type 8 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
пропустят все входящие ICMP-эхо-запросы (пинги).&lt;br /&gt;
&lt;br /&gt;
==== IPv6 ====&lt;br /&gt;
&lt;br /&gt;
Ниже перечислены критерии, которые реализованы только для протокола IPv6 и, соответственно, могут быть вызваны только через ip6tables, но не&amp;amp;nbsp;через iptables.&lt;br /&gt;
&lt;br /&gt;
Особо отметим, что критерии для некоторых подзаголовков IPv6 (dst, frag, hbh, rt) корректно вызываются ''только'' с использованием синтаксиса для расширенных критериев (ключ &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt;), хотя имеют номера протоколов в &amp;lt;tt&amp;gt;/etc/protocols&amp;lt;/tt&amp;gt; и, формально, могут быть вызваны с использованием синтаксиса для протоколов (ключ &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;) что, однако, является неверным. В таких случаях ip6tables выдает предупреждение вида&lt;br /&gt;
&amp;lt;source lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
Warning: never matched protocol: ipv6-frag. use extension match instead.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
гласящее, что в такое правило никогда не&amp;amp;nbsp;будет срабатывать. Если вы видите подобное предупреждение, удалите правило, которое его вызвало, и перепишите это правило с использованием корректного синтаксиса (&amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
С другими же критериями, которые представляют более или менее самостоятельные протоколы (ICMPv6, MH, IPSec, AH и ESP), все ровно наоборот, и для них корректным будет использование именно синтаксиса протокола (ключ &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), а не&amp;amp;nbsp;расширенного критерия. Во избежание путаницы, такие критерии вынесены в отдельные подзаголовки, по аналогии с протоколами транспортного уровня (выше).&lt;br /&gt;
&lt;br /&gt;
* '''dst''' — проверят опции назначения (подзаголовок 60 Destination Options). Имеет две опции:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --dst-len ''значение''&amp;lt;/tt&amp;gt; — проверяет длину подзаголовка;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --dst-opts ''код''[:''длина''][,''код''[:''длина'']...]&amp;lt;/tt&amp;gt; — позволяет проверить вхождение в данный подзаголовок конкретных опций. Также можно проверить длину каждой из них. Можно указать до 16 опций (представленных числовыми кодами), разделяя их запятой.&lt;br /&gt;
&lt;br /&gt;
* '''eui64''' — сравнивает младшие 64 бита исходного IPv6-адреса с битами исходного MAC-адреса, преобразованными согласно правилам автоконфигурирования IPv6-адресов на основании MAC-адресов. Таким образом, позволяет проверить, является ли IPv6-адрес отправителя пакета автоматически сконфигурированным (работает, если отправитель находится в одном широковещательном домене с нашим хостом, так как в противном случае сохранность MAC-адреса отправителя не&amp;amp;nbsp;может быть гарантирована).&lt;br /&gt;
* '''frag''' — позволяет проверять параметры фрагментации (подзаголовок 44 Fragment). Допустимые опции:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --fragid ''мин''[:''макс'']&amp;lt;/tt&amp;gt; — сверяет величину идентификатора фрагмента. Если указано одно значение, проверяется равенство, если указан диапазон — проверяется вхождение значения в этот диапазон (включая границы).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--fragres&amp;lt;/tt&amp;gt; — проверяет, заполнены ли нулями зарезервированные поля заголовка (биты 29-30).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--fragfirst&amp;lt;/tt&amp;gt; — проверяет, является ли данный фрагмент первым в последовательности.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--fraglast&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;--fragmore&amp;lt;/tt&amp;gt; — проверяют M-флаг, показывающий, является ли данный фрагмент последним в последовательности (в этом случае &amp;lt;tt&amp;gt;--fraglast&amp;lt;/tt&amp;gt; дает истину, а &amp;lt;tt&amp;gt;--fragmore&amp;lt;/tt&amp;gt; ложь), или после него должны быть еще фрагменты (соответственно, наоборот). Эти две опции являются взаимоисключающими.&lt;br /&gt;
&lt;br /&gt;
Также в документации можно найти упоминание параметра &amp;lt;tt&amp;gt;--fraglen &amp;lt;/tt&amp;gt;, который якобы проверяет длину подзаголовка Fragment. Однако, согласно текущим соглашениям, длина этого подзаголовка фиксирована и равна 8&amp;amp;nbsp; байтам, а названная опция ни на что не&amp;amp;nbsp;влияет.&lt;br /&gt;
&lt;br /&gt;
* '''hbh''' — проверяет опции Hop-by-Hop (подзаголовок 0 Hop-by-Hop). Синтаксис аналогичен параметру dst.&lt;br /&gt;
* '''hl''' — обеспечивает проверку поля Hop Limit в IPv6-заголовке. Позволяет установить, является ли значение HL проверяемого пакета большим (&amp;lt;tt&amp;gt;--hl-gt&amp;lt;/tt&amp;gt;), меньшим (&amp;lt;tt&amp;gt;--hl-lt&amp;lt;/tt&amp;gt;), равным или не&amp;amp;nbsp;равным (&amp;lt;tt&amp;gt;[!] --hl-eq&amp;lt;/tt&amp;gt;) указанному значению.&lt;br /&gt;
* '''ipv6header''' — позволяет проверить наличие вспомогательных подзаголовков IPv6. Допустимыми типами заголовков являются: hop (hop-by-hop 0), dst (ipv6-opts 60), route (ipv6-route 43), frag (ipv6-frag 44), auth (ah 50), esp (esp 59). В скобках указаны «длинные» названия и числовые идентификаторы протокола. Используя опцию&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --header ''тип''[,''тип''...]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
вы можете указывать любые из этих обозначений — короткие названия, длинные названия или числовые идентификаторы. Отметим, что пакет будет соответствовать критерию в том случае, если будет содержать ''только'' перечисленные подзаголовки. Изменить это поведение можно, указав опцию &amp;lt;tt&amp;gt;--soft&amp;lt;/tt&amp;gt; — в этом случае достаточно, чтобы пакет содержал хотя бы один из перечисленных подзаголовков.&lt;br /&gt;
&lt;br /&gt;
* '''rt''' — позволяет проверять параметры маршрутизации пакета (подзаголовок 43 Routing). Допустимые параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --rt-type ''тип''&amp;lt;/tt&amp;gt; — тип маршрутизации (0, 1 или 2);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --rt-segsleft ''мин''[:''макс'']&amp;lt;/tt&amp;gt; — проверка значения поля Segment Left (показывает, сколько еще узлов должен пройти данный пакет, прежде чем достигнет цели);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --rt-len ''значение''&amp;lt;/tt&amp;gt; — проверка длины всего подзаголовка.&lt;br /&gt;
&lt;br /&gt;
Следующие три параметра работают для типа 0 (&amp;lt;tt&amp;gt;--rt-type 0&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--rt-0-res&amp;lt;/tt&amp;gt; — проверять зарезервированные поля;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--rt-0-addrs ''адрес''[,''адрес''...]&amp;lt;/tt&amp;gt; — проверяет адреса, перечисленные в подзаголовке. Можно указать не&amp;amp;nbsp;более 16 адресов, разделяя их запятыми. Пакет считается удовлетворяющим критерию, если подзаголовок содержит все адреса, которые были перечислены в правиле, в том же порядке;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--rt-0-not-strict&amp;lt;/tt&amp;gt; — делает условие проверки по предыдущем параметру не&amp;amp;nbsp;таким жестким: достаточно, чтобы хотя бы один из перечисленных адресов совпадал с соответствующим адресом в подзаголовке, при соблюдении порядка перечисления.&lt;br /&gt;
&lt;br /&gt;
===== ICMPv6 =====&lt;br /&gt;
&lt;br /&gt;
ICMPv6 является протоколом контрольных сообщений IPv6. Несмотря на то, что ICMPv6 формально является самостоятельным протоколом, и обращение к соответствующему критерию должно производиться с использованием синтаксиса для протокола (&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;), а не&amp;amp;nbsp;для вспомогательного критерия (&amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt;), де-факто этот протокол неотделим от IPv6, и поэтому соответствующий критерий может использоваться только в ip6tables, но не&amp;amp;nbsp;в iptables.&lt;br /&gt;
&lt;br /&gt;
Критерий этого протокола имеет единственный параметр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] '''--icmpv6-type''' ''тип''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
по смыслу и синтаксису аналогичный параметру &amp;lt;tt&amp;gt;--icmp-type&amp;lt;/tt&amp;gt; критерия icmp. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -I INPUT -p icmpv6 --icmpv6-type echo-request -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
как и аналогичное&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -I INPUT -p icmpv6 --icmpv6-type 128 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
пропустит входящие ICMPv6-эхо-запросы (пинги).&lt;br /&gt;
&lt;br /&gt;
Как и в случае icmp, вы можете получить список допустимых типов сообщений, введя&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -p icmpv6 -h&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== MH =====&lt;br /&gt;
&lt;br /&gt;
Критерий mh позволяет определять пакеты с подзаголовком IPv6 Mobility Header (RFC 3775). Как и в случае с ICMPv6, вызов данного критерия должен выполняться в соответствии с синтаксисом для протокола (через ключ &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;). Имеет единственную опцию&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] '''--mh-type''' ''мин''[:''макс'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
позволяющую указать точное значение типа или диапазон допустимых значений. Перечень поддерживаемых типов MH можно получить, введя команду&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip6tables -p mh -h&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Также к данному критерию допустимо обращение по названию ipv6-mh (&amp;lt;tt&amp;gt;-p ipv6-mh&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
==== IPsec ====&lt;br /&gt;
&lt;br /&gt;
netfilter «знает» два протокола из семейства IPsec: Authentication Header (&amp;lt;tt&amp;gt;-p ah&amp;lt;/tt&amp;gt;) и Encapsulating Security Payload (&amp;lt;tt&amp;gt;-p esp&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
===== AH =====&lt;br /&gt;
Для протокола AH поддерживается единственная опция&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''--ahspi''' ''значение''[:''значение'']&amp;lt;/tt&amp;gt; — позволяет указать значение (или диапазон значений) SPI (Security Parameter Index).&lt;br /&gt;
&lt;br /&gt;
===== ESP =====&lt;br /&gt;
Протокол ESP имеет аналогичную по смыслу опцию&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''--espspi''' ''значение''[:''значение'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В большинстве конфигураций IPsec-пакеты просто пропускаются фаерволом (пусть с ними разбирается IPsec-подсистема):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p ah -j ACCEPT&lt;br /&gt;
iptables -I INPUT -p esp -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Критерии состояния соединения ===&lt;br /&gt;
&lt;br /&gt;
==== conntrack ====&lt;br /&gt;
&lt;br /&gt;
Основной критерий, используемый для контроля состояния соединения. Он предоставляет эффективный набор инструментов, позволяющий использовать информацию системы conntrack о состоянии соединения. Затронутую тему весьма проблематично осветить в двух словах и привести по ней простые примеры, не выходя за краткий формат, принятый для нашей статьи. Поэтому ограничимся мы подробно рассмотрим лишь наиболее важный параметр данного критерия — ctstate. Для прочих параметров мы лишь кратко опишем синтаксис и назначение. За более подробной информацией обратитесь к документации, прилагаемой к вашему дистрибутиву. Итак,&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctstate''' ''маска''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
''Маска'' содержит перечисление через запятую список возможных состояний соединения. Пакет считается удовлетворяющим критерию, если соединение, по которому он проходит, находится в одном из перечисленных состояний.&lt;br /&gt;
&lt;br /&gt;
Возможные состояния:&lt;br /&gt;
&lt;br /&gt;
:* '''NEW''' — соединение не открыто, то есть пакет является первым в соединении. Полезные примеры использования этого состояния приведены выше, в частности, при описании TCP-специфичных критериев.&lt;br /&gt;
&lt;br /&gt;
:* '''ESTABLISHED''' — пакет относится к уже установленному соединению. Обычно такие пакеты принимаются без дополнительной фильтрации, как и в случае с RELATED.&lt;br /&gt;
&lt;br /&gt;
:* '''RELATED''' — пакет открывает новое соединение, логически связанное с уже установленными, например, открытие канала данных в пассивном режиме FTP.&lt;br /&gt;
Например:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
modprobe nf_conntrack_ftp # Подгружаем модуль для распознавания связанных FTP-соединений&lt;br /&gt;
# В старых системах этот модуль может называться ip_conntrack_ftp&lt;br /&gt;
iptables -F # Очищаем все цепочки таблицы filter&lt;br /&gt;
# Ко всем пакетам, которые относятся к уже установленным соединениям, применяем терминальное действие ACCEPT — пропустить&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 21 -j ACCEPT # Разрешаем открывать соединения на 21 TCP-порт.&lt;br /&gt;
iptables -P INPUT DROP # В качестве действия по умолчанию устанавливаем DROP — блокирование пакета&lt;br /&gt;
iptables -P OUTPUT ACCEPT # Разрешаем все исходящие пакеты&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Этот набор команд обеспечит функционирование на хосте FTP-сервера с поддержкой как активного, так и пассивного режимов. В пассивном режиме FTP клиент сначала устанавливает управляющее соединение на TCP-порт 21 сервера. Когда возникнет необходимость передачи данных, клиент даст серверу команду PASV. Сервер выберет высокий порт и подключится к нему в режиме прослушивания, отправив номер порта клиенту по управляющему соединению. Система conntrack, при наличии подгруженного модуля ядра nf_conntrack_ftp, зафиксирует это сообщение и выделит номер порта. Когда клиент откроет соединение данных на этот высокий порт, система conntrack присвоит первому пакету статус RELATED, в результате чего пакет пройдет по нашему правилу и будет принят. Остальные пакеты в этом соединении будут иметь уже статус ESTABLISHED и тоже будут приняты.&lt;br /&gt;
&lt;br /&gt;
Возможность корректно обрабатывать пассивный режим FTP, как это было описано выше, из всех unix-фаерволов доступна только в iptables. В других фаерволах для решения данной проблемы используются различные «костыли». Например, в pf управляющие FTP-соединения [http://www.openbsd.org/faq/pf/ftp.html#client пропускаются] через специальную программу [http://www.openbsd.org/cgi-bin/man.cgi?query=ftp-proxy&amp;amp;sektion=8 ftp-proxy], которая анализирует трафик подобно conntrack и «на лету» добавляет правила для соединений данных. Однако даже подобные «костыли» существуют далеко не для всех протоколов. Поэтому можно утверждать, что в данном аспекте iptables находится вне конкуренции.&lt;br /&gt;
&lt;br /&gt;
С обработкой активного режима таких проблем не возникает, так как сервер сам устанавливает соединение данных с порта 20, поэтому первый пакет пропускается согласно правилу по умолчанию цепочки OUTPUT. Правда, проблемы могут возникнуть на стороне фаервола клиента, но это уже не относится к компетенции сервера.&lt;br /&gt;
&lt;br /&gt;
:* '''INVALID''' — пакет по смыслу должен принадлежать уже установленному соединению (например, ICMP-сообщение port-unreachable), однако такое соединение в системе не зарегистрировано. Обычно к таким пакетам применяют действие DROP:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m conntrack --ctstate INVALID -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:* '''UNTRACKED''' — отслеживание состояния соединения для данного пакета было отключено. Обычно оно отключается с помощью действия NOTRACK в таблице raw.&lt;br /&gt;
&lt;br /&gt;
:* '''DNAT''' — показывает, что к данному соединению применена операция подмены адреса назначения.&lt;br /&gt;
&lt;br /&gt;
:* '''SNAT''' — показывает, что к данному соединению применена операция подмены адреса источника.&lt;br /&gt;
&lt;br /&gt;
Остальные параметры критерия conntrack, как уже говорилось, мы опишем лишь конспективно.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctstatus''' ''маска''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Применяется для определения статуса соединения в системе conntrack. Возможные статусы:&lt;br /&gt;
:* '''EXPECTED''' — данное соединение ожидалось системой conntrack по результатам анализа других соединений. Например, после того, как клиент и сервер через управляющее FTP-соединение согласуют номер порта для соединения данных в пассивном режиме, система conntrack на сервере будет ожидать входящее соединение на этот порт.&lt;br /&gt;
:* '''CONFIRMED''' — подтвержденное соединение. Такой статус присваивается соединению после того, как инициатор начал передачу пакетов.&lt;br /&gt;
:* '''SEEN_REPLY''' — соединение, по которому поступил ответ, то есть имеет место передача данных в обоих направлениях (поддержка данного состояния появилась сравнительно недавно).&lt;br /&gt;
:* '''ASSURED''' — соединение можно считать полностью установленным. Этот статус присваивается соединению после передачи определенного количества данных. Присвоение данного статуса приводит к увеличению conntrack-тайм-аута для данного соединения (эти тайм-ауты используются для определения и удаления «повисших» и оборванных соединений).&lt;br /&gt;
:* '''NONE''' — нет статуса. Соединение не соответствует ни одному из перечисленных критериев.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctproto''' ''протокол''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Протокол транспортного уровня, определенный системой conntrack. Синтаксис аналогичен стандартному критерию &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctdir''' {ORIGINAL|REPLY}&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать направление прохождения пакетов (ORIGINAL — от инициатора к отвечающему, REPLY — наоборот). Если не указывать эту опцию, под критерий будут подпадать пакеты, идущие в обоих направлениях.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctorigsrc''' ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;[!] '''--ctorigdst''' ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;[!] '''--ctreplsrc''' ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;[!] '''--ctrepldst''' ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет определять адреса источника (src) и назначения (dst) при передаче данных от инициатора к отвечающему (orig) и наоборот (repl). Синтаксис аналогичен описанному выше стандартному критерию &amp;lt;tt&amp;gt;-s&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Обычно адрес-порт источника при передаче в прямом направлении совпадают с адресом-портом назначения при передаче в обратном направлении, и наоборот, адрес-порт источника при передаче в обратном направлении совпадает с адресом-портом назначения при передаче в прямом направлении. То есть, если клиент 192.168.1.2 обращается к серверу 192.168.1.1, то с точки зрения системы conntrack ситуация выглядит следующим образом:&lt;br /&gt;
: → В прямом направлении (от инициатора к отвечающему):&lt;br /&gt;
::  — Адрес источника (ctorigsrc): 192.168.1.2 (адрес клиента)&lt;br /&gt;
::  — Адрес назначения (ctorigdst): 192.168.1.1 (адрес сервера)&lt;br /&gt;
: ← В обратном направлении (от отвечающего к инициатору):&lt;br /&gt;
::  — Адрес источника (ctreplsrc): 192.168.1.1 (адрес сервера)&lt;br /&gt;
::  — Адрес назначения (ctrepldst): 192.168.1.2 (адрес клиента)&lt;br /&gt;
&lt;br /&gt;
Однако для соединений, к которым применена трансляция адресов или портов, это может не выполняться. Например, рассмотрим ситуацию, когда клиент из нашей подсети (192.168.1.2) обращается к некоторому серверу в интернете (204.152.191.37) через наш сервер (внешний адрес нашего сервера 208.77.188.166, внутренний 192.168.1.1). Для корректной работы такой схемы нужно обеспечить на нашем сервере подмену исходного адреса (SNAT), например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.166&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Тогда, с точки зрения системы conntrack нашего сервера,&lt;br /&gt;
: → В прямом направлении (от инициатора к отвечающему):&lt;br /&gt;
::  — Адрес источника (ctorigsrc): 192.168.1.2 (внутренний адрес клиента)&lt;br /&gt;
::  — Адрес назначения (ctorigdst): 204.152.191.37 (адрес интернет-сервера)&lt;br /&gt;
: ← В обратном направлении (от отвечающего к инициатору):&lt;br /&gt;
::  — Адрес источника (ctreplsrc): 204.152.191.37 (адрес интернет-севера)&lt;br /&gt;
::  — Адрес назначения (ctrepldst): 208.77.188.166 (внешний адрес нашего сервера)&lt;br /&gt;
&lt;br /&gt;
В том случае, если адрес-порт источника при передаче в прямом направлении отличаются от адреса-порта назначения при передаче в обратном направлении, соединению будет присвоен статус SNAT.&lt;br /&gt;
&lt;br /&gt;
Аналогично, если один из внешних адресов нашего сервера «проброшен» на внутренний сервер, например, так&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A PREROUTING -d 208.77.188.166 -j DNAT --to-destination 192.168.1.2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
то при обращении на этот адрес клиента извне (допустим, все тот же 204.152.191.37), получим&lt;br /&gt;
: → В прямом направлении (от инициатора к отвечающему):&lt;br /&gt;
::  — Адрес источника (ctorigsrc): 204.152.191.37 (адрес клиента)&lt;br /&gt;
::  — Адрес назначения (ctorigdst): 208.77.188.166 (наш внешний адрес)&lt;br /&gt;
: ← В обратном направлении (от отвечающего к инициатору):&lt;br /&gt;
::  — Адрес источника (ctreplsrc): 192.168.1.2 (адрес внутреннего сервера)&lt;br /&gt;
::  — Адрес назначения (ctrepldst): 204.152.191.37 (адрес клиента)&lt;br /&gt;
&lt;br /&gt;
В том случае, если адрес-порт назначения при передаче в прямом направлении отличаются от адреса-порта источника при передаче в обратном направлении, соединению будет присвоен статус DNAT.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctorigsrcport''' ''порт''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;[!] '''--ctorigdstport''' ''порт''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;[!] '''--ctreplsrcport''' ''порт''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;[!] '''--ctrepldstport''' ''порт''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет определять порты источника (src) и назначения (dst) при передаче данных от инициатора к отвечающему (orig) и наоборот (repl) для протоколов транспортного уровня, имеющих порты (TCP, UDP, SCTP, DCCP).&lt;br /&gt;
&lt;br /&gt;
Ситуация с портами в принципе аналогична описанной выше ситуации с адресами, поэтому рассматривать ее отдельно мы не будем.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''--ctexpire''' ''мин_время''[:''макс_время'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволяет указать в качестве критерия оставшееся по тайм-ауту время в секундах для данного соединения.&lt;br /&gt;
&lt;br /&gt;
Система conntrack присваивает каждому соединению тайм-аут (счетчик обратного отсчета времени). Когда этот счетчик доходит до нуля, система conntrack удаляет информацию о соединении из своих таблиц. Тайм-аут устанавливается в значение по умолчанию каждый раз, когда по соединению передаются данные. Таким образом, активно используемые соединения никогда не будут сброшены.&lt;br /&gt;
&lt;br /&gt;
Заметим, что значения тайм-аута по умолчанию для разных протоколов, и даже для одного протокола на разных стадиях установки соединения, могут различаться. Например, для протокола TCP вводятся отдельные значения тайм-аутов для состояний SYN_SENT, SYN_RECV, ESTABLISHED (не путать TCP-состояние ESTABLISHED с conntrack-состоянием ESTABLISHED), FIN_WAIT, CLOSE_WAIT, LAST_ACK, TIME_WAIT, CLOSE. Для UDP существуют два тайм-аута: для соединений, не получивших статуса ASSURED (conntrack_udp_timeout) и для соединений, по которым передано достаточное количество данных в обе стороны для получения этого статуса (conntrack_udp_timeout_stream). Для ICMP тайм-аут только один.&lt;br /&gt;
&lt;br /&gt;
==== state ====&lt;br /&gt;
&lt;br /&gt;
Идеологический предшественник критерия conntrack. Имеет единственный параметр &amp;lt;tt&amp;gt;--state&amp;lt;/tt&amp;gt;, аналогичный параметру &amp;lt;tt&amp;gt;--ctstate&amp;lt;/tt&amp;gt; критерия conntrack (но, в отличие от него, не поддерживающий состояния DNAT и SNAT).&lt;br /&gt;
&lt;br /&gt;
Долгое время был основным критерием определения состояния, и до сих пор фигурирует во многих руководствах и примерах. Однако в настоящее время разработчики iptables рекомендуют использовать вместо него критерий conntrack. Возможно, что критерий state вообще будет удален из будущих версий iptables/netfilter.&lt;br /&gt;
&lt;br /&gt;
=== Дополнительные критерии ===&lt;br /&gt;
&lt;br /&gt;
Дополнительные критерии iptables подгружаются при помощи параметра &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;--match&amp;lt;/tt&amp;gt;). Далее можно указать дополнительные параметры, специфичные для данного конкретного критерия. Если дополнительных критериев несколько, не смешивайте их параметры — указывайте нужные параметры каждого критерия непосредственно после его вызова через &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Перед некоторыми дополнительными параметрами критерия может стоять восклицательный знак. В соответствии с принятыми в iptables соглашениями, это означает логическую инверсию параметра, то есть его смысл меняется на противоположный. Но такая возможность предусмотрена отнюдь не для всех параметров.&lt;br /&gt;
&lt;br /&gt;
Заметим, что перечисленные выше критерии состояния и критерии, специфичные для протоколов, по сути также являются параметрами соответствующих дополнительных критериев (например, при указании &amp;lt;tt&amp;gt;-p tcp&amp;lt;/tt&amp;gt; подразумевается еще и &amp;lt;tt&amp;gt;-m tcp&amp;lt;/tt&amp;gt;). Однако в силу ряда причин более логичным и понятным было их отделение от остальных дополнительных критериев. Обратите внимание, что ''все'' параметры вышеперечисленных критериев допускают логическое отрицание (например, &amp;lt;tt&amp;gt;-m conntrack ! --ctstate NEW&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Справочную информацию по любому из дополнительных критериев можно получить, используя команду&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -m название_критерия -h&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Вспомогательные критерии ====&lt;br /&gt;
&lt;br /&gt;
К этой группе можно отнести критерии, расширяющие возможности других критериев.&lt;br /&gt;
&lt;br /&gt;
* '''multiport''' — позволяет указать несколько (до 15) портов и/или их диапазонов (для протоколов TCP, UDP, SCTP, DCCP и UDP Lite). Поддерживает следующие параметры&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --sports&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source-ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]&amp;lt;/tt&amp;gt; — улучшенная версия критерия &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;, описанного выше. Позволяет перечислить (без пробелов, через запятую) до 15 портов или их диапазонов.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --dports&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination-ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]&amp;lt;/tt&amp;gt; — улучшенная версия критерия &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt;, описанного выше. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -p tcp -m multiport --dport 80,8000:8008 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
позволит принимать TCP-пакеты, приходящие на порты 80 и с 8000 по 8008.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --ports ''порт''[:''порт''][,''порт''[:''порт''][,...]]&amp;lt;/tt&amp;gt; — пакет будет подпадать под этот критерий, если его исходный порт ''или'' порт назначения присутствует в указанном списке.&lt;br /&gt;
&lt;br /&gt;
* '''iprange''' — позволяет указать диапазон IP-адресов, не являющийся подсетью. Поддерживает следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --src-range ''адрес''[-''адрес'']&amp;lt;/tt&amp;gt; — позволяет указать диапазон исходных адресов. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m iprange --src-range 192.168.0.8-192.168.0.25 -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
заблокирует все пакеты, исходный адрес которых лежит в диапазоне с 192.168.0.8 по 192.168.0.25 включительно.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --dst-range ''адрес''[-''адрес'']&amp;lt;/tt&amp;gt; — позволяет указать диапазон адресов назначения.&lt;br /&gt;
&lt;br /&gt;
==== Критерии маркировки ====&lt;br /&gt;
&lt;br /&gt;
* '''mark''' — позволяет выделять пакеты с заданной маркировкой (nfmark). Имеет единственную опцию&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --mark ''значение''[/''маска'']&amp;lt;/tt&amp;gt; — указывает значение маркировки. Простейший пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-m mark --mark 15&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет выделять пакеты с маркировкой 15.&lt;br /&gt;
&lt;br /&gt;
Если указана маска, то перед сравнением с заданным значением маркировка каждого пакета комбинируется с этой маской посредством логической операции AND, то есть проверяется условие &amp;lt;tt&amp;gt;x &amp;amp; ''маска'' == ''значение''&amp;lt;/tt&amp;gt; (где x — маркировка текущего пакета). Такой подход позволит сравнивать значения отдельных битов. Например, критерию&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-m mark --mark 64/64&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет отлавливать пакеты, в маркировке которых установлен 7-й бит (&amp;lt;math&amp;gt;2^6=64&amp;lt;/math&amp;gt;, при этом первый бит соответствует &amp;lt;math&amp;gt;2^0&amp;lt;/math&amp;gt;). В частности, 64…127, 192…255, 320…383 и т. д.&lt;br /&gt;
&lt;br /&gt;
Еще один пример —&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-m mark --mark 2/3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет определять пакеты, в маркировке которых установлен второй бит, но снят первый. Такие числа будут нацело делиться на два, но не делиться на четыре — 2, 6, 10, 14, …&lt;br /&gt;
&lt;br /&gt;
* '''connmark''' — полностью аналогичен mark, но проверяет не маркировку пакета (nfmark), а маркировку соединения (ctmark). Также имеет параметр &amp;lt;tt&amp;gt;--mark&amp;lt;/tt&amp;gt; с аналогичным синтаксисом.&lt;br /&gt;
&lt;br /&gt;
В качестве практического примера использования меток пакетов и соединений рассмотрим улучшение работы l7-filter-userspace.&lt;br /&gt;
&lt;br /&gt;
Userspace-вариант l7-filter является демоном, взаимодействующим с netfilter через подсистему nfnetlink_queue — действие NFQUEUE в терминологии iptables. При помощи этого действия определенные пакеты можно направить на анализ демону l7-filter. По результатам анализа демон выставит маркировку пакетов: 1 — пакет принадлежит новому соединению, тип которого пока не идентифицирован; 2 — пакет принадлежит соединению, тип которого идентифицировать так и не удалось. Другие значения соответствуют установленным типам соединений (соответствие задается в конфигурационном файле демона) [http://l7-filter.sourceforge.net/HOWTO-userspace#Does].&lt;br /&gt;
&lt;br /&gt;
Задача l7-filter — определить тип протокола прикладного уровня (см. модель OSI) для данного пакета/соединения. Решается эта задача путем анализа содержимого пакета с применением регулярных выражений, позволяющих определить типовые лексемы, характерные для различных протоколов (например, «&amp;lt;tt&amp;gt;220 ftp server ready&amp;lt;/tt&amp;gt;» для FTP или «&amp;lt;tt&amp;gt;HTTP/1.1 200 OK&amp;lt;/tt&amp;gt;» для HTTP). Пакет, в котором встречаются такие лексемы, может быть однозначно классифицирован. В принципе, это дает достаточное основание классифицировать соединение в целом. Однако, в этом поведение kernel и userspace версий l7-filter существенно различается.&lt;br /&gt;
&lt;br /&gt;
Как описывается в [http://l7-filter.sourceforge.net/technicaldetails документации], версия l7-filter-kernel ''хранит'' данные о соединениях и ''использует'' их для классификации пакетов, принадлежащих к соединениям, тип которых уже установлен. В то же время, аналогичное утверждение в отношении l7-filter-userspace в документации отсутствует. И, как показывает практика, userspace-версия ''не&amp;amp;nbsp;использует'' информацию о соединениях. Возможно, это обусловлено техническими ограничениями nfnetlink_queue как средства взаимодействия l7-filter с системой netfilter.&lt;br /&gt;
&lt;br /&gt;
Описанный недостаток значительно снижает эффективность l7-filter — ведь однозначно классифицированы могут быть всего несколько пакетов из каждого соединения, а всего в соединении могут быть миллионы и миллиарды пакетов. Соответственно, применение l7-filter по своему основному назначению — классификация трафика для последующего шейпинга — не оправдывает себя.&lt;br /&gt;
&lt;br /&gt;
Итак, рассмотрим, как, используя возможности netfilter, можно исправить этот недостаток.&lt;br /&gt;
&lt;br /&gt;
Идея решения проста: после обработки пакетов демоном l7-filter, нужно добавить операции по переносу маркировки пакета на соединение (чтобы классифицировать соединение в целом) и с соединения на пакеты (чтобы пометить уже ''все'' пакеты в соединении для дальнейшей обработки шейпером, так как шейпер воспринимает только метки пакетов). Таким образом, классификация одного пакета в соединении влечет классификацию всех последующих пакетов.&lt;br /&gt;
&lt;br /&gt;
Для начала, запустим демон l7-filter-userspace. Небольшое замечание: в его конфигурационном файле (назовем его, например, &amp;lt;tt&amp;gt;l7-filter.conf&amp;lt;/tt&amp;gt;) будем помечать протоколы метками в диапазоне от 16 до 31 включительно (почему — станет понятно из дальнейших пояснений).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
l7-filter -f /etc/l7-filter.conf -q 2 -m 0x1f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Параметр &amp;lt;tt&amp;gt;-f&amp;lt;/tt&amp;gt; указывает путь к конфигурационному файлу, &amp;lt;tt&amp;gt;-q&amp;lt;/tt&amp;gt; — номер очереди, &amp;lt;tt&amp;gt;-m&amp;lt;/tt&amp;gt; — задает биты маркировки, модифицируемые демоном l7-filter (в нашем случае — с первого по пятый, что соответствует диапазону значений маркировки от 0 до 31).&lt;br /&gt;
&lt;br /&gt;
Далее, добавим правила, направляющие весь входящий и исходящий трафик (кроме локального) на анализ демону l7-filter:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -F # На всякий случай очищаем таблицу mangle&lt;br /&gt;
# Направляем на анализ входящий трафик, включая транзитный&lt;br /&gt;
iptables -t mangle -A PREROUTING ! -i lo -j NFQUEUE --queue-num 2&lt;br /&gt;
# Направляем на анализ исходящий трафик, кроме транзитного&lt;br /&gt;
iptables -t mangle -A OUTPUT ! -o lo -j NFQUEUE --queue-num 2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Добавлять второе из этих правил в цепочку POSTROUTING не стоило — ведь в нее попадает как трафик, исходящий от самого хоста, так и транзитный трафик, который уже был обработан ранее, в цепочке PREROUTING. Посмотрев на диаграмму выше, вы можете убедиться, что приведенные правила обрабатывают весь трафик, как принадлежащий самому хосту, так и транзитный, за исключением локального. Локальный трафик (идущий через интерфейс lo), бессмысленно шейпить, а значит, не стоит и классифицировать.&lt;br /&gt;
&lt;br /&gt;
Теперь добавим правила, обеспечивающие копирование маркировки пакетов в маркировку соединений и обратно:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Для входящего трафика (кроме транзитного)&lt;br /&gt;
# Копируем маркировку пакетов в маркировку соединений&lt;br /&gt;
iptables -t mangle -A INPUT -m mark --mark 0x10/0xfffffff0 -j CONNMARK --save-mark&lt;br /&gt;
# И наоборот&lt;br /&gt;
iptables -t mangle -A INPUT -m connmark --mark 0x10/0xfffffff0 -j CONNMARK --restore-mark&lt;br /&gt;
# Аналогично для исходящего трафика (включая транзитный)&lt;br /&gt;
iptables -t mangle -A POSTROUTING -m mark --mark 0x10/0xfffffff0 -j CONNMARK --save-mark&lt;br /&gt;
iptables -t mangle -A POSTROUTING -m connmark --mark 0x10/0xfffffff0 -j CONNMARK --restore-mark&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Поясним два момента. Во-первых, добавление этих правил в цепочки PREROUTING и OUTPUT, сразу после правил, передающих трафик демону l7-filter, не имеет смысла — после обработки пакетов демон [http://l7-filter.sourceforge.net/HOWTO-userspace#Does применяет] к ним действие ACCEPT, прекращающее обработку пакета в рамках исходных цепочек. Поэтому мы добавляем эти правила в цепочки, идущие «ниже по течению». Как вы можете заметить по диаграмме выше, такая комбинация правил также обеспечивает обработку всего трафика.&lt;br /&gt;
&lt;br /&gt;
Второй момент, который стоит пояснить — маски специального вида. По сути, они позволяют проверить, лежит ли маркировка пакета в диапазоне от 16 до 31. Такая защита позволяет избежать обработки маркировок 0 (такую маркировку имеет локальный трафик, так как он не проходит процедуру анализа), 1 и 2 (эти значения маркировки, как уже было замечено выше, означают, что тип пакета не определен), а также 32 и выше (эти значения мы оставляем для других задач).&lt;br /&gt;
&lt;br /&gt;
Как показывает [http://www.linux.org.ru/jump-message.jsp?msgid=3790164&amp;amp;cid=3791754 практика], даже в самом примитивном случае (детекция протокола HTTP, сервер — nginx 0.6.32, клиент — [http://www.hping.org/wbox/ wbox] 4), эффективность детекции возрастает — без использования маркировки соединений регистрируются лишь 2 исходящих пакета (l7-filter работает на сервере), с использованием — 3 исходящих и 2 входящих. Детальное исследование показывает, что детекции избегают лишь первые четыре пакета в соединении — 2 SYN-пакета и 2 пакета с данными. Это цифры, характерные для тестовой задачи — при передаче больших объемов данных количество детектированных пакетов будет значительно больше, в то время как количество не определенных пакетов сохранит тот же порядок.&lt;br /&gt;
&lt;br /&gt;
Более того, предложенный метод решает задачу, не решенную даже в реализации l7-filter-kernel — маркировка связанных соединений. Согласно документации iptables, маркировка соединений автоматически копируется с исходных соединений на связанные с ними (например, с управляющего FTP-соединения на соединение данных).&lt;br /&gt;
&lt;br /&gt;
: ''Примечание: следующий пример планируется к переносу в еще не написанный раздел статьи (Прочие критерии → statistic)''.&lt;br /&gt;
&lt;br /&gt;
В качестве практического примера использования меток пакетов и соединений можно рассмотреть задачу стохастической балансировки соединений между несколькими аплинками.&lt;br /&gt;
Допустим, у нас есть три провайдера, подключенных к интерфейсам eth0, eth1 и eth2 (это могут быть и VLAN-порты одного интерфейса, суть от этого не меняется, только названия), и их шлюзы имеются соответственно IP-адреса 208.77.188.1, 208.77.189.1, 208.77.190.1.&lt;br /&gt;
&lt;br /&gt;
Для начала, создадим для каждого провайдера свою таблицу маршрутизации&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo -e &amp;quot;\n110\tstatic\n111\tprov1\n112\tprov2\n113\tprov3&amp;quot; &amp;gt;&amp;gt; /etc/iproute2/rt_tables&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Этот код добавит в конец файла &amp;lt;tt&amp;gt;/etc/iproute2/rt_tables&amp;lt;/tt&amp;gt; строки&lt;br /&gt;
  110    static&lt;br /&gt;
  111    prov1&lt;br /&gt;
  112    prov2&lt;br /&gt;
  113    prov3&lt;br /&gt;
устанавливающие соответствие между внутренними номерами таблиц маршрутизации и их символьными именами. Используемые здесь имена prov1, prov2 и prov3, разумеется, условны. Таблица static — особая, ее мы рассмотрим чуть ниже.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что это действие выполняется только один раз — не надо повторять его при каждой загрузке системы!&lt;br /&gt;
&lt;br /&gt;
Далее, сделаем каждого провайдера шлюзом по умолчанию в «своей» таблице:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip route add default via 208.77.188.1 dev eth0 table prov1&lt;br /&gt;
ip route add default via 208.77.189.1 dev eth1 table prov2&lt;br /&gt;
ip route add default via 208.77.190.1 dev eth2 table prov3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Добавим для каждой таблицы правило, отправляющее в нее пакеты с соответствующей маркировкой:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip rule add fwmark 1 table prov1&lt;br /&gt;
ip rule add fwmark 2 table prov2&lt;br /&gt;
ip rule add fwmark 3 table prov3&lt;br /&gt;
# Но прежде всего пакеты должны пройти таблицу static&lt;br /&gt;
ip rule add table static prio 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Таблица static предназначена для обслуживания статических маршрутов. В частности, в нее мы занесем подсети провайдеров (предположим, что все они класса 1C), а также наши внутренние локальные сети (если таковые есть):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Провайдеры&lt;br /&gt;
ip route add 208.77.188.0/24 dev eth0 table static&lt;br /&gt;
ip route add 208.77.189.0/24 dev eth1 table static&lt;br /&gt;
ip route add 208.77.190.0/24 dev eth2 table static&lt;br /&gt;
# Две наших локалки&lt;br /&gt;
ip route add 192.168.1.0/24 dev eth3 table static&lt;br /&gt;
ip route add 192.168.2.0/24 dev eth4 table static&lt;br /&gt;
# Сбрасываем кеш маршрутов&lt;br /&gt;
ip route flush cache&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Таким образом, если нашему хосту нужно будет обратиться в подсеть провайдера prov2 (208.77.189.0/24), то маршрут пойдет сразу через интерфейс eth1. Также в этой таблице присутствуют маршруты для наших внутренних локальных сетей — с ними тоже все просто.&lt;br /&gt;
&lt;br /&gt;
По сути дела, таблица static обычно содержит те же маршруты, что и таблица main (главная таблица маршрутизации), за исключением маршрута по умолчанию — таких маршрутов у нас несколько и каждый из них размещается в отдельной таблице, выбор между которыми осуществляется на основании назначенной iptables/netfilter маркировки.&lt;br /&gt;
&lt;br /&gt;
Заметим, что ни в таблицу static, ни в какие-либо другие таблицы не&amp;amp;nbsp;нужно вносить loopback-маршруты, например «127.0.0.1/8 dev lo», так как все эти маршруты фигурируют в автоматически создаваемой таблице local, которую любой пакет проходит в первую очередь (нетрудно убедиться в этом, посмотрев вывод команды «ip rule show»).&lt;br /&gt;
&lt;br /&gt;
Далее, отключим статическую антиспуфинговую фильтрацию:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl net.ipv4.conf.all.rp_filter=0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Reverse path filtering — штука, конечно, удобная и полезная но, к сожалению, совершенно не совместимая с динамической маршрутизацией.&lt;br /&gt;
&lt;br /&gt;
Если вы планируете использовать этот компьютер не&amp;amp;nbsp;только как шлюз, и но и как интернет-сервер (то есть предоставлять доступ к нему извне), необходимо выполнить привязку входящих соединений к их интерфейсам&amp;amp;nbsp;— в противном случае могут возникнуть проблемы, если обращение извне придет через одного провайдера, а сервер ответит через другого.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -N bind_connect # Создаем отдельную цепочку (для простоты управления)&lt;br /&gt;
# Следите за правильным соответствием значений меток и интерфейсов!&lt;br /&gt;
iptables -t mangle -A bind_connect -i eth0 -j CONNMARK --set-mark 1&lt;br /&gt;
iptables -t mangle -A bind_connect -i eth1 -j CONNMARK --set-mark 2&lt;br /&gt;
iptables -t mangle -A bind_connect -i eth2 -j CONNMARK --set-mark 3&lt;br /&gt;
# Пропускаем через эту процедуру все новые соединения к нашему серверу&lt;br /&gt;
iptables -t mangle -I INPUT -m conntrack --ctstate NEW -j bind_connect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь, в сочетании с операцией &amp;lt;tt&amp;gt;-j CONNMARK --restore-mark&amp;lt;/tt&amp;gt;, которой мы подвергнем исходящий с нашего сервера трафик (см. ниже), эта процедура обеспечит корректную обработку входящих соединений. (Отметим, что, если бы нам не нужно было бы балансировать исходящие соединения, мы могли бы обойтись вообще без помощи iptables/netfilter, выполнив привязку входящих соединений через правила вида &amp;lt;tt&amp;gt;ip rule add from 208.77.188.100 table prov1&amp;lt;/tt&amp;gt; и т.п. — ответные пакеты всегда уходят с того же адреса, на который пришел запрос, так что в качестве критерия для выбора шлюза можно использовать исходный адрес.)&lt;br /&gt;
&lt;br /&gt;
Ввиду того, что выбор исходящего адреса для каждого нового соединения осуществляется на основании правил статической маршрутизации (таблица main), могут возникнуть ошибки. Например, если в маршруте по умолчанию (default) в таблице main указан интерфейс eth0, то все исходящие от нас во внешнюю сеть (интернет) соединения будут иметь в качестве исходного адреса первый адрес интерфейса eth0, и ответные пакеты пойдут именно на этот интерфейс. Чтобы избежать возникновения таких ситуаций, добавим маскарадинг для всех исходящих соединений (предполагается, что у всех провайдеров наши внешние адреса имеют вид 208.77.x.100):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 208.77.188.100&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to-source 208.77.189.100&lt;br /&gt;
iptables -t nat -A POSTROUTING -o eth2 -j SNAT --to-source 208.77.190.100&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
А теперь — самое интересное. Используя описанный ниже критерий statistic, мы будем случайно распределять метки между пакетами.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -N select_prov # Создаем для этого специальную цепочку&lt;br /&gt;
iptables -t mangle -A select_prov -j CONNMARK --set-mark 1 # Ставим всем соединениям маркировку 1&lt;br /&gt;
iptables -t mangle -A select_prov -m statistic --mode random --probability 0.34 -j RETURN # С вероятностью 34% выходим из этой цепочки&lt;br /&gt;
iptables -t mangle -A select_prov -j CONNMARK --set-mark 2 # Ставим всем оставшимся соединениям маркировку 2&lt;br /&gt;
iptables -t mangle -A select_prov -m statistic --mode random --probability 0.5 -j RETURN # С вероятностью 50% выходим из этой цепочки&lt;br /&gt;
iptables -t mangle -A select_prov -j CONNMARK --set-mark 3 # Всем, кто дошел досюда, ставим маркировку 3&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Первое правило в этой цепочке пройдут все пакеты, вошедшие в нее. После этого, 34 % (примерно треть из них) покинет цепочку согласно второму правилу. Далее, оставшиеся пакеты (66 % от первоначального количества) получат маркировку 2. После этого половина из них (то есть 33 % от начального) покинут цепочку с этой маркировкой. Оставшаяся половина (тоже 33 % от начального количества) получат маркировку 3.&lt;br /&gt;
&lt;br /&gt;
После этого, создадим вспомогательную цепочку, осуществляющую маркировку соединений и пакетов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -N sort_connect&lt;br /&gt;
iptables -t mangle -A sort_connect -o lo -j RETURN # Локальным соединениям балансировка не нужна&lt;br /&gt;
# Аналогично выгоняем пакеты, выходящие через интерфейсы внутренней локалки, если она есть&lt;br /&gt;
iptables -t mangle -A sort_connect -o eth3 -j RETURN&lt;br /&gt;
iptables -t mangle -A sort_connect -o eth4 -j RETURN&lt;br /&gt;
iptables -t mangle -A sort_connect -m conntrack --ctstate NEW -j select_prov # Все новые пакеты прогоняем через процедуру случайного выбора&lt;br /&gt;
iptables -t mangle -A sort_connect -j CONNMARK --restore-mark # Копируем маркировку соединений на пакеты&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Через цепочку &amp;lt;tt&amp;gt;select_prov&amp;lt;/tt&amp;gt; мы прогоняем только новые пакеты, то есть первые пакеты каждого соединения. После этой процедуры соединение уже имеет маркировку. К сожалению, на данный момент роутинговая подсистема ядра Linux не умеет маршрутизировать пакеты на основании маркировки соединения — только на основании маркировки пакетов. Поэтому действием &amp;lt;tt&amp;gt;CONNMARK --restore-mark&amp;lt;/tt&amp;gt; мы копируем маркировку соединений в маркировку пакетов.&lt;br /&gt;
&lt;br /&gt;
Осталось только добавить вызов этой цепочки в таблицу mangle:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -I OUTPUT -j sort_connect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь все ваши исходящие соединения будут балансироваться согласно описанным правилам.&lt;br /&gt;
&lt;br /&gt;
Аналогичную функциональность можно реализовать и для транзитных соединений. Для этого достаточно добавить вызов &amp;lt;tt&amp;gt;sort_connect&amp;lt;/tt&amp;gt; в цепочку FORWARD таблицы mangle:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -I FORWARD -j sort_connect&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Разумеется, при этом должна быть разрешена передача транзитного трафика, как в таблице filter, так и на уровне sysctl. Как это делается — см. выше.&lt;br /&gt;
&lt;br /&gt;
Заметим, что кроме алгоритма случайной балансировки, критерий statistic позволяет реализовать балансировку в режим round robin. Для этого поменяем цепочку &amp;lt;tt&amp;gt;select_prov&amp;lt;/tt&amp;gt; следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -F select_prov # Очищаем ее&lt;br /&gt;
iptables -t mangle -A select_prov -j CONNMARK --set-mark 1 # Ставим всем соединениям маркировку 1&lt;br /&gt;
iptables -t mangle -A select_prov -m statistic --mode nth --every 3 -j RETURN # Первый из трех пакетов - выходим&lt;br /&gt;
iptables -t mangle -A select_prov -j CONNMARK --set-mark 2 # Ставим всем оставшимся соединениям маркировку 2&lt;br /&gt;
iptables -t mangle -A select_prov -m statistic --mode nth --every 2 -j RETURN # Один из оставшихся двух - выходим&lt;br /&gt;
iptables -t mangle -A select_prov -j CONNMARK --set-mark 3 # Последний&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее о принципах работы критерия statistic см. ниже.&lt;br /&gt;
&lt;br /&gt;
В завершение нашего обсуждения стоит заметить, что в некоторых случаях для балансировки соединений достаточно единственной команды&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
ip route add default scope global nexthop via 208.77.188.1 dev eth0 weight 1 nexthop via 208.77.189.1 dev eth1 weight 1 # И т.д.&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Стоит обратить особое внимание на тот факт, что данный метод балансирует ''пакеты'', а не соединения. Например, в том случае, если вы хотите организовать выход в интернет из локальной сети через нескольких провайдеров, не имея единого внешнего адреса, этот метод может работать некорректно — часть пакетов пройдет через одного провайдера и после операции NAT получит один исходный адрес, часть пойдет через другого и соответственно получит другой адрес, и в результате удаленные хосты не смогут правильно обрабатывать соединения, исходящие из вашей сети. Однако, в большинстве случаев этот негативный эффект нивелируется другим фактором — кэшированием маршрутов. При прохождении через такое правило серии пакетов, адресованных некоторому хосту, действительно случайным выбор будет только для первого из них, после чего выбранный маршрут будет закэширован, и остальные пакеты к этому хосту будут маршрутизироваться через тот же шлюз. С одной стороны, подобный эффект позволяет соединениям корректно функционировать, с другой стороны — балансировка оказывается не такой уж и случайной. К тому же, после очистки кэша маршрутов (например, посредством ввода команды &amp;lt;tt&amp;gt;ip route flush cached&amp;lt;/tt&amp;gt;), работа существующих на этот момент соединений может быть нарушена. В качестве наиболее безопасного и целесообразного применения описанного метода можно привести задачу балансировки транзитного трафика в сетях без NAT (условия «прямой видимости» между балансирующим маршрутизатором и точкой схождения потоков трафика). В том случае, если доступ к шлюзам осуществляется через один сетевой интерфейс, этим методом можно балансировать и соединения, исходящие от самого хоста.&lt;br /&gt;
&lt;br /&gt;
Также заметим, что описанные в этом примере методы балансировки не учитывают загруженность каналов. Для этого рекомендуется использовать критерий rateest и действие RATEEST совместно с уже знакомым нам CONNMARK.&lt;br /&gt;
&lt;br /&gt;
==== Лимитирующие критерии ====&lt;br /&gt;
&lt;br /&gt;
К этой группе относятся критерии, позволяющие ограничивать количество пакетов, соединений, и переданных байт.&lt;br /&gt;
&lt;br /&gt;
* '''limit''' — позволяет ограничить количество пакетов в единицу времени. Параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--limit ''количество''[/second|/minute|/hour|/day]&amp;lt;/tt&amp;gt; — задает ограничение на количество пакетов в секунду (second), минуту (minute), час (hour) или сутки (day). Пакеты в пределах этого количества считаются удовлетворяющими критерию, сверх этого количества — не удовлетворяющими.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--limit-burst ''количество''&amp;lt;/tt&amp;gt; — задает длину очереди, то есть максимальную пропускную способность.&lt;br /&gt;
&lt;br /&gt;
Критерий -limit использует модель «дырявого ведра», и --limit-burst задает «объем ведра», а --limit — «скорость вытекания». Каждому такому критерию соответствует своя очередь, длина которой задается параметром --limit-burst. Если в очереди есть пакеты, то со скоростью, заданной в --limit, они покидают очередь и считаются удовлетворяющими критерию. Если же вся очередь занята, то новые пакеты в ней не регистрируются и считаются ''не'' удовлетворяющими критерию.&lt;br /&gt;
Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -I INPUT -m limit --limit 3/min --limit-burst 5 -j LOG --log-level debug --log-prefix &amp;quot;INPUT packet: &amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
предполагает очередь на пять пакетов, которая «продвигается» со скоростью 3 пакета в минуту. При непрерывном поступлении входящих пакетов, очередь всегда будет заполнена, и в лог будут заноситься в среднем по три пакета в минуту. Однако, если входящих пакетов долго не будет, то очередь успеет очиститься, и при поступлении пяти и менее новых пакетов, они пойдут в лог подряд. В любом случае, скорость попадания пакетов в лог остается неизменной.&lt;br /&gt;
&lt;br /&gt;
Типичная ошибка новичков — использовать limit для ограничения TCP-трафика, например, так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -m limit --limit 10000/sec --limit-burst 10000 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Это пример попытки защитить web-сервер от DDoS-атаки, ограничив количество пакетов в единицу времени. Однако, это правило не помешает без особого труда завалить сервер запросами (считая, что на один запрос требуется два входящих пакета — SYN-пакет и пакеты данных, содержащий, например, только GET /, согласно спецификации HTTP 0.9). При этом могут возникнуть помехи для легальных пользователей, например, загружающих на сервер большой файл методом POST. Более корректным решением будет ограничивать не скорость входящего потока данных, а скорость открытия новых соединений:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -m conntrack --ctstate NEW -m limit --limit 32/sec --limit-burst 32 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь мы ограничиваем количество не всех пакетов, а только новых, то есть мы разрешаем открывать не более 32 новых соединений в секунду. Впрочем, число 32 приведено здесь только для примера. Конкретное значение скорости для вашей задачи рекомендуем определять самостоятельно.&lt;br /&gt;
&lt;br /&gt;
* '''hashlimit''' — позволяет применять ограничения, аналогичные критерию limit, к группам хостов, подсетей или портов, используя всего одно правило. При этом для каждого хоста, подсети или порта создается отдельная очередь. Можно задвать, например, такие критерии:&lt;br /&gt;
&lt;br /&gt;
«1000 пакетов в секунду с каждого хоста из подсети 192.168.0.0/16»&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-s 192.168.0.0/16 -m hashlimit --hashlimit-upto 1000/sec --hashlimit-mode srcip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
«100 пакетов в секунду с каждого TCP-порта хоста 192.168.1.1»&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-s 192.168.1.1 -m hashlimit --hashlimit-upto 100/sec --hashlimit-mode srcport&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
«10000 пакетов в минуту с каждой подсети префикса 28 (маска 255.255.255.240) из диапазона 10.0.0.0/8»&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-s 10.0.0.0/8 -m hashlimit --hashlimit-upto 10000/min --hashlimit-mode srcip --hashlimit-srcmask 28&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что в ''каждом'' из этих правил нужно обязательно указать имя таблицы очередей (haslimit-name, см. ниже), однако, в целях простоты изложения, в некоторых примерах этот параметр опущен.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим основные параметры этого критерия более подробно:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-mode {srcip|srcport|dstip|dstport}[,...]&amp;lt;/tt&amp;gt; — задает список контролируемых параметров: адреса (ip) и порты (port) источника (src) и назначения (dst). Например, если указать параметр&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
--hashlimit-mode srcip,dstip&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
то будет создаваться отдельная очередь для каждой пары «адрес источника — адрес назначения», то есть ограничение будет вводиться на количество пакетов, передаваемых с каждого хоста на другой хост (разумеется, если эти пакеты идут через наш сервер). Или, например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
--hashlimit-mode srcip,srcport&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет создавать отдельную очередь для каждого исходного порта каждого хоста.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-upto ''количество''[/second|/minute|/hour|/day]&amp;lt;/tt&amp;gt; — этот параметр задает скорость движения очереди (аналог &amp;lt;tt&amp;gt;--limit&amp;lt;/tt&amp;gt;). Если пакеты поступают с такой же или меньшей скоростью, они считаются подпадающими под критерий. Обратите внимание, что этот параметр ''не'' поддерживает логической инверсии (отрицания) через восклицательный знак (см. ниже).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-above ''количество''[/second|/minute|/hour|/day]&amp;lt;/tt&amp;gt; — этот параметр таке задает скорость движения очереди, но смысл его противоположный — если пакеты поступают с ''большей'' скоростью, они считаются подпадающими под критерий.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-burst ''количество''&amp;lt;/tt&amp;gt; — задает длину каждой очереди. Аналогичен &amp;lt;tt&amp;gt;--limit-burst&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-srcmask ''префикс''&amp;lt;/tt&amp;gt; — задает размер подсети исходных адресов, для которой вводится своя очередь. Имеет смысл, только если в haslimit-mode указан режим srcip. Как уже говорилось выше,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-m hashlimit --hashlimit-mode srcip --hashlimit-srcmask 28&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет заводить отдельную очередь для каждой подсети с маской 255.255.255.240 (подробнее про префиксы и маски см. CIDR).&lt;br /&gt;
По умолчанию 32 (своя очередь для каждого отдельного хоста). Если указать 0, то контроль по параметру srcip теряет смысл.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-dstmask ''префикс''&amp;lt;/tt&amp;gt; — задает размер подсети исходных адресов, для которой вводится своя очередь. Имеет смысл, только если в haslimit-mode указан режим dstip. Принцип использования аналогичен hashlimit-srcmask.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hashlimit-name ''имя''&amp;lt;/tt&amp;gt; — позволяет использовать несколько независимых таблиц очередей (hashes), распознаваемых по имени. Обязательный параметр. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Пропускаем все, что идет по уже установленным соединениям&lt;br /&gt;
# Вводим ограничения для новых подключений по FTP&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 21 -m hashlimit --hashlimit-upto 5/min --hashlimit-mode srcip --hashlimit-name ftphash -j ACCEPT&lt;br /&gt;
# Вводим ограничения для новых подключений по rsync.&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 873 -m hashlimit --hashlimit-upto 5/min --hashlimit-mode srcip --hashlimit-name rsynchash -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP # Всех остальных не пускаем&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь очереди ограничений для подключения к службам FTP и rsync для нашего сервера будут вводиться независимо, то есть если какой-либо хост превысит предел подключений по FTP, то это никак не повлияет на подключения по rsync. Заметим, что в данном конкретном случае аналогичную функциональность можно реализовать, даже не используя разные хеши:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Пропускаем все, что идет по уже установленным соединениям&lt;br /&gt;
# Вводим ограничения для новых подключений по FTP и rsync&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 21,873 -m hashlimit --hashlimit-upto 5/min --hashlimit-mode srcip,dstport --hashlimit-name ftprsynchash -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP # Всех остальных не пускаем&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Впрочем, выбирая между этими двумя реализациями, стоит учитывать, что размер каждого хеша ограничен.&lt;br /&gt;
&lt;br /&gt;
Не забывайте указывать имя таблицы очередей при каждом использовании критерия hashlimit. Если вы не планируете совместно использовать одни и те же таблицы в нескольких правилах, эти имена должны различаться.&lt;br /&gt;
&lt;br /&gt;
Доступ к таблицам очередей возможен через procfs (файл &amp;lt;tt&amp;gt;/proc/net/ipt_hashlimit/имя_таблицы&amp;lt;/tt&amp;gt;). Подробнее о формате этого файла можно почитать [http://www.opennet.ru/base/net/iptables_tbf.txt.html здесь], однако учтите, что большая часть сведений, приведенных в указанной статье, устарела.&lt;br /&gt;
&lt;br /&gt;
Критерий haslimit также имеет ряд параметров, не описанных здесь (максимальный размер таблицы, время жизни записи в таблице, интервал «сбора мусора», и т. п.). За подробными сведениями обратитесь к документации.&lt;br /&gt;
&lt;br /&gt;
* '''connlimit''' — позволяет ограничивать количество одновременно открытых соединений с каждого IP-адреса (или подсети). Параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --connlimit-above количество&amp;lt;/tt&amp;gt; — минимальное количество соединений. Все пакеты, проходящие по соединениям, установленным сверх заданного количества, считаются удовлетворяющими критерию. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 3 -j DROP&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
разрешит не более трех одновременных соединений к нашему веб-серверу с одного IP-адреса. Аналогичного эффекта можно добиться командами&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -m connlimit ! --connlimit-above 3 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--connlimit-mask&amp;lt;/tt&amp;gt; — маска подсети, для которой устанавливается общее ограничение на количество соединений. Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -m connlimit --connlimit-above 5 --connlimit-mask 24 -j DROP&lt;br /&gt;
iptables -A INPUT -p tcp --dport 80 -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
разрешит не более пяти одновременных соединений на порт 80 с каждой подсети класса 1C.&lt;br /&gt;
&lt;br /&gt;
Не надо путать connlimit с hashlimit — hashlimit позволяет ограничить ''скорость'' поступления пакетов с хостов или подсетей (в сочетании с &amp;lt;tt&amp;gt;-m conntrack --ctstate NEW&amp;lt;/tt&amp;gt; — скорость открытия новых соединений), а connlimit — ''количество'' одновременно открытых соединений.&lt;br /&gt;
&lt;br /&gt;
* '''connbytes''' — позволяет ограничивать количество переданных байт или пакетов. Параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --connbytes ''мин'':[''макс'']&amp;lt;/tt&amp;gt; — собственно задает количество пакет или байт. Можно указать просто минимальное количество или диапазон.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--connbytes-dir {original|reply|both}&amp;lt;/tt&amp;gt; — задает направление движения пакетов. Проверяются только пакеты, движущиеся от инициатора соединения к отвечающему (original), наоборот (reply) или в обоих направлениях (both).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--connbytes-mode {packets|bytes|avgpkt}&amp;lt;/tt&amp;gt; — задает собственно учитываемую величину: количество пакетов (packets), количество байт (bytes) или средний размер пакета (avgpkt).&lt;br /&gt;
&lt;br /&gt;
Пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Для соединений, по которым передано более 500 КБ, ставим минимальный приоритет TOS (требование максимальной полосы)&lt;br /&gt;
iptables -t mangle -I INPUT -m connbytes --connbytes 512000: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Maximize-Throughput&lt;br /&gt;
iptables -t mangle -I OUTPUT -m connbytes --connbytes 512000: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Maximize-Throughput&lt;br /&gt;
# Для соединений, по которым передано менее 50 КБ, ставим максимальный приоритет TOS (требование минимальной задержки)&lt;br /&gt;
iptables -t mangle -I INPUT -m connbytes ! --connbytes 51200: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Minimize-Delay&lt;br /&gt;
iptables -t mangle -I OUTPUT -m connbytes ! --connbytes 51200: --connbytes-dir both --connbytes-mode bytes -j TOS --set-tos Minimize-Delay&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Таким образом, все пакеты, принадлежащие «легким» соединениям, будут маркироваться как наиболее приоритетные, а пакеты, проходящие по «тяжеловесным» соединениям — как наименее приоритетные. Такой подход позволит рационально распределять канал между различными задачами, например, просмотром веб-страниц («легкие» соединения) и скачиванием файлов («тяжелые» соединения).&lt;br /&gt;
&lt;br /&gt;
Конечно, при таком подходе даже «тяжелые» соединения будут занимать канал с наивысшим приоритетом, пока не превысят ограничение. Но даже на медленных соединениях (128 Кбит/с) для этого достаточно всего четырех секунд (если эта закачка в данный момент единственная). После превышения лимита 50 Кбайт соединение получит средний приоритет (TOS не установлен), а еще через некоторое время соединение превысит второй лимит — 500 Кбайт, и получит минимальный приоритет. В то же время, «легкие» соединения в большинстве случаев не превышают даже первого лимита, и поэтому целиком проходят с повышенным приоритетом.&lt;br /&gt;
&lt;br /&gt;
* '''quota''' — позволяет задать квоту в байтах для данного конкретного правила. Имеет единственный параметр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--quota количество_байт&amp;lt;/tt&amp;gt; — собственно задает квоту.&lt;br /&gt;
&lt;br /&gt;
Для каждого правила, содержащего такой критерий, создается счетчик, который уменьшается с каждым прошедшим по этому правилу пакетом на количество байт, равное размеру этого пакета. Когда значение счетчика доходит до нуля, правило перестает срабатывать. Чтобы восстановить счетчик, удалите правило и добавьте его снова.&lt;br /&gt;
&lt;br /&gt;
Например:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик&lt;br /&gt;
iptables -F FORWARD # Очищаем цепочку FORWARD&lt;br /&gt;
iptables -A FORWARD -m quota --quota 1073741824 -j ACCEPT&lt;br /&gt;
iptables -P FORWARD DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
разрешает хосту передавать не более одного гигабайта транзитного трафика (учитывается трафик в обоих направлениях).&lt;br /&gt;
&lt;br /&gt;
* '''quota2''' — критерий из уже упоминавшегося набора xtables-addons. Является результатом развития идей, заложенных в критерии quota. Позволяет создавать именованные счетчики квот (для совместного использования одного счетчика в нескольких правилах), считать не только байты, но и пакеты, а также создавать отдельные правила для пакетов, превышающих квоту (логическая инверсия параметра &amp;lt;tt&amp;gt;--quota&amp;lt;/tt&amp;gt;). Поддерживаются следующие параметры:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--name ''имя''&amp;lt;/tt&amp;gt; — задает имя счетчика. Текущее значение счетчика содержится в файле &amp;lt;tt&amp;gt;/proc/net/xt_quota/''имя''&amp;lt;/tt&amp;gt;. Его можно вывести на экран&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat /proc/net/xt_quota/имя&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
или задать вручную&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo значение &amp;gt; /proc/net/xt_quota/имя&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Для осуществления этих действий, как и для работы с iptables, нужны полномочия суперпользователя.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --quota ''количество''&amp;lt;/tt&amp;gt; — проверяет текущее значение счетчика и уменьшает его на размер текущего пакета. Этот же параметр задает начальное значение счетчика (если счетчик с таким именем уже существует, он не сбрасывается). Пакет считается подпадающим под критерий, если счетчик еще не дошел до нуля (при указании логической инверсии — наоборот). Если немного усложнить наш предыдущий пример,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl net.ipv4.ip_forward=1 # Разрешаем шлюзу передавать транзитный трафик&lt;br /&gt;
iptables -F FORWARD # Очищаем цепочку FORWARD&lt;br /&gt;
# Устанавливаем квоту для первой подсети&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.0/24 -m quota2 --name first --quota 1073741824 -j ACCEPT&lt;br /&gt;
# Для тех, кто идет из первой подсети сверх квоты - блокируем и сообщаем об отказе.&lt;br /&gt;
# Кстати, счетчик first уже создан, поэтому теперь в параметре quota можно писать любое число. Но мы все-таки напишем 1 Гб.&lt;br /&gt;
iptables -A FORWARD -s 192.168.1.0/24 -m quota2 --name first ! --quota 1073741824 -j REJECT&lt;br /&gt;
# Устанавливаем квоту для второй подсети&lt;br /&gt;
iptables -A FORWARD -s 192.168.2.0/24 -m quota2 --name second --quota 536870912 -j ACCEPT&lt;br /&gt;
iptables -P FORWARD DROP&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь для подсети 192.168.1.0/24 установлена квота в 1 Гб, и при превышении этой квоты пакеты блокируются, причем их отправителям хост отвечает пакетами icmp-port-unreachable, уведомляя их, что передача данных заблокирована. Для подсети 192.168.2.0/24 устанавливается квота 512 Мб, и при ее превышении никаких сообщений не посылается (пакеты блокируются «молча»). Так же молча блокируются транзитные пакеты из всех остальных подсетей.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--packets&amp;lt;/tt&amp;gt; — при указании этого параметра счетчик учитывает количество пакетов, а не их суммарный размер.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--grow&amp;lt;/tt&amp;gt; — ''увеличивает'' счетчик, вместо того, чтобы уменьшать его. Критерий с этим параметром всегда возвращает истину. Позволяет создавать счетчики «приходно-расходного типа». Например,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
-A INPUT -p tcp --dport 6881 -m quota2 --name bt --grow&lt;br /&gt;
-A OUTPUT -p tcp --sport 6881 -m quota2 --name bt&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
позволяет в любой момент определять разность сумм входящих (на TCP-порт 6881) и исходящих (с этого же порта) байт через файл &amp;lt;tt&amp;gt;/proc/net/xt_quota/bt&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Вот [http://jengelh.medozas.de/2009/0717-bandwidth-monitoring.php еще один пример] использования этого критерия для сбора статистики по трафику.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что при указании параметра grow критерий quota2 ''всегда'' будет возвращать истину. Действие для такого правила обычно назначать не имеет смысла — правило изменяет только счетчик квоты, а не сам пакет.&lt;br /&gt;
&lt;br /&gt;
* '''length''' — позволяет использовать в качестве критерия размер пакета. Проверятся размер пакета протокола транспортного уровня (TCP, UDP, SCTP, DCCP и т. д.) или, иначе говоря, размер пакета протокола сетевого уровня (IP, IPv6) за вычетом размера заголовков сетевого уровня. Данный критерий имеет единственный параметр&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --length ''размер''[:''макс_размер'']&amp;lt;/tt&amp;gt;, который может употребляться в нескольких формах:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tt&amp;gt;--length ''размер''&amp;lt;/tt&amp;gt; — пакет проверяется на точное соответствие заданному размеру,&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tt&amp;gt;--length ''мин_размер'':&amp;lt;/tt&amp;gt; — размер пакета должен быть больше или равен заданной величине,&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tt&amp;gt;--length :''макс_размер''&amp;lt;/tt&amp;gt; — размер пакета должен быть меньше или равен заданной величине,&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tt&amp;gt;--length ''мин_размер'':''макс_размер''&amp;lt;/tt&amp;gt; — размер пакета должен попадать в указанный диапазон (включая границы).&lt;br /&gt;
&lt;br /&gt;
Смысл всех приведенных форм может быть заменен на противоположный, как обычно, указанием перед данным параметром восклицательного знака. Все размеры задаются в байтах.&lt;br /&gt;
&lt;br /&gt;
В качестве практического примера использования данного критерия можно рассмотреть установку высокого приоритета TOS (требование минимальной задержки) для небольших транзитных пакетов (размер до 512 байт):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -t mangle -I INPUT -m length --length :512 -j TOS --set-tos Minimize-Delay&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''length2''' — расширение критерия length, доступное в наборе xtables-addons. Отличается от классического length возможностью проверять размеры пакетов на различных уровнях модели OSI. Принимает следующие опции:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--layer3&amp;lt;/tt&amp;gt; — проверка размера пакета сетевого уровня (например, IPv4-пакета).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--layer4&amp;lt;/tt&amp;gt; — проверка размера пакета транспортного уровня (например, TCP-пакета).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--layer5&amp;lt;/tt&amp;gt; — проверка размера полезной нагрузки транспортного уровня (например, содержимого TCP-пакета, ''не''&amp;amp;nbsp;учитывая размер заголовков TCP). Работает корректно только для некоторых протоколов транспортного уровня, на момент написания этих строк (конец 2009) поддерживаются: TCP, UDP, UDPLite, ICMP, ICMPv6, DCCP, SCTP, IPSec(AH и ESP). Для SCTP-пакета в этот размер включаются все секции (chunks) вместе с их заголовками.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--layer7&amp;lt;/tt&amp;gt; — для SCTP проверяется суммарный размер DATA-секций в пакете (то есть его полезная нагрузка), для остальных протоколов аналогично &amp;lt;tt&amp;gt;--layer5&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
По умолчанию используется &amp;lt;tt&amp;gt;--layer3&amp;lt;/tt&amp;gt;, однако во избежание недоразумений рекомендуется явно указывать одну из перечисленных опций. Если этого не делать, при вводе соответствующей команды появится сообщение&lt;br /&gt;
  iptables: length match: Defaulting to --layer3. Consider specifying it explicitly.&lt;br /&gt;
Это ''не''&amp;amp;nbsp;является ошибкой (только предупреждением о возможной неоднозначности). Заданное вами правило должно добавиться успешно.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --length ''размер''[:''макс_размер'']&amp;lt;/tt&amp;gt; — собственно, задает нужные значения размера. В отличие от аналогичного параметра в классическом критерии length, его синтаксические формы несколько беднее. Допускаются два варианта записи:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tt&amp;gt;--length ''размер''&amp;lt;/tt&amp;gt; — пакет проверяется на точное соответствие заданному размеру,&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;tt&amp;gt;--length ''мин_размер'':''макс_размер''&amp;lt;/tt&amp;gt; — размер пакета должен быть попадать в указанный диапазон (включая границы).&lt;br /&gt;
&lt;br /&gt;
Впрочем, недостающие варианты легко выразить через имеющиеся: для имитации &amp;lt;tt&amp;gt;--length :''макс_размер''&amp;lt;/tt&amp;gt; используйте &amp;lt;tt&amp;gt;--length 0:''макс_размер''&amp;lt;/tt&amp;gt;, а вместо &amp;lt;tt&amp;gt;--length ''мин_размер'':&amp;lt;/tt&amp;gt; применяйте &amp;lt;tt&amp;gt;--length ''мин_размер'':65535&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Будьте внимательны: в отличие от length, length2 не&amp;amp;nbsp;проверяет взаимное соответствие границ диапазона (&amp;lt;tt&amp;gt;''мин_размер'' &amp;lt;= ''макс_размер''&amp;lt;/tt&amp;gt;), и если вы зададите их неправильно (&amp;lt;tt&amp;gt;''мин_размер'' &amp;gt; ''макс_размер''&amp;lt;/tt&amp;gt;), ваше правило просто никогда не&amp;amp;nbsp;будет срабатывать. &amp;lt;!-- По крайней мере в xtables-addons 1.21 этот баг присутствует. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Подводя краткий итог по разделу «Лимитирующие критерии»''', хотелось бы заметить, что перечисленные в этом разделе критерии предназначены главным образом для ограничения доступа и защиты от различных атак. Не&amp;amp;nbsp;стоит пытаться ограничивать с их помощью трафик. Для ограничения и приоритезации трафика в Linux рекомендуется использовать стандартный шейпер ядра, управляемый при помощи утилиты tc.&lt;br /&gt;
&amp;lt;!-- Если же вам нужно ограничить именно трафик, а не отдельные пакеты или соединения, то рекомендуем использовать для этого шейпер. Управление шейпером ядра Linux производится при помощи утилиты tc. Впрочем, этот шейпер позволяет эффективно управлять лишь исходящим трафиком.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Критерий recent ====&lt;br /&gt;
&lt;br /&gt;
recent — это специальный критерий, позволяющий запоминать проходящие через него пакеты, а затем использовать полученную информацию для принятия решений. Ввиду его уникальности, широких возможностей и, как следствие, некоторых трудностей в понимании новичками принципов его использования, рассказ о нем был вынесен в отдельный подраздел.&lt;br /&gt;
&lt;br /&gt;
Если быть точным, recent запоминает не сами пакеты, а их количество, время поступления, адрес источника (в последних версиях iptables также может запоминать и адрес назначения), а также, при необходимости, TTL.&lt;br /&gt;
&lt;br /&gt;
В начале кратко рассмотрим его опции:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --set&amp;lt;/tt&amp;gt; — запомнить адрес источника/назначения пакета (внести его во внутренний список). Если такая запись уже присутствует в списке — обновить время последнего доступа для нее. Обратите внимание, что критерию recent с опцией &amp;lt;tt&amp;gt;--set&amp;lt;/tt&amp;gt; удовлетворяют ''все'' пакеты. Чтобы ему не удовлетворял ни один пакет — используйте логическую инверсию (&amp;lt;tt&amp;gt;! --set&amp;lt;/tt&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --rcheck&amp;lt;/tt&amp;gt; — позволяет проверить, присутствует ли адрес источника/назначения пакета во внутреннем списке. Критерий recent с этой опцией вернет истину, если адрес в списке присутствует.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --update&amp;lt;/tt&amp;gt; — работает аналогично &amp;lt;tt&amp;gt;--rcheck&amp;lt;/tt&amp;gt;, но еще и обновляет время последнего доступа для данной записи.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --remove&amp;lt;/tt&amp;gt; — работает аналогично &amp;lt;tt&amp;gt;--rcheck&amp;lt;/tt&amp;gt;, но еще и удаляет найденную запись из списка. Если запись не найдена, пакет считается ''не''&amp;amp;nbsp;соответствующим критерию.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--seconds ''число''&amp;lt;/tt&amp;gt; — дополнительная опция в режимах &amp;lt;tt&amp;gt;--rcheck&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--update&amp;lt;/tt&amp;gt;. Пакет считается соответствующим критерию, только если последний доступ к записи был не позднее, чем ''число'' секунд назад.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--hitcount ''число''&amp;lt;/tt&amp;gt; — дополнительная опция в режимах &amp;lt;tt&amp;gt;--rcheck&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--update&amp;lt;/tt&amp;gt;. Пакет считается удовлетворяющим критерию, если было не менее ''число'' обращений к данной записи. Обычно используется вместе с &amp;lt;tt&amp;gt;--seconds&amp;lt;/tt&amp;gt; — тогда критерий имеет смысл «не менее n обращений за последние m секунд».&lt;br /&gt;
&lt;br /&gt;
Заметим, что, хотя в официальной документации для параметров &amp;lt;tt&amp;gt;--seconds&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--hitcount&amp;lt;/tt&amp;gt; указывается возможность отрицания (указания перед ними восклицательного знака), на самом деле такое отрицание никак не&amp;amp;nbsp;обрабатывается в коде и не&amp;amp;nbsp;меняет смысла параметров, так что указывать его бессмысленно. Эта ошибка в документации исправлена в версии iptables 1.4.7.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--rttl&amp;lt;/tt&amp;gt; — дополнительно к адресу источника/назначения, заносить в список и проверять еще и TTL пакета.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--rsource&amp;lt;/tt&amp;gt; — эта опция появилась в последних версиях iptables, с тех пор, как критерий recent начал поддерживать запоминание адресов не только источника, но и назначения. Позволяет явно указать, что в список вносится именно адрес источника пакета. Однако в целях обратной совместимости этот режим используется по умолчанию, и поэтому указывать данную опцию не обязательно.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--rdest&amp;lt;/tt&amp;gt; — эта опция появилась в последних версиях iptables. Позволяет явно указать, что в список вносится именно адрес назначения пакета.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--name ''имя''&amp;lt;/tt&amp;gt; — позволяет указать имя списка при использовании нескольких списков. По умолчанию используется список DEFAULT. Каждый список представлен псевдофайлом &amp;lt;tt&amp;gt;/proc/net/xt_recent/''имя''&amp;lt;/tt&amp;gt; (на старых ядрах критерий recent реализован только для IPv4, но не&amp;amp;nbsp;для IPv6, поэтому вместо &amp;lt;tt&amp;gt;xt_recent&amp;lt;/tt&amp;gt; будет &amp;lt;tt&amp;gt;ipt_recent&amp;lt;/tt&amp;gt;). В частности, вы можете:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
cat /proc/net/xt_recent/имя # вывести список на экран&lt;br /&gt;
echo +адрес &amp;gt; /proc/net/xt_recent/имя # добавить адрес в список&lt;br /&gt;
echo -адрес &amp;gt; /proc/net/xt_recent/имя # удалить адрес из списка&lt;br /&gt;
echo / &amp;gt; /proc/net/xt_recent/имя # очистить список&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Теперь давайте рассмотрим несколько примеров.&lt;br /&gt;
* Блокирование bruteforce-атак (подбор пароля вслепую) на [[SSH|Ssh]] и аналогичные сервисы.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -N ssh_brute_check # Создаем цепочку для проверки попыток соединений на защищаемый порт&lt;br /&gt;
# Если за последние 10 минут (600 секунд) с одного адреса было 3 или более новых соединений — блокируем этот адрес&lt;br /&gt;
iptables -A ssh_brute_check -m conntrack --ctstate NEW -m recent --update --seconds 600 --hitcount 3 -j DROP&lt;br /&gt;
# В противном случае — разрешаем, и при этом заносим в список&lt;br /&gt;
iptables -A ssh_brute_check -m recent --set -j ACCEPT&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям&lt;br /&gt;
# Все попытки открыть новое соединение по SSH направляем на проверку&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_brute_check&lt;br /&gt;
# Здесь можно разрешать те порты, для которых такая проверка не нужна. Например, HTTP&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 80 -j ACCEPT&lt;br /&gt;
iptables -P INPUT DROP # Что не разрешено — то запрещено&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Теперь все попытки открыть новое SSH-соединение проверяются, и с одного IP-адреса можно открывать не более 2 соединений за 10 минут. Обратите внимание, что за одно соединение злоумышленник может проверить несколько паролей — число попыток аутентификации до обрыва соединения задает параметр MaxAuthTries в файле &amp;lt;tt&amp;gt;/etc/ssh/sshd_config&amp;lt;/tt&amp;gt;. По умолчанию это число равно 6, так что в нашем примере злоумышленник сможет проверять не более 12 паролей за 10 минут.&lt;br /&gt;
&lt;br /&gt;
Впрочем, данный пример весьма тривиален, и сходную функциональность можно получить и при помощи критерия hashlimit:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -m hashlimit --hashlimit-mode srcip --hashlimit-upto 5/hour --hashlimit-name ssh -j ACCEPT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
разрешит не более 5 новых соединений в час.&lt;br /&gt;
Данная реализация имеет недостаток по сравнению с recent — вы не можете произвольно задавать временной период.&lt;br /&gt;
&lt;br /&gt;
* Защита от сканирования портов (заметим, что кроме критерия recent для этой задачи можно также использовать критерии psd и lscan из комплекта xtables-addons).&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям&lt;br /&gt;
# Если за последний час было 10 или более запросов на нерабочие порты — блокируем&lt;br /&gt;
iptables -A INPUT -m recent --rcheck --seconds 3600 --hitcount 10 --rttl -j RETURN&lt;br /&gt;
# Если за последнюю минуту было 2 или более запросов на нерабочие порты — блокируем&lt;br /&gt;
iptables -A INPUT -m recent --rcheck --seconds 60 --hitcount 2 --rttl -j RETURN&lt;br /&gt;
# Разрешаем рабочие порты&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 21,25,53,80,110 -j ACCEPT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p udp -m multiport --dport 53,123 -j ACCEPT&lt;br /&gt;
# Всех, кто ломится в нерабочие порты — регистрируем&lt;br /&gt;
iptables -A INPUT -m recent --set&lt;br /&gt;
iptables -P INPUT DROP # Что не разрешено — то запрещено&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Все пакеты, попадающие на нерабочие порты сервера, регистрируются. После нескольких таких попыток за заданный интервал времени адрес их источника блокируется. Проверка TTL добавлена для защиты от блокировки легитимных клиентов после спуфинга злоумышленником от их имени. Хотя, с другой стороны, эта мера позволяет ему обойти защиту от сканирования, выставляя своим пакетам различный TTL. Так что вопрос о нужности этой проверки в вашем конкретном случае вам придется решать самостоятельно.&lt;br /&gt;
&lt;br /&gt;
Другой пример использования критерия recent для детекции и блокирования сканирования портов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Создаем цепочку для проверки и блокирования портсканов&lt;br /&gt;
iptables -N portscan_check&lt;br /&gt;
# Блокируем тех, кто был уличен в портскане в течение последних суток&lt;br /&gt;
iptables -A portscan_check -m recent --name portscan --rcheck --seconds 86400 -j DROP&lt;br /&gt;
# По прошествии суток можно удалять их из списка&lt;br /&gt;
iptables -A portscan_check -m recent --name portscan --remove&lt;br /&gt;
# Ну а сейчас — собственно процедура определения портскана&lt;br /&gt;
iptables -A portscan_check -p tcp --dport 139 -m recent --name portscan --set -j DROP&lt;br /&gt;
# Пускаем на проверку всех, кто пришел к нам из интернета (интерфейс eth0)&lt;br /&gt;
iptables -I INPUT -i eth0 -j portscan_check&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В данном случае сканированием портов считается обращение на порт 139/tcp (SMB). Впрочем, вы можете задать другой порт или, используя критерий multiport, даже список портов. В отличие от предыдущего примера, здесь производится автоматическая очистка списка IP-адресов: по прошествии суток с момента блокировки, первое же обращение с заблокированного адреса на наш сервер приводит к удалению этого адреса из нашего recent-списка. Однако, если это обращение вновь является попыткой сканирования портов, то есть направлено на порт 139/tcp, адрес тут же блокируется вновь. Именно поэтому процедура блокировки расположена «ниже по течению», чем процедура удаления адреса из списка.&lt;br /&gt;
&lt;br /&gt;
Для предыдущего примера реализация очистки списка адресов достигается следующим образом:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# Создаем цепочку для проверки на необходимость удаления&lt;br /&gt;
iptables -N recent_remove&lt;br /&gt;
# Последнее обращение на неиспользуемые порты было менее суток назад&lt;br /&gt;
# поэтому оставим-ка пока этот адресок в черном списке&lt;br /&gt;
iptables -A recent_remove -m recent --rcheck --seconds 86400 -j RETURN&lt;br /&gt;
# Если адрес в есть в списке — удаляем его оттуда&lt;br /&gt;
iptables -A recent_remove -m recent --remove&lt;br /&gt;
# Вставляем эту проверку вторым правилом (сразу после проверки ctstate)&lt;br /&gt;
iptables -I INPUT 2 -j recent_remove&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Проводя аналогию с ныне почившим проектом [http://www.opennet.ru/docs/RUS/portsentry/portsentry-security.html.gz PortSentry], первый наш пример соответствует режиму PortSentry «Advanced Stealth Scan Detection», а второй — «Enhanced Stealth Scan Detection». (Правда, заметим, что в режиме Advanced Stealth Scan Detection блокировка производится после ''первого'' попадания пакета на нерабочий порт&amp;amp;nbsp;— для достижения такого же эффекта в нашем примере достаточно выкинуть проверки на seconds и hitcount из блокирующих правил.) Однако, использование iptables/recent имеет значительное преимущество перед примитивными userspace-системами наподобие PortSentry&amp;amp;nbsp;— возможность интеграции с системой conntrack, что позволяет избежать ошибочной блокировки, например, при использовании высоких портов для NAT.&lt;br /&gt;
&lt;br /&gt;
* Открытие порта «по стуку».&lt;br /&gt;
&lt;br /&gt;
Port knocking — метод защиты портов, при котором доступ к определенному порту с отдельно взятого IP-адреса открывается после серии пакетов на заданную последовательность портов с заданными интервалами. &amp;lt;!-- Обычно эта задача решается демоном knockd. Также сходной функциональностью обладает критерий [http://www.netfilter.org/projects/patch-o-matic/pom-external.html#pom-external-pknock pknock] из [http://www.netfilter.org/projects/patch-o-matic/pom-external.htm patch-o-matic-ng], однако он, к сожалению, потерял разработчика и прекратил развиваться.--&amp;gt; Обычно эта задача решается при помощи демона knockd либо критерия pknock из комплекта xtables-addons.&lt;br /&gt;
&lt;br /&gt;
Несколько самых простых вариантов такой защиты можно организовать и средствами критерия recent.&lt;br /&gt;
&lt;br /&gt;
Самое простое — открывать порт ssh (22) после стука в заданный высокий порт:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -N ssh_knock # Создаем цепочку для проверки попыток соединений на защищаемый порт&lt;br /&gt;
# Если за последние 60 секунд было 2 и более стука — блокируем, на всякий случай&lt;br /&gt;
iptables -A ssh_knock -m recent --rcheck --seconds 60 --hitcount 2 -j RETURN&lt;br /&gt;
# Если за последние 10 секунд стук в нужный порт был — разрешить соединение&lt;br /&gt;
iptables -A ssh_knock -m recent --rcheck --seconds 10 -j ACCEPT&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям&lt;br /&gt;
# Все попытки открыть новое соединение по SSH направляем на проверку&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_knock&lt;br /&gt;
# Здесь мы добавляем правило для регистрации стука&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 27520 -m recent --set&lt;br /&gt;
# Опять же на всякий случай — при стуке в соседние порты закрываем SSH&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp -m multiport --dport 27519,27521 -m recent --remove&lt;br /&gt;
iptables -P INPUT DROP # Что не разрешено — то запрещено&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Даже в таком простом примере присутствуют жесткие меры защиты: защищаемый порт (22) открывается на 10 секунд после стука в заданный порт (27520), при этом более одного стука в этот порт в течение минуты считается ошибкой. Также стук в соседние с заданным порты сразу закрывает защищаемый порт. Это делается в целях защиты от подбора стука.&lt;br /&gt;
&lt;br /&gt;
Если вам не интересны такие параноидальные меры безопасности, то обратите внимание на этот простой пример:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -N ssh_knock # Создаем цепочку для проверки&lt;br /&gt;
# Если за последние 10 минут было 5 и более попыток соединения — блокируем&lt;br /&gt;
iptables -A ssh_knock -m recent --name ssh --update --seconds 600 --hitcount 5 -j RETURN&lt;br /&gt;
# Регистрируем&lt;br /&gt;
iptables -A ssh_knock -m recent --name ssh --set&lt;br /&gt;
# Если за последние 5 секунд было менее двух попыток — блокируем&lt;br /&gt;
iptables -A ssh_knock -m recent --name ssh ! --rcheck --seconds 5 --hitcount 2 -j RETURN&lt;br /&gt;
# Все остальное — разрешаем&lt;br /&gt;
iptables -A ssh_knock -j ACCEPT&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям&lt;br /&gt;
# Все попытки открыть новое соединение по SSH направляем на проверку&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate NEW -p tcp --dport 22 -j ssh_knock&lt;br /&gt;
iptables -P INPUT DROP # Что не разрешено — то запрещено&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Идея метода проста: защищаемый порт открывается со второй попытки, то есть стук идет непосредственно в него. Вторую попытку нужно сделать в течение 5 секунд после первой. При этом 5 и более попыток за десять минут блокируются (во избежание брутфорса).&lt;br /&gt;
&lt;br /&gt;
Также можно организовать защиту через стук в серию портов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
iptables -N reset_knock # Цепочка для сброса процесса стука&lt;br /&gt;
iptables -A reset_knock -m recent --name PHASE1 --remove&lt;br /&gt;
iptables -A reset_knock -m recent --name PHASE2 --remove&lt;br /&gt;
iptables -A reset_knock -m recent --name PHASE3 --remove&lt;br /&gt;
iptables -A reset_knock -m recent --name PHASE4 --remove&lt;br /&gt;
iptables -N in_phase_2 # Создаем цепочку для фазы 2&lt;br /&gt;
iptables -A in_phase_2 -m recent --name PHASE1 --remove # Удаляем запись из списка первой фазы&lt;br /&gt;
iptables -A in_phase_2 -m recent --name PHASE2 --set # Добавляем ее в список второй фазы&lt;br /&gt;
iptables -N in_phase_3 # Создаем цепочку для фазы 3&lt;br /&gt;
iptables -A in_phase_3 -m recent --name PHASE2 --remove # Удаляем запись из списка второй фазы&lt;br /&gt;
iptables -A in_phase_3 -m recent --name PHASE3 --set # Добавляем ее в список третьей фазы&lt;br /&gt;
iptables -N in_phase_4 # Создаем цепочку для фазы 4&lt;br /&gt;
iptables -A in_phase_4 -m recent --name PHASE3 --remove # Удаляем запись из списка третьей фазы&lt;br /&gt;
iptables -A in_phase_4 -m recent --name PHASE4 --set # Добавляем ее в список четвертой фазы&lt;br /&gt;
iptables -N checked # Для записей, прошедших проверку&lt;br /&gt;
iptables -A checked -j reset_knock # Очищаем списки&lt;br /&gt;
iptables -A checked -j ACCEPT # Разрешаем пакет&lt;br /&gt;
iptables -F INPUT # Очищаем цепочку INPUT&lt;br /&gt;
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Разрешаем пакеты по установленным соединениям&lt;br /&gt;
# Первая фаза&lt;br /&gt;
iptables -A INPUT -p tcp --dport 21210 -m recent --name PHASE1 --set -j RETURN&lt;br /&gt;
# Для тех, кто присутствует в списке первой фазы — переход во вторую&lt;br /&gt;
iptables -A INPUT -p tcp --dport 11992 -m recent --rcheck --name PHASE1 --seconds 5 -g in_phase_2&lt;br /&gt;
# И т.д.&lt;br /&gt;
iptables -A INPUT -p tcp --dport 16043 -m recent --rcheck --name PHASE2 --seconds 5 -g in_phase_3&lt;br /&gt;
iptables -A INPUT -p tcp --dport 23050 -m recent --rcheck --name PHASE3 --seconds 5 -g in_phase_4&lt;br /&gt;
# Если стучатся не в том порядке — сброс&lt;br /&gt;
iptables -A INPUT -p tcp -m multiport --dport 21210,11992,16043,23050 -j reset_knock&lt;br /&gt;
# Для тех, кто прошел все четыре фазы — разрешаем доступ&lt;br /&gt;
iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -m recent --rcheck --name PHASE4 --seconds 5 -j checked&lt;br /&gt;
iptables -P INPUT DROP # Дефолтное правило цепочки INPUT&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Принцип прост — при стуке в порт, соответствующий очередной фазе, проверяется наличие записи в предыдущей фазе. Теперь порт 22 откроется на 5 секунд после стука в порты 21210, 11992, 16043, 23050 со строгим соблюдением порядка перечисления и интервалами не более 5 секунд.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание на технику реализации процесса — цепочки фаз вызываются не через &amp;lt;tt&amp;gt;-j&amp;lt;/tt&amp;gt;, а через &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt;, поэтому после прохождения этих цепочек к пакетам сразу применяется правило по умолчанию цепочки INPUT, то есть DROP. В противном случае пакеты доходили бы до правила сброса (которое с multiport), и процесс стука все время сбрасывался бы.&lt;br /&gt;
&lt;br /&gt;
Последовательный стук в порты можно организовать, например, утилитой netcat&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
for it in {21210,11992,16043,23050}; do&lt;br /&gt;
    echo &amp;quot; &amp;quot; | nc -w 1 host $it&lt;br /&gt;
done&lt;br /&gt;
ssh user@host&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Другие примеры реализации port knocking’а при помощи критерия recent можно посмотреть на [http://wiki.opennet.ru/Iptables_-m_recent OpenNet wiki], [http://www.debian-administration.org/articles/268 debian-administration.org], [http://silverghost.org.ua/2007/06/13/ssh-portknocking/ silverghost.org.ua], [http://www.opennet.ru/openforum/vsluhforumID3/41732.html#32 форуме OpenNet].&lt;br /&gt;
&lt;br /&gt;
==== Критерий u32 ====&lt;br /&gt;
&lt;br /&gt;
Данный критерий предоставляет очень гибкий инструмент, позволяющий производить сложные операции по анализу содержимого пакета. Алгоритм обработки содержимого исследуемого пакета задается на специальном языке программирования, своеобразном «ассемблере». Такой подход позволяет получить огромную гибкость, но при этом его изучение и использование может представлять определенные трудности для пользователей, не знакомых с основами программирования и принципами работы машины Тьюринга.&lt;br /&gt;
&lt;br /&gt;
Этот критерий имеет единственный параметр — &amp;lt;tt&amp;gt;[!] --u32&amp;lt;/tt&amp;gt;, после которого в двойных кавычках записывается текст «программы». Если все проверки, заданные в программе, дают истинный результат, пакет считается удовлетворяющим данному критерию. Традиционно, если перед параметром указан восклицательный знак, означающий логическое отрицание, то удовлетворяющими критерию считаются только те пакеты, для которых хотя бы одна проверка дала ложный результат.&lt;br /&gt;
&lt;br /&gt;
Ключевые операторы языка критерия u32:&lt;br /&gt;
* '''=''' — оператор сравнения. Собственно, на его основе и формируются все производимые проверки. Синтаксис его вполне очевиден: &amp;lt;tt&amp;gt;выражение = значение&amp;lt;/tt&amp;gt;. В качестве значения можно использовать одно число, диапазон (в формате &amp;lt;tt&amp;gt;мин:макс&amp;lt;/tt&amp;gt;) или список чисел и/или диапазонов разделенных запятой (например, &amp;lt;tt&amp;gt;1,3:5,8,11:14&amp;lt;/tt&amp;gt;). В одном списке можно указывать не более 10 чисел/диапазонов.&lt;br /&gt;
* '''&amp;amp;&amp;amp;''' — оператор логического И, объединяющий все производимые в программе проверки. В одном критерии u32 можно указывать не более 10 таких проверок. Обратите внимание, что операция логического ИЛИ отсутствует, так как это противоречит идеологии iptables (в каждом правиле все проверки объединяются логическим И, а логическое ИЛИ объединяет правила в одной цепочке).&lt;br /&gt;
* '''&amp;amp;''' — оператор побитового логического И, позволяющий применить к обрабатываемому значению битовую маску.&lt;br /&gt;
* '''&amp;lt;&amp;lt;''' и '''&amp;gt;&amp;gt;''' — операторы побитового сдвига влево и вправо соответственно. Эквивалентны домножению или делению обрабатываемого значения на 2 в соответствующей степени. Обратите внимание, что в одном выражении для проверки можно использовать не более 9 операторов &amp;amp;, &amp;lt;&amp;lt; и &amp;gt;&amp;gt;.&lt;br /&gt;
* '''@''' — оператор задания смещения. Добавляет результат предыдущего выражения к текущему значению начального смещения (в начале работы программы, до выполнения @-операций, начальное смещение считается нулевым). Очень полезен в тех случаях, когда нужно сместиться на некоторое значение, полученное в результате обработки пакета, например, узнав после некоторых вычислений длину IP-заголовка, мы можем сместиться на данные непосредственно после него, т.е. на начало полезной нагрузки IP-пакета (как правило, там находится заголовок транспортного уровня).&lt;br /&gt;
&lt;br /&gt;
Все операторы имеют равный приоритет, исполнение операций всегда происходит слева направо.&lt;br /&gt;
&lt;br /&gt;
Обратите внимание, что программа рассматривает все значения как целые беззнаковые величины, заданные 32 битами, или четырьмя октетами (что соответствует значениям от 0 до 4294967295). Именно поэтому критерий имеет такое название (u32 — unsigned 32-bit).&lt;br /&gt;
&lt;br /&gt;
Другой не вполне очевидный момент — синтаксис операторов =, &amp;amp;, &amp;lt;&amp;lt; и &amp;gt;&amp;gt;. Дело в том, что в качестве первого операнда указывается не само значение, а его ''адрес'' в пределах пакета, заданный смещением в байтах от текущего начального смещения. Например, &amp;lt;tt&amp;gt;8 = 0x12345678&amp;lt;/tt&amp;gt; означает, что нужно взять четыре байта, начиная с восьмого (обратите внимание, что нумерация байтов в пакете начинается с нуля), т.е. байты 8, 9, 10 и 11, и сравнить полученное значение с шестнадцатеричным числом 0x12345678. Как уже говорилось, критерий u32 ''всегда'' манипулирует блоками по четыре байта, поэтому, если вас интересуют блоки меньшего размера, используйте оператор &amp;amp; и маску, например, &amp;lt;tt&amp;gt;8 &amp;amp; 0xFF = 0x78&amp;lt;/tt&amp;gt; позволяет проверить только последний в блоке (11-й от начального смещения) байт. Также можно использовать и оператор смещения, например,  &amp;lt;tt&amp;gt;8 &amp;gt;&amp;gt; 24 = 0x12&amp;lt;/tt&amp;gt; возьмет первый в блоке (8-й от начального смещения) байт и сравнит его с числом 0x12. Более подробно о битовых операциях можно почитать в соответствующей статье.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим возможности критерия u32 на нескольких простых примерах из официальной документации:&lt;br /&gt;
* Проверить, превышает ли длина пакета величину 256 байт: &amp;lt;tt&amp;gt;--u32 &amp;quot;0 &amp;amp; 0xFFFF = 0x100:0xFFFF&amp;quot;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Эта программа предписывает взять четыре байта, начиная с нулевого, затем занулить первые два байта (в них содержится информация о версии протокола, длине заголовка и типе обслуживания, которая нас сейчас не интересует), и проверить значение, формируемого оставшимися двумя байтами (это и есть полная длина пакета в байтах) на принадлежность диапазону от 0x100 (256 в десятичном счислении) до 0xFFFF (65535, максимально возможная длина пакета).&lt;br /&gt;
* Проверить, является ли данный пакет ICMP-пакетом с типом 0 (эхо-ответ). Учитывая переменную длину IP-заголовка, эта проверка требует несколько большего количества операций: &amp;lt;tt&amp;gt;--u32 &amp;quot;6 &amp;amp; 0xFF = 1 &amp;amp;&amp;amp; 4 &amp;amp; 0x3FFF = 0 &amp;amp;&amp;amp; 0 &amp;gt;&amp;gt; 22 &amp;amp; 0x3C @ 0 &amp;gt;&amp;gt; 24 = 0&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
Рассмотрим эти операции последовательно:&lt;br /&gt;
:*'''6 &amp;amp; 0xFF = 1''' — проверка кода протокола. Код протокола хранится в 9-м (считая с нуля) байте IPv4-заголовка. Чтобы получить это значение, мы берем 4-х байтовый блок с шестого по девятый байт, а затем при помощи маски выделяем последний, интересующий нас байт в это блоке, и сравниваем его с единицей (код протокола ICMP).&lt;br /&gt;
:*'''4 &amp;amp; 0x3FFF = 0''' — проверка, не является ли наш пакет фрагментом. Фрагменты ICMP-пакетов не содержат ICMP-заголовка, в котором должен храниться тип ICMP, поэтому для них дальнейшая проверка не имеет смысла. Пользуясь описанным выше принципом, наша программа выделяет последние 14 бит в блоке с 4-го по 7-й байт, и сравнивает полученное значение с нулем. Строго говоря, для наших целей достаточно было бы и 13 бит (маска 0x1FFF), выделяющих только поле смещения фрагмента (fragment offset, оно должно быть равным нулю для первого пакета в цепочке фрагментов), а использование 14 бит, как это сделано в примере из официальной документации, также захватит и флаг MF (more fragments), что отсечет вообще все фрагментированные пакеты, даже те, которые являются первыми в последовательности и содержат все нужные нам заголовки.&lt;br /&gt;
:*'''0 &amp;gt;&amp;gt; 22 &amp;amp; 0x3C @''' — определение длины IP-заголовка в байтах. Последние четыре бита в первом байте IP-пакета показывают длину IP-заголовка в блоках по четыре байта. Смещая это значение на 22 позиции вправо, мы оставляем справа «зазор» в два бита, которые впоследствии зануляем при помощи маски (3C&amp;lt;sub&amp;gt;16&amp;lt;/sub&amp;gt; = 111100&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;). Также эта маска отсекает лишние биты слева (версия протокола). Полученные два нулевых бита справа соответствуют умножению на четыре, так что в результате мы получаем длину заголовка уже в байтах. Например, если длина IP-заголовка составляет 5 четырехбайтовых блоков (т.е. 20 байт), то изначально первый блок заголовка имеет вид &amp;lt;tt&amp;gt;xxxx0101 yyzzzzzz uuuuuuuu uuuuuuuu&amp;lt;/tt&amp;gt; (где биты &amp;lt;tt&amp;gt;xxxx&amp;lt;/tt&amp;gt; задают версию протокола, 0101&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;=5&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt;­ — собственно длину заголовка, &amp;lt;tt&amp;gt;yyzzzzzz&amp;lt;/tt&amp;gt; — тип обслуживания, а два байта &amp;lt;tt&amp;gt;uuuuuuuu uuuuuuuu&amp;lt;/tt&amp;gt; показывают полную длину пакета вместе с нагрузкой), то после смещения вправо на 22 бита мы получим в этом блоке следующую картину: &amp;lt;tt&amp;gt;00000000 00000000 000000xx xx0101yy&amp;lt;/tt&amp;gt;. После применения маски она пример вид &amp;lt;tt&amp;gt;00000000 00000000 00000000 00010100&amp;lt;/tt&amp;gt;. Полученное число — 10100&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;=20&amp;lt;sub&amp;gt;10&amp;lt;/sub&amp;gt; и будет равно длине заголовка в байтах. Наконец, оператор @ устанавливает полученное значение в качестве начального смещения, поэтому вся дальнейшая адресация ведется уже начиная с начала ICMP-заголовка, который следует непосредственно после IP-заголовка.&lt;br /&gt;
:*'''0 &amp;gt;&amp;gt; 24 = 0''' — выделяет блок с нулевого по третий байт ICMP-заголовка, а затем при помощи смещения (на три байта вправо) оставляет от него только один, нулевой, байт, в котором и хранится тип ICMP. Нас интересует тип 0, поэтому мы и сравниваем этот байт с нулем.&lt;br /&gt;
* Проверить, задают ли байты с восьмого по одиннадцатый полезной нагрузки TCP-пакета одно из значений: 1, 2, 5, 8. Достигается следующим кодом: &amp;lt;tt&amp;gt;--u32 &amp;quot;6 &amp;amp; 0xFF = 6 &amp;amp;&amp;amp; 4 &amp;amp; 0x3FFF = 0 &amp;amp;&amp;amp; 0 &amp;gt;&amp;gt; 22 &amp;amp; 0x3C @ 12 &amp;gt;&amp;gt; 26 &amp;amp; 0x3C @ 8 = 1,2,5,8&amp;quot;&amp;lt;/tt&amp;gt;&lt;br /&gt;
:*'''6 &amp;amp; 0xFF = 6''' — выделение байта с кодом протокола и сравнение его с кодом 6 (соответствует TCP). Описание этой проверки уже приведено при рассмотрении предыдущего примера.&lt;br /&gt;
:*'''4 &amp;amp; 0x3FFF = 0''' — проверка, не является ли данный пакет фрагментом. Полностью аналогична описанной в предыдущем примере.&lt;br /&gt;
:*'''0 &amp;gt;&amp;gt; 22 &amp;amp; 0x3C @''' — определение длины IP-заголовка в байтах. Также полностью аналогично описанному в предыдущем примере. После данной операции, начальное смещение указывает на нулевой байт TCP-заголовка.&lt;br /&gt;
:*'''12 &amp;gt;&amp;gt; 26 &amp;amp; 0x3C @''' — определение длины TCP-заголовка в байтах. Принцип действия аналогичен предыдущей операции, с тем лишь отличием, что длина TCP-заголовка закодирована в первых четырех битах двенадцатого байта (а не в последних четырех битах нулевого байта, как в случае с IP-заголовком), поэтому необходимое нам смещение вправо составляет уже 26 бит. Как и в предыдущей операции, мы оставляем справа зазор в два бита, которые впоследствии зануляем маской, и таким образом сразу получаем длину заголовка в байтах. Итак, после второго оператора @, начальное смещение будет указывать на начало полезной нагрузки TCP-пакета (следует непосредственно после заголовка).&lt;br /&gt;
:*'''8 = 1,2,5,8''' — эта операция сравнения вполне тривиальна: выделяется четырехбайтовый блок, начиная с восьмого байта (разумеется, считая от начала полезной нагрузки), и полученное значение сравнивается с одним из допустимых по условию задачи.&lt;br /&gt;
&lt;br /&gt;
Также, в качестве полезных примеров использования критерия u32, можно упомянуть проверку портов источника и назначения в протоколе UDPLite: &amp;lt;tt&amp;gt;--u32 &amp;quot;6 &amp;amp; 0xFF = 136 &amp;amp;&amp;amp; 4 &amp;amp; 0x3FFF = 0 &amp;amp;&amp;amp; 0 &amp;gt;&amp;gt; 22 &amp;amp; 0x3C @ 0 &amp;gt;&amp;gt; 16 = исходный_порт&amp;quot;&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;--u32 &amp;quot;6 &amp;amp; 0xFF = 136 &amp;amp;&amp;amp; 4 &amp;amp; 0x3FFF = 0 &amp;amp;&amp;amp; 0 &amp;gt;&amp;gt; 22 &amp;amp; 0x3C @ 0 &amp;amp; OxFFFF = порт_назначения&amp;quot;&amp;lt;/tt&amp;gt; соответственно (после сказанного выше нетрудно догадаться, что исходный порт указывается в первой паре байт UDPLite-заголовка, а порт назначения — во второй, согласно [http://tools.ietf.org/html/rfc3828 RFC3828]).&lt;br /&gt;
&lt;br /&gt;
==== Прочие критерии ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Критерии из набора xtables-addons ====&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Программы ==&lt;br /&gt;
&lt;br /&gt;
=== Основные ===&lt;br /&gt;
&lt;br /&gt;
==== iptables ====&lt;br /&gt;
&lt;br /&gt;
===== Работа с цепочками =====&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] -N chain&lt;br /&gt;
&lt;br /&gt;
Создать цепочку&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] {-F|-L|-Z} [chain [rulenum]] [options...]&lt;br /&gt;
&lt;br /&gt;
* -F - Удалить все правила из цепочки&lt;br /&gt;
* -L - Просмотреть цепочку&lt;br /&gt;
* -Z - Обнулить счётчики пакетов в цепочке&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] -P chain target&lt;br /&gt;
&lt;br /&gt;
Установить политику по умолчанию для цепочки&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] -X {chain}&lt;br /&gt;
&lt;br /&gt;
Удалить цепочку. Внимание! На удаляемую цепочку не должно быть ссылок.&lt;br /&gt;
&lt;br /&gt;
===== Работа с правилами =====&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] -I chain [rulenum] rule-specification&lt;br /&gt;
&lt;br /&gt;
Вставить правило в начало цепочки (или в позицию rulenum, считая с 1)&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] -R chain rulenum rule-specification&lt;br /&gt;
&lt;br /&gt;
Заменить правило с номером rulenum на rule-specification&lt;br /&gt;
&lt;br /&gt;
  iptables [-t table] {-A|-C|-D} chain rule-specification&lt;br /&gt;
&lt;br /&gt;
* -A - добавить правило в конец&lt;br /&gt;
* -С - проверить, что такое правило есть в таблице&lt;br /&gt;
* -D - удалить правило по описанию или по rulenum&lt;br /&gt;
&lt;br /&gt;
===== Вывод информации =====&lt;br /&gt;
&lt;br /&gt;
==== iptables-save, iptables-restore и iptables-xml ====&lt;br /&gt;
&lt;br /&gt;
==== /etc/init.d/iptables ====&lt;br /&gt;
&lt;br /&gt;
==== iptables-apply ====&lt;br /&gt;
&lt;br /&gt;
==== ipset ====&lt;br /&gt;
ipset работает с типами данных, которые представляют из себя (man ipset):&lt;br /&gt;
* bitmap:ip     — список IP адресов из определенной подсети&lt;br /&gt;
* bitmap:ip,mac — связки IP+MAC&lt;br /&gt;
* bitmap:port   — список портов&lt;br /&gt;
* hash:ip       — произвольный набор IP&lt;br /&gt;
* hash:net      — произвольный набор сетей&lt;br /&gt;
* hash:mac&lt;br /&gt;
* hash:net,net&lt;br /&gt;
* hash:ip,port&lt;br /&gt;
* hash:net,port&lt;br /&gt;
* hash:ip,port,ip&lt;br /&gt;
* hash:ip,port,net&lt;br /&gt;
* hash:ip,mark&lt;br /&gt;
* hash:net,port,net&lt;br /&gt;
* hash:net,iface&lt;br /&gt;
* list:set&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пример правила iptables с применением ipset (man iptables-extensions):&lt;br /&gt;
 iptables -I INPUT 1 -i eth0 -p tcp -m tcp --dport 8080 -m set --match-set test123 src  -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
-где test123 это заданное имя сета&lt;br /&gt;
 ipset create test123 hash:net&lt;br /&gt;
&lt;br /&gt;
=== Вспомогательные ===&lt;br /&gt;
&lt;br /&gt;
==== Полезные при конфигурировании фаервола ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Пожалуй, стоит оформить их просто как список, и не мусорить в оглавлении&lt;br /&gt;
&lt;br /&gt;
===== sysctl =====&lt;br /&gt;
&lt;br /&gt;
===== modprobe =====&lt;br /&gt;
&lt;br /&gt;
===== shell =====&lt;br /&gt;
&lt;br /&gt;
===== ipcalc =====&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Полезные при тестировании фаервола ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Пожалуй, стоит оформить их просто как список, и не мусорить в оглавлении&lt;br /&gt;
&lt;br /&gt;
===== ping =====&lt;br /&gt;
&lt;br /&gt;
===== nmap =====&lt;br /&gt;
&lt;br /&gt;
===== nc и telnet =====&lt;br /&gt;
&lt;br /&gt;
===== netstat и ss =====&lt;br /&gt;
--&amp;gt;&amp;lt;blockquote&amp;gt;iptables -L -n -v  #Статистика всех правил iptables и счетчики обработанных пакетов&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Фронтенды ==&lt;br /&gt;
&lt;br /&gt;
=== С удобным интерфейсом ===&lt;br /&gt;
&lt;br /&gt;
=== С графическим интерфейсомм ===&lt;br /&gt;
&lt;br /&gt;
=== С веб-интерфейсом ===&lt;br /&gt;
[http://www.117.su iptadmin] - это пользовательский web интерфейс для iptables, редактор настроек файрволла операционной системы Linux. Реализован в виде отдельного http(s) сервера.&lt;br /&gt;
&lt;br /&gt;
Особенностью программы являются подробные сообщения об ошибках при редактировании правил файрволла.&lt;br /&gt;
&lt;br /&gt;
iptadmin работает на уровне iptables. Настройки файрволла сохраняются в стандартных файлах. В системе не создаются никакие вспомогательные данные. Логика работы спроектирована таким образом, что нарушение целостности конфигурации iptables исключено. Iptadmin можно в любой момент установить или удалить без потери настроек файрволла.&lt;br /&gt;
&lt;br /&gt;
=== Программные интерфейсы ===&lt;br /&gt;
&lt;br /&gt;
== Модули ядра ==&lt;br /&gt;
&lt;br /&gt;
=== Модули conntrack и nat ===&lt;br /&gt;
&lt;br /&gt;
=== Модули критериев и действий ===&lt;br /&gt;
&lt;br /&gt;
== Параметры sysctl/procfs ==&lt;br /&gt;
&lt;br /&gt;
=== Псевдофайлы procfs ===&lt;br /&gt;
&lt;br /&gt;
==== Базовые ====&lt;br /&gt;
&lt;br /&gt;
==== Относящиеся к критериям и действиям ====&lt;br /&gt;
&lt;br /&gt;
=== Основные параметры sysctl ===&lt;br /&gt;
ip_forward=1&lt;br /&gt;
&lt;br /&gt;
=== Параметры конфигурации интерфейсов ===&lt;br /&gt;
&lt;br /&gt;
=== Параметры, относящиеся к протоколам ===&lt;br /&gt;
&lt;br /&gt;
==== TCP ====&lt;br /&gt;
&lt;br /&gt;
==== UDP ====&lt;br /&gt;
&lt;br /&gt;
==== ICMP ====&lt;br /&gt;
&lt;br /&gt;
=== Параметры conntrack ===&lt;br /&gt;
&lt;br /&gt;
== Расширения ==&lt;br /&gt;
&lt;br /&gt;
=== Userspace-компоненты ===&lt;br /&gt;
&lt;br /&gt;
==== NuFW ====&lt;br /&gt;
&lt;br /&gt;
==== l7-filter-userspace ====&lt;br /&gt;
&lt;br /&gt;
==== iplist ====&lt;br /&gt;
&lt;br /&gt;
=== Наборы дополнительных критериев и действий ===&lt;br /&gt;
&lt;br /&gt;
==== Patch-o-Matic ====&lt;br /&gt;
Смотри на официальном сайте http://www.netfilter.org/projects/patch-o-matic/pom-external.html&lt;br /&gt;
&lt;br /&gt;
==== Patch-o-Matic-NG ====&lt;br /&gt;
&lt;br /&gt;
==== xtables-addons ====&lt;br /&gt;
&lt;br /&gt;
== Команды ==&lt;br /&gt;
Программа позволяет задать правила, которым должны соответствовать проходящие через брандмауэр IP-пакеты. Эти правила, как и все настройки Linux, записываются в текстовый файл, находящийся в папке /etc. Последовательность правил называется цепочкой (CHAIN). Для одного и того же сетевого интерфейса используются несколько цепочек. Если проходящий пакет не соответствует ни одному из правил, то выполняется действие по умолчанию.&lt;br /&gt;
&lt;br /&gt;
При вызове, параметром указывается команда, которую нужно выполнить. Обычно можно указать только одну команду (но есть исключения). Команду можно указать одной большой буквой или словом. Если при вызове любой команды не указано название таблицы, то команда выполняется в таблице filter. Программа имеет подробную справку, вызываемую командой ''man iptables''.&lt;br /&gt;
&lt;br /&gt;
;Вывести правила (&amp;lt;tt&amp;gt;-L&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--list&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -L [''цепочка''] [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вывести список правил для указанной таблицы и цепочки. Если цепочка не указана, то выводятся список правил для каждой цепочки. Например для вывода правил из таблицы nat:&lt;br /&gt;
&amp;lt;tt&amp;gt;iptables -t nat -n -L&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Часто используются параметры -n (во избежение медленных запросов DNS) и -v (для вывода более подробной информации).&lt;br /&gt;
&lt;br /&gt;
Команду -L можно использовать с -Z (&amp;lt;tt&amp;gt;iptables -L -Z&amp;lt;/tt&amp;gt;) для вывода значений счетчиков и одновременного их обнуления.&lt;br /&gt;
&lt;br /&gt;
;Удалить все правила из цепи (&amp;lt;tt&amp;gt;-F&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--flush&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -[F] [''цепочка''] [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если цепочка не указана, то удаляются все цепочки из таблицы.&lt;br /&gt;
&lt;br /&gt;
;Обнулить все счетчики (&amp;lt;tt&amp;gt;-Z&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--zero&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -Z [''цепочка''] [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Присваивает счетчикам числа пакетов и объема данных нулевые значения. Если цепочка не указана, то обнуление выполняется для всех цепочек.&lt;br /&gt;
&lt;br /&gt;
Команду -Z можно использовать с -L (&amp;lt;tt&amp;gt;iptables -L -Z&amp;lt;/tt&amp;gt;) для вывода значений счетчиков и одновременного их обнуления.&lt;br /&gt;
&lt;br /&gt;
;Создать новую цепочку (&amp;lt;tt&amp;gt;-N&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--new-chain&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -N ''цепочка''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Создать новую цепочку в указанной таблице с указанным именем. Если в указанной таблице уже есть цепочка с указанным именем, то новая не создается.&lt;br /&gt;
&lt;br /&gt;
;Удалить созданную цепочку (&amp;lt;tt&amp;gt;-X&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--delete-chain&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -X [''цепочка'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Удалить цепочку ранее созданную с помощью команды '''-N'''. Перед удалением цепи необходимо удалить или заменить все правила, которые ссылаются на эту цепочку. Если цепочка не указана, то из таблицы будут удалены все цепи кроме стандартных (INPUT, OUTPUT, FORWARD, PREROUTING, POSTROUTING). Стандартные цепочки не удаляются.&lt;br /&gt;
&lt;br /&gt;
;Переименование цепи (&amp;lt;tt&amp;gt;-E&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--rename-chain&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -E ''цепочка'' ''новое_название''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Присваивает указанной цепочке новое название. Косметическая функция, не влияющая на функциональность.&lt;br /&gt;
&lt;br /&gt;
;Установить политику для стандартной цепи (&amp;lt;tt&amp;gt;-P&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--policy&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -P ''цепочка'' ''действие'' [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Над пакетами которые доходят до конца указанной цепочки будет выполняться указанное действие. В качестве действия нельзя указывать название какой-либо цепочки. Устанавливать политику можно только на встроенных цепочках. Например:&lt;br /&gt;
&amp;lt;tt&amp;gt;iptables -P INPUT DROP&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Команды модификации правил ===&lt;br /&gt;
&lt;br /&gt;
;Добавить новое правило (&amp;lt;tt&amp;gt;-A&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--append chain&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -A ''цепочка'' ''спецификация_правила'' [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Правило добавляется в конец указанной цепочки. Если в спецификации правила указано имя отправителя или получателя, которое одновременно соответствует нескольким адресам, то в конец цепочки добавляются правила для всех возможных комбинаций.&lt;br /&gt;
&lt;br /&gt;
;Вставить новое правило (&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--insert&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -I ''цепочка'' [''номер_правила''] спецификация_правила [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Указанное правило вставляется в указанное место указанной цепочки. Правила нумеруются с 1, поэтому если указать номер 1 (или не указать вообще), то правило будет вставлено в начало цепочки.&lt;br /&gt;
&lt;br /&gt;
;Удалить правило (&amp;lt;tt&amp;gt;-D&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--delete&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -D ''цепочка'' ''номер_правила'' [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -D ''цепочка'' ''спецификация_правила'' [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Правило можно указывать при помощи его номера в цепочке (нумерация начинается с 1) или его спецификации.&lt;br /&gt;
&lt;br /&gt;
;Заменить правило (&amp;lt;tt&amp;gt;-R&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--replace&amp;lt;/tt&amp;gt;)&lt;br /&gt;
&amp;lt;tt&amp;gt;'''iptables''' [-t ''таблица''] -R ''цепочка'' ''номер_правила'' ''спецификация_правила'' [''параметры'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Заменить правило с указанным номером в указанной цепочке. Правила нумеруются с 1. Спецификация правила не может содержать имени отправителя или получателя, которое одновременно соответствует нескольким адресам.&lt;br /&gt;
&lt;br /&gt;
=== Параметры определения правил ===&lt;br /&gt;
'''Важно.'''&lt;br /&gt;
В последующих версиях описанный ниже синтаксис изменился. Например, старому синтаксису&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-s'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--src&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source [!] ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
теперь соответствует новый&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-s'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--src&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Перечисленные ниже параметры используются при задании спецификации правил и указываются с командами модификации правил. Эти параметры ограничивают применение правил — если обрабатываемый пакет не соответствует указанным в спецификации критериям, то указанное в правиле действие на этот пакет не распространяется.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-p'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--protocol [!] ''протокол''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ограничение протокола. Основные значения: &amp;lt;tt&amp;gt;tcp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;udp&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;icmp&amp;lt;/tt&amp;gt;, или &amp;lt;tt&amp;gt;all&amp;lt;/tt&amp;gt;. Протокол также можно указать с помощью номера, или названия указанного в файле &amp;lt;tt&amp;gt;/etc/protocols&amp;lt;/tt&amp;gt;. Знак «!» перед именем протокола изменяет критерий на противоположенный (например &amp;lt;tt&amp;gt;!tcp&amp;lt;/tt&amp;gt; означает «любой протокол, кроме TCP»). Значение «Любой протокол» можно указать с помощью слова &amp;lt;tt&amp;gt;all&amp;lt;/tt&amp;gt; или числа 0. Если протокол не указан, то подразумевается «Любой протокол».&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-s'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--src&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--source [!] ''адрес''[/''маска'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ограничение отправителя. Адрес может быть IP-адресом (возможно с маской), именем хоста, или доменным именем. Маска может быть в стандартном формате (например 255.255.255.0) или же в виде числа, указывающего число единиц с «левой стороны» маски (например 24). Знак «!» перед адресом изменяет критерий на противоположенный.&lt;br /&gt;
&lt;br /&gt;
Настоятельно не рекомендуется использовать имена, для разрешения которых требуется удаленный запрос, например по системе DNS.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-d'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--dst&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--destination [!] ''address''[/''mask'']&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ограничение получателя. Синтаксис такой же, как у --src.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-i'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--in-interface [!] ''имя_интерфейса''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ограничение входящего сетевого интерфейса. Знак «!» перед адресом изменяет критерий на противоположенный. Если указанное имя интерфейса заканчивается на «+», то критерию совпадают все интерфейсы, чьи имена начинаются на указанное имя. Если параметр --in-interface не указан, то критерию соответствуют пакеты из любого сетевого интерфейса.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-o'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--out-interface [!] ''имя_интерфейса''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ограничение выходящего сетевого интерфейса. Синтаксис такой же, как и для --in-interface.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;[!] '''-f'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--fragment&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ограничение пр фрагментам: критерию соответствуют только фрагменты пакета, начиная со второго фрагмента. Знак «!» перед адресом изменяет критерий на противоположенный.&lt;br /&gt;
&lt;br /&gt;
У таких фрагментов начиная со второго нет заголовка с портами отправителя и получателя (или с типом ICMP). Следовательно, такие фрагменты не соответствуют критериям, указывающим номера портов.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-j'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--jump ''действие_или_цепочка''&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-g'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--goto ''цепочка''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Спецификация действий и переходов. Если указанно название цепочки ранее созданной командой -N, то пакеты соответствующие критериям правила переносится в начало указанной цепочки (запрещено указывать название цепочки, в котором это правило находится). Если указано действие, то оно выполняется над пакетами соответствующим критериям правила. Если в правиле нет параметров --jump и --goto, то правило не влияет на проверяемые пакеты (но счетчик правила продолжает работать).&lt;br /&gt;
&lt;br /&gt;
--goto отличается от --jump поведением при действии RETURN. Действие RETURN переводит пакет в правило, следующее после того, которое вызвало предыдущий переход --jump. То есть, если пакет перешел из цепочки X в цепочку Y при помощи --jump, а потом в Z опять при помощи --jump, то действие RETURN из цепочки Z возвращает его в Y. Если же пакет перешел в Z при помощи --goto, то RETURN возвращает его в X.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;'''-c'''&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;--set-counters ''пакеты байты''&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Параметр позволяет при добавлении или изменении правил одновременно инициализировать счетчики числа пакетов и размера данных.&lt;br /&gt;
&amp;lt;sub&amp;gt;Подстрочный текст&amp;lt;/sub&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Модули ==&lt;br /&gt;
Кроме фильтров по умолчанию поддерживаются дополнительные модули, подключающиеся автоматически при выборе протокола ('''-p''') или вручную опцией '''-m''' (''--match''), после которой следует имя подключаемого фильтра и его опции. Также как и для остальных правил фильтрации, здесь можно использовать '''!''' в качестве отрицания.&lt;br /&gt;
&lt;br /&gt;
=== Некоторые из встроенных (входящие в стандартный пакет) ===&lt;br /&gt;
&lt;br /&gt;
==== state ====&lt;br /&gt;
Соединением для NetFilter является закономерно оформленная последовательность обмена пакетами между хостами, с выделением роли каждого пакета в соединении. Эта особенность позволяет контролировать трафик с точки зрения транспортного уровня (модели OSI). Ядро NetFilter отслеживает соединения и ведёт активное наблюдение за открытием новых, протеканием и завершением установленных соединений. Каждый пакет может быть классифицирован по одному из следующих состояний: NEW, ESTABLISHED, RELATED и INVALID.&lt;br /&gt;
&lt;br /&gt;
NEW — типов пакетов, участвующих в установке нового соединения.&lt;br /&gt;
&lt;br /&gt;
ESTABLISHED — пакет уже установленного соединения&lt;br /&gt;
&lt;br /&gt;
RELATED — Соединение получает статус RELATED если оно связано с другим соединением, имеющим признак ESTABLISHED. Это означает, что соединение получает признак RELATED тогда, когда оно инициировано из уже установленного соединения, имеющего признак ESTABLISHED.&lt;br /&gt;
&lt;br /&gt;
Состояние RELATED относится к служебному трафику, протоколу ICMP стека TCP/IP.&lt;br /&gt;
&lt;br /&gt;
INVALID — неправильный/ошибочный/испорченный пакет. Обычно для таких пакетов применяют действие DROP&lt;br /&gt;
&lt;br /&gt;
ПРИМЕР:&lt;br /&gt;
 &lt;br /&gt;
 iptables -t nat -A PREROUTING -s 10.10.10.10 -m conntrack --ctstate NEW,INVALID -j DROP&lt;br /&gt;
&lt;br /&gt;
Все новые и ошибочные пакеты, идущие с адреса 10.10.10.10 отбрасываются&lt;br /&gt;
&lt;br /&gt;
==== connlimit ====&lt;br /&gt;
Позволяет задавать возможное количество одновременных подключений к машине от заданного IP или блока адресов&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --connlimit-above n&amp;lt;/tt&amp;gt; — пакет подойдет под описание, если количество одновременных подключений на данный момент больше (меньше), чем n&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;--connlimit-mask bits&amp;lt;/tt&amp;gt; — позволяет задать маску блока адресов&lt;br /&gt;
&lt;br /&gt;
 iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 20 -j REJECT --reject-with tcp-reset&lt;br /&gt;
&lt;br /&gt;
==== iprange ====&lt;br /&gt;
Выделяет не один адрес, как &amp;lt;tt&amp;gt;--src&amp;lt;/tt&amp;gt;, а все адреса от ip1 до ip2&lt;br /&gt;
&lt;br /&gt;
Нужно учитывать тот факт что перед использованием данного критерия, необходимо подгрузить модуль его реализующий «-m iprange»&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!]--src-range ip1-ip2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!]--dst-range ip1-ip2&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== multiport ====&lt;br /&gt;
&lt;br /&gt;
Выделяет не один порт, как &amp;lt;tt&amp;gt;--dport&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;--sport&amp;lt;/tt&amp;gt;, а несколько по списку (до 15 штук). Можно задавать диапазоны как первый_порт:последний_порт. Может быть использовано только вместе с &amp;lt;tt&amp;gt;-p udp&amp;lt;/tt&amp;gt; или &amp;lt;tt&amp;gt;-p tcp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!]--source-ports port1,port2,port3:port4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!]--destination-ports port1,port2,port3:port4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!]--ports port1,port2,port3:port4&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== mac ====&lt;br /&gt;
Сравнение не IP источника пакета, а его ethernet-адреса&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;[!] --mac-source address&amp;lt;/tt&amp;gt;. MAC-адрес должен быть указан в стандартном формате XX:XX:XX:XX:XX:XX.&lt;br /&gt;
&lt;br /&gt;
Если нужна фильтрация по MAC-адресу в мостовых соединениях (например, pppoe), то можно воспользоваться утилитой ebtables, которая предназначена как раз для более низкоуровневой фильтрации пакетов.&lt;br /&gt;
&lt;br /&gt;
Фиксируем получение IP-адреса по DHCP не из доверенного источника (MAC-адреса 00:50:8D:FD:E6:32):&lt;br /&gt;
&lt;br /&gt;
 iptables -A INPUT -i eth0 -p UDP --sport 68 --dport 67 -m mac ! --mac-source 00:50:8D:FD:E6:32 -m limit --limit 3/minute -j LOG  --log-prefix &amp;quot;IPT::DHCP: &amp;quot; --log-level warning&lt;br /&gt;
 iptables -A INPUT -i eth0 -p UDP --sport 68 --dport 67 -j ACCEPT&lt;br /&gt;
&lt;br /&gt;
== Примечания ==&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* https://ru.wikibooks.org/wiki/Iptables&lt;br /&gt;
* http://www.netfilter.org/ — Сайт проекта Netfilter&lt;br /&gt;
* [http://security.maruhn.com/iptables-manual.html Man page of iptables]&lt;br /&gt;
* [http://www.frozentux.net/documents/iptables-tutorial/ Frozentux Iptables Tutorial]&lt;br /&gt;
* [http://www.opennet.ru/docs/RUS/iptables Руководство по iptables (Iptables Tutorial 1.1.19)]&lt;br /&gt;
* [http://wiki.archlinux.org/index.php/Simple_stateful_firewall_HOWTO#Prerequisites Простой полноценный межсетевой экран (готовый шаблон для дектопа)]&lt;br /&gt;
* [http://posix.ru/network/iptables Настройка межсетевого экрана Iptables (готовый шаблон для дектопа)]&lt;br /&gt;
* http://freecode.com/projects/flex-fw — гибкая надстройка над iptables для построения сервис-ориентированного statefull-фаервола с простым синтаксисом команд.&lt;br /&gt;
* https://help.ubuntu.com/community/IptablesHowTo&lt;br /&gt;
* https://help.ubuntu.com/community/UFW&lt;br /&gt;
* https://help.ubuntu.com/community/Gufw&lt;br /&gt;
* https://help.ubuntu.com/9.10/serverguide/C/firewall.html&lt;br /&gt;
* https://wiki.ubuntu.com/UncomplicatedFirewall&lt;br /&gt;
* https://help.ubuntu.com/community/Firewall&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Vim</id>
		<title>Vim</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Vim"/>
				<updated>2017-05-15T06:48:51Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:Vim.png|thumb|Vim]]&lt;br /&gt;
Продвинутый текстовый редактор — кошмар для случайного пользователя. Если его удается в конце концов закрыть, то вздыхаешь с облегчением и твердой уверенностью, что больше не будешь запускать эту программу ни разу в жизни.&lt;br /&gt;
&lt;br /&gt;
Пожалуй, [[Vim]] нельзя просто запустить и начать работать — требуется определенная подготовка. Зато стоит раз испытать его в деле и поражаешься тому, как можно было без него обходиться.&lt;br /&gt;
&lt;br /&gt;
:Для быстрого ознакомления с функциональностью Vim запустите команду vimtutor.&lt;br /&gt;
&lt;br /&gt;
== Начнём с примера ==&lt;br /&gt;
&lt;br /&gt;
Типичная сессия работы с Vim выглядит так:&lt;br /&gt;
 # vim httpd.conf&lt;br /&gt;
В открывшемся редакторе:&lt;br /&gt;
 /SSLVerif&lt;br /&gt;
 nwr1ZZ&lt;br /&gt;
&lt;br /&gt;
В данном случае задачей было изменить значение определенного параметра конфигурации apache. В обычном редакторе подобный результат достигается следующими действиями:&lt;br /&gt;
&lt;br /&gt;
 # editor_name httpd.conf&lt;br /&gt;
&lt;br /&gt;
или [Ctrl]+[O] и выбрать файл из диалога открытия файла.&lt;br /&gt;
&lt;br /&gt;
 [Ctrl]+[F]SSLVerif[Enter][Enter][Esc]&lt;br /&gt;
 [Ctrl]+[→] [Del] 1&lt;br /&gt;
 [Ctrl]+[S]&lt;br /&gt;
 [Alt]+[F4]&lt;br /&gt;
&lt;br /&gt;
Объяснение команд обычного редактора:&lt;br /&gt;
* Открыть файл «httpd.conf» одним из указанных способов.&lt;br /&gt;
* [Ctrl]+[F] — открыть диалог поиска.&lt;br /&gt;
* Ввести «SSLVerif».&lt;br /&gt;
* [Enter] — фокус в диалоге поиска обычно всегда стоит на поиске следующего вхождения искомого слова.&lt;br /&gt;
* [Esc] — закроет окно поиска, а [Ctrl]+[→] снимет фокус с найденного слова и перейдёт к следующему (в некоторых редакторах курсор проскакивает слово и переходит через слово — тогда нажимаем [←] не отпуская [Ctrl], а в некоторых одиночное нажатие приводит только лишь к снятию фокуса и нужно повторно нажать [→]).&lt;br /&gt;
* [Del] удалит &amp;quot;0&amp;quot; и остаётся напечатать &amp;quot;1&amp;quot;.&lt;br /&gt;
* [Ctrl]+[S] — сохранить изменения.&lt;br /&gt;
* [Alt+F4] — закрыть файл и выйти.&lt;br /&gt;
&lt;br /&gt;
Объяснение команд VIM:&lt;br /&gt;
* / — Перейти в режим поиска&lt;br /&gt;
* Kлавиша '''Enter''' — Искать'.&lt;br /&gt;
* n — Перейти к следующему вхождению искомой строки&lt;br /&gt;
* w — Переместить курсор к следующему слову&lt;br /&gt;
* r — Заменить знак под курсором&lt;br /&gt;
* ZZ — Сохранить изменения и выйти&lt;br /&gt;
* ZQ — Выйти без сохранения изменений&lt;br /&gt;
&lt;br /&gt;
С одной стороны у vim более лаконичные команды, с другой же клавиши для «обычного» редактора работают в практически неизменном виде во многих приложениях и их нужно выучить лишь раз.&lt;br /&gt;
&lt;br /&gt;
== Введение ==&lt;br /&gt;
&lt;br /&gt;
Здесь я делюсь опытом работы в [[Vim]]. Предполагается, читатель имеет установленные vi и vim, а также знаком с основами работы с UNIX-подобной системой.&lt;br /&gt;
&lt;br /&gt;
Помнится, когда товарищ установил FreeBSD на мою домашнюю ЭВМ, некоторые файлы открывались непонятным мне образом. Я быстро старался избавиться от этого несчастья. Через некоторое время я понял, что происходит: в системе по умолчанию, в переменной окружения EDITOR, установлен редактор vi. Я сразу поменял его на 'ee' (easy editor). Это действительно простой редактор, затруднений с ним возникнуть просто не может, однако и особой свободы в нем не испытать. Вскоре его стало не хватать…&lt;br /&gt;
&lt;br /&gt;
Описание работы с редактором я привожу в хронологическом порядке — от простого к сложному. Так как Vim на 99 % совместим с Vi, сначала я дам краткое описание работы с vi.&lt;br /&gt;
&lt;br /&gt;
Легенда сокращений и специальных символов:&lt;br /&gt;
 Строки, начинающиеся с символа &amp;quot;#&amp;quot; - командная строка;&lt;br /&gt;
 &amp;lt;ESC&amp;gt; - нажатие клавишу Escape (или Ctrl-[);&lt;br /&gt;
 &amp;lt;CR&amp;gt; - ... Enter;&lt;br /&gt;
 &amp;lt;SHIFT&amp;gt; - ... Shift&lt;br /&gt;
 ^x - ... Ctrl-x&lt;br /&gt;
&lt;br /&gt;
== Vi ==&lt;br /&gt;
Главное отличие Vi от других редакторов в том, что у него несколько режимов работы. При этом привычный нам режим ввода текста — не основной. Вместо этого, в обычном режиме vi воспринимает каждое нажатие на клавишу, как команду. Это позволяет мгновенно перемещаться по файлу и быстро осуществлять редактирование.&lt;br /&gt;
&lt;br /&gt;
Насколько Vi быстрее других редакторов? — Давайте сравним. Например, вот действия, которые необходимо выполнить [«продвинутому»] пользователю, чтобы поменять местами две буквы в обычном редакторе и в vi:&lt;br /&gt;
&lt;br /&gt;
Обычный редактор:&lt;br /&gt;
 &amp;lt;Shift-Стрелка вправо&amp;gt;&lt;br /&gt;
 &amp;lt;Ctrl-x&amp;gt;&lt;br /&gt;
 &amp;lt;Стрелка влево&amp;gt;&lt;br /&gt;
 &amp;lt;Ctrl-v&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vi:&lt;br /&gt;
 xp&lt;br /&gt;
&lt;br /&gt;
=== Переключение режимов ===&lt;br /&gt;
&lt;br /&gt;
* '''«Обычный режим»''' — перемещение по файлу, стирание текста и другие редактирующие функции. Переход в него из любого другого режима:&lt;br /&gt;
 &amp;lt;ESC&amp;gt;, иногда 2 раза;&lt;br /&gt;
 &amp;lt;Ctrl-[&amp;gt;&lt;br /&gt;
Это основной режим работы, в которым совершаются различные операции с текстом. Описываемый далее &amp;quot;режим ввода&amp;quot; используется для непродолжительных операций ввода текста после чего рекомендуется сразу же возвращаться в обычный режим. Как только завершается ввод текста сразу необходимо перейти в обычный режим. Не рекомендуется оставлять программу в режиме ввода.&lt;br /&gt;
* '''«Режим ввода»''' — ввод текста. Заметьте, что стирание и ввод текста происходит в двух разных режимах. Переход в него из обычного режима:&lt;br /&gt;
 i&lt;br /&gt;
 &amp;lt;Insert&amp;gt;&lt;br /&gt;
* '''«Командный режим»''' — Команды (операции с файлом, поиск и замена, настройка редактора…). Переход в него из обычного режима:&lt;br /&gt;
 :&lt;br /&gt;
* '''«Режим поиска»''' — ввод поискового запроса. Переход в него из обычного режима&lt;br /&gt;
 / , поиск от курсора до конца документа&lt;br /&gt;
 ? , поиск от курсора до начала документа&lt;br /&gt;
* '''«Визуальный режим»''' — режим выделения текста. Переход в него из обычного режима&lt;br /&gt;
 v&lt;br /&gt;
&lt;br /&gt;
=== Открыть/создать файл ===&lt;br /&gt;
&lt;br /&gt;
Опишем операции, которые можно производить с файлом.&lt;br /&gt;
&lt;br /&gt;
 # vi mamapapa.txt           - открыть один файл&lt;br /&gt;
 # vi mamapapa.txt ++11      - открыть файл и перейти к строке 11.&lt;br /&gt;
 # vi mama.txt papa.txt      - открыть файл mama.txt, после выхода из него открыть файл papa.txt&lt;br /&gt;
 # vi -о mama.txt papa.txt   - открыть сразу все файлы.&lt;br /&gt;
&lt;br /&gt;
Файл открывается в обычном режиме с помощью команды vi. Строка статуса будет отображать название файла. Теперь мы можем просмотреть файл, переместиться по его содержимому, стереть текст, но ввести текст в этом режиме нельзя.&lt;br /&gt;
&lt;br /&gt;
Создание файла происходит при помощи той же команды. Собственно создание файла происходит в момент сохранения.&lt;br /&gt;
 &lt;br /&gt;
Для открытия или создания нового файла в обычном режиме набираем&lt;br /&gt;
 :e filename&lt;br /&gt;
или&lt;br /&gt;
 :new filename&lt;br /&gt;
Перед этим нужно сохранить предыдущий файл&lt;br /&gt;
 :w            - сохраняет файл с существующим именем&lt;br /&gt;
 :w filename   - сохраняет файл с новым именем&lt;br /&gt;
&lt;br /&gt;
=== Перемещение по файлу ===&lt;br /&gt;
&lt;br /&gt;
Самые часто используемые в vi клавиши — клавиши перемещения. Это знаменитые h j k l, соответствующие стрелкам влево, вниз, вверх и вправо. Стрелочки тоже работают (при правильном указании терминала). Можно использовать также быстрые клавиши:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;Ctrl-f&amp;gt; — на страницу (экран) вниз&lt;br /&gt;
* &amp;lt;Ctrl-b&amp;gt; — на страницу (экран) верх&lt;br /&gt;
* &amp;lt;Ctrl-d&amp;gt; — на пол страницы (экрана) вниз&lt;br /&gt;
* &amp;lt;Ctrl-u&amp;gt; — на пол страницы (экрана) верх&lt;br /&gt;
* &amp;lt;Ctrl-y&amp;gt; — на строку вниз, без изменения положения курсора&lt;br /&gt;
* &amp;lt;Ctrl-e&amp;gt; — на строку верх, без изменения положения курсора&lt;br /&gt;
* 0 (&amp;quot;ноль&amp;quot;) — в начало текущей строки;&lt;br /&gt;
* ^ — в начало текущей строки (к первому непробельному символу); &lt;br /&gt;
* $ — в конец текущей строки&lt;br /&gt;
* w — на слово вправо&lt;br /&gt;
* b — на слово влево&lt;br /&gt;
* W — до пробела вправо&lt;br /&gt;
* B — до пробела влево&lt;br /&gt;
* } — абзац вниз&lt;br /&gt;
* { — абзац вверх&lt;br /&gt;
* gg — перейти в начало файла&lt;br /&gt;
* G — перейти в конец файла&lt;br /&gt;
* &amp;lt;number&amp;gt;G — перейти на конкретную строку &amp;lt;number&amp;gt;&lt;br /&gt;
* /&amp;lt;text&amp;gt;&amp;lt;CR&amp;gt; — перейти к &amp;lt;text&amp;gt;&lt;br /&gt;
* ?&amp;lt;text&amp;gt;&amp;lt;CR&amp;gt; — то же самое, но искать назад&lt;br /&gt;
* n — повторить поиск&lt;br /&gt;
* N — повторить поиск назад&lt;br /&gt;
* [[ — в начало функции&lt;br /&gt;
* “ — к месту выполнения команды [[&lt;br /&gt;
&lt;br /&gt;
===Перемещение по экрану===&lt;br /&gt;
&lt;br /&gt;
Изменение положения экрана без изменения положения курсора.&lt;br /&gt;
*&amp;lt;code&amp;gt;z-&amp;lt;/code&amp;gt; сдвинуть страницу так чтобы строка с курсором оказалась внизу.&lt;br /&gt;
*&amp;lt;code&amp;gt;z[Enter]&amp;lt;/code&amp;gt; сдвинуть страницу так чтобы строка с курсором оказалась вверху&lt;br /&gt;
*&amp;lt;code&amp;gt;z.&amp;lt;/code&amp;gt; страницу так чтобы строка с курсором оказалась посредине&lt;br /&gt;
&lt;br /&gt;
Перемещение в пределах экрана&lt;br /&gt;
* &amp;lt;code&amp;gt;H&amp;lt;/code&amp;gt; перемещение на верхнюю строку экрана (&amp;lt;code&amp;gt;5H&amp;lt;/code&amp;gt; на пять строк ниже верхней строки) &lt;br /&gt;
* &amp;lt;code&amp;gt;M&amp;lt;/code&amp;gt; перемещение на среднюю строку экрана&lt;br /&gt;
* &amp;lt;code&amp;gt;L&amp;lt;/code&amp;gt; перемещение на последнюю строку экрана (&amp;lt;code&amp;gt;5L&amp;lt;/code&amp;gt; на пять строк выше нижней строки)&lt;br /&gt;
&lt;br /&gt;
=== Редактирование файла ===&lt;br /&gt;
&lt;br /&gt;
Предположим в нашем файле записан следующий текст:&lt;br /&gt;
&amp;lt;blockquote&amp;gt;— Винни, тебе что намазать на хлеб, мёду или сгущённого молока?&amp;lt;br/&amp;gt;&lt;br /&gt;
— И того, и другого, и можно без хлеба!&amp;lt;br/&amp;gt;&lt;br /&gt;
— Ну, если вы больше ничего не хотите…&amp;lt;br/&amp;gt;&lt;br /&gt;
— А что, что-то есть ещё?&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Диалог симпатичный, но несколько несвязный. Давайте изменим его — для этого необходимо перейти в режим ввода. Самый простой способ — из обычного режима нажатие клавиши «i». После чего можно смело приступать к вводу текста. &amp;lt;ESC&amp;gt; вернет нас к обычному режиму.&lt;br /&gt;
&lt;br /&gt;
''Вводное замечание.'' Поскольку заглавные и строчные буквы команд соотвествуют разным командам, следует быть внимательным к регистру ввода, например, не нажата ли случано клавиша &amp;lt;code&amp;gt;&amp;lt;CAPS LOCK&amp;gt;&amp;lt;/code&amp;gt;. Чтобы отменить ошибочные действия используйте команду &amp;lt;code&amp;gt;U&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Другие важные команды:&lt;br /&gt;
&lt;br /&gt;
====Ввод текста====&lt;br /&gt;
Все эти команды переводят редактор в режим ввода. Эти команды экономят время на движение курсора или на перевод его на новую строку. В командах ввода текста могут применяться числовые аргументы (за исключением &amp;lt;code&amp;gt;O&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;o&amp;lt;/code&amp;gt;). Например, команда &amp;lt;code&amp;gt;20iПривет&amp;lt;ESC&amp;gt;&amp;lt;/code&amp;gt; вставляет 20 слов &amp;quot;Привет&amp;quot;. &lt;br /&gt;
* &amp;lt;code&amp;gt;i&amp;lt;/code&amp;gt; — перейти в режим ввода с текущей позиции&lt;br /&gt;
* &amp;lt;code&amp;gt;a&amp;lt;/code&amp;gt; — перейти в режим ввода после курсора&lt;br /&gt;
* &amp;lt;code&amp;gt;I&amp;lt;/code&amp;gt; — переместиться в начало строки и перейти в режим ввода&lt;br /&gt;
* &amp;lt;code&amp;gt;А&amp;lt;/code&amp;gt; — переместиться в конец строки и перейти в режим ввода&lt;br /&gt;
* &amp;lt;code&amp;gt;o&amp;lt;/code&amp;gt; — перейти в режим ввода с новой строки под курсором&lt;br /&gt;
* &amp;lt;code&amp;gt;O&amp;lt;/code&amp;gt; — перейти в режим ввода с новой строки над курсором&lt;br /&gt;
* &amp;lt;code&amp;gt;s&amp;lt;/code&amp;gt; - заменяет указанное количество символов (удалет указанное число символов и переходит в режим ввода). В отличии от команды &amp;lt;code&amp;gt;с&amp;lt;/code&amp;gt; которая может удалить кусок текста размером не меньше слова (&amp;lt;code&amp;gt;cw&amp;lt;/code&amp;gt;), командой &amp;lt;code&amp;gt;s&amp;lt;/code&amp;gt; можно удалить любое число символов. Например &amp;lt;code&amp;gt;4s&amp;lt;/code&amp;gt; удалит четыре символа начиная с того который находится под курсором. Эта команда применяется для замены одного или нескольких символов другими символами.&lt;br /&gt;
* &amp;lt;code&amp;gt;S&amp;lt;/code&amp;gt; - удаляет всю текущую строку и переходит в режим ввода. Число перед командой показывает сколько нужно удалить строк начиная с текущей. Например &amp;lt;code&amp;gt;4S&amp;lt;/code&amp;gt; удалит четрые строки включая текущую.&lt;br /&gt;
* &amp;lt;code&amp;gt;R&amp;lt;/code&amp;gt; — перейти в режим ввода с заменой текста (аналог insert). Символы под курсором заменяются на вводимые. Команда применяется когда неизвестно сколько придется изменить символов на другие (иначе можно было бы использовать команду &amp;lt;code&amp;gt;s&amp;lt;/code&amp;gt; с указанием числа заменяемых символов, например, &amp;lt;code&amp;gt;7s&amp;lt;/code&amp;gt;). При удалении вводимых символов возвращаются те которые были до ввода команды. Такой режим сохраняется до конца строки. При вводе новой строки (по нажатию Enter), происходит не переход на другую строку с тем же режимом замены текста, а создание новой строки.&lt;br /&gt;
* &amp;lt;code&amp;gt;r&amp;lt;/code&amp;gt; — заменить один символ. Заменяет символ находящийся под курсором на символ который следует за командой. При этом не происходит выхода из командного режима (не надо нажимать ESC после изменения текста). Например, команда &amp;lt;code&amp;gt;ry&amp;lt;/code&amp;gt; - символ под курсором меняется на &amp;quot;y&amp;quot;. Числовой показатель указывает сколько символов необходимо заменить на данный. Например, &amp;lt;code&amp;gt;3ry&amp;lt;/code&amp;gt; вставляет три символа &amp;quot;y&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
====Удаление====&lt;br /&gt;
* &amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; — удалить символ под курсором (&amp;lt;code&amp;gt;&amp;lt;число&amp;gt;x&amp;lt;/code&amp;gt; удаляет указанное число символов начиная с того который находится под курсором)&lt;br /&gt;
* &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; — удалить символ влево (удалить символ перед курсором)&lt;br /&gt;
* &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt; — используется совместно с командами перемещения. Удаляет символы с текущего положения курсора до положения после ввода команды перемещения. Пример: &lt;br /&gt;
:* &amp;lt;code&amp;gt;dw&amp;lt;/code&amp;gt; - удаляет символы с текущего до конца слова. включая пробел после слова, чтобы удалить символы до конца слова, но оставить пробел используется команда &amp;lt;code&amp;gt;de&amp;lt;/code&amp;gt;, &lt;br /&gt;
:* &amp;lt;code&amp;gt;dE&amp;lt;/code&amp;gt; - удаляет символы с текущего до конца слова, включая символы пунктуации, но оставляет пробел после слова, &lt;br /&gt;
:* &amp;lt;code&amp;gt;diw&amp;lt;/code&amp;gt; - удаляет слово под курсором,&lt;br /&gt;
:* &amp;lt;code&amp;gt;dd&amp;lt;/code&amp;gt; — удалить текущую строку (вырезать)&lt;br /&gt;
:* &amp;lt;code&amp;gt;d&amp;lt;число&amp;gt;d&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;&amp;lt;число&amp;gt;dd&amp;lt;/code&amp;gt; — стирание числа строк начиная с текущей,&lt;br /&gt;
:* &amp;lt;code&amp;gt;db&amp;lt;/code&amp;gt; - удаляет символы с текущего до начала слова (удаление в обратном направлении)&lt;br /&gt;
:* &amp;lt;code&amp;gt;d0&amp;lt;/code&amp;gt; - удаление символов с начала строки до текущего положения курсора&lt;br /&gt;
:* &amp;lt;code&amp;gt;d$&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;D&amp;lt;/code&amp;gt; - удаление символов с текущего положения курсора до конца строки.&lt;br /&gt;
* &amp;lt;code&amp;gt;с&amp;lt;/code&amp;gt; — команда аналогичная &amp;lt;code&amp;gt;d&amp;lt;/code&amp;gt;, но после удаление переходит в режим ввода. (замена текста) Очень удобная альтернатива команде &amp;lt;code&amp;gt;R&amp;lt;/code&amp;gt;&lt;br /&gt;
:* &amp;lt;code&amp;gt;сс&amp;lt;/code&amp;gt; - команда удаляет текущую строку и переходит в режим ввода.&lt;br /&gt;
:* &amp;lt;code&amp;gt;C&amp;lt;/code&amp;gt; - удаляет текст с текущего положения курсора до конца строки, аналогична команде &amp;lt;code&amp;gt;с$&amp;lt;/code&amp;gt; (где $ - символ конца строки)&lt;br /&gt;
* &amp;lt;code&amp;gt;yy&amp;lt;/code&amp;gt; (также &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt;) — копирование текущей строки в неименованный буфер&lt;br /&gt;
* &amp;lt;code&amp;gt;y&amp;lt;число&amp;gt;y&amp;lt;/code&amp;gt; — копирование числа строк начиная с текущей в неименованный буфер&lt;br /&gt;
* &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; — вставка содержимого неименнованного буфера под курсором. Поскольку в vim девять ячеек буфера удаления. Можно вставить не только последнее удаление но и удаления сделанные ранее. Например &amp;quot;&amp;lt;code&amp;gt;4p&amp;lt;/code&amp;gt; вставит под курсор содержимое четвертого удаления начиная с последнего. Также чтобы поменять местами два символа можно использовать комбинацию команд &amp;quot;удалить&amp;quot; -&amp;lt;code&amp;gt;x&amp;lt;/code&amp;gt; (удаление в буфер) и &amp;quot;вставить&amp;quot; - &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt; (вставить из буфера). Таким образом, поставив курсор на первую букву из двух которые необходимо поменять местами и нажав комбинацию клавиш &amp;lt;code&amp;gt;xp&amp;lt;/code&amp;gt; мы совершим необходимые действия.&lt;br /&gt;
* &amp;lt;code&amp;gt;P&amp;lt;/code&amp;gt; — вставка содержимого неименнованного буфера перед курсором&lt;br /&gt;
* &amp;lt;code&amp;gt;J&amp;lt;/code&amp;gt; — слияние текущей строки со следующей. Числовой аргумент перед командой показывает сколько следующих линий необходимо объединить с текущей. Например &amp;lt;code&amp;gt;2J&amp;lt;/code&amp;gt; объединить две следующие строки с текущей, на которой расположен курсор.&lt;br /&gt;
&lt;br /&gt;
====Отмена изменений====&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;u&amp;lt;/code&amp;gt; — отмена последней команды&lt;br /&gt;
* &amp;lt;code&amp;gt;U&amp;lt;/code&amp;gt; — отмена всех последних изменений в строке, если строка удалена, то применить эту команду к данной строке будет невозможно&lt;br /&gt;
&lt;br /&gt;
Команды &amp;lt;code&amp;gt;u&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;U&amp;lt;/code&amp;gt; могут отменять друг друга.&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;&amp;lt;Ctrl-r&amp;gt;&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;:redo&amp;lt;/code&amp;gt; вперед по изменениям&lt;br /&gt;
* &amp;lt;code&amp;gt;.&amp;lt;/code&amp;gt; — повтор последней команды, включая ввод текста.&lt;br /&gt;
* &amp;lt;code&amp;gt;~&amp;lt;/code&amp;gt; - тильда меняет символы под курсором на противоположный регистр (заглавные в прописные и прописные в заглавные) может применяться числовой показатель. например, команда &amp;lt;code&amp;gt;5~&amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;&amp;lt;/code&amp;gt; поменяет пять символов начиная с текущего под курсором на противоположный регистр.&lt;br /&gt;
&lt;br /&gt;
Конечно, запомнить все команды сразу трудно, даже не нужно (к тому же здесь перечислены не все). Уверяю вас, через некоторое время эти команды будут пользоваться спросом.&lt;br /&gt;
Некоторые особенности использования редактора в режиме редактирования:&lt;br /&gt;
* Любой удаляемый текст сохраняется временно в буфере. Из этого буфера его можно вставить в текст.(см. команду &amp;lt;code&amp;gt;p&amp;lt;/code&amp;gt;). Буфер изменяется также после применения команды &amp;lt;code&amp;gt;y&amp;lt;/code&amp;gt;- копировать.&lt;br /&gt;
* Любая команда редактирования хранится в буфере, пока не будет вызвана другая команда.&lt;br /&gt;
&lt;br /&gt;
Наконец мы дошли к самому главному — командному режиму. Помним как в него перейти? «:». Шифт-ж, если по-русски.&lt;br /&gt;
&lt;br /&gt;
=== Запись/выход ===&lt;br /&gt;
&lt;br /&gt;
Если вы в режиме ввода, то необходимо предварительно нажать &amp;lt;ESC&amp;gt;, чтобы перейти в обычный режим.&lt;br /&gt;
&lt;br /&gt;
 ZQ - выйти без сохранения&lt;br /&gt;
или&lt;br /&gt;
 :q! - выйти без сохранения&lt;br /&gt;
&lt;br /&gt;
 ZZ - записать файл и выйти(Если файл не изменяли, то записываться он не будет)&lt;br /&gt;
или&lt;br /&gt;
 :wq - записать файл и выйти&lt;br /&gt;
или&lt;br /&gt;
 :x - записать файл и выйти&lt;br /&gt;
&lt;br /&gt;
 :w&amp;lt;CR&amp;gt; - записать файл&lt;br /&gt;
&lt;br /&gt;
 :sav filename&amp;lt;CR&amp;gt; - &amp;quot;Сохранить как&amp;quot;&lt;br /&gt;
или&lt;br /&gt;
 :w filename&amp;lt;CR&amp;gt; - &amp;quot;Сохранить как&amp;quot;&lt;br /&gt;
&lt;br /&gt;
 :w!&amp;lt;CR&amp;gt; - записать файл. &lt;br /&gt;
Эта команда может помочь, если файл открыт в режиме &amp;quot;read-only&amp;quot; (с опцией -R), если файл заблокирован другим пользователем, либо отсутствуют такие привилегии, либо еще какая беда. При попытке записи без «!» будет выдано соответствующее предупреждение.&lt;br /&gt;
&lt;br /&gt;
 :w new_file&amp;lt;CR&amp;gt;&lt;br /&gt;
Создать новый файл «new_file» и записать в него текущее содержимое. Если файл существует, будет показано предупреждение. Дальше вы продолжаете работать со старым файлом — mamapapa.txt&lt;br /&gt;
&lt;br /&gt;
Если при попытке сохранения появляется сообщение, что места на диске не осталось можно выйти в командную оболочку и освободить место на диске стерев ненужные файлы. Для &lt;br /&gt;
этог применяется команда&lt;br /&gt;
&lt;br /&gt;
 :sh&amp;lt;CR&amp;gt; - переход в командную оболочку.&lt;br /&gt;
Чтобы из командной оболочки вернуться в редактор нажмите CTRL-D или введите exit.&lt;br /&gt;
&lt;br /&gt;
 :q&amp;lt;CR&amp;gt; - выйти из редактора.&lt;br /&gt;
Если файл был изменен, у вас ничего не получится. В таких случаях необходимо добавлять после команды «!»:&lt;br /&gt;
&lt;br /&gt;
 :q!&amp;lt;CR&amp;gt; - выйти из файла, не сохраняя изменения&lt;br /&gt;
 :qa!&amp;lt;CR&amp;gt; - выйти из всех файлов, не сохраняя изменения&lt;br /&gt;
&lt;br /&gt;
Чтобы отменить все сделанные в текущей сессии изменения и вернуться к первоначальному варианту файла применяют команду &lt;br /&gt;
 :e!&amp;lt;CR&amp;gt; - отменить изменения в текущей сессии&lt;br /&gt;
&lt;br /&gt;
=== Коэффициент повторения ===&lt;br /&gt;
&lt;br /&gt;
Почти все команды vi принимают так называемый коэффициент повторения. Попросту говоря, если перед командой в обычном режиме вы указываете число, то команда повторяется соответствующее количество раз. Например, команда «j» перемещает курсор на одну строку вниз — «3j» переместит курсор на 3 строки вниз. Результатом команды «iпривет&amp;lt;ESC&amp;gt;», как вы, наверное, догадались, будет вставка слова «привет» — «2iпривет&amp;lt;ESC&amp;gt;» вставит «приветпривет».&lt;br /&gt;
&lt;br /&gt;
=== Дополнительные возможности ===&lt;br /&gt;
Есть несколько вещей, без которых редактирование похоже на пытку:&lt;br /&gt;
 ^G - показать информацию о файле&lt;br /&gt;
&lt;br /&gt;
 :&amp;lt;number&amp;gt; - перейти на строку с номером &amp;lt;number&amp;gt;&lt;br /&gt;
 &amp;lt;number&amp;gt;G - перейти на строку с номером &amp;lt;number&amp;gt;&lt;br /&gt;
 :set number - отобразить слева нумерацию строк (:set nonumber - спрятать нумерацию)&lt;br /&gt;
 :set wrap - переносить длинные строки(:set nowrap - не переносить)&lt;br /&gt;
 :sy[ntax] on/off - включить/выключить подсветку синтаксиса&lt;br /&gt;
 :colorscheme &amp;lt;name&amp;gt; - задать цветовую тему (где &amp;lt;name&amp;gt; имя темы, TAB работает как авто-дополнение)&lt;br /&gt;
 :h или :help - список возможной помощи(:viusage, :exusage)&lt;br /&gt;
 привести концы строк в файле к виду dos или unix соответственно:&lt;br /&gt;
 :set fileformat=dos&lt;br /&gt;
 :set fileformat=unix&lt;br /&gt;
 Задать размер табуляции в 4 пробела:&lt;br /&gt;
 :set tabstop=4&lt;br /&gt;
 :set expandtab&lt;br /&gt;
 Размер табуляции новой строки&lt;br /&gt;
 :set shiftwidth=4&lt;br /&gt;
&lt;br /&gt;
Конвертация кодировки файла:&lt;br /&gt;
 :set fenc=cp1251&amp;lt;CR&amp;gt;&lt;br /&gt;
 :set fenc=koi8-r&amp;lt;CR&amp;gt;&lt;br /&gt;
 :set fenc=ibm866&amp;lt;CR&amp;gt;&lt;br /&gt;
 :set fenc=utf-8&amp;lt;CR&amp;gt;&lt;br /&gt;
Смена кодировки (возможна до внесения изменений в редактируемый файл. т.е. сразу после открытия)&lt;br /&gt;
 :e ++enc=cp1251&amp;lt;CR&amp;gt;&lt;br /&gt;
 :e ++enc=koi8-r&amp;lt;CR&amp;gt;&lt;br /&gt;
 :e ++enc=ibm866&amp;lt;CR&amp;gt;&lt;br /&gt;
 :e ++enc=utf-8&amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Vim ==&lt;br /&gt;
&lt;br /&gt;
=== Главные отличия от vi ===&lt;br /&gt;
* Неограниченное число undo/redo. (в 7-ой версии появились деревья)&lt;br /&gt;
* Многооконность.&lt;br /&gt;
* Поддержка множества буферов. (в 7-ой версии появились закладки)&lt;br /&gt;
* Подсветка синтаксиса.&lt;br /&gt;
* Редактирование командной строкой.&lt;br /&gt;
* Достраивание имен файлов.&lt;br /&gt;
* Визуальное редактирование.&lt;br /&gt;
* Кроссплатформенность.&lt;br /&gt;
* Графический интерфейс (GUI).&lt;br /&gt;
* Проверка орфографии&lt;br /&gt;
&lt;br /&gt;
=== Команды ===&lt;br /&gt;
Переход к началу файла в Vim отличается от Vi:&lt;br /&gt;
 gg&lt;br /&gt;
Переход к строке под номером &amp;lt;number&amp;gt;:&lt;br /&gt;
 &amp;lt;number&amp;gt;gg&lt;br /&gt;
&lt;br /&gt;
=== Слово под курсором ===&lt;br /&gt;
Перейти к следующему вхождению слова под курсором&lt;br /&gt;
 *&lt;br /&gt;
Перейти к предыдущему вхождению слова под курсором&lt;br /&gt;
 #&lt;br /&gt;
Перейти к определению слова под курсором&lt;br /&gt;
 gd (go definition)&lt;br /&gt;
Перейти к редактированию файла (под курсором должен быть путь)&lt;br /&gt;
 gf (go file)&lt;br /&gt;
&lt;br /&gt;
=== Визуальный режим ===&lt;br /&gt;
Это существенное расширение возможностей Vi, без которого не обходится ни один «нормальный» текстовой редактор. Режим предназначен для выделения блока текста и дальнейшей работы с ним и состоит из 3-х последовательных шагов:&lt;br /&gt;
# Пометка начала блока с помощью «v», «V» или CTRL-V. Блок помечается с того символа на котором находится курсор(по умолчанию).&lt;br /&gt;
# Перемещение курсора в конец необходимого блока. Последний символ также будет включен в выделенный блок.&lt;br /&gt;
# Вызов необходимой команды.&lt;br /&gt;
&lt;br /&gt;
Команда «v» предназначена для выделения текста посимвольно. Символы до и после курсора в строке не будут входить в выделение. Необходима в первую очередь для копирования участков текста в строке.&amp;lt;br /&amp;gt;&lt;br /&gt;
«V» — для выделения текста построчно.&amp;lt;br /&amp;gt;&lt;br /&gt;
CTRL-V — для выделения прямоугольного участка текста. Удобна в случае редактирования структурированного текста.&lt;br /&gt;
&lt;br /&gt;
С выделенным участком текста можно производить стандартные действия по редактированию(копирование — «y», удаление — «d»). Напомню, что в Vim при удалении участка текста, он автоматически помещается в специальный регистр, что равноценно «вырезанию» участка текста, который потом можно будет вставить с помощью команды «p»(вставка текста после курсора) или «P»(вставка текста перед курсором).&lt;br /&gt;
&lt;br /&gt;
=== ~/.vimrc ===&lt;br /&gt;
'''vimrc''' — это файл конфигурации Vim. При запуске Vim сначала читает этот файл и применяет записанные в нем настройки. Рекомендуемое расположение этого файла для различных платформ:&lt;br /&gt;
 Unix-like         $HOME/.vimrc&lt;br /&gt;
 MS-DOS and Win32  $HOME/_vimrc или $VIM/_vimrc&lt;br /&gt;
&lt;br /&gt;
Файл конфигурации используется для настройки различных аспектов поведения и внешнего вида Vim.&lt;br /&gt;
&lt;br /&gt;
Комментарии в этом файле начинаются с символа '''&amp;quot;''' (двойная кавычка) и продолжаются до конца строки.&lt;br /&gt;
&lt;br /&gt;
==== Для примера приводится выдержка из файла .vimrc автора: ====&lt;br /&gt;
 &amp;quot; установить keymap, чтобы по Ctrl+^ переключался на русский и обратно&lt;br /&gt;
 set keymap=russian-jcukenwin &lt;br /&gt;
 &amp;quot; по умолчанию - латинская раскладка&lt;br /&gt;
 set iminsert=0&lt;br /&gt;
 &amp;quot; по умолчанию - латинская раскладка при поиске&lt;br /&gt;
 set imsearch=0&lt;br /&gt;
 &amp;quot; игнорировать регистр при поиске&lt;br /&gt;
 set ic&lt;br /&gt;
 &amp;quot; подсвечивать поиск&lt;br /&gt;
 set hls&lt;br /&gt;
 &amp;quot; использовать инкрементальный поиск&lt;br /&gt;
 set is&lt;br /&gt;
 &amp;quot; ширина текста &lt;br /&gt;
 set textwidth=70&lt;br /&gt;
 &amp;quot; минимальная высота окна пусть будет 0 (по умолчанию - 1)&lt;br /&gt;
 set winminheight=0&lt;br /&gt;
 &amp;quot; всегда делать активное окно максимального размера&lt;br /&gt;
 set noequalalways&lt;br /&gt;
 set winheight=9999&lt;br /&gt;
 &amp;quot; установить шрифт Courier New Cyr&lt;br /&gt;
 set guifont=courier_new:h10:cRUSSIAN&lt;br /&gt;
 &amp;quot; настраиваю для работы с русскими словами (чтобы w, b, * понимали&lt;br /&gt;
 &amp;quot; русские слова)&lt;br /&gt;
 set iskeyword=@,48-57,_,192-255&lt;br /&gt;
 &amp;quot; задать размер табуляции в четыре пробела&lt;br /&gt;
 set ts=4&lt;br /&gt;
 &amp;quot; отображение выполняемой команды&lt;br /&gt;
 set showcmd &lt;br /&gt;
 &amp;quot; перенос по словам, а не по буквам&lt;br /&gt;
 set linebreak&lt;br /&gt;
 set dy=lastline&lt;br /&gt;
&lt;br /&gt;
==== Можно добавить привычное поведение и привычные сочетания клавиш. ====&lt;br /&gt;
&lt;br /&gt;
* Например, можно будет прокручивать (скроллить) текст колесиком мыши и вставлять выделенное в X`ах мышкой в Vim нажатием средней кнопки мыши (нажать на колесико мыши):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 set mouse=a&lt;br /&gt;
 map &amp;lt;S-Insert&amp;gt; &amp;lt;MiddleMouse&amp;gt;&lt;br /&gt;
 map! &amp;lt;S-Insert&amp;gt; &amp;lt;MiddleMouse&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* По &amp;lt;code&amp;gt;&amp;lt;F2&amp;gt;&amp;lt;/code&amp;gt; сохранение сделанных изменений:&lt;br /&gt;
 imap &amp;lt;F2&amp;gt; &amp;lt;Esc&amp;gt;:w&amp;lt;CR&amp;gt;&lt;br /&gt;
 map &amp;lt;F2&amp;gt; &amp;lt;Esc&amp;gt;:w&amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* По &amp;lt;code&amp;gt;&amp;lt;F3&amp;gt;&amp;lt;/code&amp;gt; вставка содержимого заданного файла в редактируемый текст. Требуется ввести имя файла. Работает авто-дополнение имени файла по &amp;lt;code&amp;gt;&amp;lt;Tab&amp;gt;&amp;lt;/code&amp;gt; в текущем каталоге.&lt;br /&gt;
 imap &amp;lt;F3&amp;gt; &amp;lt;Esc&amp;gt;:read &lt;br /&gt;
 map &amp;lt;F3&amp;gt; &amp;lt;Esc&amp;gt;:read &lt;br /&gt;
Также возможен интересный прием работы:&lt;br /&gt;
 :read !ls -la&lt;br /&gt;
Эта команда вставит в текущую позицию редактируемого текста весь вывод указанной после &amp;quot;&amp;lt;code&amp;gt;!&amp;lt;/code&amp;gt;&amp;quot; команды (в нашем случае: &amp;lt;code&amp;gt;ls -la&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
* По &amp;lt;code&amp;gt;&amp;lt;F4&amp;gt;&amp;lt;/code&amp;gt; открывается новая вкладка (tab) и выводится список каталогов и файлов текущего каталога. Клавишами управления курсором можно выбрать каталог или файл. Нажатие &amp;lt;code&amp;gt;&amp;lt;Enter&amp;gt;&amp;lt;/code&amp;gt; на каталог отобразит его содержимое в том же режиме (можно путешествовать по каталогам), а нажатие &amp;lt;code&amp;gt;&amp;lt;Enter&amp;gt;&amp;lt;/code&amp;gt; на файле - откроет его в этой же вкладке. Работает быстрый поиск-перемещение по &amp;quot;&amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
 imap &amp;lt;F4&amp;gt; &amp;lt;Esc&amp;gt;:browse tabnew&amp;lt;CR&amp;gt; &lt;br /&gt;
 map &amp;lt;F4&amp;gt; &amp;lt;Esc&amp;gt;:browse tabnew&amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* По &amp;lt;code&amp;gt;&amp;lt;F5&amp;gt;&amp;lt;/code&amp;gt; позволяет переключать вкладки справа-налево, по-порядку, отображая открытые в них файлы.&lt;br /&gt;
 imap &amp;lt;F5&amp;gt; &amp;lt;Esc&amp;gt; :tabprev &amp;lt;CR&amp;gt;i&lt;br /&gt;
 map &amp;lt;F5&amp;gt; :tabprev &amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* По &amp;lt;code&amp;gt;&amp;lt;F6&amp;gt;&amp;lt;/code&amp;gt; позволяет переключать вкладки слева-направо, по-порядку, отображая открытые в них файлы.&lt;br /&gt;
 imap &amp;lt;F6&amp;gt; &amp;lt;Esc&amp;gt; :tabnext &amp;lt;CR&amp;gt;i&lt;br /&gt;
 map &amp;lt;F6&amp;gt; :tabnext &amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Пользовательское меню. По &amp;lt;code&amp;gt;&amp;lt;F9&amp;gt;&amp;lt;/code&amp;gt; позволяет приостановить работу Vim и вызвать соответствующие программы:&lt;br /&gt;
 set wildmenu&lt;br /&gt;
 set wcm=&amp;lt;Tab&amp;gt;&lt;br /&gt;
 menu Exec.GForth  :!gforth % &amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.Perl    :!perl % &amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.Python  :!python % &amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.Ruby    :!ruby % &amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.bash      :!/bin/bash&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.xterm     :!xterm&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.mc        :!mc&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exec.xterm_mc  :!xterm -e mc&amp;lt;CR&amp;gt;&lt;br /&gt;
 map &amp;lt;F9&amp;gt; :emenu Exec.&amp;lt;Tab&amp;gt;&lt;br /&gt;
::Обратите внимание на, например, конструкцию &amp;lt;code&amp;gt;:!python % &amp;lt;CR&amp;gt;&amp;lt;/code&amp;gt; — символ &amp;lt;code&amp;gt;%&amp;lt;/code&amp;gt; будет заменён на имя текущего редактируемого файла. В итоге, Vim приостановит работу и вызовет &amp;lt;code&amp;gt;python filename.ext&amp;lt;/code&amp;gt; (если вы редактировали &amp;lt;code&amp;gt;filename.ext&amp;lt;/code&amp;gt;) в текущем терминале (в том же, где запущен Vim), а затем, после завершения работы &amp;lt;code&amp;gt;python filename.ext&amp;lt;/code&amp;gt;, вернётся к редактированию файла. Не забудьте сохранить изменения перед вызовом. Впрочем, Vim должен будет вам напомнить о том, что изменения нужно сохранить, если вы этого не сделали.&lt;br /&gt;
::Заметьте: что &amp;lt;code&amp;gt;Exec.&amp;lt;/code&amp;gt; — это не специальная команда, в всего лишь идентификатор меню, объединяющая группу команд и их идентификаторы/названия пунктов меню/.&lt;br /&gt;
&lt;br /&gt;
* Пользовательское меню. По &amp;lt;code&amp;gt;&amp;lt;F10&amp;gt;&amp;lt;/code&amp;gt; позволяет вызвать меню различных вариантов завершения работы с Vim. ( Глоток воздуха для новичка :)&lt;br /&gt;
 set wildmenu&lt;br /&gt;
 set wcm=&amp;lt;Tab&amp;gt;&lt;br /&gt;
 menu Exit.quit     :quit&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exit.quit!    :quit!&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Exit.save     :exit&amp;lt;CR&amp;gt;&lt;br /&gt;
 map &amp;lt;F10&amp;gt; :emenu Exit.&amp;lt;Tab&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Позволяет по &amp;lt;code&amp;gt;&amp;lt;Tab&amp;gt;&amp;lt;/code&amp;gt;, более привычному некоторым пользователям, вызывать авто-дополнение для текущего активного синтаксиса:&lt;br /&gt;
 &amp;lt;pre&amp;gt;&lt;br /&gt;
 function! InsertTabWrapper(direction)&lt;br /&gt;
    let col = col('.') - 1&lt;br /&gt;
    if !col || getline('.')[col - 1] !~ '\k'&lt;br /&gt;
        return &amp;quot;\&amp;lt;tab&amp;gt;&amp;quot;&lt;br /&gt;
    elseif &amp;quot;backward&amp;quot; == a:direction&lt;br /&gt;
        return &amp;quot;\&amp;lt;c-p&amp;gt;&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        return &amp;quot;\&amp;lt;c-n&amp;gt;&amp;quot;&lt;br /&gt;
    endif&lt;br /&gt;
 endfunction&lt;br /&gt;
 inoremap &amp;lt;tab&amp;gt; &amp;lt;c-r&amp;gt;=InsertTabWrapper (&amp;quot;forward&amp;quot;)&amp;lt;cr&amp;gt;&lt;br /&gt;
 inoremap &amp;lt;s-tab&amp;gt; &amp;lt;c-r&amp;gt;=InsertTabWrapper (&amp;quot;backward&amp;quot;)&amp;lt;cr&amp;gt;&lt;br /&gt;
 &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Дополнительно ====&lt;br /&gt;
Для получения более подробной информации по файлу _vimrc можно набрать в командной строке Vim команду&lt;br /&gt;
 :help vimrc&lt;br /&gt;
&lt;br /&gt;
=== Vim и русская раскладка клавиатуры ===&lt;br /&gt;
В обычном режиме Vim по умолчанию ожидает, что консоль находится в режиме ввода латинских символов. Если вы, к примеру, редактируете с помощью Vim текст на русском языке, или в смешанных кодировках (к примеру, HTML-страницу на русском), то постоянная необходимость переключать системную клавиатурную раскладку очень быстро вам надоест. Существует несколько способов решить эту проблему.&lt;br /&gt;
==== Способ 1 ====&lt;br /&gt;
Сделать так, чтобы русские буквы можно было вводить, когда системная раскладка находится в режиме ввода латинских символов.&lt;br /&gt;
&lt;br /&gt;
Для этого в файл конфигурации Vim, который называется [[Vim#~/.vimrc|.vimrc]] (или _vimrc в Microsoft Windows) нужно добавить следующие строки:&lt;br /&gt;
&lt;br /&gt;
 set keymap=russian-jcukenwin &lt;br /&gt;
 set iminsert=0&lt;br /&gt;
&lt;br /&gt;
После этого системную раскладку клавиатуры можно будет оставить в режиме ввода латинских символов, а переключение между языками осуществлять уже внутри самого редактора с помощью команды &amp;lt;code&amp;gt;Ctrl+^&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;Ctrl+6&amp;lt;/code&amp;gt; в версии для Windows)&lt;br /&gt;
&lt;br /&gt;
Чтобы настроить переключение языков на другую кнопку (например на &amp;lt;code&amp;gt;F12&amp;lt;/code&amp;gt;), можно использовать такие команды: &lt;br /&gt;
:для режима ввода символов: &lt;br /&gt;
:imap &amp;lt;F12&amp;gt; {ctrl-k}{ctrl-6}{ctrl-6}&lt;br /&gt;
При этом &amp;lt;code&amp;gt;{ctrl-k}&amp;lt;/code&amp;gt; нужно вводить нажатием клавиш &amp;lt;code&amp;gt;&amp;lt;Ctrl&amp;gt;&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt;. Это означает, что сначала нажимается клавиша &amp;lt;code&amp;gt;&amp;lt;Ctrl&amp;gt;&amp;lt;/code&amp;gt; и удерживается нажатой, затем нажимается клавиша &amp;lt;code&amp;gt;k&amp;lt;/code&amp;gt; и после этого обе клавиши одновременно отпускаются. После нажатия &amp;lt;code&amp;gt;{ctrl-k}&amp;lt;/code&amp;gt; появится подсвеченный значок вопроса, который потом заменится на код клавиши\комбинации, которую Вы введёте, в данном случае &amp;lt;code&amp;gt;{ctrl-6}&amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;{ctrl-6}&amp;lt;/code&amp;gt;, что будет выглядеть как &amp;lt;code&amp;gt;^^&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:для режима ввода командной строки: &lt;br /&gt;
:cmap &amp;lt;F12&amp;gt; {ctrl-k}{ctrl-6}{ctrl-6}&lt;br /&gt;
&lt;br /&gt;
В итоге, визуально в [[Vim#~/.vimrc|.vimrc]] это должно выглядеть так:&lt;br /&gt;
&lt;br /&gt;
 imap &amp;lt;F12&amp;gt; ^^&lt;br /&gt;
 cmap &amp;lt;F12&amp;gt; ^^&lt;br /&gt;
&lt;br /&gt;
Кроме этого, в версии для Windows Vim по умолчанию не настроен на использование кодировок клавиатуры, содержащих символы кириллицы, например CP1251 и KOI8-R (в версии же для Linux настройка по умолчанию корректна). Как следствие этого, Vim при редактировании русского текста будет неправильно обрабатывать команды перемещения по тексту, основанные на поиске слова, такие как '''w''' (одно слово вперед), '''b''' (одно слово назад), '''*''' (найти в тексте слово под курсором) и т. п. Чтобы настроить Vim для корректной работы с этими командами независимо от языка, достаточно добавить в файл конфигурации [[Vim#~/.vimrc|_vimrc]] следующую строку:&lt;br /&gt;
 set iskeyword=@,48-57,_,192-255&lt;br /&gt;
&lt;br /&gt;
Однако вышеуказанная строка не позволяет изменять регистр русского текста в версии Vim для Windows. Для решения обеих этих проблем&lt;br /&gt;
вместо вышеуказанной строки в файл конфигурации может быть добавлена следующая строка:&lt;br /&gt;
 language ctype Russian_Russia.1251&lt;br /&gt;
&lt;br /&gt;
==== Способ 2 ====&lt;br /&gt;
Сделать так, чтобы Vim понимал, какие клавиши нажимаются, если включена русская раскладка.&lt;br /&gt;
&lt;br /&gt;
Для этого в [[Vim#~/.vimrc|.vimrc]] добавьте следующую строчку:&lt;br /&gt;
&lt;br /&gt;
Для стандартной раскладки (Windows, Linux):&lt;br /&gt;
&lt;br /&gt;
 set langmap=ёйцукенгшщзхъфывапролджэячсмитьбю;`qwertyuiop[]asdfghjkl\;'zxcvbnm\,.,ЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ;QWERTYUIOP{}ASDFGHJKL:\&amp;quot;ZXCVBNM&amp;lt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для раскладки Mac:&lt;br /&gt;
&lt;br /&gt;
 set langmap=йцукенгшщзхъфывапролджэячсмитьбю/ЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ/;qwertyuiop[]asdfghjkl;'zxcvbnm,./QWERTYUIOP[]ASDFGHJKL:'ZXCVBNM,./&lt;br /&gt;
&lt;br /&gt;
(Так как в Mac-раскладке символы под цифрами вводят другие символы, соответствующие английским, например, нажатие Shift+4 вводит &amp;quot;%&amp;quot; вместо &amp;quot;$&amp;quot;, их не получится переназначить, поэтому способ 1 подходит лучше.)&lt;br /&gt;
&lt;br /&gt;
После этого Vim будет нормально понимать команды, вводимые при включенной русской раскладке.&lt;br /&gt;
&lt;br /&gt;
Если у вас локаль UTF, то данный способ не работает в старых версиях Vim. Необходимо каждый символ назначить индивидуально:&lt;br /&gt;
&lt;br /&gt;
   map ё `&lt;br /&gt;
   map й q&lt;br /&gt;
   map ц w&lt;br /&gt;
   map у e&lt;br /&gt;
   map к r&lt;br /&gt;
   map е t&lt;br /&gt;
   map н y&lt;br /&gt;
   map г u&lt;br /&gt;
   map ш i&lt;br /&gt;
   map щ o&lt;br /&gt;
   map з p&lt;br /&gt;
   map х [&lt;br /&gt;
   map ъ ]&lt;br /&gt;
   map ф a&lt;br /&gt;
   map ы s&lt;br /&gt;
   map в d&lt;br /&gt;
   map а f&lt;br /&gt;
   map п g&lt;br /&gt;
   map р h&lt;br /&gt;
   map о j&lt;br /&gt;
   map л k&lt;br /&gt;
   map д l&lt;br /&gt;
   map ж ;&lt;br /&gt;
   map э '&lt;br /&gt;
   map я z&lt;br /&gt;
   map ч x&lt;br /&gt;
   map с c&lt;br /&gt;
   map м v&lt;br /&gt;
   map и b&lt;br /&gt;
   map т n&lt;br /&gt;
   map ь m&lt;br /&gt;
   map б ,&lt;br /&gt;
   map ю .&lt;br /&gt;
   map Ё ~&lt;br /&gt;
   map Й Q&lt;br /&gt;
   map Ц W&lt;br /&gt;
   map У E&lt;br /&gt;
   map К R&lt;br /&gt;
   map Е T&lt;br /&gt;
   map Н Y&lt;br /&gt;
   map Г U&lt;br /&gt;
   map Ш I&lt;br /&gt;
   map Щ O&lt;br /&gt;
   map З P&lt;br /&gt;
   map Х {&lt;br /&gt;
   map Ъ }&lt;br /&gt;
   map Ф A&lt;br /&gt;
   map Ы S&lt;br /&gt;
   map В D&lt;br /&gt;
   map А F&lt;br /&gt;
   map П G&lt;br /&gt;
   map Р H&lt;br /&gt;
   map О J&lt;br /&gt;
   map Л K&lt;br /&gt;
   map Д L&lt;br /&gt;
   map Ж :&lt;br /&gt;
   map Э &amp;quot;&lt;br /&gt;
   map Я Z&lt;br /&gt;
   map Ч X&lt;br /&gt;
   map С C&lt;br /&gt;
   map М V&lt;br /&gt;
   map И B&lt;br /&gt;
   map Т N&lt;br /&gt;
   map Ь M&lt;br /&gt;
   map Б &amp;lt;&lt;br /&gt;
   map Ю &amp;gt;&lt;br /&gt;
&lt;br /&gt;
Возможно это зависит от версии, у меня работает так и причём в UTF:&lt;br /&gt;
&lt;br /&gt;
 set langmap=ёйцукенгшщзхъфывапролджэячсмитьбюЁЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ;`qwertyuiop[]asdfghjkl;'zxcvbnm,.~QWERTYUIOP{}ASDFGHJKL:\&amp;quot;ZXCVBNM&amp;lt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Так как в последних версиях возможна проблема с парсером символа экранирования '\' - его необходимо записывать как '\\' перед специальными символами ',', ';', '&amp;quot;' и '\'. Потому в версии 7.3 правильная строка может быть такой:&lt;br /&gt;
&lt;br /&gt;
 set langmap=!\\&amp;quot;№\\;%?*ёйцукенгшщзхъфывапролджэячсмитьбюЁЙЦУКЕHГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ;!@#$%&amp;amp;*`qwertyuiop[]asdfghjkl\\;'zxcvbnm\\,.~QWERTYUIOP{}ASDFGHJKL:\\&amp;quot;ZXCVBNM&amp;lt;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Способы 3 и 4 ====&lt;br /&gt;
&lt;br /&gt;
Использование плагинов http://www.vim.org/scripts/script.php?script_id=3885 или http://www.vim.org/scripts/script.php?script_id=4503&lt;br /&gt;
&lt;br /&gt;
== Вставка форматированного текста с отступами ==&lt;br /&gt;
У начинающих часто возникает ситуация, когда при копировании форматированного текста с отступами (например, текст страницы из браузера или пример форматированного кода из документации) в vim строки «съезжают» вправо. Это происходит потому, что редактор пытается помочь отформатировать текст «красиво» и копирует отступы с предыдущей строки в новую. Бороться с этим легко:&lt;br /&gt;
 :set paste&lt;br /&gt;
...вставляем форматированный текст с отступами в режиме редактирования (например, средней кнопкой мыши) и строки «съезжать» вправо не будут. После этого режим «вставки» можно отключить командой:&lt;br /&gt;
 :set nopaste&lt;br /&gt;
&lt;br /&gt;
== Поиск в файлах с выводом в список ==&lt;br /&gt;
В некоторых IDE есть очень удобная функция Find In Files. Она ищет заданную строку или регулярное выражение в файлах в заданной папке и выводит результат поиска в виде списка. Если щёлкнуть по строке этого списка то откроется файл в том месте где была найдена заданная строка. Подобная функция есть и в Vim. Чтобы найти в файлах нужную строку надо набрать команду:&lt;br /&gt;
 :vimgrep /искомая строка/ Путь к файлам | :copen&lt;br /&gt;
Более конкретный пример:&lt;br /&gt;
 :vimgrep /translator/ R:\projects\**\*.txt | :copen&lt;br /&gt;
Команда vimgrep ищет строку или регулярное выражение заключенное между символами // в файле или файлах и сбрасывает результаты в специальный буфер. А так же открывает файл с первым найденным результатом. Команда copen открывает буфер с результатами поиска.&lt;br /&gt;
Путь к файлам может указывать как на один файл так и на набор файлов. Чтобы путь указывал на несколько файлов надо использовать символы ? и *. Значение этих символов такое же как и в командной строке операционной системы. Чтобы поиск прошел по всем подпапкам указанной папки можно использовать две звездочки **. Пример использования **:&lt;br /&gt;
 /usr/inc**/*.h&lt;br /&gt;
может означать:&lt;br /&gt;
 /usr/include/types.h&lt;br /&gt;
 /usr/include/sys/types.h&lt;br /&gt;
 /usr/inc_old/types.h&lt;br /&gt;
&lt;br /&gt;
== Как открыть файл в нужной кодировке ==&lt;br /&gt;
&lt;br /&gt;
=== Автоматически ===&lt;br /&gt;
При открытии файла Vim попытается определить кодировку, и открыть файл в этой кодировке. Для этого, в &amp;lt;code&amp;gt;~/.vimrc&amp;lt;/code&amp;gt;:&lt;br /&gt;
 set encoding=utf-8                                  &amp;quot; set charset translation encoding&lt;br /&gt;
 set termencoding=utf-8                              &amp;quot; set terminal encoding&lt;br /&gt;
 set fileencoding=utf-8                              &amp;quot; set save encoding&lt;br /&gt;
 set fileencodings=utf8,koi8r,cp1251,cp866,ucs-2le   &amp;quot; список предполагаемых кодировок, в порядке предпочтения&lt;br /&gt;
К сожалению Vim не всегда удается определить кодировку файла правильно, и вместо осмысленного текста мы можем наблюдать кракозябры.&lt;br /&gt;
&lt;br /&gt;
=== Можно указать кодировку текста вручную ===&lt;br /&gt;
Например, можно вручную указать кодировку &amp;lt;code&amp;gt;cp1251&amp;lt;/code&amp;gt; (MS Windows) уже открытому тексту:&lt;br /&gt;
 :e ++enc=cp1251&lt;br /&gt;
&lt;br /&gt;
=== Можно предварительно, перед открытием файла, указать ожидаемую кодировку ===&lt;br /&gt;
Для этого нужно установить переменную &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; (сокращенно &amp;lt;code&amp;gt;enc&amp;lt;/code&amp;gt;). Например, установить кодировку &amp;lt;code&amp;gt;ucs-2le&amp;lt;/code&amp;gt; (unicode MS Windows):&lt;br /&gt;
 :set enc=ucs-2le&lt;br /&gt;
После этого можно открывать файл. Он откроется в этой кодировке.&lt;br /&gt;
&lt;br /&gt;
=== Пользовательское меню ===&lt;br /&gt;
Часто, для упрощения работы в Vim с файлами в различных кодировках, в &amp;lt;code&amp;gt;~/.vimrc&amp;lt;/code&amp;gt; определяют специальное пользовательское меню, которое будет вызываться, например, по &amp;lt;code&amp;gt;&amp;lt;F12&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
 set wildmenu&lt;br /&gt;
 set wcm=&amp;lt;Tab&amp;gt;&lt;br /&gt;
 menu Encoding.koi8-r  :e ++enc=koi8-r&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Encoding.cp1251  :e ++enc=cp1251&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Encoding.cp866   :e ++enc=cp866&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Encoding.ucs-2le :e ++enc=ucs-2le&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu Encoding.utf-8   :e ++enc=utf-8&amp;lt;CR&amp;gt;&lt;br /&gt;
 map &amp;lt;F12&amp;gt; :emenu Encoding.&amp;lt;Tab&amp;gt;&lt;br /&gt;
Перемещаться по пунктам пользовательского меню можно по &amp;lt;code&amp;gt;&amp;lt;Tab&amp;gt;&amp;lt;/code&amp;gt; или клавишами управления курсором.&lt;br /&gt;
&lt;br /&gt;
=== Дополнительно ===&lt;br /&gt;
Чтобы узнать список всех поддерживаемых кодировок, наберите команду:&lt;br /&gt;
 :help encoding-values&lt;br /&gt;
&lt;br /&gt;
== Конвертация кодировки файла ==&lt;br /&gt;
Vim автоматически пытается распознать текущую кодировку открываемого файла, отображает открываемый файл в кодировке отображения терминала, а при сохранении конвертирует в кодировку сохранения файла.&lt;br /&gt;
&lt;br /&gt;
* Текущая используемая в Vim кодировка задается переменной &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;enc&amp;lt;/code&amp;gt;). &lt;br /&gt;
* Кодировка отображения задается переменной &amp;lt;code&amp;gt;termencoding&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;tenc&amp;lt;/code&amp;gt;). &lt;br /&gt;
* Кодировка сохранения файла задается переменной &amp;lt;code&amp;gt;fileencoding&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;fenc&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
Кодировка файла &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; определяется при его открытии или берется из настроек системы. При отображении, Vim производит трансляцию текущей кодировки &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; в кодировку отображения &amp;lt;code&amp;gt;termencoding&amp;lt;/code&amp;gt;. При сохранении в файл Vim конвертирует из текущей кодировки &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; в кодировку сохранения &amp;lt;code&amp;gt;fileencoding&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Обычно &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;fileencoding&amp;lt;/code&amp;gt; совпадают. Для того, чтобы сохранить файл в другой кодировке, надо перед сохранением задать соответствующее значение переменной &amp;lt;code&amp;gt;fileencoding&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Чтобы узнать список всех доступных значений переменных &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;fileencoding&amp;lt;/code&amp;gt; наберите команду:&lt;br /&gt;
 :help encoding-values&lt;br /&gt;
&lt;br /&gt;
=== Пример: как сконвертировать файл из MS Windows &amp;lt;code&amp;gt;cp1251&amp;lt;/code&amp;gt; в Linux &amp;lt;code&amp;gt;utf-8&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
* Открываем файл в Vim:&lt;br /&gt;
 vim filename.txt&lt;br /&gt;
* Задаем текущую кодировку &amp;lt;code&amp;gt;cp1251&amp;lt;/code&amp;gt;:&lt;br /&gt;
 :e ++enc=cp1251&lt;br /&gt;
* Текст конвертируется и Vim отобразит изменения, если они произошли. Исходный файл не изменился.&lt;br /&gt;
* Задаем кодировку сохранения файла &amp;lt;code&amp;gt;utf-8&amp;lt;/code&amp;gt;:&lt;br /&gt;
 :set fileencoding=utf-8&lt;br /&gt;
* Задаем формат переводов строки (&amp;lt;code&amp;gt;dos&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;unix&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;mac&amp;lt;/code&amp;gt;):&lt;br /&gt;
 :set fileformat=unix&lt;br /&gt;
* Сохраняем файл.&lt;br /&gt;
 :w&lt;br /&gt;
* Выходим&lt;br /&gt;
 :q&lt;br /&gt;
&lt;br /&gt;
=== Пример: конвертировать файл из Linux &amp;lt;code&amp;gt;utf-8&amp;lt;/code&amp;gt; в MS Windows &amp;lt;code&amp;gt;cp1251&amp;lt;/code&amp;gt; ===&lt;br /&gt;
Обратная операция — конвертировать файл из Linux &amp;lt;code&amp;gt;utf-8&amp;lt;/code&amp;gt; в MS Windows &amp;lt;code&amp;gt;cp1251&amp;lt;/code&amp;gt; — будет такой:&lt;br /&gt;
 vim filename.txt&lt;br /&gt;
 :e ++enc=utf-8&lt;br /&gt;
 :set fileencoding=cp1251&lt;br /&gt;
 :set fileformat=dos&lt;br /&gt;
 :w&lt;br /&gt;
 :q&lt;br /&gt;
&lt;br /&gt;
== Vim при переводах текста, или для чтения английской документации ==&lt;br /&gt;
Итак, чтобы можно было успешно читать и переводить документацию на английском языке, нужно ИМХО всего 3 вещи:&lt;br /&gt;
* Редактор.&lt;br /&gt;
* Переводчик.&lt;br /&gt;
* Проверка орфографии&lt;br /&gt;
&lt;br /&gt;
Если их удобно объединить, то можно получить хорошую среду, для перевода/чтения.&lt;br /&gt;
&lt;br /&gt;
=== Что возьмем ===&lt;br /&gt;
Редактор мы естественно возьмем VIM. Переводчик mueller консольная версия, работает так:&lt;br /&gt;
 % mueller sex&lt;br /&gt;
 sex  [seks] _n. 1&amp;gt; _биол. пол; the weaker sex слАбый пол, жЕнщины; the sterner (или stronger) sex сИльный пол, мужчИны; the sex _шутл.  жЕнщины 2&amp;gt; секс 3&amp;gt; _at&lt;br /&gt;
 tr. половОй, сексуАльный; sex instinct половОй инстИнкт; sex intergrade гермафродИт&lt;br /&gt;
&lt;br /&gt;
И орфографмометр: это spell в виме, словари скачаем с vim.org&lt;br /&gt;
&lt;br /&gt;
=== Как настроим ===&lt;br /&gt;
Мне интересна возможность выпадающего списка, при наведением на неизвестное мне слово мышкой. Для этого, после долгого чтения манов (или гугленья) узнаем что с помошью команды system можно выполнить какое-то действие, вывод которой куда-либо записать. Короче, пишем где-нибудь в ~/.vimrc&lt;br /&gt;
&lt;br /&gt;
 function! MyBalloonExpr()&lt;br /&gt;
        return system(&amp;quot;mueller &amp;quot;. v:beval_text)&lt;br /&gt;
 endfunction&lt;br /&gt;
 set bexpr=MyBalloonExpr()&lt;br /&gt;
 set ballooneval&lt;br /&gt;
 set balloondelay=100&lt;br /&gt;
&lt;br /&gt;
Определили функцию MyBallonExpr которая будет формировать строку mueller [слово на которое навели] и выполнять. Результат выполнения будет выдавать в «балоне» выпадающем окошке, через 100 миллисекунд.&lt;br /&gt;
&lt;br /&gt;
Естественно вместо mueller вы можете поставить любую другую программу, которая переводит текст.&lt;br /&gt;
&lt;br /&gt;
=== Рецепт для очень умелых ручек ===&lt;br /&gt;
&lt;br /&gt;
Если у вас нет консольной версии &amp;lt;code&amp;gt;mueller&amp;lt;/code&amp;gt;, но есть много энтузиазма, то можно поступить так:&lt;br /&gt;
&lt;br /&gt;
* Идем на &amp;lt;code&amp;gt;http://sourceforge.net/projects/mueller-dict/&amp;lt;/code&amp;gt; и забираем оттуда &amp;lt;code&amp;gt;mueller-dict-3.1.1.tar.gz&amp;lt;/code&amp;gt;&lt;br /&gt;
* Извлекаем из полученного архива файл &amp;lt;code&amp;gt;mueller-base.dict.dz&amp;lt;/code&amp;gt; и кладем его, скажем, в &amp;lt;code&amp;gt;~/dict/&amp;lt;/code&amp;gt;&lt;br /&gt;
* Там же создаем файл &amp;lt;code&amp;gt;mueller-base.sh&amp;lt;/code&amp;gt; со следующим содержимым:&lt;br /&gt;
 #!/bin/bash&lt;br /&gt;
 # &lt;br /&gt;
 WORD=`echo $1 | sed -e 's/[A-Z]*/\L&amp;amp;/g;s/[,.;:]//g'`;&lt;br /&gt;
 if [ -z $WORD ]; then exit; fi;&lt;br /&gt;
 LINES=50;  &lt;br /&gt;
 DICTIONARY=&amp;quot;$HOME/dict/mueller-base.dict.dz&amp;quot;; &lt;br /&gt;
 # &lt;br /&gt;
 zgrep -aA$LINES '^'$WORD'$' $DICTIONARY | sed -e '/^$/d; 1s/^/ &amp;amp;/;/^[^ ]/,$d'&lt;br /&gt;
 #&lt;br /&gt;
&lt;br /&gt;
* даем нашему новому консольному словарику право на исполнение:&lt;br /&gt;
 $ chmod +x ~/dict/mueller-base.sh&lt;br /&gt;
* и проверяем его работоспособность:&lt;br /&gt;
 $ ~/dict/mueller-base.sh head&lt;br /&gt;
&lt;br /&gt;
* Для графической версии редактора (&amp;lt;code&amp;gt;gvim&amp;lt;/code&amp;gt;) функция перевода в нашем &amp;lt;code&amp;gt;~/.vimrc&amp;lt;/code&amp;gt; должна будет выглядеть так:&lt;br /&gt;
&lt;br /&gt;
 function! MyBalloonExpr()&lt;br /&gt;
    return system(&amp;quot;$HOME/dict/mueller-base.sh &amp;quot;. v:beval_text)&lt;br /&gt;
 endfunction&lt;br /&gt;
 set bexpr=MyBalloonExpr()&lt;br /&gt;
 set ballooneval&lt;br /&gt;
 set balloondelay=500&lt;br /&gt;
&lt;br /&gt;
Примечание: &lt;br /&gt;
:::* Естественно, что функция &amp;lt;code&amp;gt;MyBalloonExpr()&amp;lt;/code&amp;gt; работает только в gVim, зато выглядит красиво. Наведите курсор мышки на слово и оставьте его неподвижным секунду-две (поначалу, можно вообще убирать руку с мышки, позже приловчитесь).&lt;br /&gt;
:::* &amp;lt;code&amp;gt;LINES=50&amp;lt;/code&amp;gt; ограничивает количество выводимых строчек. Можете подобрать цифру под свой монитор.&lt;br /&gt;
:::* Рекомендую выставить &amp;lt;code&amp;gt;balloondelay=500&amp;lt;/code&amp;gt; миллисекунд. Да, помедленнее. Но мышка будет меньше цепляться за слова.&lt;br /&gt;
&lt;br /&gt;
* Для текстовой версии редактора (&amp;lt;code&amp;gt;vim&amp;lt;/code&amp;gt;) придётся делать специальную функцию &amp;lt;code&amp;gt;TranslateWord()&amp;lt;/code&amp;gt; и вешать её вызов на специальную функциональную клавишу, например &amp;lt;code&amp;gt;&amp;lt;F9&amp;gt;&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 function! TranslateWord()&lt;br /&gt;
    let s:dict    = &amp;quot;$HOME/dict/mueller-base.sh&amp;quot;&lt;br /&gt;
    let s:phrase  = expand(&amp;quot;&amp;lt;cword&amp;gt;&amp;quot;)&lt;br /&gt;
    let s:tmpfile = tempname()&lt;br /&gt;
    silent execute &amp;quot;!&amp;quot; . s:dict . &amp;quot; &amp;quot; . s:phrase . &amp;quot; &amp;gt; &amp;quot; . s:tmpfile&lt;br /&gt;
    execute &amp;quot;botright sp &amp;quot; . s:tmpfile&lt;br /&gt;
 endfunction&lt;br /&gt;
 map &amp;lt;F9&amp;gt; :call TranslateWord()&amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примечание: &lt;br /&gt;
:::* Это работает точно так же и в графической версии редактора (&amp;lt;code&amp;gt;gvim&amp;lt;/code&amp;gt;). Поэтому метод можно считать универсальным, но требует нескольких нажатий клавиш, и сплит-окно выглядит менее элегантно, чем подсказки.&lt;br /&gt;
:::* Открывшееся окно с переводом можно закрыть стандартным способом (&amp;lt;code&amp;gt; :q &amp;lt;/code&amp;gt;). Ну, а если вы воспользовались советом выше и забиндили на клавишу &amp;lt;code&amp;gt;&amp;lt;F10&amp;gt;&amp;lt;/code&amp;gt; предложенное пользовательское меню, то алгоритм работы будет совсем простой: &amp;lt;code&amp;gt;&amp;lt;F9&amp;gt;&amp;lt;/code&amp;gt; смотрим перевод &amp;lt;code&amp;gt;&amp;lt;F10&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;code&amp;gt;&amp;lt;Enter&amp;gt;&amp;lt;/code&amp;gt; вернули как было.&lt;br /&gt;
:::* Этот метод использует временный файл&lt;br /&gt;
:::* Т.к. в этом методе нет необходимости в ограничении, чтоб подсказка помещалась на экран, то для &amp;lt;code&amp;gt;LINES&amp;lt;/code&amp;gt; можно увеличить лимиты, хоть до &amp;lt;code&amp;gt;LINES=500&amp;lt;/code&amp;gt;. Этот метод не имеет ограничений на количество выводимых строчек.&lt;br /&gt;
&lt;br /&gt;
== Строка статуса редактора ==&lt;br /&gt;
&lt;br /&gt;
Строка статуса редактора бывает очень полезна, если вам не жалко пары строчек на экране. Добавьте в &amp;lt;code&amp;gt;~/.vimrc&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 set laststatus=2   &amp;quot; всегда показывать строку статуса&lt;br /&gt;
 set statusline=%f%m%r%h%w\ %y\ enc:%{&amp;amp;enc}\ ff:%{&amp;amp;ff}\ fenc:%{&amp;amp;fenc}%=(ch:%3b\ hex:%2B)\ col:%2c\ line:%2l/%L\ [%2p%%]&lt;br /&gt;
&lt;br /&gt;
...и у вас в предпоследней строке будет выводиться что-то вроде этого:&lt;br /&gt;
 .vimrc [vim] enc:utf-8 ff:unix fenc:utf-8       (ch: 92 hex:5C) col:26 line:158/168 [94%]&lt;br /&gt;
&lt;br /&gt;
Комментарий:&lt;br /&gt;
:::&amp;lt;code&amp;gt;%f&amp;lt;/code&amp;gt; - имя файла и путь к нему, относительно текущего каталога&lt;br /&gt;
:::&amp;lt;code&amp;gt;%m&amp;lt;/code&amp;gt; - флаг модификации/изменения, выводит &amp;lt;code&amp;gt;[+]&amp;lt;/code&amp;gt; если буфер изменялся&lt;br /&gt;
:::&amp;lt;code&amp;gt;%r&amp;lt;/code&amp;gt; - флаг &amp;quot;только для чтения&amp;quot;, выводит &amp;lt;code&amp;gt;[RO]&amp;lt;/code&amp;gt; если буфер только для чтения&lt;br /&gt;
:::&amp;lt;code&amp;gt;%h&amp;lt;/code&amp;gt; - флаг буфера помощи, выводит &amp;lt;code&amp;gt;[help]&amp;lt;/code&amp;gt; если буфер со справкой vim&lt;br /&gt;
:::&amp;lt;code&amp;gt;%w&amp;lt;/code&amp;gt; - флаг окна превью, выводит &amp;lt;code&amp;gt;[Preview]&amp;lt;/code&amp;gt;&lt;br /&gt;
:::&amp;lt;code&amp;gt;'\ '&amp;lt;/code&amp;gt; - экранированный символ пробела. Пробел можно указывать только экранированным, иначе ошибка синтаксиса&lt;br /&gt;
:::&amp;lt;code&amp;gt;%y&amp;lt;/code&amp;gt; - тип файла в буфере, например &amp;lt;code&amp;gt;[vim]&amp;lt;/code&amp;gt;&lt;br /&gt;
:::&amp;lt;code&amp;gt;enc:%{&amp;amp;enc}&amp;lt;/code&amp;gt; - отображение кодировки &amp;lt;code&amp;gt;encoding&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;enc&amp;lt;/code&amp;gt;). Обратите внимание: &amp;quot;&amp;lt;code&amp;gt;enc:&amp;lt;/code&amp;gt;&amp;quot; - текст, &amp;quot;&amp;lt;code&amp;gt;%{&amp;amp;enc}&amp;lt;/code&amp;gt;&amp;quot; - вывод значения внутренней переменной (&amp;lt;code&amp;gt;enc&amp;lt;/code&amp;gt;)&lt;br /&gt;
:::&amp;lt;code&amp;gt;ff:%{&amp;amp;ff}&amp;lt;/code&amp;gt; - отображение формата перевода строки &amp;lt;code&amp;gt;fileformat&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;ff&amp;lt;/code&amp;gt;)&lt;br /&gt;
:::&amp;lt;code&amp;gt;fenc:%{&amp;amp;fenc}&amp;lt;/code&amp;gt; - отображение кодировки сохранения в файл &amp;lt;code&amp;gt;fileencoding&amp;lt;/code&amp;gt; (&amp;lt;code&amp;gt;fenc&amp;lt;/code&amp;gt;)&lt;br /&gt;
:::&amp;lt;code&amp;gt;%=&amp;lt;/code&amp;gt; - далее выравнивать вправо&lt;br /&gt;
:::&amp;lt;code&amp;gt;ch:%3b&amp;lt;/code&amp;gt; - код символа под курсором в десятичной чистеме счисления, минимум 3 символа&lt;br /&gt;
:::&amp;lt;code&amp;gt;hex:%2B&amp;lt;/code&amp;gt; - код символа под курсором в шестнадцатеричной системе счисления, минимум 2 символа&lt;br /&gt;
:::&amp;lt;code&amp;gt;col:%2c&amp;lt;/code&amp;gt; - курсор в колонке, минимум 2 символа&lt;br /&gt;
:::&amp;lt;code&amp;gt;line:%2l/%L&amp;lt;/code&amp;gt; - курсор в строке (минимум 2 символа)/всего строк в файле&lt;br /&gt;
:::&amp;lt;code&amp;gt;%2p&amp;lt;/code&amp;gt; - число % в строках, где находится курсор (0% - начало файла; 100% - конец файла), минимум 2 символа&lt;br /&gt;
:::&amp;lt;code&amp;gt;%%&amp;lt;/code&amp;gt; - т.к. символ '%' используется для переменных, то вывод символа '%' в строке статуса нужно делать особым образом - &amp;lt;code&amp;gt;%%&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Подробнее о формате вывода &amp;lt;code&amp;gt;statusline&amp;lt;/code&amp;gt; можно узнать из справки:&lt;br /&gt;
&lt;br /&gt;
 :help statusline&lt;br /&gt;
&lt;br /&gt;
==Проверка орфографии==&lt;br /&gt;
&lt;br /&gt;
===Пользовательское меню===&lt;br /&gt;
&lt;br /&gt;
Часто бывает удобно оформить процедуры, связанные с проверкой орфографии, в виде пользовательского меню:&lt;br /&gt;
 set wildmenu&lt;br /&gt;
 set wcm=&amp;lt;Tab&amp;gt;&lt;br /&gt;
 &amp;quot; проверка орфографии:&lt;br /&gt;
 menu SetSpell.ru  :set spl=ru spell&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu SetSpell.en  :set spl=en spell&amp;lt;CR&amp;gt;&lt;br /&gt;
 menu SetSpell.off :set nospell&amp;lt;CR&amp;gt;&lt;br /&gt;
 map &amp;lt;F7&amp;gt; :emenu SetSpell.&amp;lt;Tab&amp;gt;&lt;br /&gt;
 &amp;quot; выбор альтернатив:&lt;br /&gt;
 imap &amp;lt;F8&amp;gt; &amp;lt;Esc&amp;gt; z=&amp;lt;CR&amp;gt;i&lt;br /&gt;
 map &amp;lt;F8&amp;gt; z=&amp;lt;CR&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Здесь, по &amp;lt;code&amp;gt;&amp;lt;F7&amp;gt;&amp;lt;/code&amp;gt; вызывается подменю: проверить орфографию русского языка [&amp;lt;code&amp;gt;ru&amp;lt;/code&amp;gt;], проверить орфографию английского языка [&amp;lt;code&amp;gt;en&amp;lt;/code&amp;gt;] или отключить проверку орфографии [&amp;lt;code&amp;gt;off&amp;lt;/code&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
По &amp;lt;code&amp;gt;&amp;lt;F8&amp;gt;&amp;lt;/code&amp;gt; для слова под курсором можно найти корректную альтернативу из словаря. Порядок работы следующий:&lt;br /&gt;
* Наводим курсор на выбранное слово (или подсвеченное проверкой орфографии слово)&lt;br /&gt;
* Нажимаем &amp;lt;code&amp;gt;&amp;lt;F8&amp;gt;&amp;lt;/code&amp;gt; и видим список альтернатив. Каждый вариант в списке помечен цифрой. &lt;br /&gt;
* Находим понравившийся вариант и запоминаем его номер.&lt;br /&gt;
* Смело начинаем набирать запомненный номер, неважно, одна это цифра или две.&lt;br /&gt;
* Снова нажимаем &amp;lt;code&amp;gt;&amp;lt;F8&amp;gt;&amp;lt;/code&amp;gt;. &lt;br /&gt;
* Слово под курсором будет заменено альтернативой с указанным номером.&lt;br /&gt;
Последовательность: &amp;lt;code&amp;gt;&amp;lt;F8&amp;gt;&amp;lt;/code&amp;gt;&amp;lt;одна-или-две-цифры&amp;gt;&amp;lt;code&amp;gt;&amp;lt;F8&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Как это работает?===&lt;br /&gt;
Попробуйте на примере слова &amp;quot;Шпоргалка&amp;quot;. &lt;br /&gt;
* Откройте Vim, перейдите в режим редактирования и наберите слово &amp;quot;Шпоргалка&amp;quot;.&lt;br /&gt;
* Выйдите из режима редактирования в командный режим (обычно, &amp;lt;code&amp;gt;&amp;lt;Esc&amp;gt;&amp;lt;Esc&amp;gt;&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Установите курсор на слово &amp;quot;Шпоргалка&amp;quot;&lt;br /&gt;
* Нажмите последовательно два символа &amp;quot;&amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt;&amp;quot; и &amp;quot;&amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt;&amp;quot; (два символа: &amp;lt;code&amp;gt;z=&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Как результат, вы должны увидеть экран с альтернативами, подобранными для слова под курсором. Нажатие любой клавиши скроет этот экран, но безопасными и не оставляющими следов в буфере клавиатуры будут либо &amp;lt;code&amp;gt;&amp;lt;Esc&amp;gt;&amp;lt;Esc&amp;gt;&amp;lt;/code&amp;gt;, либо &amp;lt;code&amp;gt;&amp;lt;Enter&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
* Запоминаем, что хорошей альтернативой слову &amp;quot;Шпоргалка&amp;quot; было слово &amp;quot;Шпаргалка&amp;quot;, под номером &amp;quot;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&amp;quot;.&lt;br /&gt;
* А теперь магия! Нажимаем последовательно три символа: &amp;quot;&amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&amp;quot;, &amp;quot;&amp;lt;code&amp;gt;z&amp;lt;/code&amp;gt;&amp;quot; и &amp;quot;&amp;lt;code&amp;gt;=&amp;lt;/code&amp;gt;&amp;quot; (три символа: &amp;lt;code&amp;gt;1z=&amp;lt;/code&amp;gt;)&lt;br /&gt;
* Слово под курсором &amp;quot;Шпоргалка&amp;quot; заменено на &amp;quot;Шпаргалка&amp;quot;.&lt;br /&gt;
* С использованием пользовательского меню, операция будет выглядеть, как три нажатия на кнопки: &amp;lt;code&amp;gt;&amp;lt;F8&amp;gt;1&amp;lt;F8&amp;gt;&amp;lt;/code&amp;gt;.&lt;br /&gt;
Теперь мы с вами знаем, что если навести на слово &amp;quot;Шпоргалка&amp;quot; курсор и нажать три магических символа &amp;lt;code&amp;gt;1z=&amp;lt;/code&amp;gt; ,то ошибочное слово будет волшебным образом заменено на правильное (&amp;quot;Шпаргалка&amp;quot;). А если нажать четыре магических символа &amp;lt;code&amp;gt;39z=&amp;lt;/code&amp;gt; ,то слово &amp;quot;Шпоргалка&amp;quot; под курсором будет волшебным образом заменено, скорее всего, на слово &amp;quot;Прогулка&amp;quot; (это если у вас стоят словари той же версии, что и у меня).&lt;br /&gt;
&lt;br /&gt;
А теперь, самая главная тайна:&lt;br /&gt;
 для того, чтоб все вышеуказанное работало,&lt;br /&gt;
 проверка орфографии русского языка должна быть включена.&lt;br /&gt;
&lt;br /&gt;
На всякий случай, напоминаю, что выход без сохранения изменений:&lt;br /&gt;
 :q!&amp;lt;Enter&amp;gt;&lt;br /&gt;
Выход, с сохранением всех изменений:&lt;br /&gt;
 :x&amp;lt;Enter&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Влияние Vim ==&lt;br /&gt;
Существуют браузеры и расширения для браузеров делающее управление ими похожим на управление текстовым редактором Vim. Например,&lt;br /&gt;
&lt;br /&gt;
* Vimperator — расширение для Mozilla Firefox&lt;br /&gt;
* Pentadactyl - расширение для Mozilla Firefox&lt;br /&gt;
* Conkeror - лёгкий веб-браузер на основе движка Gecko&lt;br /&gt;
* Luakit - лёгкий, быстрый браузер на основе движке WebKit&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
* [http://www.vim.org Vim.org] — официальный сайт vim — документация, файлы, плагины&lt;br /&gt;
* [http://www.opennet.ru/docs/HOWTO-RU/Vim-HOWTO.html Vim-howto] — руководство по использованию vim&lt;br /&gt;
* [http://www.net4me.net/examples/32/net34.html www.net4me.net] — vim коротко от простого с сложному&lt;br /&gt;
* [http://funix.ru/programs_utilities/klavishi-i-kombinacii-klavish-vim.html Клавиши и комбинации клавиш VIM] &lt;br /&gt;
* [http://jenyay.net/Programming/Vim Vim. Первая установка]&lt;br /&gt;
* [http://gvim.org.ua/ Все о редакторе VI (VIM, GVIM). Форум, документация]&lt;br /&gt;
* [https://zalinux.ru/?p=239 Памятка по Vim (Vi) - основы]&lt;br /&gt;
* [http://konishchevdmitry.blogspot.com/2008/07/howto-vim.html Очередной HowTo по Vim] — HowTo, описывающий основные проблемы, возникающие при работе в Vim. Содержит примеры конфигурационных файлов и список наиболее полезных команд&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Yum</id>
		<title>Yum</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Yum"/>
				<updated>2017-04-17T12:18:02Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;На странице представлены основные команды, необходимые для управления пакетами через менеджер пакетов Yum.&lt;br /&gt;
&lt;br /&gt;
= Предназначение Yum =&lt;br /&gt;
&lt;br /&gt;
Yum создан для решения следующих задач:&lt;br /&gt;
&lt;br /&gt;
* Поиск пакетов в репозитариях&lt;br /&gt;
* Установка пакетов из репозиториев&lt;br /&gt;
* Установка пакетов из &amp;lt;code&amp;gt;.rpm&amp;lt;/code&amp;gt; файлов, с разрешением зависимостей с помощью репозитариев&lt;br /&gt;
* Обновление системы&lt;br /&gt;
* Удаление не нужных пакетов&lt;br /&gt;
* Фактически, yum представляет собой оболочку для &amp;lt;code&amp;gt;rpm&amp;lt;/code&amp;gt; обеспечивающую работу с репозиториями.&lt;br /&gt;
&lt;br /&gt;
= Основные операции над пакетами =&lt;br /&gt;
== Поиск в репозиториях ==&lt;br /&gt;
&lt;br /&gt;
Для поиска в репозиториях с помощью yum используются три команды: &amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;search&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;provides&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Самый простой способ поиска - использование команды &amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;. Команда &amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt; просматривает названия пакетов и их версии в поисках совпадений. Например, для просмотра пакетов с названием &amp;lt;code&amp;gt;tsclient&amp;lt;/code&amp;gt; используйте:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum list tsclient&amp;lt;/pre&amp;gt;&lt;br /&gt;
Команда &amp;lt;code&amp;gt;search&amp;lt;/code&amp;gt; ищет в названии пакета и его описании указанную строку. Например, для поиска пакетов связанных с &amp;lt;code&amp;gt;PalmPilot&amp;lt;/code&amp;gt; введите:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum search PalmPilot&amp;lt;/pre&amp;gt;&lt;br /&gt;
Команда &amp;lt;code&amp;gt;provides&amp;lt;/code&amp;gt; позволяет производить поиск пакетов содержащих указанный файл. Например, для поиска пакетов содержащих &amp;lt;code&amp;gt;libneon&amp;lt;/code&amp;gt; введите:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum provides libneon&amp;lt;/pre&amp;gt;&lt;br /&gt;
Все команды поиска поддерживают групповые символы &amp;lt;code&amp;gt;?&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt; (экранируйте их символом &amp;lt;code&amp;gt;\&amp;lt;/code&amp;gt; для корректной обработки &amp;lt;code&amp;gt;bash&amp;lt;/code&amp;gt;). К примеру, при для поиска пакетов начинающихся на &amp;lt;code&amp;gt;tsc&amp;lt;/code&amp;gt; введите:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum list tsc\*&amp;lt;/pre&amp;gt;&lt;br /&gt;
для поиска пакетов, содержащих файлы в директории &amp;lt;code&amp;gt;/etc/httpd&amp;lt;/code&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum provides /etc/httpd\* &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
или для поиска определённых команд/программ, например для поиска mc(midnight commander)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum provides \*/mc &amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
в результате получим следующий вывод&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;1:mc-4.7.4-1.fc14.i686 : User-friendly text console file manager and visual shell&lt;br /&gt;
Репозиторий : base&lt;br /&gt;
Совпадения с:&lt;br /&gt;
Имя файла   : /usr/share/mc&lt;br /&gt;
Имя файла   : /usr/libexec/mc&lt;br /&gt;
Имя файла   : /etc/mc&lt;br /&gt;
Имя файла   : /usr/bin/mc&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Установка пакетов с помощью Yum ==&lt;br /&gt;
&lt;br /&gt;
Для установки пакетов с помощью yum используется параметр &amp;lt;code&amp;gt;install&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для установки &amp;lt;code&amp;gt;tsclient&amp;lt;/code&amp;gt; введите:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum install tsclient&amp;lt;/pre&amp;gt;&lt;br /&gt;
Yum автоматически разрешит (если сможет) зависимости, и предложит установить их: &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
============================================================================= &lt;br /&gt;
 Package                 Arch       Version          Repository        Size&lt;br /&gt;
=============================================================================&lt;br /&gt;
Installing:&lt;br /&gt;
 tsclient                i386       0.132-6          base              247 k&lt;br /&gt;
Installing for dependencies:&lt;br /&gt;
 rdesktop                i386       1.4.0-2          base              107 k&lt;br /&gt;
&lt;br /&gt;
Transaction Summary&lt;br /&gt;
=============================================================================&lt;br /&gt;
Install      2 Package(s)&lt;br /&gt;
Update       0 Package(s)&lt;br /&gt;
Remove       0 Package(s)&lt;br /&gt;
Total download size: 355 k&lt;br /&gt;
Is this ok [y/N]:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
== Установка пакетов из .rpm файлов ==&lt;br /&gt;
&lt;br /&gt;
Для установки &amp;lt;code&amp;gt;.rpm&amp;lt;/code&amp;gt; пакета с автоматическим разрешением зависимостей раньше использовалась команда &amp;lt;code&amp;gt;localinstall&amp;lt;/code&amp;gt;. Теперь можно использовать обычный &amp;lt;code&amp;gt;install&amp;lt;/code&amp;gt;. Так команда:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum install foo.rpm&amp;lt;/pre&amp;gt;&lt;br /&gt;
автоматически найдет зависимости пакета &amp;lt;code&amp;gt;foo.rpm&amp;lt;/code&amp;gt; в репозиториях (если сможет) и предложит их установить.&amp;lt;br&amp;gt; Может возникнуть проблема в отсутствии или неизвестной GPG подписи у RPM пакета, результатом чего будет отказ в установке и как следствие следующая ошибка &lt;br /&gt;
&amp;lt;pre&amp;gt;Публичный ключ для foo.rpm не установлен&amp;lt;/pre&amp;gt;&lt;br /&gt;
Для того чтобы обойти это (в случае если Вы доверяете источнику предоставляющему пакет) необходимо выключить проверку GPG ключей, добавив в конце команды параметр &amp;lt;code&amp;gt;--nogpgcheck&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Обновление системы ==&lt;br /&gt;
&lt;br /&gt;
Обновление системы осуществляется с помощью одной команды - &amp;lt;code&amp;gt;update&amp;lt;/code&amp;gt;. Таким образом:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum update&amp;lt;/pre&amp;gt;&lt;br /&gt;
обновит всю вашу систему. А команда&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum update foo&amp;lt;/pre&amp;gt;&lt;br /&gt;
обновит только пакет &amp;lt;code&amp;gt;foo&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Удаление пакетов ==&lt;br /&gt;
&lt;br /&gt;
Удаление пакетов осуществляется с помощью команд &amp;lt;code&amp;gt;remove&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;erase&amp;lt;/code&amp;gt;. Так,&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;yum remove foo&amp;lt;/pre&amp;gt;&lt;br /&gt;
удалит пакет &amp;lt;code&amp;gt;foo&amp;lt;/code&amp;gt; из системы.&lt;br /&gt;
&lt;br /&gt;
Удаление пакетов вместе с зависимостями (аналогично утилиты apt в deb-дистрибутивах) возможно 2-мя способами:&lt;br /&gt;
&lt;br /&gt;
1. можно добавить в файл &amp;lt;code&amp;gt;/etc/yum.conf&amp;lt;/code&amp;gt; строчку&lt;br /&gt;
&amp;lt;pre&amp;gt;clean_requirements_on_remove=1&amp;lt;/pre&amp;gt;&lt;br /&gt;
подробнее можно прочитать в  &amp;lt;code&amp;gt;man yum.conf&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
2. можно воспользоваться плагином '''''Remove with leaves'''''&lt;br /&gt;
&lt;br /&gt;
При использовании обоих методов работоспособность сохраняется.&lt;br /&gt;
&lt;br /&gt;
== Использование Yum с прокси-сервером ==&lt;br /&gt;
&amp;lt;p&amp;gt;Для того чтобы заставить Yum работать через прокси-сервер необходимо добавить следующий параметр в /etc/yum.conf:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;proxy=http://yourproxy:8080/&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;где - yourproxy это имя прокси-сервера, а 8080 это порт прокси-сервера. Если сервер требует аутентификации, вы можете указать логин как:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;proxy=http://username:password@yourproxy:8080/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt; &lt;br /&gt;
&amp;lt;p&amp;gt;RPM Package Manager позволяет использовать прокси-переменные среды.  Это может быть задано в /etc/profile или специфизированно для конкретного пользователя в файле ~/.bash_profile::&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;export http_proxy=http://yourproxy:8080/&lt;br /&gt;
export ftp_proxy=http://yourproxy:8080/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Для использования wget через прокси-сервер, добавте следующие строки в /etc/wgetrc &amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;http_proxy = http://yourproxy:8080/&lt;br /&gt;
ftp_proxy = http://yourproxy:8080/&lt;br /&gt;
https_proxy = https://yourproxy:8080/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt; &lt;br /&gt;
&amp;lt;p&amp;gt;В обоих случаях логин и пароль могут быть заданы как в примере выше.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Использование Yum для установки локального пакета, автоматически проверяя и удовлетворяя зависимости ==&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;yum --nogpgcheck localinstall packagename.arch.rpm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt; &lt;br /&gt;
== Отображение приоритетов для всех установленных репозиториев ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Вы можете получить список всех установленных у вас репозиториев - &amp;lt;strong&amp;gt;yum repolist all&amp;lt;/strong&amp;gt;. Однако, он не показывает индекс приоритета. Вот  строка необходимая для этого. Если номер не определен, по умолчанию, это самый низкий приоритет (99).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;cat /etc/yum.repos.d/*.repo | sed -n -e &amp;amp;quot;/^\[/h; /priority *=/{ G; s/\n/ /; s/ity=/ity = /; p }&amp;amp;quot;  | sort -k3n&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt; &lt;br /&gt;
&lt;br /&gt;
== Поиск с помощью YUM в репозитории пакета по заданной строке ==&lt;br /&gt;
&amp;lt;p&amp;gt;Поиск пакетов, содержащих нужную строку в названии или описании пакета.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;yum search строка_для_поиска | less&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Запрос имеющихся пакетов из репозитория ==&lt;br /&gt;
&amp;lt;p&amp;gt;Найти все пакеты, доступные из определенного репозитория, например RPMforge. Пакеты уже установленные из этого репозитория показываться не будут.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;yum --disablerepo &amp;amp;quot;*&amp;amp;quot; --enablerepo &amp;amp;quot;rpmforge&amp;amp;quot; list available&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;/p&amp;gt; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Исключить из обновления yum определенные пакеты ==&lt;br /&gt;
&lt;br /&gt;
Заходим в /etc/yum.conf.&lt;br /&gt;
Прописываем параметр '''exclude=''' и в нем прописываем через запятую пакеты, например, для xmms строчка выглядит так: &amp;lt;pre&amp;gt;exclude=xmms-a52dec,xmms-cdread,xmms-mad,xmms-devel,xmms-wma,xmms,xmms-lirc,xmms-alarm,xmms-coverviewer,xmmsctrl&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Скачать пакет, не устанавливая его ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt; yumdownloader httpd&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Вывести зависимости пакета ==&lt;br /&gt;
&amp;lt;pre&amp;gt;yum deplist package&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Удаление ненужных зависимостей ==&lt;br /&gt;
&amp;lt;pre&amp;gt;yum install yum-tools&lt;br /&gt;
package-cleanup --leaves&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Эта команда выдаст список пакетов-&amp;quot;листьев&amp;quot;, от которых не зависят никакие пакеты в системе. &lt;br /&gt;
&lt;br /&gt;
Проверьте не попали ли в этот список какие-то ценные пакеты, после чего можете удалить все пакеты из списка простым bash-скриптом наподобие:&lt;br /&gt;
 package-cleanup --leaves | xargs yum remove -y&lt;br /&gt;
&lt;br /&gt;
= При ошибках в работе пакетного менеджера = &lt;br /&gt;
&lt;br /&gt;
* почистите кэш&lt;br /&gt;
 yum clean all&lt;br /&gt;
* попробуйте создать кеш заново&lt;br /&gt;
 yum makecache&lt;br /&gt;
&lt;br /&gt;
При обращении в форум/конференцию/рассылку за помощью всегда предоставляйте информацию о настроенных репозиториях&lt;br /&gt;
 yum repolist&lt;br /&gt;
&lt;br /&gt;
= Ссылки =&lt;br /&gt;
[http://www.tech-notes.net/yum-notes/ Шпаргалка по Yum]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://unix.freegeek.ru/centos-localrepo/ Создание собственного локального репозитория CentOS]&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://redhat-club.org/2011/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-%D0%B8-%D0%BD%D0%B0%D1%81%D1%82%D1%80%D0%BE%D0%B9%D0%BA%D0%B0-%D1%81%D0%B5%D1%80%D0%B2%D0%B5%D1%80%D0%B0-%D0%BE%D0%B1%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%B8%D0%B9-%D0%B4%D0%BB%D1%8F-%D0%B4%D0%B8%D1%81%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%B8%D0%B2%D0%BE%D0%B2-centos-%D0%B8-fedora Установка и Настройка Сервера Обновлений для Дистрибутивов CentOS и Fedora]&lt;br /&gt;
----&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Chattr_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B0%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%BE%D0%B2_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2</id>
		<title>Chattr — Команда изменения атрибутов файлов</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Chattr_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D0%B0%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%BE%D0%B2_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2"/>
				<updated>2017-04-17T07:38:59Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''chattr'''(от англ. '''ch'''ange '''attr'''ibute) — изменяет атрибуты файлов на файловых системах ext2, ext3, ex…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''chattr'''(от англ. '''ch'''ange '''attr'''ibute) — изменяет атрибуты файлов на файловых системах ext2, ext3, ext4 и частично на других файловых системах Linux.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
* &amp;lt;tt&amp;gt;chattr [ -RV ] [ -v версия ] [ атрибуты ] файлы…&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Описание ==&lt;br /&gt;
''chattr'' изменяет атрибуты файлов на файловой системе в ОС на ядре Linux.&lt;br /&gt;
&lt;br /&gt;
Формат символьного режима: &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;+-&amp;lt;/nowiki&amp;gt;=[ASacDdIijsTtu]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Оператор «+» обозначает добавление указанных атрибутов к существующим; «-» обозначает их снятие; «=» обозначает установку только этих атрибутов файлам.&lt;br /&gt;
&lt;br /&gt;
Символы «ASacDdijsu» указывают на новые атрибуты файлов, некоторые атрибуты может назначить только суперпользователь (root):&lt;br /&gt;
* не обновлять время последнего доступа к файлу atime (A)&lt;br /&gt;
* синхронное обновление (S)&lt;br /&gt;
* синхронное обновление каталогов (D)&lt;br /&gt;
* только добавление к файлу (a)&lt;br /&gt;
* сжатый (c)&lt;br /&gt;
* не архивировать (d)&lt;br /&gt;
* неизменяемый (i) &lt;br /&gt;
* безопасное удаление (s)&lt;br /&gt;
* вершина иерархического дерева (T)&lt;br /&gt;
* запрет слияния в конце файла (t)&lt;br /&gt;
* неудаляемый (u)&lt;br /&gt;
&lt;br /&gt;
== Ключи POSIX ==&lt;br /&gt;
;-R&lt;br /&gt;
: Рекурсивно изменять атрибуты каталогов и их содержимого. Все найденные символические ссылки будут игнорироваться.&lt;br /&gt;
;-V&lt;br /&gt;
: Выводит более полную выводимую информацию и версию программы chattr.&lt;br /&gt;
;-v версия&lt;br /&gt;
: Установить номер версии/генерации файла.&lt;br /&gt;
&lt;br /&gt;
''chattr'' является частью пакета e2fsprogs, получить его можно с адреса.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Lsattr_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B0_%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B0%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%BE%D0%B2_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2</id>
		<title>Lsattr — Команда просмотра установленных атрибутов файлов</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Lsattr_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%BF%D1%80%D0%BE%D1%81%D0%BC%D0%BE%D1%82%D1%80%D0%B0_%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BB%D0%B5%D0%BD%D0%BD%D1%8B%D1%85_%D0%B0%D1%82%D1%80%D0%B8%D0%B1%D1%83%D1%82%D0%BE%D0%B2_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2"/>
				<updated>2017-04-17T07:32:43Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''lsattr''' (от англ. '''li'''st '''attr'''ibute) — программа для просмотра расширенных прав доступа к фай…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''lsattr''' (от англ. '''li'''st '''attr'''ibute) — программа для просмотра расширенных прав доступа к файлам и директориям. &lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
&amp;lt;code bash&amp;gt; lsattr [ -RVadv ] [ files... ]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Опции ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
| '''''Ключ''''' || '''''Значение'''''&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''-R''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Рекурсивно выводит атрибуты каталогов и их содержимого&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''-V''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Выводит версию программы&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''-a''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Выводит информацию по всем файлам в каталогах, включая скрытые файлы, чьи имена начинаются с ''.''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''-d''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Отображает имена каталогов также, как и остальные обычные файлы (взамен вывода списков их содержимого)&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''-v''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Выводит версию или номер поколения файла&amp;lt;/tt&amp;gt; &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Атрибуты ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:left&amp;quot;&lt;br /&gt;
| '''''Атрибут''''' || '''''Значение'''''&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''A''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Не обновлять время последнего доступа к файлу atime (no atime)&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''a''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Разрешить только добавление записи к файлу (append-only), удаление и переименование запрещено&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''C''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;No copy on write&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''c''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Автоматически сжимать информацию файла на диске. Операция чтения информации из этого файла возвращает несжатые данные. Запись информации в такой файл сопровождается предварительной её упаковкой и, наконец, последующим сохранением на диск&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;''D''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Использовать синхронное обновление каталогов; это эквивалентно применению опции монтирования ''dirsync'' к подмножеству файлов&amp;lt;/tt&amp;gt; &lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''d''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Не выполнять резервное копирование, когда запущена программа dump&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''e''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Использовать экстенты для адресации данных&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''i''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Запретить изменение файла.  Только суперпользователь или процесс, обладающий возможностью **CAP_LINUX_IMMUTABLE** может установить или очистить такой атрибут&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''j''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Все данные файла прежде, чем быть записанными непосредственно в файл, сохраняются в журнал файловой системы. Правда, это происходит в том случае, если файловая система смонтирована с опциями &amp;quot;data=ordered&amp;quot; или &amp;quot;data=writeback&amp;quot;. Когда файловая система смонтирована с опцией &amp;quot;data=journal&amp;quot; все данные файла уже журналируются и этот атрибут не имеет никакого эффекта. Только суперпользователь или процесс, обладающий возможностью **CAP_SYS_RESOURCE**, может установить или очистить этот атрибут.&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''S''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Синхронное изменение всех данных на диск, без кэширования. Использование этого атрибута эквивалентно применению опции монтирования `sync' к подмножеству расположенных файлов&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''s''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Безопасное удаление файла: выполняется обнуление его блоков и запись их обратно на диск&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''T''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Директория с установленным атрибутом 'T' будет считаться, как расположенная на вершине иерархии директорий с целью использования метода распределения блоков по Orlov (который применяется в системах с Linux 2.5.46 или выше&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''t''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Файл нельзя объединять с другими файлами. Фне будет иметь в конце (в блоке на диске) дописанных (склеенных с ним) частичных фрагментов (хвостов) других файлов (для тех файловых систем, которые поддерживают &amp;quot;склеивание хвостов&amp;quot; файлов). Это необходимо для программ типа LILO, которые непосредственно обращаются к файловой системе и не понимают &amp;quot;склеивание хвостов&amp;quot; файлов. Правда, здесь следует отметить, что файловые системы ext2 или ext3 не поддерживают для файлов &amp;quot;склеивание хвостов&amp;quot; (всё же, кроме некоторых весьма экспериментальных заплаток)&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''h''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Огромный файл&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''E''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Сжатый файл имеет ошибку сжатия&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''l''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Директория находится позади индексированных хешированных деревьев&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''X''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;К необработанному содержанию сжатого файла можно получить непосредственный доступ&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
||&amp;lt;tt&amp;gt;''Z''&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;Сжатый файл является необработанным&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Sudo</id>
		<title>Sudo</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Sudo"/>
				<updated>2017-04-17T06:10:37Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''sudo''' (от англ. &amp;quot;'''su'''bstitute user and '''do'''&amp;quot;, дословно &amp;quot;подменить пользователя и выполнить&amp;quot;) — про…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''sudo''' (от англ. &amp;quot;'''su'''bstitute user and '''do'''&amp;quot;, дословно &amp;quot;подменить пользователя и выполнить&amp;quot;) — программа для системного администрирования UNIX-систем, позволяющая делегировать те или иные привилегированные ресурсы пользователям с ведением протокола работы. Основная идея — дать пользователям как можно меньше прав, при этом достаточных для решения поставленных задач. Программа поставляется для большинства UNIX и UNIX-подобных операционных систем.&lt;br /&gt;
&lt;br /&gt;
Команда sudo предоставляет возможность пользователям выполнять команды от имени суперпользователя root либо других пользователей. Правила, используемые sudo для принятия решения о предоставлении доступа, находятся в файле &amp;lt;code&amp;gt;/etc/sudoers&amp;lt;/code&amp;gt; (для редактирования файла можно использовать специальный редактор &amp;lt;code&amp;gt;visudo&amp;lt;/code&amp;gt;, запускаемый из командной строки без параметров, в том числе без указания пути к файлу); язык их написания и примеры использования подробно изложены в ''man sudoers(5)''.&lt;br /&gt;
&lt;br /&gt;
В большинстве случаев грамотная настройка sudo делает небезопасную работу от имени суперпользователя ненужной. Все действия оказываются выполнимы из-под аккаунта пользователя, которому разрешено использовать sudo без ограничений. Имеется возможность запрещать и разрешать определённым пользователям или группам выполнение конкретного набора программ, а также разрешить выполнение определённых программ без необходимости ввода своего пароля.&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
Разрешить пользователям, входящим в группу «admin», выполнять команды с правами любого пользователя (с запросом пароля):&lt;br /&gt;
&amp;lt;pre&amp;gt;%admin ALL=(ALL) ALL&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Позволить пользователю «user1» выполнять команды с правами «user2» или «user3», не запрашивая пароль:&lt;br /&gt;
&amp;lt;pre&amp;gt;user1 ALL=(user2, user3)NOPASSWD: ALL&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Разрешить пользователю «backup» выполнять команду &amp;lt;code&amp;gt;/usr/bin/[[rsync]]&amp;lt;/code&amp;gt; без запроса пароля:&lt;br /&gt;
&amp;lt;pre&amp;gt;backup ALL=NOPASSWD: /usr/bin/rsync&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Особенности ==&lt;br /&gt;
Программу критикуют, в частности, за невозможность выполнять некоторые команды. К примеру:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;sudo cat sources.list &amp;gt; /etc/apt/sources.list&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
выдаст ошибку прав доступа (так как с правами root выполняется только процесс cat, а перенаправление выполняет [[Командная оболочка UNIX|shell]] с правами обычного пользователя), хотя такое можно сделать, использовав [[Конвейер (UNIX)|конвейер]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;cat sources.list | sudo tee /etc/apt/sources.list&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
также можно выполнить shell с административными правами, а строку к выполнению взять в кавычки, используя параметр «&amp;lt;code&amp;gt;-с&amp;lt;/code&amp;gt;»:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;sudo sh -c 'cat sources.list &amp;gt; /etc/apt/sources.list'&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
или же попасть в &amp;lt;code&amp;gt;shell&amp;lt;/code&amp;gt; интерактивно аналогично работе &amp;lt;code&amp;gt;su&amp;lt;/code&amp;gt;, используя параметр «&amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt;»:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;sudo -s&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
можно и так&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;sudo su&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
или выполнив&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=bash&amp;gt;sudo sh&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Схожие программы ==&lt;br /&gt;
&lt;br /&gt;
В ''OpenSolaris'' вместо sudo используется команда ''pfexec'', работающая на основе механизма &amp;quot;Управление доступом на основе ролей(RBAC)&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Windows имеет похожую команду ''runas''.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Faq</id>
		<title>Faq</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Faq"/>
				<updated>2017-04-11T07:32:10Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Отличие обычного пользователя Linux от профессионала заключается во времени, проведённом за изучением хитростей и приёмов, которые позволяют решать не быстрые задачи в одно мгновение. Если вы хотите увеличить скорость работы без долгого набивания шишек в консоли, здесь приводится список лёгких для изучения приёмов. Они помогут сделать вашу работу эффективной и менее трудозатратной.&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Список не ваших процессов'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для получения списка всех процессов, запущенных &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;''не текущим пользователем''&amp;lt;/span&amp;gt;, выполните команду:&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ps aux | grep -v `whoami`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для получения списка из 10 процессов, которые сильнее всего загружают систему, выполните команду:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ps aux --sort=-%cpu | grep -m 11 -v `whoami`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Замена текста в файлах'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Если надо заменить текст не в одном файле, то имеется несколько способов. Для того, чтобы заменить текст '''''«Windows»''''' на '''''«Linux»''''' во всех файлах в текущей директории, название которой начинается с «test», введите в консоли('''''необходим интерпретатор perl'''''):&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$perl -i -pe 's/Windows/Linux/;' test*&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Чтобы провести ту же операцию во всех поддиректориях:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$find. -name '*.txt' -print | xargs perl -pi -e's/Windows/Linux/ig' *.txt&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Если Вы хотите сделать то же самое для на обычных файлов со множеством переносов строк и странных символов (файл — в другой кодировке):&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$find -type f -name '*.txt' -print0 | xargs --null perl -pi -e 's/Windows/Linux/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Исправить консоль'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Если использовать команду [[less]] или [[cat]] для просмотра файла, в конце которого — бинарные данные, то можно легко испортить консоль. Потому что в бинарных данных могут попасться любые сочетания управляющих кодов: компьютер будет издавать звуки «бип-бип», появятся прикольные символы, странные цветовые сочетания. В конце концов, шрифт изменится на какие-то иероглифы. Bash, очевидно, продолжает работать, но вы ничего не можете прочитать и сделать. Просто наберите в консоли команду инициализации:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$reset&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Запуск множественных X-сессий'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Если надо дать кому-нибудь доступ к Вашему компьютеру, то вы откроете для себя, что это не всегда необходимо. Если предположить, что компьютер стартует в графическом режиме (''runlevel 5''), то, одновременно нажав '''Ctrl+Alt+&amp;lt;F7&amp;gt;''', вы попадете в консоль. Введите логин и пароль, потом исполните следующий код:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$startx -- :1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;чтобы войти в графическое окружение. Чтобы вернуться в предыдущую сессию, нажмите '''Ctrl+Alt+&amp;lt;F7&amp;gt;''', для ещё одного возврата — '''Ctrl+Alt+&amp;lt;F8&amp;gt;'''. Вы можете этот трюк: клавиши с '''F1''' по '''F6''' отвечают за &amp;lt;u&amp;gt;6 сессий консоли&amp;lt;/u&amp;gt;, а клавиши с '''F7''' по '''F12''' — за &amp;lt;u&amp;gt;6 Х-сессий&amp;lt;/u&amp;gt;. Подводный камень: в разных дистрибутивах могут использоваться разные сочетания клавиш.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Лёгкое резервное копирование'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Если надо сделать резервную копию папки и скопировать только изменившиеся файлы, то можно использовать для этого rsync (вам нужен аккаунт на удалённом компьютере):&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$rsync -vare ssh jono@192.168.0.2:/home/jono/importantfiles/* /home/jono/backup/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Поиск самых больших файлов в текущей директории'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Можно столкнуться с проблемой, когда надо удалить несколько больших файлов. Их можно найти в текущей директории с помощью команды:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ls -lSrh&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Ключ “r” означает, что большие файлы должны выводиться в конце. Следующей командой можно найти самые большие файлы MP3/MPEG:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$ls -lSrh *.mp*&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Также можно найти самые большие директории:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$du -kx | egrep -v &amp;quot;\./.+/&amp;quot; | sort -n&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Оптимизация баз данных MySQL'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;При любом изменении структуры базы данных или удалении больших объёмов данных, файлы могут стать фрагментированными, что приводит к потере производительности. Просто запомните простое правило — запускать оптимизатор базы при любом изменении базы:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#mysqloptimize -A -u&amp;lt;username&amp;gt; -p&amp;lt;password&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#mysqlcheck --optimize -A -u&amp;lt;username&amp;gt; -p&amp;lt;password&amp;gt;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Список открытых портов'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Получить список открытых портов в состоянии ''Listen'' в Linux очень просто, для этого достаточно выполнить:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#netstat -lnp&lt;br /&gt;
 Active Internet connections (only servers)&lt;br /&gt;
 Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name &lt;br /&gt;
 tcp 0 0 0.0.0.0:5280 0.0.0.0:* LISTEN 698/perl &lt;br /&gt;
 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 217/httpd tcp&lt;br /&gt;
 0 0 10.42.3.2:53 0.0.0.0:* LISTEN 220/named tcp&lt;br /&gt;
 0 0 10.42.4.6:53 0.0.0.0:* LISTEN 220/named tcp&lt;br /&gt;
 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 220/named tcp &lt;br /&gt;
 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 200/sshd udp &lt;br /&gt;
 0 0 0.0.0.0:32768 0.0.0.0:* 220/named udp &lt;br /&gt;
 0 0 10.42.3.2:53 0.0.0.0:* 220/named udp &lt;br /&gt;
 0 0 10.42.4.6:53 0.0.0.0:* 220/named udp &lt;br /&gt;
 0 0 127.0.0.1:53 0.0.0.0:* 220/named udp &lt;br /&gt;
 0 0 0.0.0.0:67 0.0.0.0:* 222/dhcpd raw &lt;br /&gt;
 0 0 0.0.0.0:1 0.0.0.0:* 7 222/dhcpd&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;В этом примере видно, что процесс с PID'ом 698 — процесс интерпретатора Perl, который слушает порт 5280. Если вы не root в системе, то система не покажет пути к программам.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Поиск занятых устройств'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Вы наверняка сталкивались с ситуацией, когда надо отмаунтить диск, но система при попытке отключения сообщает о том, что он занят. Одной командой можно узнать, какое приложение использует его:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof +D /mnt/windows&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Она показывает PID и команду запуска любого процесса, использующего /mnt/windows.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt; '''Поиск изменённых сегодня файлов'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Например, утром вы создали файл, который именно сейчас очень нужен. Однако, вы не можете вспомнить его название. Вручную перебирать домашнюю директорию бессмысленно, где скопилась не одна тысяча файлов. Но есть небольшой приём, показывающий эффективность пайпов и объединения нескольких команд консоли:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ls -al --time-style=+%D | grep `date +%D`&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Параметры команды [[Ls_—_Команда_печати_содержимого_каталога|ls]] требуют вывода даты в определенном формате. Хитрость в том: то, что выдаст [[Ls_—_Команда_печати_содержимого_каталога|ls]], идет на вход [[grep]]. Параметр grep сами по себе команда (заключена в обратные апострофы), которая подставляет текущую дату в шаблон для отсева. Её легко модифицировать для поиска по другим датам, размеру файла и т.д.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Поиск больших файлов в Linux'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Поиск больших файлов особенно актуален когда на диске заканчивается место и приходится искать кандидатов на удаление. Самый лучший способ чтобы найти все самые большие файлы на хосте с Linux - воспользоваться командной строкой. В принципе не существует простой команды для поиска самых больших файлов в Linux. Однако, можно с лёгкостью получить список самых больших файлов, используя комбинацию нескольких простых команд.Выполните следующую комбинацию команд для поиска десяти самых больших файлов в Linux, начиная с директории &amp;lt;DIR&amp;gt; (измените &amp;lt;DIR&amp;gt; на директорию в которой Вы хотите запустить поиск):&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#find &amp;lt;DIR&amp;gt; -mount -type f -ls 2&amp;gt; /dev/null | sort -rnk7 | head -10 | awk '{printf &amp;quot;%10d MB\t%s\n&amp;quot;,($7/1024)/1024,$NF}'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 106 MB /var/lib/mysql/ibdata1 &lt;br /&gt;
 94 MB /usr/lib/locale/locale-archive &lt;br /&gt;
 41 MB /scripts/20130206-015833.tar.gz &lt;br /&gt;
 41 MB /scripts/20130206-004839.tar.gz &lt;br /&gt;
 41 MB /scripts/20130206-130400.tar.gz &lt;br /&gt;
 41 MB /scripts/20130206-000442.tar.gz &lt;br /&gt;
 41 MB /scripts/20130206-132019.tar.gz &lt;br /&gt;
 41 MB /root/20130208-133954.tar.gz &lt;br /&gt;
 33 MB /var/log/messages-20130303 &lt;br /&gt;
 32 MB /var/lib/rpm/Packages&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Найти 10 самых больших фалов, начиная с '/home'&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#find /home -mount -type f -ls 2&amp;gt; /dev/null | sort -rnk7 | head -10 | awk '{printf &amp;quot;%10d MB\t%s\n&amp;quot;,($7/1024)/1024,$NF}'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
 3007 MB /home/user/Desktop/share/linux-65835.iso &lt;br /&gt;
 448 MB /home/user/Pictures/Turkey/SAM_4590.AVI &lt;br /&gt;
 266 MB /home/user/Pictures/Turkey/SAM_4588.AVI &lt;br /&gt;
 173 MB /home/user/Camera/VID_20130909_120713.mp4 &lt;br /&gt;
 152 MB /home/user/Camera/VID_20130909_115427.mp4 &lt;br /&gt;
 133 MB /home/user/Camera/VID_20130909_210904.mp4 &lt;br /&gt;
 133 MB /home/user/Pictures/Paris/VID_20130928_182431.mp4 &lt;br /&gt;
 131 MB /home/user/Pictures/Turkey/SAM_4597.AVI &lt;br /&gt;
 129 MB /home/user/Pictures/Turkey/SAM_4641.AVI&lt;br /&gt;
 127 MB /home/user/Desktop/tmp/Camera/VID_20130911_164440.mp4&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Сортировка вывода по размеру файлов командой &amp;lt;code&amp;gt;du&amp;lt;/code&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#du -k /opt/ruby_projects/* | sort -nr | cut -f2 | xargs -d '\n' du -sh&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Определить дату установки Linux'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Есть несколько вариантов узнать дату и время установки:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ls -clt / | tail -n 1 | awk '{ print $7, $6, $8 }'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#tune2fs -l /dev/sda1 | grep create&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#LC_TIME=&amp;quot;en_DK&amp;quot; rpm -qia |grep &amp;quot;Install Date&amp;quot;|awk '{print $3}'|uniq |sort -r|tail -n 1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Очистка КЭШа оперативной памяти в Linux'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для того, чтобы посмотреть сколько оперативной памяти занято и сколько закешировано в данный момент, можно воспользоваться командой &amp;lt;code&amp;gt;free&amp;lt;/code&amp;gt;. С параметром -g она выведет информацию об использовании памяти в гигабайтах, с параметром -m в мегабайтах:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#free -g&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для очистки кеша страниц('''pagecache''') использовать команду:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#echo 1 &amp;gt; /proc/sys/vm/drop_caches&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для очистки directory entry('''dentries''') и index node('''inode''') использовать команду:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#echo 2 &amp;gt; /proc/sys/vm/drop_caches&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для очистки кеша страниц('''pagecache'''), directory entry('''dentries''') и index node('''inode''') использовать команду:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#echo 3 &amp;gt; /proc/sys/vm/drop_caches&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Проверка количества открытых файлов для процесса'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;В примере ниже описана команда получения количества открытых процессом файлов, для процесса ''line4'':&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#for pid in `pidof line4`; do echo &amp;quot;$(&amp;lt; /proc/$pid/cmdline)&amp;quot;; egrep 'files|Limit' /proc/$pid/limits; \&lt;br /&gt;
echo &amp;quot;Currently open files: $(ls -1 /proc/$pid/fd | wc -l)&amp;quot;; echo; done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Вывод представлен на скриншоте ниже:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Open files.PNG|1200px|center]]&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Просмотреть краткую информацию по сетевому интерфейсу'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Для просмотра выполнить команду:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ip addr show &amp;lt;NIC&amp;gt; | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Подсчитать Количество Файлов(Директорий) в Папке'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Ниже приведены лучшие способы поиска и подсчета количества файлов и папок в конкретной директории.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Подсчитать количество файлов в текущей папке:&amp;lt;/p&amp;gt;&lt;br /&gt;
* Если Вам необходимо подсчитать довольно большое количество файлов, данный метод является самым быстрым:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ls -f . | wc -l&lt;br /&gt;
#find . -type f -maxdepth 1 | wc -l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Команда рекурсивно считает количество файлов в текущей директории и всех её поддиректориях:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#find . -type f | wc -l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Команда рекурсивно считает количество папок в текущей директории и всех её поддиректориях:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#find . -type d | wc -l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
* Команда рекурсивно считает количество файлов с расширением &amp;quot;.txt&amp;quot; в текущей директории и всех её поддиректориях:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#find . -type f -name &amp;quot;*.txt&amp;quot; | wc -l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Настройка ssh на авторизацию по ключам'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Бывают случаи, когда необходимо настроить ssh c доступом к серверам с использованием авторизации по ключам. Для этого необходимо выполнить следующие команды(на сервере с которого планируются подключения к серверам, используя ключи):&amp;lt;/p&amp;gt;&lt;br /&gt;
Переходим в директорию .ssh, расположенную в домашней директории пользователя:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#cd ~/.ssh/&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Генерируем ключи, которые будем передавать. На все вопросы нажимаем клавишу ''Enter'':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh-keygen&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отправляем на сервер 192.168.1.21 содержимое ~/.ssh/id_rsa.pub в файл /home/user/.ssh/authorized_keys:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#cat ~/.ssh/id_rsa.pub | ssh user@192.168.1.21 'cat &amp;gt;&amp;gt; .ssh/authorized_keys'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отправляем на сервер 192.168.1.21 команду, которая выставит права записи и чтения на файл authorized_keys только для владельца:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh user@192.168.1.21 'chmod 600 ~/.ssh/authorized_keys'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Отправляем на сервер 192.168.1.21 команду, которая выставит права записи и чтения и исполнения на директорию .ssh только для владельца:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh user@192.168.1.21 'chmod 700 ~/.ssh'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Вводим данную команду, для проверки, что авторизации по ключам работает:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh user@192.168.1.21&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Следует учитывать, что на домашнюю директорию пользователя и директорию .ssh(/home/&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;&amp;lt;''username''&amp;gt;&amp;lt;/span&amp;gt;/.ssh) на удалённом сервере должны быть выставлены права '''''drwx------'''''('''700'''), а на файл /home/&amp;lt;span style=&amp;quot;color:blue&amp;quot;&amp;gt;&amp;lt;''username''&amp;gt;&amp;lt;/span&amp;gt;/.ssh/authorized_keys '''''-rw-------'''''('''600''').&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Ошибка &amp;quot;Broken pipe&amp;quot; при авторизации пользователя по ssh'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Бывают случаи, когда при авторизации обычным пользователем по ssh появляется ошибка &amp;quot;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Broken pipe'''&amp;lt;/span&amp;gt;&amp;quot;. При этом авторизация под root может проходить успешно. Если из-под '''root''' выполнить команду &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;'''''su - &amp;lt;username&amp;gt;'''''&amp;lt;/span&amp;gt; и получить результат &amp;quot;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''su: cannot set user id: Resource temporarily unavailable'''&amp;lt;/span&amp;gt;&amp;quot; или &amp;quot;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''su:невозможно установить пользовательский id: Ресурс временно недоступен'''&amp;lt;/span&amp;gt;&amp;quot;, то надо посмотреть в сторону того, какое кол-во процессов разрешено запускать пользователю и какое кол-во процессов из-под этого пользователя запущенно на данный момент. Для этого необходимо выполнить следующие команды:&amp;lt;/p&amp;gt;&lt;br /&gt;
Команда покажет сколько процессов запущено от пользователя &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''&amp;lt;username&amp;gt;'''&amp;lt;/span&amp;gt; на данный момент:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ps -eLF|grep '&amp;lt;username&amp;gt;'|wc -l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда покажет сколько файлов открыто от пользователя &amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''&amp;lt;username&amp;gt;'''&amp;lt;/span&amp;gt; на данный момент:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -u '&amp;lt;username&amp;gt;'|wc -l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда покажет сколько процессов разрешено запускать пользователям(&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''*'''&amp;lt;/span&amp;gt; - любой пользователь) в RHEL 6.x/CentOS 6.x:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#cat /etc/security/limits.d/90-nproc.conf&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Команда покажет сколько процессов разрешено запускать пользователям(&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''*'''&amp;lt;/span&amp;gt; - любой пользователь) в RHEL 7.x/CentOS 7.x:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#cat /etc/security/limits.d/20-nproc.conf&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В случае, если вывод команды &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#ps -eLF|grep '&amp;lt;username&amp;gt;'|wc -l&amp;lt;/source&amp;gt; превышает указанное в 90-nproc.conf/20-nproc.conf значение, тогда необходимо это значение увеличить или закомментировать с последующей перезагрузкой параметров командой &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#sysctl -p&amp;lt;/source&amp;gt;('''''правка параметров и перезагрузка выполняется из-под root''''').&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Копирование директорий на удалённый сервер используя tar, ssh, cat или dd'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Архивирование директории на удалённый сервер с использованием [[cat]]:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# tar zcvfp - /home/user/sourcedir | ssh user@remote_host &amp;quot;cat &amp;gt; ~/from_somehost.tar.gz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
То, что [[tar]] выведет на стандартный вывод, перенаправляется на удалённый сервер ('''''user@remote_host'''''), где и запускается команда &amp;quot;'''''cat &amp;gt; ~/from_somehost.tar.gz'''''&amp;quot;. [[cat]] принимает на вход то, что выдал [[tar]], а затем всё это складывает в файл '''''~/from_somehost.tar.gz'''''.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Архивирование директории на удалённый сервер с [[dd]]:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#tar zcvfp - /home/user/sourcedir | ssh user@remote_host &amp;quot;dd of=~/from_somehost.tar.gz&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В этом примере вместо [[cat]] используется [[dd]] (disk destroy ;), у которой есть параметр '''of''' (output file), то есть тот, куда нужно складывать то, что пришло от [[tar]]. Остальное по аналогии должно быть понятно.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Архивирование  с удалённой машины на локальную с использованием [[cat]]:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh user@remote_host &amp;quot;tar zcvfp - /home/user/sourcedir&amp;quot; | cat &amp;gt; ~/from_somehost.tar.gz&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Архивирование  с удалённой машины на локальную с использованием [[dd]]:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh user@remote_host &amp;quot;tar zcvfp - /home/user/sourcedir&amp;quot; | dd of=~/from_somehost.tar.gz&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Распаковка удалённого архива на локальную машину:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#ssh user@remote_host &amp;quot;cat /home/user/from_somehost.tar.gz&amp;quot; |tar xvfp -&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Работа с процессами'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
Часто бывает полезным узнать разного рода параметры уже запущенных процессов, а так же манипулировать ими. Рассмотрим несколько разных примеров по работе с процессами.&lt;br /&gt;
Много информации нам предоставляет файловая система '''procfs'''.&amp;lt;br /&amp;gt;&lt;br /&gt;
'''procfs''' — виртуальная файловая система, используемая в ''UNIX-like'' ОС. '''procfs''' позволяет получить доступ к информации о системных процессах из ядра, она необходима для выполнения таких команд как [[ps]], [[w]], [[top]]. Обычно её монтируют на ''/proc''. '''procfs''' создаёт двухуровневое представление пространств процессов. На верхнем уровне процессы представляют собой директории, именованные в соответствии с их ''pid''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Некоторые файлы и директории из '''ProcFS''', где '''PID''' – идентификатор процесса или ''self'':&lt;br /&gt;
* /proc/'''PID'''/cmdline – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;аргументы командной строки&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/'''PID'''/environ – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;переменные окружения для данного процесса&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/'''PID'''/status – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;статус процесса&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/'''PID'''/fd – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;директория, содержащая символьные ссылки на каждый открытый файловый дескриптор&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/cpuinfo – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;информация о процессоре (производитель, модель, поколение и т.п.)&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/cmdline – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;параметры, передаваемые ядру при загрузке&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/uptime – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;количество секунд, прошедших с момента загрузки ядра и проведенных в режиме бездействия&amp;lt;/span&amp;gt;;&lt;br /&gt;
* /proc/version – &amp;lt;span style=&amp;quot;color:green&amp;quot;&amp;gt;содержит информацию о версии ядра, компилятора и другую информацию, связанную с загруженным ядром&amp;lt;/span&amp;gt;.&lt;br /&gt;
Посмотрев на размер файлов в каталоге ''/proc'', можно увидеть, что они все нулевого размера. Дело в том, что в действительности все эти файлы не существуют.&lt;br /&gt;
Примеры использования '''procfs''':&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;1) Текущий рабочий каталог процесса&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# ls -la /proc/3165/cwd&lt;br /&gt;
lrwxrwxrwx 1 clamav clamav 0 Авг 18 16:07 /proc/3165/cwd -&amp;gt; /var/lib/clamav&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
где 3165 — номер pid’a процесса.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;2) Вывести все переменные процесса&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# cat /proc/2361/environ | strings&lt;br /&gt;
XDG_SESSION_ID=1&lt;br /&gt;
TERM=xterm&lt;br /&gt;
SHELL=/bin/bash&lt;br /&gt;
SSH_CLIENT=10.0.2.2 1383 22&lt;br /&gt;
SSH_TTY=/dev/pts/0&lt;br /&gt;
USER=vaal&lt;br /&gt;
LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:&lt;br /&gt;
*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:*.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.tzo=01;31:*.t7z=01;31:&lt;br /&gt;
*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:&lt;br /&gt;
*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:&lt;br /&gt;
*.cab=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:&lt;br /&gt;
*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:&lt;br /&gt;
*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:&lt;br /&gt;
*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:&lt;br /&gt;
*.flac=00;36:*.m4a=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:&lt;br /&gt;
*.spx=00;36:*.xspf=00;36:&lt;br /&gt;
DOCKER_TLS_VERIFY=0&lt;br /&gt;
MAIL=/var/mail/vaal&lt;br /&gt;
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games&lt;br /&gt;
PWD=/home/vaal&lt;br /&gt;
LANG=ru_RU.UTF-8&lt;br /&gt;
SHLVL=1&lt;br /&gt;
HOME=/home/vaal&lt;br /&gt;
LOGNAME=vaal&lt;br /&gt;
SSH_CONNECTION=10.0.2.2 1383 10.0.2.15 22&lt;br /&gt;
LESSOPEN=| /usr/bin/lesspipe %s&lt;br /&gt;
XDG_RUNTIME_DIR=/run/user/1000&lt;br /&gt;
LESSCLOSE=/usr/bin/lesspipe %s %s&lt;br /&gt;
_=/usr/bin/mc&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;3) Удалили файл, используемый процессом. Как восстановить файл?&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
Попробовать поискать файл в каталоге /proc/'''PID'''/fd&lt;br /&gt;
Почему так можно делать? Всё дело в том, что при удалении файла, который всё-таки открыт процессом, файл перестал быть виден в файловой системе, но не исчез, и окончательно удалён он будет только когда закроется последний ссылающийся на него дескриптор. Каталог /proc/'''PID'''/fd содержит символьные ссылки на все открытые процессом '''PID''' дескрипторы.&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;4) Связь между /proc и sysctl(взято с [http://linuxcenter.ru Linux-center])&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
'''Sysctl''' использует файлы в ''/proc/sys'' как индивидуальные переменные, которые могут быть изменены. К примеру, файл в ''/proc/sys'', который представляет максимальное количество заголовков файлов в системе, ''/proc/sys/fs/file-max'', представлен как '''fs.file-max'''. Этот пример требует некоторых дополнительных пояснений в записи '''sysctl'''. Так как '''sysctl''' может только изменять переменные в директории '''/proc/sys''', то часть имени переменной обозначающая директорию отбрасывается. Другое изменение касается слэшей, которые заменяются на точки. Вот два простых правила для преобразования файлов в ''/proc/sys'' и переменных в '''sysctl''':&amp;lt;br /&amp;gt;&lt;br /&gt;
* Отбросьте ''/proc/sys'' от начала.&lt;br /&gt;
* Замените слэши на точки в имени файла.&lt;br /&gt;
Эти два правила позволят вам преобразовать любой файл в ''/proc/sys'' в любое имя переменной в '''sysctl'''. Обычное преобразование имени файла в переменную:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
/proc/sys/dir/file --&amp;gt; dir.file&lt;br /&gt;
dir1.dir2.file --&amp;gt; /proc/sys/dir1/dir2/file&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Можно отобразить все переменные, доступные для изменения, используя команду '''sysctl -a'''. Переменные могут также быть изменены с помощью '''sysctl''', которая выполняет ту же работу что и '''echo'''. Эта запись объясняет это:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl -w dir.file=&amp;quot;value&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Используя пример с ''file-max'', мы можем изменить это значение на 16384, используя один из двух методов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
sysctl -w fs.file-max=&amp;quot;16384&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
или&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
echo &amp;quot;16384&amp;quot; &amp;gt; /proc/sys/fs/file-max&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;5) Максимальное количество процессов&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
По умолчанию процессов 32768. Узнать текущее значение можно так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#sysctl kernel.pid_max&lt;br /&gt;
kernel.pid_max = 32768&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Изменить это число можно так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#sysctl kernel.pid_max=256000&lt;br /&gt;
kernel.pid_max = 256000&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Это возможно только на '''64'''-битных системах. Такое ограничение связано с разрядностью '''32'''-битного числа, которое не может превышать ''32768''. А поскольку эти лимиты определены как тип '''int''', то соответственно действует такое ограничение. Если же вы попробуете изменить, то получите такое сообщение:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# sysctl kernel.pid_max=327600&lt;br /&gt;
error: &amp;quot;Invalid argument&amp;quot; setting key &amp;quot;kernel.pid_max&amp;quot;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;6) Утилита lsof&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
Утилита, служит для вывода информации о том, какие файлы используются теми или иными процессами.Ниже будет продемонстрировано несколько полезных примеров работы этой утилиты.&lt;br /&gt;
* Список всех открытых файлов&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
$lsof&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Показывает все открытые файлы текущего пользователя (если '''root''' — тогда все файлы) всеми процессами.&lt;br /&gt;
* Какие процессы используют файл file&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof /path/to/file&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Можно указать несколько файлов через пробел, тогда получите суммарный список процессов.&lt;br /&gt;
&lt;br /&gt;
* Какие процессы/файлы использует пользователь ''user''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -u user&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если хотите узнать информацию по нескольким пользователям, разделите их имена запятой. Для групп используйте конструкцию ‘-g groupname’&lt;br /&gt;
&lt;br /&gt;
* Какие процессы открыты программой prog_name&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -c prog_name&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Можно указывать неполное имя. [lsof] будет искать по указанному буквосочетанию. Если нужно узнать информацию для нескольких приложений, разделяйте их имена пробелом и перед каждым именем должно идти ‘-c’&lt;br /&gt;
&lt;br /&gt;
* Какие файлы открыты pid’ом NNN&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -p NNN&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Список всех открытых интернет сокетов&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -i&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Если нужно посмотреть только tcp сокеты, то после ‘i’ через пробел добавляем ''tcp''. Аналогично и для ''udp''.&amp;lt;br /&amp;gt;&lt;br /&gt;
Так же можно посмотреть и список всех unix сокетов:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -U&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Просмотр ресурсов в realtime&lt;br /&gt;
Можно задать период обновления информации, например, 1 секунда:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -r 1 -u username&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
будет обновлять информацию об использованных пользователем ''username'' процессах, каждую секунду.&lt;br /&gt;
&lt;br /&gt;
* Вывод только pid’ов&lt;br /&gt;
По умолчанию, выводится таблица с колонками. Но если требуется вывести только сами pid’ы, можно воспользоваться такой командой:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#lsof -t -u username&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;7) Поиск всех pid’ов процесса&amp;lt;/span&amp;gt;:&amp;lt;/p&amp;gt;&lt;br /&gt;
Есть одна замечательная утилита [[pidof]], которая позволяет найти все pid’ы связанные с определённым процессом. К примеру, найдём все pid’ы apache2:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
# pidof apache2&lt;br /&gt;
9370 9369 9368 9367 9364 9362 9314 9280 9277 9268 4940&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В большинстве дистрибутивов это обычный симлинк на ''/sbin/killall5'':&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
#file /bin/pidof&lt;br /&gt;
/bin/pidof: symbolic link to `../sbin/killall5'&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;p style=&amp;quot;text-align:center&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;color:red&amp;quot;&amp;gt;'''Быстрое копирование данных при помощи Python'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt; ===&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;Иногда необходимо быстро предоставить доступ к файлам на машине Linux. В случае, если на такой машине имеется установленный python, то можно запустить простой HTTP-сервер, который предоставит такой доступ. Для этого перейдём в директорию содержащую целевые файлы и выполним команду интерпретатора python, который откроет HTTP-сервер на порту 8080:&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
$ cd &amp;lt;source_dir&amp;gt;&lt;br /&gt;
$ python -m SimpleHTTPServer 8080&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;p style=&amp;quot;text-align:left&amp;quot;&amp;gt;&lt;br /&gt;
или таким образом:&lt;br /&gt;
&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
$ cd &amp;lt;source_dir&amp;gt;&lt;br /&gt;
$ python3 -m http.server 8080&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ссылки ===&lt;br /&gt;
[https://nixadmin.ru/copy_on_the_fly nixadmin.ru — копирование &amp;quot;на лету&amp;quot;]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://eax.me/ssh-backup/ Резервное копирование базы данных и файлов по SSH]&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
[https://skeletor.org.ua/?p=1506 Работаем с процессами]&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/More</id>
		<title>More</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/More"/>
				<updated>2017-04-11T06:12:48Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''more''' — утилита терминала, используемая для просмотра содержимого текстовых файлов в о…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''more''' — утилита терминала, используемая для просмотра содержимого текстовых файлов в операционных системах, основанных на Unix. В отличие от [[less]], more выводит содержимое файла на экран отдельными страницами. Для перехода на следующую страницу используется клавиша пробела. Нажатие на клавишу «Enter» приводит к смещению вниз на одну строку. Кроме клавиш пробела и «Enter», в режиме паузы ещё некоторые клавиши действуют как управляющие (например, клавиша «В» возвращает текст на один экран назад). Выйти из режима просмотра можно с помощью клавиши «Q». Обо всех опциях команды more можно прочитать на справочной странице man.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Less</id>
		<title>Less</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Less"/>
				<updated>2017-04-11T06:07:18Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''less''' — программа для текстовых терминалов UNIX-подобных ОС, используемая для просмотра (…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''less''' — программа для текстовых терминалов UNIX-подобных ОС, используемая для просмотра (но '''не изменения''') содержимого текстовых файлов на экране. Отображает файл с возможностью прокрутки. Less — улучшение утилиты '''more'''. Возможна и обратная прокрутка. В отличие от многих текстовых редакторов (которые также можно использовать для просмотра файлов), &amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt; не нуждается в чтении всего файла перед стартом и в результате быстрее работает с большими файлами. Синтаксис команды:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;less [''параметры''] [''имя файла''...]&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt; можно вызывать с параметрами, изменяющими поведение (например, число строк, отображаемых на экране). Некоторые параметры могут различаться в разных Unix-системах. При просмотре доступен ряд команд навигации. Эти команды базируются на используемых &amp;lt;code&amp;gt;more&amp;lt;/code&amp;gt; и &amp;lt;code&amp;gt;vi&amp;lt;/code&amp;gt;. Также возможен поиск в файле.&lt;br /&gt;
&lt;br /&gt;
По умолчанию, &amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt; отображает содержимое файла на стандартный вывод. Если файл не указан, отображается стандартный ввод, что может использоваться для отображения результата работы конвейера. Если стандартный вывод команды &amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt; направлен не на терминал (в частности, на вход другой команды с использованием конвейера, или в обычный файл), &amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt; ведёт себя как &amp;lt;code&amp;gt;[[cat]]&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;less&amp;lt;/code&amp;gt; был написан ''Mark Nudelman'' и сейчас включён в проект GNU. Эта команда включена во многие Unix-системы.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Netstat</id>
		<title>Netstat</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Netstat"/>
				<updated>2017-04-10T12:01:45Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;code&amp;gt;netstat&amp;lt;/code&amp;gt; ('''net'''work '''stat'''istics) — утилита командной строки выводящая на дисплей состояние TCP-соединений (как входящих, так и исходящих), таблицы маршрутизации, число сетевых интерфейсов и сетевую статистику по протоколам. Она доступна на всех unix-подобных операционных системах, включая OS X, Linux, Solaris, и BSD, но также существует в основанных на Windows NT операционных системах начиная с Windows XP вплоть до Windows 10.&lt;br /&gt;
&lt;br /&gt;
Основное назначение утилиты — это поиск сетевых проблем и определение производительности сети.&lt;br /&gt;
&lt;br /&gt;
Следует иметь в виду, что в среде Linux утилита netstat, входящая в пакет net-tools, устарела. Вместо неё следует использовать утилиту ''&amp;lt;code&amp;gt;ss&amp;lt;/code&amp;gt;'' из пакета '''iproute2'''.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис ==&lt;br /&gt;
 netstat [-Aan] [-f семейство_адресов] [-I интерфейс] [-p имя_протокола] [система] [core] &lt;br /&gt;
 netstat [-n] [-s] [-i | -r] [-f семейство_адресов] [-I интерфейс] [-p имя_протокола] [система] [core] &lt;br /&gt;
 netstat [-n] [-I интерфейс] интервал [система] [core]&lt;br /&gt;
&lt;br /&gt;
== Использование ==&lt;br /&gt;
Команда netstat выводит на экран содержимое различных структур данных, связанных с сетью, в различных форматах в зависимости от указанных опций.&lt;br /&gt;
&lt;br /&gt;
Первая форма команды показывает список активных сокетов для каждого протокола. Вторая форма выбирает одну из нескольких других сетевых структур данных. Третья форма показывает динамическую статистику пересылки пакетов по сконфигурированным сетевым интерфейсам; аргумент интервал задает, сколько секунд собирается информация между последовательными показами.&lt;br /&gt;
&lt;br /&gt;
Значение по умолчанию для аргумента система — /unix; для аргумента core в качестве значения по умолчанию используется /dev/kmem.&lt;br /&gt;
&lt;br /&gt;
== Опции ==&lt;br /&gt;
{| align=&amp;quot;centr&amp;quot; class=&amp;quot;standard&amp;quot;&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-a&amp;lt;/code&amp;gt;&lt;br /&gt;
| Показывать состояние всех сокетов; обычно сокеты, используемые серверными процессами, не показываются.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-A&amp;lt;/code&amp;gt;&lt;br /&gt;
| Показывать адреса любых управляющих блоков протокола, связанных с сокетами; используется для отладки.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;-b&amp;lt;/code&amp;gt;&lt;br /&gt;
|Отображение исполняемого файла, участвующего в создании каждого подключения, или ожидающего порта. Иногда известные исполняемые файлы содержат множественные независимые компоненты. Тогда отображается последовательность компонентов, участвующих в создании подключения, либо ожидающий порт. В этом случае имя исполняемого файла находится снизу в скобках [ ], сверху - компонент, который им вызывается, и так до тех пор, пока не достигается TCP/IP. Заметьте, что такой подход может занять много времени и требует достаточных разрешений.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-i&amp;lt;/code&amp;gt;&lt;br /&gt;
| Показывать состояние автоматически сконфигурированных (auto-configured) интерфейсов. Интерфейсы, статически сконфигурированные в системе, но не найденные во время загрузки, не показываются.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-n&amp;lt;/code&amp;gt;&lt;br /&gt;
| Показывать сетевые адреса как числа. netstat обычно показывает адреса как символы. Эту опцию можно использовать с любым форматом показа.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-r&amp;lt;/code&amp;gt;&lt;br /&gt;
| Показать таблицы маршрутизации. При использовании с опцией -s показывает статистику маршрутизации.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt;&lt;br /&gt;
| Показать статистическую информацию по протоколам. При использовании с опцией -r показывает статистику маршрутизации.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-f сеймество_адресов&amp;lt;/code&amp;gt;&lt;br /&gt;
| Ограничить показ статистики или адресов управляющих блоков только указанным семейством_адресов, в качестве которого можно указывать:&lt;br /&gt;
'''inet''' Для семейства адресов '''AF_INET''', или '''unix''' для семейства адресов '''AF_UNIX'''.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-I интерфейс&amp;lt;/code&amp;gt;&lt;br /&gt;
| Выделить информацию об указанном интерфейсе в отдельный столбец; по умолчанию (для третьей формы команды) используется интерфейс с наибольшим объёмом переданной информации с момента последней перезагрузки системы. В качестве интерфейса можно указывать любой из интерфейсов, перечисленных в файле конфигурации системы, например, emd1 или lo0.&lt;br /&gt;
|-----&lt;br /&gt;
| &amp;lt;code&amp;gt;-p&amp;lt;/code&amp;gt;&lt;br /&gt;
| Отобразить идентификатор/название процесса, создавшего сокет (-p, --programs display PID/Program name for sockets)&lt;br /&gt;
|+&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Выдаваемая информация ==&lt;br /&gt;
'''Активные сокеты'''&lt;br /&gt;
&lt;br /&gt;
Для каждого активного сокета показывается протокол, размер очередей приема и получения (в байтах), локальный и удаленный адрес, а также внутреннее состояние протокола.&lt;br /&gt;
Символьный формат, обычно используемый для показа адресов сокетов, — это либо:&lt;br /&gt;
 имя_хоста.порт&lt;br /&gt;
&lt;br /&gt;
если имя хоста указано, либо:&lt;br /&gt;
 сеть.порт&lt;br /&gt;
&lt;br /&gt;
если адрес сокета задает сеть, но не конкретный хост. Имена хостов и сетей берутся из соответствующих записей в файле /etc/hosts или /etc/networks.&lt;br /&gt;
&lt;br /&gt;
Если имя сети или хоста для адреса неизвестно (или если указана опция -n), адрес показывается числами. Не указанные или «обобщенные» адреса и Порт (TCP/IP)|порты показываются как «*». Подробнее о соглашениях по именованию в Internet см. страницу справочного руководства inet.&lt;br /&gt;
&lt;br /&gt;
'''Сокеты TCP'''&lt;br /&gt;
&lt;br /&gt;
Для сокетов TCP допустимы следующие значения состояния:&lt;br /&gt;
{| align=&amp;quot;center&amp;quot; class=&amp;quot;standard&amp;quot;&lt;br /&gt;
|-----&lt;br /&gt;
|'''''CLOSED'''''&lt;br /&gt;
|''Закрыт. Сокет не используется.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''LISTEN (LISTENING)'''''&lt;br /&gt;
|''Ожидает входящих соединений.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''SYN_SENT'''''&lt;br /&gt;
|''Активно пытается установить соединение.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''SYN_RECEIVED'''''&lt;br /&gt;
|''Идет начальная синхронизация соединения.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''ESTABLISHED'''''&lt;br /&gt;
|''Соединение установлено.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''CLOSE_WAIT'''''&lt;br /&gt;
|''Удаленная сторона отключилась; ожидание закрытия сокета.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''FIN_WAIT_1'''''&lt;br /&gt;
|''Сокет закрыт; отключение соединения.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''CLOSING'''''&lt;br /&gt;
|''Сокет закрыт, затем удаленная сторона отключилась; ожидание подтверждения.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''LAST_ACK'''''&lt;br /&gt;
|''Удаленная сторона отключилась, затем сокет закрыт; ожидание подтверждения.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''FIN_WAIT_2'''''&lt;br /&gt;
|''Сокет закрыт; ожидание отключения удаленной стороны.''&lt;br /&gt;
|-----&lt;br /&gt;
|'''''TIME_WAIT'''''&lt;br /&gt;
|''Сокет закрыт, но ожидает пакеты, ещё находящиеся в сети для обработки''&lt;br /&gt;
|+&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Сетевые структуры данных'''&lt;br /&gt;
&lt;br /&gt;
Показываемые данные зависят от выбора опции, -i или -r. Если указаны обе опции, netstat выберет -i.&lt;br /&gt;
&lt;br /&gt;
'''Показ таблицы маршрутизации'''&lt;br /&gt;
&lt;br /&gt;
Таблица маршрутизации показывает все имеющиеся маршруты (routes) и статус каждого из них. Каждый маршрут состоит из целевого хоста или сети и шлюза (gateway), который используется для пересылки пакетов. Столбец flags (флаги) показывает статус маршрута (U, если он включен), ведёт ли маршрут на шлюз (G), был ли маршрут создан динамически при помощи перенаправления (D), и используется ли адрес индивидуального хоста (H) вместо адреса сети. Например, интерфейс закольцовывания (loopback transport provider) lo0 всегда имеет флаг H.&lt;br /&gt;
&lt;br /&gt;
Прямые маршруты создаются для каждого интерфейса, подключенного к локальному хосту; поле gateway (шлюз) для таких записей показывает адрес выходного интерфейса.&lt;br /&gt;
&lt;br /&gt;
Столбец refcnt показывает текущее количество активных использований для маршрута. Протоколы, ориентированные на соединение, обычно используют в ходе соединения один маршрут, тогда как протоколы без соединения получают маршрут для каждой посылки одному и тому же адресату.&lt;br /&gt;
&lt;br /&gt;
Столбец use показывает количество пакетов, посланных по маршруту.&lt;br /&gt;
&lt;br /&gt;
Столбец interface показывает сетевой интерфейс, используемый маршрутом.&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -rn&amp;lt;/source&amp;gt;&lt;br /&gt;
 Routing tables&lt;br /&gt;
 Internet:&lt;br /&gt;
 Destination        Gateway            Flags    Refs      Use  Netif Expire&lt;br /&gt;
 default            10.26.95.253      UGS         0  2983649    rl0&lt;br /&gt;
 10.26.95.0/24      link#3             UC          0        0    vr0&lt;br /&gt;
 10.26.95.253/32    link#3             UC          0        0    vr0&lt;br /&gt;
 127.0.0.1          127.0.0.1          UH          0     8602    lo0&lt;br /&gt;
&lt;br /&gt;
'''Показать все активные TCP (-t)соединения с интернетом:'''&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -tap&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -nlp | grep snmpd&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -anp --tcp | grep -v 1720&amp;lt;/source&amp;gt;&lt;br /&gt;
'''Суммарная статистика передачи данных'''&lt;br /&gt;
&lt;br /&gt;
Когда задан аргумент интервал, netstat показывает таблицу суммарной статистической информации о переданных пакетах, ошибках и коллизиях. Первая показываемая строка данных, а также каждая последующая 24-я строка содержит суммарную статистическую информацию с момента последней перезагрузки системы. Каждая последующая строка показывает данные, накопленные за очередной указанный в командной строке интервал с момента последнего показа.&lt;br /&gt;
&lt;br /&gt;
'''Показать все активные соединения по протоколу TCP и UDP:'''&lt;br /&gt;
 &amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -ntu&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Непрерывно отслеживаем соединения:'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -cat&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Список прослушиваемых портов:'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -anltp | grep &amp;quot;LISTEN&amp;quot;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Показать статистику UDP или TCP:'''&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;#netstat -su&amp;lt;/source&amp;gt;&lt;br /&gt;
 IcmpMsg:&lt;br /&gt;
 InType3: 9040&lt;br /&gt;
 InType5: 27&lt;br /&gt;
 InType8: 1&lt;br /&gt;
 InType11: 407&lt;br /&gt;
 OutType0: 1&lt;br /&gt;
 OutType3: 1244&lt;br /&gt;
 Udp:&lt;br /&gt;
 пакетов принято: 75849&lt;br /&gt;
 принято пакетов на неизвестный порт: 1183&lt;br /&gt;
 ошибок приема пакетов: 0&lt;br /&gt;
 пакетов послано: 144780&lt;br /&gt;
 UdpLite:&lt;br /&gt;
 IpExt:&lt;br /&gt;
 InMcastPkts: 1390&lt;br /&gt;
 OutMcastPkts: 185&lt;br /&gt;
 InBcastPkts: 17666&lt;br /&gt;
 OutBcastPkts: 1473&lt;br /&gt;
 InOctets: 92565327&lt;br /&gt;
 OutOctets: 855223704&lt;br /&gt;
 InMcastOctets: 129017&lt;br /&gt;
 OutMcastOctets: 23069&lt;br /&gt;
 InBcastOctets: 1609681&lt;br /&gt;
 OutBcastOctets: 202516&lt;br /&gt;
&lt;br /&gt;
== Предупреждения ==&lt;br /&gt;
Таблицы ядра могут изменяться по ходу их обработки программой netstat, что приводит к некорректным или неполным результатам.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Ping</id>
		<title>Ping</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Ping"/>
				<updated>2017-04-10T11:20:59Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''Ping''' — утилита для проверки целостности и качества соединений в сетях на основе TCP/IP, а…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Ping''' — утилита для проверки целостности и качества соединений в сетях на основе TCP/IP, а также обиходное наименование самого запроса.&lt;br /&gt;
&lt;br /&gt;
Первоначально словом «ping» (по созвучию) именовали направленный акустический сигнал противолодочных гидролокаторов или «асдиков» (от англ. ASDIC, аббревиатура от Allied Submarine Detection Investigation Committee) времён Второй мировой войны.&lt;br /&gt;
&lt;br /&gt;
Утилита отправляет запросы (ICMP Echo-Request) протокола ICMP указанному узлу сети и фиксирует поступающие ответы (ICMP Echo-Reply). Время между отправкой запроса и получением ответа (RTT, от англ. Round Trip Time) позволяет определять двусторонние задержки (RTT) по маршруту и частоту потери пакетов, то есть косвенно определять загруженность на каналах передачи данных и промежуточных устройствах.&lt;br /&gt;
&lt;br /&gt;
'''Пример:''' &lt;br /&gt;
&lt;br /&gt;
Если осуществляется диагностика сети в запросах скорости соединения, в первую очередь происходит оценка эхо-запроса Ping, который определяет целостность и качество соединения на предмет запроса потери пакетов отражённого сигнала от источника соединения. В данном случае, если ответ запроса приходит с минимальным количеством пакетов, к примеру около 30 или менее, то в данном случае настройка сетевого оборудования нестабильна и имеет брешь в системе безопасности. Таким образом, стоит придать значение политике IP безопасности, Брандмауэру, групповой политике и настройкам сетевых адаптеров, настроек маршрутизатора. Не стоит путать Ping - '''определяющий целостность и качество связи''', с транспортными протоколами связи TCP  и UDP - '''определяющих передачу и  скорость передачи данных!''' &lt;br /&gt;
&lt;br /&gt;
Обычный эхо-запрос имеет длину 64 байта (плюс 20 байт IP-заголовка). По стандарту RFC 791 IPv4 суммарный объём пакета не может превышать 65 535 байт.&lt;br /&gt;
&lt;br /&gt;
В разговорной речи пингом называют также время, затраченное на передачу пакета игровой информации в компьютерных сетях от клиента к серверу и обратно от сервера к клиенту.&lt;br /&gt;
&lt;br /&gt;
Полное отсутствие ICMP-ответов может также означать, что удалённый узел (или какой-либо из промежуточных маршрутизаторов) блокирует ICMP Echo-Reply или игнорирует ICMP Echo-Request.&lt;br /&gt;
&lt;br /&gt;
Программа ping является одним из основных диагностических средств в сетях TCP/IP и входит в поставку всех современных сетевых операционных систем. Функциональность ping также реализована в некоторых встроенных ОС маршрутизаторов, доступ к результатам выполнения ping для таких устройств по протоколу SNMP определяется RFC 2925 (Definitions of Managed Objects for Remote Ping, Traceroute, and Lookup Operations).&lt;br /&gt;
&lt;br /&gt;
Так как для отправки ICMP-пакетов требуется создавать RAW-сокеты, для выполнения программы ping в UNIX-системах необходимы права суперпользователя(root). Чтобы обычные пользователи могли использовать ping, в правах доступа файла /bin/ping устанавливают SUID-бит.&lt;br /&gt;
&lt;br /&gt;
== Этимология ==&lt;br /&gt;
Название происходит от английского названия звука импульса, издаваемого сонаром.&lt;br /&gt;
&lt;br /&gt;
Также есть несколько альтернативных толкований:&lt;br /&gt;
* PING — акроним «'''P'''acket '''I'''nter'''N'''et '''G'''rouper (Groper)».&lt;br /&gt;
* Ping — часть названия игры пинг-понг. Это толкование подразумевает, что компьютеры обмениваются сигналами аналогично тому, как игроки в пинг-понг отбивают друг другу мяч.&lt;br /&gt;
* Pong — иногда так называют ответ (ICMP Echo-Reply), полученный благодаря удачно выполненной команде ping.&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
Программа была написана Майком Мууссом, учёным Исследовательской Лаборатории Баллистики (Ballistics Research Lab) США в декабре 1983 года.&lt;br /&gt;
&lt;br /&gt;
== Практическое использование ==&lt;br /&gt;
* Можно узнать IP-адрес по доменному имени.&lt;br /&gt;
* Можно узнать, работает ли сервер. Например, системный администратор может узнать, завис ли только веб-сервер или проблемы с хостом.&lt;br /&gt;
* Можно узнать, есть ли связь с сервером. Например, проблемы с настройкой DNS серверов на машине можно узнать, задав в ping сначала доменное имя, а потом IP-адрес.&lt;br /&gt;
* Также можно узнать качество канала, посмотрев, сколько ответов не пришло. Это часто используется игроками в сетевых играх, потому что качество связи для них очень важно. Хотя не всегда это является показателем качества связи, в некоторых сетях протокол ICMP может иметь низкий приоритет либо блокироваться полностью.&lt;br /&gt;
&lt;br /&gt;
== Структура ICMP пакета ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;margin: 0 auto; text-align: center;border:1&amp;quot;&lt;br /&gt;
|+ IP Datagram&lt;br /&gt;
|-----&lt;br /&gt;
!  &lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;100&amp;quot; | Bit 0 — 7&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;100&amp;quot; | Bit 8 — 15&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;100&amp;quot; | Bit 16 — 23&lt;br /&gt;
! scope=&amp;quot;col&amp;quot; width=&amp;quot;100&amp;quot; | Bit 24 — 31&lt;br /&gt;
|----- bgcolor=&amp;quot;#e0e0ff&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;5&amp;quot; | IP Header&amp;lt;br /&amp;gt;(20 bytes)&lt;br /&gt;
| Version/IHL&lt;br /&gt;
| Type of service&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; | Length&lt;br /&gt;
|----- bgcolor=&amp;quot;#e8e8ff&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; | Identification&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; |''flags'' and ''offset''&lt;br /&gt;
|----- bgcolor=&amp;quot;#e8e8ff&amp;quot;&lt;br /&gt;
| Time To Live (TTL)&lt;br /&gt;
| Protocol&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; | Checksum&lt;br /&gt;
|----- bgcolor=&amp;quot;#e8e8ff&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;4&amp;quot; | Source IP address&lt;br /&gt;
|----- bgcolor=&amp;quot;#e8e8ff&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;4&amp;quot; | Destination IP address&lt;br /&gt;
|----- bgcolor=&amp;quot;#ffe8e8&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | ICMP Header&amp;lt;br /&amp;gt;(8 bytes)&lt;br /&gt;
| Type of message&lt;br /&gt;
| Code&lt;br /&gt;
| colspan=&amp;quot;2&amp;quot; | Checksum&lt;br /&gt;
|----- bgcolor=&amp;quot;#ffe8e8&amp;quot;&lt;br /&gt;
| colspan=&amp;quot;4&amp;quot; | Header Data&lt;br /&gt;
|----- bgcolor=&amp;quot;#ffe8e8&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;1&amp;quot; | ICMP Payload&amp;lt;br /&amp;gt;(''optional'')&lt;br /&gt;
| colspan=&amp;quot;4&amp;quot; | Payload Data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Общее содержание ICMP пакета&lt;br /&gt;
&lt;br /&gt;
* IP Header (синим цветом):&lt;br /&gt;
** ''Protocol'' устанавливается значение — 1 (ICMP) и ''Type of Service'' — 0&lt;br /&gt;
* ICMP Header (красным цветом):&lt;br /&gt;
** Type of ICMP message (8 бит) — тип сообщения ICMP&lt;br /&gt;
** Code (8 бит)&lt;br /&gt;
** Checksum (16 бит) — контрольная сумма, вычисляется из части ICMP пакета, заголовок не используется.&lt;br /&gt;
** Header Data (32 бита) — содержит Идентификатор(Identifier) (16 бит) и Порядковый номер(Sequence number) (16 бит) необходимые для корректного определения отправителя.&lt;br /&gt;
* ICMP Payload&lt;br /&gt;
** Payload — необходим для хранения и передачи ответов различного типа. К примеру TimeStamp.&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
&lt;br /&gt;
=== UNIX-подобные системы ===&lt;br /&gt;
&lt;br /&gt;
Послать 3 пакета с интервалом в 5 секунд, сопровождая получение откликов звуковыми сигналами&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ ping -ai 5 -c 3 wikipedia.org&amp;lt;/source&amp;gt; &lt;br /&gt;
 PING wikipedia.org (208.80.152.2) 56(84) bytes of data.&lt;br /&gt;
 64 bytes from rr.pmtpa.wikimedia.org (208.80.152.2): icmp_seq=1 ttl=46 time=176 ms&lt;br /&gt;
 64 bytes from rr.pmtpa.wikimedia.org (208.80.152.2): icmp_seq=2 ttl=46 time=177 ms&lt;br /&gt;
 64 bytes from rr.pmtpa.wikimedia.org (208.80.152.2): icmp_seq=3 ttl=46 time=181 ms&lt;br /&gt;
 &lt;br /&gt;
 --- wikipedia.org ping statistics ---&lt;br /&gt;
 3 packets transmitted, 3 received, 0% packet loss, time 10007ms&lt;br /&gt;
 rtt min/avg/max/mdev = 176.253/178.291/181.339/2.222 ms&lt;br /&gt;
 &lt;br /&gt;
Не расшифровывать имена адресов, выводить только ip-адреса&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ ping -n wikipedia.org&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
По истечении времени (в данном случае 5 сек) ping завершит свою работу&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ ping -w 5 wikipedia.org&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Установить размер отправляемых пакетов в 1000 байт (Debian)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt; $ ping -s 1000 wikipedia.org&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Установить размер отправляемых пакетов в 1000 байт (Solaris)&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ ping -s wikipedia.org 1000&amp;lt;/source&amp;gt; &lt;br /&gt;
&lt;br /&gt;
=== Windows ===&lt;br /&gt;
 &lt;br /&gt;
Ping в командной строке Windows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;dos&amp;quot;&amp;gt;  ping ru.wikipedia.org&amp;lt;/source&amp;gt; &lt;br /&gt;
 &lt;br /&gt;
 Обмен пакетами с rr.esams.wikimedia.org [91.198.174.225] по 32 байт:&lt;br /&gt;
 &lt;br /&gt;
 Ответ от 91.198.174.225: число байт=32 время=54мс TTL=32&lt;br /&gt;
 Ответ от 91.198.174.225: число байт=32 время=54мс TTL=32&lt;br /&gt;
 Ответ от 91.198.174.225: число байт=32 время=54мс TTL=32&lt;br /&gt;
 Ответ от 91.198.174.225: число байт=32 время=54мс TTL=32&lt;br /&gt;
 &lt;br /&gt;
 Статистика Ping для 91.198.174.225:&lt;br /&gt;
 Пакетов: отправлено = 4, получено = 4, потеряно = 0 (0% потерь),&lt;br /&gt;
 Приблизительное время приёма-передачи в мс:&lt;br /&gt;
 Минимальное = 54 мсек, Максимальное = 54 мсек, Среднее = 54 мсек&lt;br /&gt;
&lt;br /&gt;
'''ping''' с ключами командной строки Windows:&lt;br /&gt;
&lt;br /&gt;
-w &amp;lt;тайм-аут&amp;gt; Тайм-аут для каждого ответа (в миллисекундах), в данном случае ждать ответ 1 мс.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 С:\Users\&amp;gt;ping ya.ru '''-w''' 1&lt;br /&gt;
 Обмен пакетами с ya.ru [93.158.134.3] с 32 байтами данных:&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=60&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=58&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=58&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=58&lt;br /&gt;
 Статистика Ping для 93.158.134.3:&lt;br /&gt;
 Пакетов: отправлено = 4, получено = 4, потеряно = 0  (0% потерь)&lt;br /&gt;
 Приблизительное время приёма-передачи в мс:&lt;br /&gt;
 Минимальное = 1мсек, Максимальное = 1 мсек, Среднее = 1 мсек&lt;br /&gt;
&lt;br /&gt;
Проверка связи с указанным узлом до прекращения. Для отображения статистики и продолжения проверки нажмите сочетание клавиш CTRL+BREAK; для прекращения нажмите CTRL+C.&lt;br /&gt;
&lt;br /&gt;
 C:\Users\&amp;gt;ping ya.ru '''-t'''&lt;br /&gt;
 Обмен пакетами с ya.ru [93.158.134.3] с 32 байтами данных:&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=60&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=58&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=58&lt;br /&gt;
 [вырезано]&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=60&lt;br /&gt;
 Ответ от 93.158.134.3: число байт=32 время=1мс TTL=58&lt;br /&gt;
 Статистика Ping для 93.158.134.3:&lt;br /&gt;
 Пакетов: отправлено = 125, получено = 125, потеряно = 0 (0% потерь)&lt;br /&gt;
 Приблизительное время приёма-передачи в мс:&lt;br /&gt;
 Минимальное = 1мсек, Максимальное = 1 мсек, Среднее = 1 мсек&lt;br /&gt;
&lt;br /&gt;
Дополнительные ключи и синтаксис:&lt;br /&gt;
    ping [-t] [-a] [-n &amp;lt;число&amp;gt;] [-l &amp;lt;размер&amp;gt;] [-f] [-i &amp;lt;TTL&amp;gt;] [-v &amp;lt;TOS&amp;gt;]&lt;br /&gt;
         [-r &amp;lt;число&amp;gt;] [-s &amp;lt;число&amp;gt;] [[-j &amp;lt;список узлов&amp;gt;] | [-k &amp;lt;список узлов&amp;gt;]]&lt;br /&gt;
         [-w &amp;lt;тайм-аут&amp;gt;] [-R] [-S &amp;lt;адрес источника&amp;gt;] [-4] [-6] конечный_узел&lt;br /&gt;
&lt;br /&gt;
Параметры&lt;br /&gt;
    -t                    Проверка связи с указанным узлом до прекращения.&lt;br /&gt;
                          Для отображения статистики и продолжения проверки&lt;br /&gt;
                          нажмите сочетание клавиш CTRL+BREAK;&lt;br /&gt;
                          для прекращения нажмите CTRL+C.&lt;br /&gt;
    -a                    Определение имен узлов по адресам.&lt;br /&gt;
    -n &amp;lt;число&amp;gt;            Число отправляемых запросов эха.&lt;br /&gt;
    -l &amp;lt;размер&amp;gt;           Размер буфера отправки.&lt;br /&gt;
    -f                    Установка в пакете флага, запрещающего&lt;br /&gt;
                          фрагментацию (только IPv4).&lt;br /&gt;
    -i &amp;lt;TTL&amp;gt;              Задание срока жизни пакетов.&lt;br /&gt;
    -v &amp;lt;TOS&amp;gt;              Задание типа службы (только IPv4. Этот параметр&lt;br /&gt;
                          недоступен и не влияет на поле TOS в заголовке IP).&lt;br /&gt;
    -r &amp;lt;число&amp;gt;            Запись маршрута для указанного числа прыжков&lt;br /&gt;
                          (только IPv4).&lt;br /&gt;
    -s &amp;lt;число&amp;gt;            Отметка времени для указанного числа прыжков&lt;br /&gt;
                          (только IPv4).&lt;br /&gt;
    -j &amp;lt;список_узлов&amp;gt;     Свободный выбор маршрута по списку узлов&lt;br /&gt;
                          (только IPv4).&lt;br /&gt;
    -k &amp;lt;список_узлов&amp;gt;     Жесткий выбор маршрута по списку узлов&lt;br /&gt;
                          (только IPv4).&lt;br /&gt;
    -w &amp;lt;тайм-аут&amp;gt;         Тайм-аут для каждого ответа (в миллисекундах).&lt;br /&gt;
    -R                    Использование заголовка для проверки также и&lt;br /&gt;
                          обратного маршрута (только IPv6).&lt;br /&gt;
    -S &amp;lt;адрес источника&amp;gt;  Используемый адрес источника.&lt;br /&gt;
    -4                    Принудительное использование протокола IPv4.&lt;br /&gt;
    -6                    Принудительное использование протокола IPv6.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Scp_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2</id>
		<title>Scp — Команда безопасного сетевого копирования файлов</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Scp_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%B1%D0%B5%D0%B7%D0%BE%D0%BF%D0%B0%D1%81%D0%BD%D0%BE%D0%B3%D0%BE_%D1%81%D0%B5%D1%82%D0%B5%D0%B2%D0%BE%D0%B3%D0%BE_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2"/>
				<updated>2017-04-10T07:08:57Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''SCP''' (от англ. '''S'''ecure '''c'''o'''p'''y}}) — протокол особого  RCP копирования файлов, использующий…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''SCP''' (от англ. '''S'''ecure '''c'''o'''p'''y}}) — протокол особого  RCP копирования файлов, использующий в качестве транспорта не RSH, а SSH.&lt;br /&gt;
&lt;br /&gt;
В UNIX-подобных операционных системах существует одноимённая (&amp;lt;tt&amp;gt;scp&amp;lt;/tt&amp;gt;) утилита удалённого копирования файлов &lt;br /&gt;
(входит в состав ''openssh'').&lt;br /&gt;
&lt;br /&gt;
Команда копирования локального SourceFile на удалённый хост:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp ''SourceFile'' ''user''@''host'':''/''directory''/''TargetFile''&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Команда копирования SourceFile с удалённого хоста:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp ''user''@''host'':''/''directory''/''SourceFile'' ''TargetFile''&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Если ssh работает на другом порту, то тогда указывается:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp -P port user@host:/directory/SourceFile /directory/TargetFile&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Копирование SourceFolder с удалённого хоста внутрь локального TargetFolder (на локальном хосте получится, что SourceFolder будет находиться внутри TargetFolder):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;scp -r ''user''@''host'':''/''directory''/''SourceFolder'' ''TargetFolder''&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Ssh</id>
		<title>Ssh</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Ssh"/>
				<updated>2017-04-10T07:03:12Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''SSH''' (от англ. '''S'''ecure '''Sh'''ell)- «безопасная оболочка» )— Сетевой протокол прикладного уровня, позволяющий производить удалённое управление операционной системой и туннелирование TCP-соединений (например, для передачи файлов). Схож по функциональности с протоколами Telnet и rlogin, но, в отличие от них, шифрует весь сетевой трафик, включая и передаваемые пароли. SSH допускает выбор различных алгоритмов шифрования. SSH-клиенты и SSH-серверы доступны для большинства сетевых операционных систем.&lt;br /&gt;
&lt;br /&gt;
SSH позволяет безопасно передавать в незащищённой среде практически любой другой сетевой протокол. Таким образом, можно не только удалённо работать на компьютере через командную оболочку, но и передавать по шифрованному каналу звуковой поток или видео (например, с веб-камеры).Для этого используется ''Port Forwarding'' соединения TCP. Также SSH может использовать cжатие передаваемых данных для последующего их шифрования, что удобно, например, для удалённого запуска клиентов X Window System.&lt;br /&gt;
&lt;br /&gt;
Большинство хостинг-провайдеров за определённую плату предоставляют клиентам доступ к их домашнему каталогу по SSH. Это может быть удобно как для работы в командной строке, так и для удалённого запуска программ (в том числе графических приложений).&lt;br /&gt;
&lt;br /&gt;
== Техническая информация о протоколе ==&lt;br /&gt;
SSH — это протокол прикладного уровня. SSH-сервер обычно прослушивает соединения на TCP-порту 22. Спецификация протокола SSH-2 содержится в RFC 4251. Для аутентификации сервера в SSH используется протокол аутентификации сторон на основе алгоритмов электронно-цифровой подписи RSA или DSA, но допускается также аутентификация при помощи пароля (режим обратной совместимости с Telnet) и даже ip-адреса хоста (режим обратной совместимости с rlogin).&lt;br /&gt;
&lt;br /&gt;
#Аутентификация по паролю наиболее распространена. При каждом подключении подобно https вырабатывается общий секретный ключ для шифрования трафика.&lt;br /&gt;
#При аутентификации по ключевой паре предварительно генерируется пара открытого и закрытого ключей для определённого пользователя. На машине с которой требуется произвести подключение хранится закрытый ключ, а на удалённой машине - открытый. Эти файлы не передаются при аутентификации, система лишь проверяет, что владелец открытого ключа также владеет и закрытым. При данном подходе, как правило, настраивается автоматический вход от имени конкретного пользователя в ОС.&lt;br /&gt;
#Аутентификация по ip-адресу небезопасна, эту возможность чаще всего отключают.&lt;br /&gt;
&lt;br /&gt;
Для создания общего секрета (сеансового ключа) используется алгоритм Диффи — Хеллмана(DH). Для шифрования передаваемых данных используется симметричное шифрование, алгоритмы Advanced Encryption Standard(AES), Blowfish или 3DES. Целостность передачи данных проверяется с помощью CRC32 в SSH1 или HMAC-SHA1/HMAC-MD5 в SSH2.&lt;br /&gt;
&lt;br /&gt;
Для сжатия шифруемых данных может использоваться алгоритм LempelZiv(LZ77), который обеспечивает такой же уровень сжатия, что и архиватор ZIP. Сжатие SSH включается лишь по запросу клиента, и на практике используется редко.&lt;br /&gt;
&lt;br /&gt;
== Стандарты и программные реализации ==&lt;br /&gt;
Первая версия протокола, SSH-1, была разработана в 1995 году исследователем Тату Улёненом из Технологического университета Хельсинки(Финляндия). SSH-1 был написан для обеспечения большей конфиденциальности, чем протоколы rlogin, telnet и rsh. В 1996 году была разработана более безопасная версия протокола, SSH-2, несовместимая с SSH-1. Протокол приобрел ещё большую популярность, и к 2000 году у него было около двух миллионов пользователей. В настоящее время под термином «SSH» обычно подразумевается именно SSH-2, т.к. первая версия протокола ввиду существенных недостатков сейчас практически не применяется.&lt;br /&gt;
&lt;br /&gt;
В 2006 году протокол был утвержден рабочей группой IETF в качестве Интернет‐стандарта.&lt;br /&gt;
&lt;br /&gt;
Однако в некоторых странах(Франция, Россия, Ирак и Пакистан) требуется специальное разрешение в соответствующих структурах для использования определённых методов шифрования, включая SSH.&lt;br /&gt;
Распространены две реализации SSH: частная коммерческая и бесплатная свободная. Свободная реализация называется OpenSSH. К 2006 году 80 % компьютеров сети Интернет использовало именно OpenSSH. Частная реализация разрабатывается организацией SSH Communications Security, которая является стопроцентным подразделением корпорации Tectia, она бесплатна для некоммерческого использования. Эти реализации содержат практически одинаковый набор команд.&lt;br /&gt;
&lt;br /&gt;
Протокол SSH-1, в отличие от протокола telnet, устойчив к атакам прослушивания трафика («Анализатор трафика(снифинг)»), но неустойчив к атакам «человек посередине(MITM)». Протокол SSH-2 также устойчив к атакам путём присоединения посередине (от англ. session hijacking), так как невозможно включиться в уже установленную сессию или перехватить её.&lt;br /&gt;
&lt;br /&gt;
Для предотвращения атак «человек посередине» при подключении к хосту, ключ которого ещё не известен клиенту, клиентское ПО показывает пользователю «слепок ключа» (от англ. key fingerprint). Рекомендуется тщательно сверять показываемый клиентским ПО «слепок ключа» со слепком ключа сервера, желательно полученным по надёжным каналам связи или лично.&lt;br /&gt;
&lt;br /&gt;
Поддержка SSH реализована во всех UNIX‑подобных системах, и на большинстве из них в числе стандартных утилит присутствуют клиент и сервер ssh. Существует множество реализаций SSH-клиентов и для не-UNIX ОС. Большую популярность протокол получил после широкого развития анализаторов трафика и способов нарушения работы локальных сетей, как альтернативное небезопасному протоколу Telnet решение для управления важными узлами.&lt;br /&gt;
&lt;br /&gt;
Для работы по SSH нужен SSH-сервер и SSH-клиент. Сервер прослушивает соединения от клиентских машин и при установлении связи производит аутентификацию, после чего начинает обслуживание клиента. Клиент используется для входа на удалённую машину и выполнения команд.&lt;br /&gt;
&lt;br /&gt;
Для соединения сервер и клиент должны создать пары ключей — открытых и закрытых — и обменяться открытыми ключами.&lt;br /&gt;
Обычно используется также и пароль.&lt;br /&gt;
&lt;br /&gt;
=== SSH-серверы ===&lt;br /&gt;
* *'''BSD''': ''OpenSSH''&lt;br /&gt;
* '''Linux''': ''dropbear'', ''lsh-server'', ''openssh-server'', ''ssh'', Tectia SSH Server&lt;br /&gt;
* '''Windows''': ''freeSSHd'', ''copssh'', ''WinSSHD'', ''KpyM Telnet/SSH Server'', ''MobaSSH'', ''OpenSSH через Cygwin, Tectia SSH Server&lt;br /&gt;
&lt;br /&gt;
=== SSH-клиенты и оболочки ===&lt;br /&gt;
* '''GNU/Linux, *BSD''': kdessh, lsh-client, openssh-client, putty, ssh, Vinagre, Tectia SSH (SSH Communications Security) Client&lt;br /&gt;
* '''MS Windows и Windows NT''': ''PuTTY''\''KiTTY'', ''SecureCRT'', ''ShellGuard'', ''Axessh'', ''ZOC'', ''SSHWindows'', ''ProSSHD'', ''XShell'', ''Tectia SSH (SSH Communications Security) Client''&lt;br /&gt;
* '''MS Windows Mobile''': ''PocketPuTTy'', ''mToken'', ''sshCE'', ''PocketTTY'', ''OpenSSH'', ''PocketConsole'', ''Tectia SSH (SSH Communications Security) Client''&lt;br /&gt;
* '''Mac OS''': ''NiftyTelnet SSH''&lt;br /&gt;
* '''Symbian OS''': ''PuTTY''&lt;br /&gt;
* '''Java''': ''MindTerm'', ''AppGate Security Server''&lt;br /&gt;
* '''J2ME''': ''MidpSSH''&lt;br /&gt;
* '''iPhone''': ''i-SSH'', ''ssh (в комплекте с Terminal)''&lt;br /&gt;
* '''Android''': ''connectBot'', ''Admin Hands'', ''Server Auditor'', ''JuiceSSH''&lt;br /&gt;
* '''Blackberry''': ''BBSSH''&lt;br /&gt;
* '''MAEMO 5''': ''OpenSSH''&lt;br /&gt;
* '''MeeGo 1.2 Harmattan''': ''OpenSSH''&lt;br /&gt;
&lt;br /&gt;
== Советы по безопасности использования SSH ==&lt;br /&gt;
# Запрещение удалённого ''root''-доступа.&lt;br /&gt;
# Запрещение подключения с пустым паролем или отключение входа по паролю.&lt;br /&gt;
# Выбор нестандартного порта для SSH-сервера.&lt;br /&gt;
# Использование длинных ''SSH2 RSA''-ключей (2048 бит и более). Системы шифрования на основе ''RSA'' считаются  надёжными, если длина ключа не менее 1024 бит.&lt;br /&gt;
# Ограничение списка IP-адресов, с которых разрешён доступ (например, настройкой файервола).&lt;br /&gt;
# Запрещение доступа с некоторых потенциально опасных адресов.&lt;br /&gt;
# Отказ от использования распространённых или широко известных системных логинов для доступа по ''SSH''.&lt;br /&gt;
# Регулярный просмотр сообщений об ошибках аутентификации.&lt;br /&gt;
# Установка систем обнаружения вторжений ''(IDS)''.&lt;br /&gt;
# Использование ловушек, подделывающих SSH-сервис ''(honeypot)''.&lt;br /&gt;
# Реализация технологии Port knocking&lt;br /&gt;
&lt;br /&gt;
== Примеры использования SSH ==&lt;br /&gt;
Команда подключения к локальному SSH-серверу из командной строки GNU/Linux или FreeBSD для пользователя pacify (сервер прослушивает нестандартный порт 30000):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ssh -p 30000 pacify@127.0.0.1&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Генерация пары ключей (в UNIX-подобных ОС) осуществляется командой&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ssh-keygen&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Генерация пары SSH-2 RSA-ключей длиной 4096 бита программой puttygen под UNIX‐подобными ОС:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$puttygen -t rsa -b 4096 -o sample&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Некоторые клиенты, например, PuTTY, имеют и графический интерфейс пользователя.&lt;br /&gt;
&lt;br /&gt;
Для использования SSH в Python существуют такие модули, как python-paramiko и python-twisted-conch.&lt;br /&gt;
&lt;br /&gt;
== SSH-туннелирование ==&lt;br /&gt;
SSH-туннель — это туннель, создаваемый посредством SSH-соединения и используемый для шифрования туннелированных данных. Используется для того, чтобы обезопасить передачу данных в Интернете (аналогичное назначение имеет IPsec). При пересылке через SSH-туннель незашифрованный трафик любого протокола шифруется на одном конце SSH-соединения и расшифровывается на другом.&lt;br /&gt;
&lt;br /&gt;
Практическая реализация может выполняться несколькими способами:&lt;br /&gt;
* Созданием Socks-прокси для приложений, которые не умеют работать через SSH-туннель, но могут работать через Socks-прокси&lt;br /&gt;
* Использованием приложений, умеющих работать через SSH-туннель.&lt;br /&gt;
* Созданием VPN-туннеля, подходит практически для любых приложений.&lt;br /&gt;
* Если приложение работает с одним определённым сервером, можно настроить SSH-клиент таким образом, чтобы он пропускал через SSH-туннель TCP-соединения, приходящие на определённый TCP-порт машины, на которой запущен SSH-клиент. Например, клиенты Jabber подключаются по умолчанию на порт 443. Тогда, чтобы настроить подключение к серверу Jabber через SSH-туннель, SSH-клиент настраивается на перенаправление подключений с любого порта локальной машины (например, с порта 4430) на удалённый сервер (например, jabber.example.com и порт 443):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;$ ssh -L 4430:jabber.example.com:443 somehost&amp;lt;/source&amp;gt;В данном случае Jabber-клиент настраивается на подключение к порту 4430 сервера localhost (если ssh-клиент запущен на той же машине что и Jabber-клиент).&lt;br /&gt;
Для создания ssh-туннеля необходима машина с запущенным ssh-сервером и доступом к jabber.example.com. Такая конфигурация может использоваться в случае, если с локальной машины доступ к jabber.example.com закрыт файерволом, но есть доступ к некоторому ssh-серверу, у которого ограничения доступа в Интернет отсутствуют.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Find</id>
		<title>Find</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Find"/>
				<updated>2017-04-10T06:34:42Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «&amp;lt;code&amp;gt;'''find'''&amp;lt;/code&amp;gt; — утилита поиска файлов по имени и другим свойствам, используемая в UNIX‐под…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;code&amp;gt;'''find'''&amp;lt;/code&amp;gt; — утилита поиска файлов по имени и другим свойствам, используемая в UNIX‐подобных операционных системах. Может производить поиск в одном или нескольких каталогах с использованием критериев, заданных пользователем. По умолчанию, &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; возвращает все файлы в рабочей директории. Более того, &amp;lt;code&amp;gt;find&amp;lt;/code&amp;gt; позволяет применять пользователю определённые действия ко всем найденным файлам. Также поддерживаются регулярные выражения. Для поиска файлов по содержимому следует пользоваться утилитой grep.&lt;br /&gt;
&lt;br /&gt;
== Список ключей ==&lt;br /&gt;
* &amp;lt;code&amp;gt;-name&amp;lt;/code&amp;gt; — искать по имени файла, при использовании подстановочных образцов параметр заключается в кавычки. Опция `-name' различает прописные и строчные буквы; чтобы использовать поиск без этих различий, воспользуйтесь опцией `-iname'.&lt;br /&gt;
* &amp;lt;code&amp;gt;-type&amp;lt;/code&amp;gt; — тип искомого: f=файл, d=каталог, l=ссылка (link), p=канал (pipe), s=сокет.&lt;br /&gt;
* &amp;lt;code&amp;gt;-user&amp;lt;/code&amp;gt; — владелец: имя пользователя или UID.&lt;br /&gt;
* &amp;lt;code&amp;gt;-group&amp;lt;/code&amp;gt; — владелец: группа пользователя или GID.&lt;br /&gt;
* &amp;lt;code&amp;gt;-perm&amp;lt;/code&amp;gt; — указываются права доступа.&lt;br /&gt;
* &amp;lt;code&amp;gt;-size&amp;lt;/code&amp;gt; — размер: указывается в 512-байтных блоках или байтах (признак байтов — символ «c» за числом).&lt;br /&gt;
* &amp;lt;code&amp;gt;-atime&amp;lt;/code&amp;gt; — время последнего обращения к файлу (в днях).&lt;br /&gt;
* &amp;lt;code&amp;gt;-amin&amp;lt;/code&amp;gt; — время последнего обращения к файлу (в минутах).&lt;br /&gt;
* &amp;lt;code&amp;gt;-ctime&amp;lt;/code&amp;gt; — время последнего изменения владельца или прав доступа к файлу (в днях).&lt;br /&gt;
* &amp;lt;code&amp;gt;-cmin&amp;lt;/code&amp;gt; — время последнего изменения владельца или прав доступа к файлу (в минутах).&lt;br /&gt;
* &amp;lt;code&amp;gt;-mtime&amp;lt;/code&amp;gt; — время последнего изменения файла (в днях).&lt;br /&gt;
* &amp;lt;code&amp;gt;-mmin&amp;lt;/code&amp;gt; — время последнего изменения файла (в минутах).&lt;br /&gt;
* &amp;lt;code&amp;gt;-newer другой_файл&amp;lt;/code&amp;gt; — искать файлы созданные позже, чем другой_файл.&lt;br /&gt;
* &amp;lt;code&amp;gt;-delete&amp;lt;/code&amp;gt; — удалять найденные файлы.&lt;br /&gt;
* &amp;lt;code&amp;gt;-ls&amp;lt;/code&amp;gt; — генерирует вывод как команда [[Ls_—_Команда_печати_содержимого_каталога|ls]] -dgils.&lt;br /&gt;
* &amp;lt;code&amp;gt;-print&amp;lt;/code&amp;gt; — показывает на экране найденные файлы.&lt;br /&gt;
* &amp;lt;code&amp;gt;-print0&amp;lt;/code&amp;gt; — выводит путь к текущему файлу на стандартный вывод, за которым следует символ ASCII NULL (код символа 0).&lt;br /&gt;
* &amp;lt;code&amp;gt;-exec command {} \;&amp;lt;/code&amp;gt; — выполняет над найденным файлом указанную команду; обратите внимание на синтаксис.&lt;br /&gt;
* &amp;lt;code&amp;gt;-ok&amp;lt;/code&amp;gt; — перед выполнением команды указанной в -exec, выдаёт запрос.&lt;br /&gt;
* &amp;lt;code&amp;gt;-depth&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;-d&amp;lt;/code&amp;gt; — начинать поиск с самых глубоких уровней вложенности, а не с корня каталога.&lt;br /&gt;
* &amp;lt;code&amp;gt;-maxdepth&amp;lt;/code&amp;gt; — максимальный уровень вложенности для поиска. «-maxdepth 0» ограничивает поиск текущим каталогом.&lt;br /&gt;
* &amp;lt;code&amp;gt;-prune&amp;lt;/code&amp;gt; — используется, когда вы хотите исключить из поиска определённые каталоги.&lt;br /&gt;
* &amp;lt;code&amp;gt;-mount&amp;lt;/code&amp;gt; или &amp;lt;code&amp;gt;-xdev&amp;lt;/code&amp;gt; — не переходить на другие файловые системы.&lt;br /&gt;
* &amp;lt;code&amp;gt;-regex&amp;lt;/code&amp;gt; —  искать по имени файла используя регулярные выражения.&lt;br /&gt;
* &amp;lt;code&amp;gt;-regextype тип&amp;lt;/code&amp;gt; — указание типа используемых регулярных выражений.&lt;br /&gt;
* &amp;lt;code&amp;gt;-P&amp;lt;/code&amp;gt; — не разворачивать символьные ссылки (поведение по умолчанию).&lt;br /&gt;
* &amp;lt;code&amp;gt;-L&amp;lt;/code&amp;gt; — разворачивать символические ссылки.&lt;br /&gt;
* &amp;lt;code&amp;gt;-empty&amp;lt;/code&amp;gt; — только пустые каталоги.&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Поиск в текущей директории ===&lt;br /&gt;
Найти все файлы, начиная с текущей директории, название которых начинается на ''my''.&lt;br /&gt;
&amp;lt;pre&amp;gt;find . -name 'my*'&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Поиск в определенном каталоге ===&lt;br /&gt;
Найти все файлы, начиная с корневой директории, название которых начинается на ''my''.&lt;br /&gt;
&amp;lt;pre&amp;gt;find / -name 'my*'&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поиск в директориях /usr/local/man и /opt/local/man файлов, название которых начинается на ''my''.&lt;br /&gt;
&amp;lt;pre&amp;gt;find /usr/local/man /opt/local/man -name 'my*'&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Поиск по нескольким именам файлов ===&lt;br /&gt;
Найти все файлы, начиная с текущей директории, название которых начинается на ''my'' или ''qu''. Обратите внимание, что по умолчанию все аргументы соединены с помощью ''логического и'' (опция '-a'). Если необходимо объединить несколько аргументов ''логическим или'' — используйте опцию '-o'.&lt;br /&gt;
&amp;lt;pre&amp;gt;find . \( -name &amp;quot;my*&amp;quot; -o -name &amp;quot;qu*&amp;quot; \) -print&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Поиск нескольких типов файлов, используя регулярные выражения ===&lt;br /&gt;
Найти все графические файлы, начиная с текущей директории,  используя регулярные выражения. &lt;br /&gt;
&amp;lt;pre&amp;gt;find . -type f -regex &amp;quot;.*\.\(jpg\|jpeg\|gif\|png\|JPG\|JPEG\|GIF\|PNG\)&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Выполнение команды ===&lt;br /&gt;
Опция ''-exec'' выполняет следующую за ней команду и подставляет вместо ''{}'' текущий файл.&lt;br /&gt;
Найти все каталоги ниже указанного каталога и изменить им права доступа:&lt;br /&gt;
&amp;lt;pre&amp;gt;find /path -type d -exec chmod 0755 {} \;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Опция -exec работает примерно в 10 раз медленнее, чем перенаправление вывода через xargs, поэтому данный код рекомендуется писать следующим образом:&lt;br /&gt;
&amp;lt;pre&amp;gt;find /path -type d | xargs chmod 0755&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Однако, директории с именами, содержащими пробелы, методом перенаправления через xargs обработаны не будут, поэтому следует использовать первый вариант, дополненный:&lt;br /&gt;
&amp;lt;pre&amp;gt;find /path -type d -exec chmod 0755 &amp;quot;{}&amp;quot; \;&amp;lt;/pre&amp;gt;&lt;br /&gt;
Или (что лучше) вот так (опция -- -0 позволяет обрабатывать аргументы, содержащие пробелы и кавычки, т.к. использует NULL (&amp;quot;\0&amp;quot;) вместо символов-разделителей &amp;quot;пробел&amp;quot; и &amp;quot;перевод строки&amp;quot;):&lt;br /&gt;
&amp;lt;pre&amp;gt;find /path -type d -print0 | xargs -0 chmod 0755&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Поиск  всех файлов php.ini от текущего каталога и  замена текста в каждом  найденном файле.&lt;br /&gt;
 find . -name 'php.ini' -exec sed -i 's/log_errors = Off/log_errors = On/g' &amp;quot;{}&amp;quot; \;&lt;br /&gt;
Сложный поиск в нескольких видах файлов  и замен текста в каждом из них, от текущего каталога и ниже.&lt;br /&gt;
 find . -regex &amp;quot;.*\.\(php\|js\|css\)&amp;quot; -exec sed -i 's/\/bitrix\/templates\//\/local\/templates\//g' &amp;quot;{}&amp;quot; \;&lt;br /&gt;
&lt;br /&gt;
=== Поиск в зависимости от времени создания ===&lt;br /&gt;
Вывести список файлов во всей файловой системе, изменённых в течение последней минуты:&lt;br /&gt;
&amp;lt;pre&amp;gt;find / -mmin -1 -print&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Вывести список файлов во всей файловой системе, которые были изменены более 31 дня назад:&lt;br /&gt;
&amp;lt;pre&amp;gt;find / -mtime +31 -print&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Поиск по размеру файла ===&lt;br /&gt;
Вывести список файлов во всей файловой системе, чей размер больше 100 Мб:&lt;br /&gt;
&amp;lt;pre&amp;gt;find / -size +100M -print&amp;lt;/pre&amp;gt;&lt;br /&gt;
=== Поиск файлов принадлежащих определенному пользователю ===&lt;br /&gt;
&amp;lt;pre&amp;gt;find . -user &amp;lt;userid&amp;gt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Поиск файлов c ограничением глубины ===&lt;br /&gt;
При поиске в текущем каталоге, глубина поиска указывается от корневого каталога, а не от текущего.&lt;br /&gt;
 find . -maxdepth 4 -name 'restore.php'&lt;br /&gt;
&lt;br /&gt;
=== Поиск файлов с перечислением каталогов. ===&lt;br /&gt;
Ищет файлы в указанных каталогах.&lt;br /&gt;
 find /var/spool/postfix/{deferred,active,maildrop,incoming}/ -type f&lt;br /&gt;
&lt;br /&gt;
=== Рекурсивное удаление  файла от текущего каталога, на заданную глубину. ===&lt;br /&gt;
Удаляет все файлы restore.php от текущего каталога, но не глубже 4 уровня вложенности относительно корневого каталога /  &lt;br /&gt;
&lt;br /&gt;
Начинает поиск в папке /var/www, но не глубже /var/www/*/*/  и удаляет все файлы restore.php в найденном. &lt;br /&gt;
 find /var/www -maxdepth 4 -name 'restore.php' -exec rm -r {} \;&lt;br /&gt;
&lt;br /&gt;
=== Игнорирование ошибок ===&lt;br /&gt;
Если при поиске возникает ошибка (например — нет доступа чтения из каталога) то вывод команды становится менее информативным. Перенаправьте вывод STDERR в /dev/null.&lt;br /&gt;
&amp;lt;pre&amp;gt;find / -name 'secret.keys' -print 2&amp;gt;/dev/null&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
&lt;br /&gt;
=== Поиск в текущей директории ===&lt;br /&gt;
&lt;br /&gt;
=== Поиск файлов ===&lt;br /&gt;
 find . -name &amp;quot;my*&amp;quot; -type f&lt;br /&gt;
Эта команда отличается от предыдущей тем, что поиск будет производиться только для регулярных файлов, то есть в результатах поиска не будет директорий, специальных файлов, символических ссылок и т. д.&lt;br /&gt;
&lt;br /&gt;
=== Поиск всех файлов для владельца user ===&lt;br /&gt;
&lt;br /&gt;
 find . -user &amp;lt;userid&amp;gt;&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Grep</id>
		<title>Grep</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Grep"/>
				<updated>2017-04-06T10:34:32Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «== Введение ==  Команда grep, одна из самых известных и употребительных команд Юниксовидных…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Введение ==&lt;br /&gt;
&lt;br /&gt;
Команда grep, одна из самых известных и употребительных команд Юниксовидных ОС, ведет свое начало от первого текстового редактора Юникс - ed. В этом редакторе была команда g/re/p (global/regular expression/print), которая и дала свое название новой программе.&lt;br /&gt;
&lt;br /&gt;
Команда grep служит для поиска строк, содержащих заданный пользователем образец.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;grep ОБРАЗЕЦ имя_файла&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Причем обязательным для ввода является только ОБРАЗЕЦ, можно обойтись даже без имени файла (аргумента).&lt;br /&gt;
&lt;br /&gt;
== Команда grep без опций и аргумента. ==&lt;br /&gt;
&lt;br /&gt;
Если не указано имени файла, то команда обрабатывает стандартный ввод, например строки, набранные на клавиатуре:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
  grep кот&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
  у меня есть кошка,(Enter)&lt;br /&gt;
  вернее это кот,(Enter)&lt;br /&gt;
  вернее это кот,&lt;br /&gt;
  который умеет(Enter)&lt;br /&gt;
  который умеет&lt;br /&gt;
  ловить мышей.(Enter)&lt;br /&gt;
  (Ctrl+c)&lt;br /&gt;
&lt;br /&gt;
В скобках показано, когда я нажимал клавишу Enter, чтобы перейти на новую строку. Одновременно, при нажатии Enter, программа выводила строки, содержащие ОБРАЗЕЦ (кот), отсюда и удвоение этих строк. Видно, что команда реагировала просто на сочетание букв, а не на слово &amp;quot;кот&amp;quot;, иначе строка со словом &amp;quot;который&amp;quot; не попала бы в вывод.&lt;br /&gt;
&lt;br /&gt;
Тут мы подошли к очень важному определению строки.&lt;br /&gt;
Строкой команда grep (как и все остальные команды Юникс) считает все символы, находящиеся между двумя символами новой строки. Эти невидимые на экране символы возникают в тексте каждый раз, когда пользователь нажимает клавишу Enter. В Юниксовидных системах символ новой строки обозначается обратным слэшем с буквой n (\n). Таким образом, строка может быть любого размера, начиная с одного символа и до многомегабайтного текста. И команда grep честно выведет эту строку, при условии, что она содержит ОБРАЗЕЦ.&lt;br /&gt;
&lt;br /&gt;
== Работа с файлами ==&lt;br /&gt;
&lt;br /&gt;
Команда grep может обрабатывать любое количество файлов одновременно. Создадим три файла:&lt;br /&gt;
&lt;br /&gt;
  123.txt:     alice.txt:              ast.txt:&lt;br /&gt;
  1234         Алиса очень             Символ астериска &lt;br /&gt;
  5678         красивая девочка,       обозначается (*)&lt;br /&gt;
  89*0         у нее такая ******      звездочкой.&lt;br /&gt;
               длинная коса!&lt;br /&gt;
&lt;br /&gt;
И дадим команду:&lt;br /&gt;
&lt;br /&gt;
  grep '*' 123.txt ast.txt alice.txt&lt;br /&gt;
  &lt;br /&gt;
  123.txt:89*0&lt;br /&gt;
  ast.txt:обозначается (*).&lt;br /&gt;
  alice.txt:у нее такая ******&lt;br /&gt;
&lt;br /&gt;
В выводе перечислены файлы, и указано, в каком из них какая строка содержит символ астериска. ОБРАЗЕЦ (*) пришлось взять в кавычки, чтобы командный интерпретатор понял, что имеется в виду символ, а не условный знак. Попробуйте без кавычек, увидите - ничего не получится.&lt;br /&gt;
&lt;br /&gt;
Команда grep вовсе не ограничена одним выражением в качестве ОБРАЗЦА, можно задавать хоть целые фразы. Только их нужно заключать в кавычки (одинарные или двойные):&lt;br /&gt;
&lt;br /&gt;
  grep 'ная ко' 123.txt ast.txt alice.txt&lt;br /&gt;
  alice.txt:длинная коса!&lt;br /&gt;
&lt;br /&gt;
Возможности поиска при помощи команды grep могут быть значительно расширены применением групповых символов. Например, уже упоминавшийся астериск (звездочка) используется для представления любого символа или группы символов, если речь идет о тексте, и любого файла или группы файлов, если речь идет о директории.&lt;br /&gt;
&lt;br /&gt;
Создадим директорию /example, в которую поместим файлы наших примеров: 123.txt, ast.txt, alice.txt и дадим команду:&lt;br /&gt;
&lt;br /&gt;
  grep '*' example/*&lt;br /&gt;
  example/123.txt:89*0&lt;br /&gt;
  example/alice.txt:у нее такая ******&lt;br /&gt;
  example/ast.txt:обозначается (*)&lt;br /&gt;
&lt;br /&gt;
То есть мы приказали просмотреть все файлы директории /example. Таким способом можно обследовать такие огромные директории как /usr, /dev, и любые другие.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Параметры grep ==&lt;br /&gt;
&lt;br /&gt;
=== Опция -r ===&lt;br /&gt;
&lt;br /&gt;
--recursive&lt;br /&gt;
&lt;br /&gt;
Еще больше увеличит зону поисков опция -r, которая заставит команду grep рекурсивно обследовать все дерево указанной директории, то есть субдиректории, субдиректории субдиректорий, и так далее вплоть до файлов. Например:&lt;br /&gt;
&lt;br /&gt;
  grep -r menu /boot&lt;br /&gt;
  &lt;br /&gt;
  /boot/grub/grub.txt:Highlight the menu entry you want to edit and press 'e', then&lt;br /&gt;
/boot/grub/grub.txt:Press the [Esc] key to return to the GRUB menu.&lt;br /&gt;
/boot/grub/menu.lst:# GRUB configuration file '/boot/grub/menu.lst'.&lt;br /&gt;
/boot/grub/menu.lst:gfxmenu (hd0,3)/boot/message&lt;br /&gt;
&lt;br /&gt;
=== Опция -i ===&lt;br /&gt;
&lt;br /&gt;
--ignore-case&lt;br /&gt;
&lt;br /&gt;
Приказывает команде игнорировать регистр символов, таким образом, поиск будет производиться как среди заглавных, так и среди строчных букв.&lt;br /&gt;
&lt;br /&gt;
=== Опция -c ===&lt;br /&gt;
&lt;br /&gt;
--count&lt;br /&gt;
&lt;br /&gt;
Эта опция не выводит строки, а подсчитывает количество строк, в которых обнаружен ОБРАЗЕЦ. Например:&lt;br /&gt;
&lt;br /&gt;
  grep -c root /etc/group&lt;br /&gt;
  8&lt;br /&gt;
&lt;br /&gt;
То есть в восьми строках файла /etc/group встречается сочетание символов root.&lt;br /&gt;
&lt;br /&gt;
=== Опция -n ===&lt;br /&gt;
&lt;br /&gt;
--line-number&lt;br /&gt;
&lt;br /&gt;
При использовании этой опции вывод команды grep будет указывать номера строк, содержащих ОБРАЗЕЦ:&lt;br /&gt;
&lt;br /&gt;
  grep -n print /etc/printcap&lt;br /&gt;
  1:# /etc/printcap&lt;br /&gt;
  3:# See &amp;quot;man printcap&amp;quot; for information on editing this file.&lt;br /&gt;
  5:# In most cases it is better to use a tool to write the printcap&lt;br /&gt;
  9:# cupsd print daemon at this URL: http://localhost:631&lt;br /&gt;
&lt;br /&gt;
=== Опция -v ===&lt;br /&gt;
&lt;br /&gt;
--invert-match&lt;br /&gt;
&lt;br /&gt;
Выполняет работу, обратную обычной - выводит строки, в которых ОБРАЗЕЦ не встречается:&lt;br /&gt;
&lt;br /&gt;
  grep -v print /etc/printcap&lt;br /&gt;
  #&lt;br /&gt;
  #&lt;br /&gt;
  # for you (at least initially), such as apsfilter&lt;br /&gt;
  # (/usr/share/apsfilter/SETUP, used in conjunction with the&lt;br /&gt;
  # LPRng lpd daemon), or with the web interface provided by the&lt;br /&gt;
  # (if you use CUPS).&lt;br /&gt;
&lt;br /&gt;
=== Опция -w ===&lt;br /&gt;
&lt;br /&gt;
--word-regexp&lt;br /&gt;
&lt;br /&gt;
Заставит команду grep искать только строки, содержащие все слово или фразу, составляющую ОБРАЗЕЦ. Например:&lt;br /&gt;
&lt;br /&gt;
  grep -w &amp;quot;длинная ко&amp;quot; example/*&lt;br /&gt;
&lt;br /&gt;
Не дает вывода, то есть не находит строк, содержащих выражение &amp;quot;длинная ко&amp;quot;. А вот команда:&lt;br /&gt;
&lt;br /&gt;
  grep -w &amp;quot;длинная коса&amp;quot; example/*&lt;br /&gt;
  &lt;br /&gt;
  example/alice.txt:длинная коса!&lt;br /&gt;
&lt;br /&gt;
находит точное соответствие в файле alice.txt.&lt;br /&gt;
&lt;br /&gt;
=== Опция -x ===&lt;br /&gt;
&lt;br /&gt;
--line-regexp&lt;br /&gt;
&lt;br /&gt;
Еще более строгая. Она отберет только те строки исследуемого файла или файлов, которые полностью совпадают с ОБРАЗЦОМ.&lt;br /&gt;
&lt;br /&gt;
  grep -x &amp;quot;1234&amp;quot; example/*&lt;br /&gt;
  &lt;br /&gt;
  example/123.txt:1234&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''''Внимание:''''' Мне попадались (на собственном компьютере) версии grep (например, GNU 2.5), в которых опция -x работала неадекватно. В то же время, другие версии (GNU 2.5.1) работали прекрасно. Если что-то не ладится с этой опцией, попробуйте другую версию, или обновите свою.&lt;br /&gt;
&lt;br /&gt;
=== Опция -l ===&lt;br /&gt;
&lt;br /&gt;
--files-with-matches&lt;br /&gt;
&lt;br /&gt;
Команда grep с этой опцией не возвращает строки, содержащие ОБРАЗЕЦ, но сообщает лишь имена файлов, в которых данный образец найден:&lt;br /&gt;
&lt;br /&gt;
  grep -l 'Алиса' example/*&lt;br /&gt;
  &lt;br /&gt;
  example/alice.txt&lt;br /&gt;
&lt;br /&gt;
Замечу, что сканирование каждого из заданных файлов продолжается только до первого совпадения с ОБРАЗЦОМ.&lt;br /&gt;
&lt;br /&gt;
=== Опция -L ===&lt;br /&gt;
&lt;br /&gt;
--files-without-match&lt;br /&gt;
&lt;br /&gt;
Наоборот, сообщает имена тех файлов, где не встретился ОБРАЗЕЦ:&lt;br /&gt;
&lt;br /&gt;
  grep -L 'Алиса' example/*&lt;br /&gt;
  &lt;br /&gt;
  example/123.txt&lt;br /&gt;
  example/ast.txt&lt;br /&gt;
&lt;br /&gt;
Как мы имели случай заметить, команда grep, в поисках соответствия ОБРАЗЦУ, просматривает только содержимое файлов, но не их имена. А так часто нужно найти файл по его имени или другим параметрам, например времени модификации! Тут нам придет на помощь простейший программный канал (pipe). При помощи знака программного канала - вертикальной черты (|) мы можем направить вывод команды ls, то есть список файлов в текущей директории, на ввод команды grep, не забыв указать, что мы, собственно, ищем (ОБРАЗЕЦ). Например:&lt;br /&gt;
&lt;br /&gt;
  ls | grep grep&lt;br /&gt;
  &lt;br /&gt;
  grep/&lt;br /&gt;
  grep-ru.txt&lt;br /&gt;
&lt;br /&gt;
Находясь в директории Desktop, мы &amp;quot;попросили&amp;quot; найти на Рабочем столе все файлы, в названии которых есть выражение &amp;quot;grep&amp;quot;. И нашли одну директорию grep/ и текстовой файл grep-ru.txt, который я в данный момент и пишу.&lt;br /&gt;
&lt;br /&gt;
Если мы хотим искать по другим параметрам файла, а не по его имени, то следует применить команду ls -l, которая выводит файлы со всеми параметрами:&lt;br /&gt;
&lt;br /&gt;
  ls -l | grep 2008-12-30&lt;br /&gt;
  -rw-r--r-- 1 ya users 27 2008-12-30 08:06 123.txt&lt;br /&gt;
  drwxr-xr-x 2 ya users 4096 2008-12-30 08:49 example/&lt;br /&gt;
  -rw-r--r-- 1 ya users 11931 2008-12-30 14:59 grep-ru.txt&lt;br /&gt;
&lt;br /&gt;
И вот мы получили список всех файлов, модифицированных 30 декабря 2008 года.&lt;br /&gt;
&lt;br /&gt;
Команда grep незаменима при просмотре логов и конфигурационных файлов. Классически примером использования команды grep стал программный канал с командой dmesg. Команда dmesg выводит те самые сообщения ядра, которые мы не успеваем прочесть во время загрузки компьютера. Допустим, мы подключили через USB порт новый принтер, и теперь хотим узнать, как ядро &amp;quot;окрестило&amp;quot; его. Дадим такую команду:&lt;br /&gt;
&lt;br /&gt;
  dmesg | grep -i usb&lt;br /&gt;
&lt;br /&gt;
Опция -i необходима, так как usb часто пишется заглавными буквами. Проделайте этот пример самостоятельно - у него длинный вывод, который не укладывается в рамки данной статьи.&lt;br /&gt;
&lt;br /&gt;
== Немного хитростей ==&lt;br /&gt;
&lt;br /&gt;
Если продолжить описание множества опций команды grep, то статья станет утомительной и нечитаемой. Поэтому, рассмотрев необходимый минимум опций, можно развлечься всякими хитростями при применении этой замечательной команды.&lt;br /&gt;
&lt;br /&gt;
=== Хитрость первая ===&lt;br /&gt;
&lt;br /&gt;
Как заставить grep указать в выводе имя файла, где найдено соответствие ОБРАЗЦУ? Например, мы хотим найти строку, содержащую выражение &amp;quot;красивая девочка&amp;quot; в файле alice.txt, да так, чтобы в выводе фигурировало имя файла (для отчета). Если просто дать команду:&lt;br /&gt;
&lt;br /&gt;
  grep -w 'красивая девочка' alice.txt&lt;br /&gt;
  красивая девочка,&lt;br /&gt;
&lt;br /&gt;
То никакого имени файла там не будет. Но стоит добавить в аргументы еще один файл, как все заработает. Обычно, чтобы избежать неожиданностей, указывают файл /dev/null:&lt;br /&gt;
&lt;br /&gt;
  grep -w 'красивая девочка' alice.txt /dev/null&lt;br /&gt;
  alice.txt:красивая девочка,&lt;br /&gt;
&lt;br /&gt;
=== Хитрость вторая ===&lt;br /&gt;
&lt;br /&gt;
Используя &amp;quot;чистые&amp;quot; опции команды grep, мы можем получить все строки, содержащие ОБРАЗЕЦ либо в составе других слов (без опций), либо в виде заданного слова (опция -w). А как найти слова, которые заканчиваются на -ОБРАЗЕЦ или начинаются с ОБРАЗЕЦ-? Для этого существуют специальные значки: \&amp;lt; означает, что ОБРАЗЕЦ будет началом слова, и \&amp;gt;, означающий, что ОБРАЗЕЦ будет концом слова.&lt;br /&gt;
&lt;br /&gt;
  grep 'kot' kot.txt&lt;br /&gt;
  kot&lt;br /&gt;
  kotoroe&lt;br /&gt;
  antrekot&lt;br /&gt;
  kotovasiya&lt;br /&gt;
  okot&lt;br /&gt;
  skotobaza&lt;br /&gt;
  nekotoroe&lt;br /&gt;
&lt;br /&gt;
Это был файл kot.txt целиком.&lt;br /&gt;
&lt;br /&gt;
  grep 'kot\&amp;gt;' kot.txt&lt;br /&gt;
  kot&lt;br /&gt;
  antrekot&lt;br /&gt;
  okot&lt;br /&gt;
&lt;br /&gt;
А это были слова, оканчивающиеся на -kot.&lt;br /&gt;
&lt;br /&gt;
  grep '\&amp;lt;kot' kot.txt&lt;br /&gt;
  kot&lt;br /&gt;
  kotoroe&lt;br /&gt;
  kotovasiya&lt;br /&gt;
&lt;br /&gt;
Эти начинаются на kot-.&lt;br /&gt;
&lt;br /&gt;
  grep '\&amp;lt;kot\&amp;gt;' kot.txt&lt;br /&gt;
  kot&lt;br /&gt;
&lt;br /&gt;
А вот был &amp;quot;чистый&amp;quot; кот.&lt;br /&gt;
&lt;br /&gt;
Прошу простить за транслитерацию, но с нашими буквами эта хитрость как-то не срабатывает, а с английскими словами не все поймут.&lt;br /&gt;
&lt;br /&gt;
=== Хитрость третья ===&lt;br /&gt;
&lt;br /&gt;
Как быть, если ОБРАЗЕЦ начинается с дефиса, ведь команда примет его за опцию?&lt;br /&gt;
&lt;br /&gt;
Попробуем:&lt;br /&gt;
&lt;br /&gt;
  grep  '--анонимность' anonim.txt&lt;br /&gt;
  grep: unrecognized option `--анонимность'&lt;br /&gt;
&lt;br /&gt;
Так и есть - принимает за опцию. Ну так дадим ей опцию -e, которая означает: &amp;quot;Воспринимать ОБРАЗЕЦ только как образец&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
  grep -e '--анонимность' anonim.txt&lt;br /&gt;
  --анонимность&lt;br /&gt;
&lt;br /&gt;
Совсем другое дело.&lt;br /&gt;
&lt;br /&gt;
=== Хитрость четвертая ===&lt;br /&gt;
&lt;br /&gt;
Как посмотреть соседние строчки?&lt;br /&gt;
&lt;br /&gt;
  grep -C 2 -e  '--анонимность' anonim.txt&lt;br /&gt;
&lt;br /&gt;
Требуется соблюсти следующие условия:&lt;br /&gt;
  --анонимность&lt;br /&gt;
  --секретность&lt;br /&gt;
  --неразглашение.&lt;br /&gt;
&lt;br /&gt;
Просмотр вверх и вниз на две строки.&lt;br /&gt;
&lt;br /&gt;
 grep -A 1 -e  '--анонимность' anonim.txt&lt;br /&gt;
  --анонимность&lt;br /&gt;
  --секретность&lt;br /&gt;
&lt;br /&gt;
Просмотр вниз на одну строку.&lt;br /&gt;
&lt;br /&gt;
  grep -B 1 -e  '--анонимность' anonim.txt&lt;br /&gt;
&lt;br /&gt;
Требуется соблюсти следующие условия:&lt;br /&gt;
  --анонимность&lt;br /&gt;
&lt;br /&gt;
Просмотр вверх на одну строку.&lt;br /&gt;
&lt;br /&gt;
=== Хитрость пятая ===&lt;br /&gt;
&lt;br /&gt;
  grep -r menu /boot&lt;br /&gt;
  &lt;br /&gt;
  Бинарный файл /boot/grub/stage2 совпадает&lt;br /&gt;
  Бинарный файл /boot/grub/stage2_eltorito совпадает&lt;br /&gt;
  /boot/grub/grub.txt:Highlight the menu entry you want to edit and press 'e', then&lt;br /&gt;
  /boot/grub/grub.txt:Press the [Esc] key to return to the GRUB menu.&lt;br /&gt;
  /boot/grub/menu.lst:# GRUB configuration file '/boot/grub/menu.lst'.&lt;br /&gt;
  /boot/grub/menu.lst:gfxmenu (hd0,3)/boot/message&lt;br /&gt;
&lt;br /&gt;
Что означают сообщения в первых двух строках вывода?&lt;br /&gt;
&lt;br /&gt;
Сообщение &amp;quot;Бинарный файл совпадает&amp;quot; (&amp;quot;Binary file matches&amp;quot;) появляется, когда совпадение с образцом встречается в бинарных файлах. Если бы grep вывел строки из таких файлов на дисплей, толку было бы немного, а на дисплее могла возникнуть неразбериха (а может быть, и чего похуже, если драйвер терминала воспримет какие-либо фрагменты бинарного файла как команды). Если вы хотите все-таки увидеть эти строки, то применяйте опцию -a или --binary-files=text. Если хотите подавить вывод сообщений &amp;quot;Бинарный файл совпадает&amp;quot;, то применяйте опцию -I или --binary-files=without-match.&lt;br /&gt;
&lt;br /&gt;
=== Хитрость шестая ===&lt;br /&gt;
&lt;br /&gt;
Как искать строки, содержащие несколько ОБРАЗЦОВ?&lt;br /&gt;
&lt;br /&gt;
Применить программный канал, канализируя вывод одной команды grep с вводом следующей команды grep.&lt;br /&gt;
&lt;br /&gt;
  grep 'у' example/* | grep '*'&lt;br /&gt;
  example/alice.txt:у нее такая ******&lt;br /&gt;
&lt;br /&gt;
Первый grep ищет у нас &amp;quot;у&amp;quot;, а второй - &amp;quot;*&amp;quot; и оба находят искомое в одной строке: &amp;quot;у нее такая ******&amp;quot;. Можно сделать эту цепочку команд grep любой длины, было бы чего искать, да строчки достаточно длинные :-)&lt;br /&gt;
&lt;br /&gt;
=== Хитрость седьмая ===&lt;br /&gt;
&lt;br /&gt;
Можно ли искать одновременно в стандартном вводе и в файле?. Можно, если перед именем файла поставить дефис:&lt;br /&gt;
&lt;br /&gt;
  echo многие употребляют астериск неправильно | grep 'астериск' - example/*&lt;br /&gt;
  (стандартный ввод):многие употребляют астериск неправильно&lt;br /&gt;
  example/ast.txt:Символ астериска&lt;br /&gt;
&lt;br /&gt;
'''''Внимание:''''' Если перед дефисом и после него не будет пробелов, то команда не сработает.&lt;br /&gt;
&lt;br /&gt;
Но настало время вернуться к опциям команды grep.&lt;br /&gt;
&lt;br /&gt;
Пока я занимался хитростями, успел позабыть, какие из опций уже описал, а какие нет. Поэтому я дал команду:&lt;br /&gt;
&lt;br /&gt;
  grep 'Опция' grep-ru.txt &amp;gt; option.txt&lt;br /&gt;
&lt;br /&gt;
и получил файл option.txt, в котором перечислены все фигурирующие в файле grep-ru.txt опции.&lt;br /&gt;
&lt;br /&gt;
Общее количество опций программы подавляет, поэтому пойдем по алфавиту, пропуская те, что я уже описал.&lt;br /&gt;
&lt;br /&gt;
  Опция -f имя_файла&lt;br /&gt;
  --file=имя_файла&lt;br /&gt;
&lt;br /&gt;
Весьма полезная опция, когда нужно искать несколько ОБРАЗЦОВ, причем не в одной строке, как мы делали в шестой Хитрости, а в разных. Для того чтобы воспользоваться этой опцией, нужно составить файл, в котором поместить искомые ОБРАЗЦЫ по одному на строчке:&lt;br /&gt;
&lt;br /&gt;
  pattern.txt:&lt;br /&gt;
  nobody&lt;br /&gt;
  root&lt;br /&gt;
  ya&lt;br /&gt;
&lt;br /&gt;
А затем дать команду:&lt;br /&gt;
&lt;br /&gt;
  grep -f pattern.txt /etc/passwd&lt;br /&gt;
  nobody:x:65534:65533:nobody:/var/lib/nobody:/bin/bash&lt;br /&gt;
  root:x:0:0:root:/root:/bin/bash&lt;br /&gt;
  ya:x:1000:100:alex dmitriev:/home/ya:/bin/bash&lt;br /&gt;
&lt;br /&gt;
'''''Предупреждение:''''' Эта полезная опция, к сожалению, работает не на всех версиях grep. На версии GNU grep 2.5 работает неадекватно, а на GNU grep 2.5.1 - прекрасно. Так что обновляйтесь, господа. Текущая стабильная версия GNU grep - 2.5.3.&lt;br /&gt;
&lt;br /&gt;
=== Опция -o ===&lt;br /&gt;
&lt;br /&gt;
--only-matching&lt;br /&gt;
&lt;br /&gt;
Возвращает не всю строку, где найдено соответствие ОБРАЗЦУ, а только совпадающую с ОБРАЗЦОМ часть строки.&lt;br /&gt;
&lt;br /&gt;
Без опции -o:&lt;br /&gt;
&lt;br /&gt;
$ grep 'английскими' grep-ru.txt&lt;br /&gt;
&lt;br /&gt;
Прошу простить за транслитерацию, но с нашими буквами как-то эта хитрость не срабатывает,&lt;br /&gt;
а с английскими словами не все поймут.&lt;br /&gt;
&lt;br /&gt;
А вот с опцией -o:&lt;br /&gt;
&lt;br /&gt;
  grep -o 'английскими' grep-ru.txt&lt;br /&gt;
  английскими&lt;br /&gt;
&lt;br /&gt;
=== Опция -q ===&lt;br /&gt;
&lt;br /&gt;
--quiet --silent&lt;br /&gt;
&lt;br /&gt;
Ничего не выдает на стандартный вывод. В случае нахождения соответствия с ОБРАЗЦОМ немедленно отключается с нулевым статусом. Отключается также при обнаружении ошибки. Для чего это - не знаю. У меня получалось, что программа мгновенно прекращает работу, есть ли совпадения, нет ли, без всяких сообщений, в том числе и о нулевом статусе. Опробовал обе доступные версии grep.&lt;br /&gt;
&lt;br /&gt;
=== Опция -s ===&lt;br /&gt;
&lt;br /&gt;
--no-messages&lt;br /&gt;
&lt;br /&gt;
Подавляет сообщения о несуществующих или нечитаемых файлах.&lt;br /&gt;
&lt;br /&gt;
Предупреждение: традиционные версии последних двух опции (-q и -s) не соответствуют стандарту POSIX.2 и не совпадают с GNU версиями. Поэтому их нельзя применять в скриптах для командной оболочки. Просто перенаправляйте вывод на /dev/null.&lt;br /&gt;
&lt;br /&gt;
== Опции - расширения GNU ==&lt;br /&gt;
&lt;br /&gt;
'''Опции'''&lt;br /&gt;
-A --after-context=ЧИСЛО_СТРОК&lt;br /&gt;
&lt;br /&gt;
-B --before-context=ЧИСЛО_СТРОК&lt;br /&gt;
&lt;br /&gt;
-C --context=ЧИСЛО_СТРОК&lt;br /&gt;
&lt;br /&gt;
С этими тремя опциями мы уже познакомились в четвертой Хитрости, они позволяют посмотреть соседние строки. -A: количество строк после совпадения с ОБРАЗЦОМ,&lt;br /&gt;
&lt;br /&gt;
-B: количество строк перед совпадением, и -C: количество строк вокруг совпадения.&lt;br /&gt;
&lt;br /&gt;
Опция --colour[=КОГДА]&lt;br /&gt;
&lt;br /&gt;
Выделяет найденные строки цветом. Значения КОГДА могут быть: never (никогда), always (всегда), или auto. Пример:&lt;br /&gt;
&lt;br /&gt;
  grep -o 'английскими' --color grep-ru.txt&lt;br /&gt;
  английскими&lt;br /&gt;
&lt;br /&gt;
=== Опция -D ДЕЙСТВИЕ ===&lt;br /&gt;
&lt;br /&gt;
--devices=ДЕЙСТВИЕ&lt;br /&gt;
&lt;br /&gt;
Если исследуемый файл является файлом устройства, FIFO (именованным каналом) или сокетом, то следует применять эту опцию. ДЕЙСТВИЙ всего два: read (прочесть), и skip (пропустить). Если вы указываете ДЕЙСТВИЕ read (используется по умолчанию), то программа попытается прочесть специальный файл, как если бы он был обычным файлом; если указываете ДЕЙСТВИЕ skip, то файлы устройств, FIFO и сокеты будут молча проигнорированы.&lt;br /&gt;
&lt;br /&gt;
=== Опция -d ДЕЙСТВИЕ ===&lt;br /&gt;
&lt;br /&gt;
--directories=ДЕЙСТВИЕ&lt;br /&gt;
&lt;br /&gt;
Если входной файл является директорией, то используйте эту опцию. ДЕЙСТВИЕ read (прочесть) попытается прочесть директорию как обычный файл (некоторые ОС и файловые системы запрещают это; тогда появятся соответствующие сообщения, либо директории молча пропустят). Если ДЕЙСТВИЕ skip (пропустить), то директории будут молча проигнорированы. Если ДЕЙСТВИЕ recurse (рекурсивно), то grep будет просматривать все файлы и субдиректории внутри заданного каталога рекурсивно. Это эквивалент опции -r, с которой мы уже познакомились.&lt;br /&gt;
&lt;br /&gt;
=== Опция -H ===&lt;br /&gt;
&lt;br /&gt;
--with-filename&lt;br /&gt;
&lt;br /&gt;
Выдает имя файла для каждого совпадения с ОБРАЗЦОМ. Мы успешно делали это без всяких опций в Хитрости второй.&lt;br /&gt;
&lt;br /&gt;
=== Опция -h ===&lt;br /&gt;
&lt;br /&gt;
--no-filename&lt;br /&gt;
&lt;br /&gt;
Подавляет вывод имен файлов, когда задано несколько файлов для исследования.&lt;br /&gt;
&lt;br /&gt;
=== Опция -I ===&lt;br /&gt;
&lt;br /&gt;
Обрабатывает бинарные файлы как не содержащие совпадений с ОБРАЗЦОМ; эквивалент опции --binary-files=without-match.&lt;br /&gt;
&lt;br /&gt;
=== Опция --include=ОБРАЗЕЦ_имени_файла ===&lt;br /&gt;
&lt;br /&gt;
При рекурсивном исследовании директорий обследовать только файлы, содержащие в своем имени ОБРАЗЕЦ_имени_файла.&lt;br /&gt;
&lt;br /&gt;
=== Опция --exclude=ОБРАЗЕЦ_имени_файла ===&lt;br /&gt;
&lt;br /&gt;
При рекурсивном исследовании директорий пропускать файлы, содержащие в своем имени ОБРАЗЕЦ_имени_файла.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Опция -m ЧИСЛО_СТРОК ===&lt;br /&gt;
&lt;br /&gt;
--max-count=ЧИСЛО_СТРОК&lt;br /&gt;
&lt;br /&gt;
Прекратить обработку файла после того, как количество совпадений с ОБРАЗЦОМ достигнет ЧИСЛА_СТРОК:&lt;br /&gt;
&lt;br /&gt;
  grep -m 2 'kot' kot.txt&lt;br /&gt;
  kot&lt;br /&gt;
  kotoroe&lt;br /&gt;
&lt;br /&gt;
=== Опция -y ===&lt;br /&gt;
&lt;br /&gt;
Синоним опции -i (не различать верхний и нижний регистр символов).&lt;br /&gt;
&lt;br /&gt;
Опции -U и -u применяются только под MS-DOS и MS-Windows, тут нечего о них говорить.&lt;br /&gt;
&lt;br /&gt;
=== Опция --mmap ===&lt;br /&gt;
&lt;br /&gt;
Использует системный вызов mmap вместо системного вызова read. Может дать лучшую производительность, а может привести к ошибкам. Это для продвинутых пользователей.&lt;br /&gt;
&lt;br /&gt;
=== Опция -Z ===&lt;br /&gt;
&lt;br /&gt;
--null&lt;br /&gt;
&lt;br /&gt;
Если в выводе программы имена файлов (например при опции -l), то опция -Z после каждого имени файла выводит нулевой байт вместо символа новой строки (как обычно происходит). Это делает вывод однозначным, даже если имена файлов содержат символы новой строки. Эта опция может быть использована совместно с такими командами как: find -print0, perl -0, sort -z, xargs -0 для обработки файловых имен, составленных необычно, даже содержащих символы новой строки.&lt;br /&gt;
(Хотел бы я знать, как можно включить символ новой строки в имя файла. Если кто знает, не поленитесь - сообщите мне.)&lt;br /&gt;
&lt;br /&gt;
=== Опция -z ===&lt;br /&gt;
&lt;br /&gt;
--null-data&lt;br /&gt;
&lt;br /&gt;
Рассматривает ввод как набор строк, каждая из которых заканчивается не символом новой строки, а нулевым байтом. Как и предыдущая опция, используется совместно с вышеперечисленными командами для обработки экзотических имен файлов.&lt;br /&gt;
&lt;br /&gt;
== Команда grep и регулярные выражения ==&lt;br /&gt;
&lt;br /&gt;
Регулярные выражения (Regular Expressions) это система синтаксического разбора текстовых фрагментов по формализованному шаблону, основанная на системе записи ОБРАЗЦОВ для поиска. Проще говоря, регулярное выражение - тот же, уже привычный нам ОБРАЗЕЦ для поиска, только составленный по определенным правилам. Как математические формулы составляются при помощи набора операторов (плюс, минус, степень, корень и прочее), так и регулярные выражения конструируются при помощи различных операторов (?, *, +, {n} и прочие).&lt;br /&gt;
&lt;br /&gt;
Тема регулярных выражений настолько обширна, что требует для своего освещения отдельной статьи; в данной статье мы не будем ее подробно разбирать. Скажу лишь, что существует несколько версий синтаксиса регулярных выражений: Базовый (basic) BRE, Расширенный (extended) ERE и регулярные выражения языка Perl.&lt;br /&gt;
&lt;br /&gt;
=== Опция -G ===&lt;br /&gt;
&lt;br /&gt;
--basic-regexp&lt;br /&gt;
&lt;br /&gt;
Рассматривает ОБРАЗЕЦ как базовое регулярное выражение. Эта опция используется по умолчанию.&lt;br /&gt;
&lt;br /&gt;
=== Опция -E ===&lt;br /&gt;
&lt;br /&gt;
--extended-regexp&lt;br /&gt;
&lt;br /&gt;
Рассматривает ОБРАЗЕЦ как расширенное регулярное выражение.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Опция -P ===&lt;br /&gt;
&lt;br /&gt;
--perl-regexp&lt;br /&gt;
&lt;br /&gt;
Рассматривает ОБРАЗЕЦ как регулярное выражение языка Perl.&lt;br /&gt;
&lt;br /&gt;
=== Опция -F ===&lt;br /&gt;
&lt;br /&gt;
--fixed-strings&lt;br /&gt;
&lt;br /&gt;
Рассматривает ОБРАЗЕЦ как список &amp;quot;фиксированных выражений&amp;quot; (fixed strings - термин из области регулярных выражений), разделенных символами новой строки. Будет искать соответствия любому из них.&lt;br /&gt;
&lt;br /&gt;
Кроме того, существуют две альтернативные команды EGREP и FGREP. Обе они соответствуют опциям -E и -F соответственно.&lt;br /&gt;
&lt;br /&gt;
Опции --help и --version (-V) общеизвестны, и я не буду на них останавливаться.&lt;br /&gt;
&lt;br /&gt;
== Команда grep и символы кириллицы. ==&lt;br /&gt;
&lt;br /&gt;
Читая эту статью, вы не могли не заметить, что большинство примеров составлено на русском языке. Я еще не встречал консольных команд, столь хорошо &amp;quot;владеющих русским&amp;quot;. Теперь, когда я разобрался с этой командой, то уже не понимаю, как мог обходиться без нее при написании статей (по-русски, разумеется). Лишь некоторые опции &amp;quot;дают прокол&amp;quot; при обработке символов кириллицы.&lt;br /&gt;
&lt;br /&gt;
== Резюме команды grep ==&lt;br /&gt;
&lt;br /&gt;
Команда grep настолько полезна, многофункциональна и проста в употреблении, что, однажды познакомившись с ней, невозможно представить себе работы без нее. Особенно полезна эта команда в качестве фильтра в составе программных каналов (pipes).&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Df</id>
		<title>Df</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Df"/>
				<updated>2017-04-06T07:26:15Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''df''' (аббревиатура от '''d'''isk '''f'''ree) — утилита в UNIX и UNIX-подобных системах, показывает спис…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''df''' (аббревиатура от '''d'''isk '''f'''ree) — утилита в UNIX и UNIX-подобных системах, показывает список всех файловых систем по именам устройств, сообщает их размер, занятое и свободное пространство и точки монтирования.&lt;br /&gt;
&lt;br /&gt;
Ключ '''-k''' используется для отображения размеров блоками по 1 килобайту, вместо установленных по умолчанию блоков в 512 байт&lt;br /&gt;
&lt;br /&gt;
    $ df -k&lt;br /&gt;
    Filesystem           1K-blocks      Used Available Use% Mounted on&lt;br /&gt;
    /dev/sda1              4166504   2449824   1505028  62% /&lt;br /&gt;
    /dev/sda2             30056044  14173604  14351852  50% /usr&lt;br /&gt;
    /dev/sda3             63988404   2690328  58047656   5% /var&lt;br /&gt;
    tmpfs                   524288        60    524228   1% /tmp&lt;br /&gt;
&lt;br /&gt;
Ключ '''-h''' или '''--human-readable''' отобразит размер в человеко-читабельном формате&lt;br /&gt;
&lt;br /&gt;
    $ df -h&lt;br /&gt;
    Filesystem            Size  Used Avail Use% Mounted on&lt;br /&gt;
    /dev/sda1             4.0G  2.4G  1.5G  62% /&lt;br /&gt;
    /dev/sda2              29G   14G   14G  50% /usr&lt;br /&gt;
    /dev/sda3              62G  2.6G   56G   5% /var&lt;br /&gt;
    tmpfs                 512M   60K  512M   1% /tmp&lt;br /&gt;
&lt;br /&gt;
Утилиту df можно использовать для получения информации о том, к какой файловой системе относится какой-либо каталог. Например, для текущего каталога:&lt;br /&gt;
&lt;br /&gt;
    $ df -k .&lt;br /&gt;
    Filesystem           1K-blocks      Used Available Use% Mounted on&lt;br /&gt;
    /dev/sda1              4166504   2449796   1505056  62% /&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Ln</id>
		<title>Ln</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Ln"/>
				<updated>2017-04-06T07:21:04Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''ln''' — команда UNIX, устанавливающая связь между файлом и именем файла.  Формат команды:  '''…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''ln''' — команда UNIX, устанавливающая связь между файлом и именем файла.&lt;br /&gt;
&lt;br /&gt;
Формат команды:&lt;br /&gt;
 '''ln''' файл имя_ссылки&lt;br /&gt;
 # создаётся «жёсткая» ссылка (hard link)&lt;br /&gt;
 '''ln''' -s файл имя_ссылки&lt;br /&gt;
 # создаётся «символьная» ссылка (symbolic link)&lt;br /&gt;
&lt;br /&gt;
Эта команда создаёт '''''жёсткую ссылку''''' на файл «файл1», которая будет выглядеть и располагаться как «файл2». Таким образом для файловой системы заданный файл «файл1» и ссылка на него «файл2», на самом деле физически будут являться одним и тем же файлом. Жесткие ссылки не могут указывать на файлы, расположенные на разных дисковых разделах. Также невозможно создать жёсткую ссылку на каталог.&lt;br /&gt;
&lt;br /&gt;
Если вы создаёте '''''символьную ссылку''''' (используя ключ «-s»), то при этом файла «файл1» может и не существовать. Символьная ссылка с именем «файл2» всё равно будет создана.Пример: &lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;quot;# ln -s /media/home/ed /home/ed&amp;quot;&amp;lt;/code&amp;gt; — будет создана символьная ссылка в каталоге &amp;quot;/home/ed&amp;quot; на каталог &amp;quot;/media/home/ed&amp;quot;&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Dd</id>
		<title>Dd</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Dd"/>
				<updated>2017-04-06T07:09:21Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''dd''' ('''d'''ataset '''d'''efinition) — программа UNIX, предназначенная как для копирования, так и для конвертации файлов. Название унаследовано от оператора DD ('''D'''ataset '''D'''efinition) из языка JCL.&lt;br /&gt;
&lt;br /&gt;
Поскольку в UNIX очень многие объекты (жёсткие/гибкие диски, COM/LPT-порты, оперативная память компьютера, память с кодом/данными каждого процесса) представлены в виде специальных файлов, спектр применения утилиты &amp;lt;tt&amp;gt;dd&amp;lt;/tt&amp;gt; гораздо шире, чем кажется на первый взгляд. Регулярно возникает необходимость не просто скопировать файл или несколько файлов (для чего предназначена утилита [[Cp_—_Команда_копирования_файлов_и/или_каталогов|cp]]), а скопировать первые ''n'' байт файла, пропустить ''m'' байт от начала, прочитать файл с дефектного носителя, транслировать содержимое файла в ASCII, «развернуть» порядок байтов в файле, просто скопировать очень большой файл или всё вместе взятое. Для этой цели и служит &amp;lt;tt&amp;gt;dd&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Кроме всего прочего, данная утилита позволяет скопировать регионы из файлов «сырых» устройств, например, сделать резервную копию загрузочного сектора жёсткого диска, или прочитать фиксированные блоки данных из специальных файлов, таких, как ''/dev/zero'' или ''/dev/random''.&lt;br /&gt;
&lt;br /&gt;
Название утилиты &amp;lt;tt&amp;gt;dd&amp;lt;/tt&amp;gt; иногда в шутку расшифровывают, как «disk destroyer», «data destroyer» или «delete data», так как утилита позволяет производить низкоуровневые операции на жёстких дисках — при малейшей ошибке (такой, как реверс параметров '''&amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;''' и '''&amp;lt;tt&amp;gt;of&amp;lt;/tt&amp;gt;''') можно потерять часть данных на диске (или даже все данные). Есть и более «уважительное» прозвище — «disk duplicator», потому что на практике основное её применение — это копии, образы и бэкапы разделов.&lt;br /&gt;
&lt;br /&gt;
== Некоторые параметры ==&lt;br /&gt;
При написании статьи были использованы материалы ''man dd'', описывающие версию ''dd'' от GNU. Версии ''dd'' на других операционных системах могут отличаться.&lt;br /&gt;
&lt;br /&gt;
=== Базовые параметры ===&lt;br /&gt;
dd  [--help] [--version] [status] [if=''файл''] [of=''файл''] [ibs=''байты''] [obs=''байты''] [bs=''байты''] [cbs=''байты''] [skip=''блоки''] [seek=''блоки''] [count=''блоки''] [conv={ascii, ebcdic, ibm, block, unblock, lcase, ucase, swab, noerror, notrunc, sync}]&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;tt&amp;gt;status=&amp;lt;/tt&amp;gt;progress — отображает статистику передачи, возможны 3 варианта 'none', 'noxfer', 'progress'                                                        GNU Coreutils 8.24+ (Ubuntu 16.04 and newer) .&lt;br /&gt;
* &amp;lt;tt&amp;gt;if=файл&amp;lt;/tt&amp;gt; — читает данные из файла вместо стандартного ввода.&lt;br /&gt;
* &amp;lt;tt&amp;gt;of=файл&amp;lt;/tt&amp;gt; — пишет данные в файл вместо стандартного вывода.&lt;br /&gt;
* &amp;lt;tt&amp;gt;bs=''n''&amp;lt;/tt&amp;gt; — размер блока.&lt;br /&gt;
* &amp;lt;tt&amp;gt;ibs=''nn''&amp;lt;/tt&amp;gt; и &amp;lt;tt&amp;gt;obs=''nn''&amp;lt;/tt&amp;gt; — задаёт, сколько байтов нужно считывать или записывать за раз.&lt;br /&gt;
* &amp;lt;tt&amp;gt;count=''n''&amp;lt;/tt&amp;gt; — сколько блоков скопировать.&lt;br /&gt;
* &amp;lt;tt&amp;gt;seek=''n''&amp;lt;/tt&amp;gt; — сколько блоков пропустить от начала в выходном файле перед копированием.&lt;br /&gt;
* &amp;lt;tt&amp;gt;skip=''n''&amp;lt;/tt&amp;gt; — сколько блоков пропустить от начала во входном файле перед копированием.&lt;br /&gt;
* &amp;lt;tt&amp;gt;conv=''фильтр'',''фильтр''&amp;lt;/tt&amp;gt; — применить фильтры конвертации. Типы фильтров:&lt;br /&gt;
** &amp;lt;tt&amp;gt;ascii&amp;lt;/tt&amp;gt; — сконвертировать в ASCII из EBCDIC…&lt;br /&gt;
** &amp;lt;tt&amp;gt;ebcdic&amp;lt;/tt&amp;gt; — …и наоборот.&lt;br /&gt;
** &amp;lt;tt&amp;gt;block&amp;lt;/tt&amp;gt; — выравнивание блоков.&lt;br /&gt;
** &amp;lt;tt&amp;gt;lcase&amp;lt;/tt&amp;gt; — преобразовать к нижнему регистру.&lt;br /&gt;
** &amp;lt;tt&amp;gt;ucase&amp;lt;/tt&amp;gt; — преобразовать к верхнему регистру.&lt;br /&gt;
** &amp;lt;tt&amp;gt;swab&amp;lt;/tt&amp;gt; — менять местами пары байт.&lt;br /&gt;
** &amp;lt;tt&amp;gt;noerror&amp;lt;/tt&amp;gt; — игнорировать ошибки ввода-вывода.&lt;br /&gt;
&lt;br /&gt;
== Примеры использования ==&lt;br /&gt;
&lt;br /&gt;
=== Работа с CD/DVD-дисками и образами ===&lt;br /&gt;
Создать образ CD/DVD, используя большой размер блока. Игнорировать ошибки:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/cdrom of=backup.iso bs=65536 conv=noerror&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Записать ISO-образ «image.iso» на устройство sdb вместе с его загрузочным сектором и форматированием раздела в файловую систему образа (как правило, ISO 9660 или UDF):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=image.iso of=/dev/sdb&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
=== Работа с файлами ===&lt;br /&gt;
&lt;br /&gt;
Скопировать файл foo в файл bar:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=foo of=bar&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Скопировать файл foo в файл bar, пропустив первые 10 КБ из файла foo:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=foo of=bar bs=1k skip=10&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Порезать 10-мегабайтный файл foo на 2 по 5 МБ:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=foo of=bar.0 bs=1M count=5&lt;br /&gt;
    dd if=foo of=bar.1 bs=1M skip=5&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Склеить четыре 100-мегабайтных файла в один:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=SMILE.001 of=SMILE  bs=1M seek=0&lt;br /&gt;
    dd if=SMILE.002 of=SMILE  bs=1M seek=100&lt;br /&gt;
    dd if=SMILE.003 of=SMILE  bs=1M seek=200&lt;br /&gt;
    dd if=SMILE.004 of=SMILE  bs=1M seek=300&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
а можно и так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=SMILE.001 &amp;gt; SMILE&lt;br /&gt;
    dd if=SMILE.002 &amp;gt;&amp;gt; SMILE&lt;br /&gt;
    dd if=SMILE.003 &amp;gt;&amp;gt; SMILE&lt;br /&gt;
    dd if=SMILE.004 &amp;gt;&amp;gt; SMILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
или же (для сбора файла из большого количества кусков):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    for i in {1..4}; do &lt;br /&gt;
        dd if=SMILE.00$i &amp;gt;&amp;gt; SMILE&lt;br /&gt;
    done&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примеры выше показывают возможности dd; на практике, обычно, используется [[cat]]:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    cat SMILE.00{1,2,3,4} &amp;gt;&amp;gt; SMILE&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Вывести на экран (в /dev/stdout) первые 256 байт файла foo:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=foo of=/dev/stdout bs=128 count=2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
или:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=foo bs=128 count=2&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Предыдущая команда годится только для просмотра текстового файла. Содержимое бинарного файла рекомендуется смотреть так:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=foo bs=1 count=10 2&amp;gt;/dev/null | hexdump&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Резервное копирование и удаление данных ===&lt;br /&gt;
&lt;br /&gt;
В большинстве случаев следует быть внимательным, чтобы файл назначения не оказался на том же самом диске, с которого снимается образ.&lt;br /&gt;
&lt;br /&gt;
Скопировать один раздел жёсткого диска на другой жёсткий диск, игнорируя ошибки ввода-вывода:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/sda1 of=/dev/sdb2 bs=4096 conv=noerror,sync&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Сделать копию главной загрузочной записи (MBR) первого жёсткого диска:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/hda of=bootloader.mbr bs=512 count=1&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Заполнить всё свободное место в текущем разделе нулями:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/zero of=zerofill&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Создать сжатый образ первого жёсткого диска со всеми разделами (рекомендуется сначала заполнить свободное место нулями для лучшего сжатия):&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/sda | xz -9 &amp;gt; MyFuBu.ISO.XZ&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Просмотреть содержимое главной загрузочной записи (MBR) первого жёсткого диска:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/sda bs=512 count=1 | hexdump -C&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Копировать всё, кроме метки, с диска на магнитную ленту:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    (dd bs=4k skip=1 count=0 &amp;amp;&amp;amp; dd bs=512k) &amp;lt;$disk &amp;gt;$tape&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Копировать всё, не перезаписывая метку, с магнитной ленты на диск:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    (dd bs=4k seek=1 count=0 &amp;amp;&amp;amp; dd bs=512k) &amp;lt;$tape &amp;gt;$disk&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
'''Уничтожить''' содержимое устройства &amp;lt;tt&amp;gt;/dev/sdg&amp;lt;/tt&amp;gt;, заполнив его «нулями» из &amp;lt;tt&amp;gt;/dev/zero&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=/dev/zero of=/dev/sdg bs=65536&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Узнать статус выполнения операции:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    killall -USR1 dd&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
В некоторых случаях статус выполнения просматривается командой:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    pkill -USR1 -x dd&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В последних версиях статус выполнения можно выводить в консоль, задав команду dd с параметром status=progress&lt;br /&gt;
&amp;lt;source lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
    dd if=image.iso of=/dev/sdb status=progress&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
== Варианты dd, ориентированные на восстановление ==&lt;br /&gt;
&lt;br /&gt;
Программы с открытым исходным кодом для восстановления включают [http://www.garloff.de/kurt/linux/ddrescue/ dd_rescue] и [http://www.kalysto.org/utilities/dd_rhelp/index.en.html dd_rhelp], которые работают вместе, [http://seed7.sourceforge.net/scrshots/savehd7.htm savehd7] и [http://www.gnu.org/software/ddrescue/ddrescue.html GNU ddrescue].&lt;br /&gt;
&lt;br /&gt;
Antonio Diaz Diaz (разработчик GNU ddrescue) сравнивает варианты dd для задач восстановления:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&lt;br /&gt;
Стандартная утилита '''dd''' осуществляет линейное чтение диска, и это может занять много времени или даже сжечь накопитель без восстановления чего-либо, если ошибки расположены в начале жесткого диска.&lt;br /&gt;
&lt;br /&gt;
'''dd_rescue''' делает то же самое, что и dd, только более эффективно.&lt;br /&gt;
&lt;br /&gt;
'''dd_rhelp''' — это сложный shell-скрипт, который запускает dd_rescue много раз, стараясь стратегически копировать накопитель, но это очень неэффективно.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* dd_rhelp сначала извлекает все доступные к чтению данные и сохраняет их в файл, вставляя нули вместо байтов, которые не смог прочесть. Потом утилита пытается повторно прочитать некорректные данные и обновить этот файл.&lt;br /&gt;
* GNU dd_rescue может быть использована для копирования данных прямо на новый диск по необходимости, как и dd.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Cat</id>
		<title>Cat</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Cat"/>
				<updated>2017-04-06T07:07:33Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''cat''' (от англ. '''c'''onc'''at'''enate) — утилита UNIX, выводящая последовательно указанные файлы (ил…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''cat''' (от англ. '''c'''onc'''at'''enate) — утилита UNIX, выводящая последовательно указанные файлы (или устройства), таким образом, объединяя их в единый поток.&lt;br /&gt;
Если вместо имени файла указывается «-», то читается стандартный ввод.&lt;br /&gt;
&lt;br /&gt;
  cat a.txt - b.txt &amp;gt; abc.txt&lt;br /&gt;
  cat /dev/null &amp;gt; file_to_clear.txt&lt;br /&gt;
&lt;br /&gt;
Иногда (в учебных примерах) используется в качестве первой ступени конвейера обработки текста утилитами '''sed''', '''awk''' и так далее, хотя в большинстве случаев её можно заменить оператором '&amp;amp;lt;' либо передачей имени файла в качестве аргумента, что позволяет избежать создания отдельного процесса. Может использоваться в следующих случаях:&lt;br /&gt;
* когда требуется вывести куда-то файл без изменений;&lt;br /&gt;
* когда требуется объединить более одного файла (например части одного файла, разбитого командой '''split'''), либо файл(ы) с потоком стандартного ввода;&lt;br /&gt;
* когда требуется просмотреть содержимое файла.&lt;br /&gt;
&lt;br /&gt;
== Аналоги в других операционных системах ==&lt;br /&gt;
&lt;br /&gt;
В Windows для аналогичных целей можно использовать команду следующего вида:&lt;br /&gt;
&lt;br /&gt;
  copy /b a.txt + b.txt abc.txt&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Shred</id>
		<title>Shred</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Shred"/>
				<updated>2017-04-05T13:32:39Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;tt&amp;gt;'''shred'''&amp;lt;/tt&amp;gt; is a [[Unix]] command that can be used to [[data remanence|securely delete]] files and devices so that they can be recovered only with great difficulty with specialised hardware, if at all. It is a part of [[GNU Core Utilities]].&lt;br /&gt;
&lt;br /&gt;
==Background==&lt;br /&gt;
For efficiency, the process of erasing a file from [[data storage device | storage]] usually only erases the file's [[file system | file-system]] entry while keeping the content of the file intact. This frequently allows commonly available software to recover the &amp;quot;erased&amp;quot; file's data. Even if the file is overwritten, residual magnetic fields may allow data recovery using [[data remanence|specialist hardware equipment]]. To prevent this, &amp;lt;tt&amp;gt;shred&amp;lt;/tt&amp;gt; overwrites the contents of a file multiple times, using patterns chosen to maximize destruction of the residual data.&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
&amp;lt;tt&amp;gt;shred&amp;lt;/tt&amp;gt; can be invoked either on ordinary files or on devices (such as hard disk partitions), which are represented as files in Unix. By default, the command overwrites the file three times with multiple patterns, but the number is user configurable. It has an option to do an additional final overwrite with zeroes, which may help to hide the fact that it was used.&lt;br /&gt;
&lt;br /&gt;
By default, shred also shreds [[fragmentation (computer)#Internal fragmentation|file slack]] (unused space in file allocations). For example, a 5 KB file on a file system with 4 KB clusters actually requires 8 KB of storage. Shred has an option to overwrite only the file itself, as well as an option to delete the file after it has completed operation.&lt;br /&gt;
&lt;br /&gt;
==Limitations==&lt;br /&gt;
A limitation of &amp;lt;tt&amp;gt;shred&amp;lt;/tt&amp;gt; when invoked on ordinary files is that it only overwrites the data in place without overwriting other copies of the file. Copies can manifest themselves in a variety of ways, such as through manual and automatic backups, file system snapshots, copy-on-write filesystems, [[wear leveling]] on [[solid-state drive|flash drive]]s, caching such as [[Network File System (protocol)|NFS]] caching, and [[Journaling file system|journaling]]. All limitations imposed by the file system can be overcome by shredding every device on which the data resides instead of specific files. However, since wear leveled devices do not guarantee a fixed relationship between logical blocks addressable through the interface and the physical locations in which the data is stored, shredding may not provide adequate security. If available, the SATA secure erase command, issued through [[hdparm]] or a similar utility, may be helpful in this situation. Even for magnetic devices, SATA secure erase will be faster and more reliable than shredding. Physical destruction may be necessary to securely erase devices such as [[memory card]]s and unusable hard disks.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Install</id>
		<title>Install</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Install"/>
				<updated>2017-04-05T13:27:05Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''&amp;lt;tt&amp;gt;install&amp;lt;/tt&amp;gt;''' — команда Unix копирующая файлы и устанавливающая атрибуты. Некоторые реализ…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''&amp;lt;tt&amp;gt;install&amp;lt;/tt&amp;gt;''' — команда Unix копирующая файлы и устанавливающая атрибуты. Некоторые реализации предлагают использовать strip при установке исполняемых файлов.&lt;br /&gt;
&lt;br /&gt;
Использование: install [КЛЮЧ]... [-T] ИСТОЧНИК НАЗНАЧЕНИЕ&lt;br /&gt;
       или:    install [КЛЮЧ]... ИСТОЧНИК... КАТАЛОГ&lt;br /&gt;
       или:    install [КЛЮЧ]... -t КАТАЛОГ ИСТОЧНИК...&lt;br /&gt;
       или:    install [КЛЮЧ]... -d КАТАЛОГ...&lt;br /&gt;
В первых трёх формах копирует ИСТОЧНИК в НАЗНАЧЕНИЕ или несколько&lt;br /&gt;
ИСТОЧНИКОВ в существующий КАТАЛОГ, устанавливая режимы доступа и&lt;br /&gt;
владельца/группу.  В четвёртой форме создаёт все компоненты указанных&lt;br /&gt;
КАТАЛОГОВ.&lt;br /&gt;
&lt;br /&gt;
Аргументы, обязательные для длинных ключей, обязательны и для коротких:&lt;br /&gt;
  --backup[=CONTROL]                 создавать резервную копию каждого существующего файла назначения&lt;br /&gt;
  -b                                 аналогично -backup, но не принимает аргумент&lt;br /&gt;
  -c                                 (игнорируется)&lt;br /&gt;
  -C, --compare                      сравнивать каждую пару исходных и конечных файлов, а в некоторых случаях вообще не изменяет назначение&lt;br /&gt;
  -d, --directory                    рассматривать все аргументы как имена каталогов; создаёт все указанные каталоги&lt;br /&gt;
  -D                                 создавать все начальные составляющие НАЗНАЧЕНИЯ кроме последнего, затем копировать ИСТОЧНИК в НАЗНАЧЕНИЕ&lt;br /&gt;
  -g, --group=ГРУППА                 устанавливать ГРУППУ, а не группу текущего процесса&lt;br /&gt;
  -m, --mode=РЕЖИМ                   устанавливать РЕЖИМ (как chmod), а не rwxr-xr-x&lt;br /&gt;
  -o, --owner=ВЛАДЕЛЕЦ               устанавливать ВЛАДЕЛЬЦА (только для суперпользователя)&lt;br /&gt;
  -p, --preserve-timestamps          устанавливать целевым файлам времена доступа/изменения, как у их файлов-ИСТОЧНИКОВ&lt;br /&gt;
  -s, --strip                        удалять таблицы символов&lt;br /&gt;
  -S, --suffix=СУФФИКС               использовать для резервных копий заданный СУФФИКС&lt;br /&gt;
  -t, --target-directory=КАТАЛОГ     копировать все аргументы-ИСТОЧНИКИ в КАТАЛОГ&lt;br /&gt;
  -T, --no-target-directory          считать НАЗНАЧЕНИЕ обычным файлом&lt;br /&gt;
  -v, --verbose                      выводить название каждого создаваемого каталога&lt;br /&gt;
  -P, --preserve_context (SELinux)   сохранять контекст безопасности&lt;br /&gt;
  -Z, --context=CONTEXT  (SELinux)   установить контекст безопасности файлов и каталогов&lt;br /&gt;
  --help                             показать эту справку и выйти&lt;br /&gt;
  --version                          показать информацию о версии и выйти&lt;br /&gt;
&lt;br /&gt;
По умолчанию суффикс для запасных копий ~, если только не установлена&lt;br /&gt;
переменная окружения SIMPLE_BACKUP_SUFFIX или ключ --suffix. Способ контроля&lt;br /&gt;
версий может быть установлен при помощи ключа --backup или переменной&lt;br /&gt;
окружения VERSION_CONTROL. Допустимые значения:&lt;br /&gt;
&lt;br /&gt;
  none, off                          никогда не создавать резервных копий (даже если указан ключ --backup)&lt;br /&gt;
  numbered, t                        создавать нумерованные копии&lt;br /&gt;
  existing, nil                      если существуют нумерованные копии, то создавать нумерованные иначе создавать простые&lt;br /&gt;
  simple. never                      всегда создавать простые копии&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Mv_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D1%8F/%D0%BF%D0%B5%D1%80%D0%B5%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D1%8B%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%B8/%D0%B8%D0%BB%D0%B8_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2</id>
		<title>Mv — Команда перемещения/переименовывания файлов и/или каталогов</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Mv_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%BF%D0%B5%D1%80%D0%B5%D0%BC%D0%B5%D1%89%D0%B5%D0%BD%D0%B8%D1%8F/%D0%BF%D0%B5%D1%80%D0%B5%D0%B8%D0%BC%D0%B5%D0%BD%D0%BE%D0%B2%D1%8B%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%B8/%D0%B8%D0%BB%D0%B8_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2"/>
				<updated>2017-04-03T10:22:58Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''mv''' (от англ. '''m'''o'''v'''e) — утилита в '''''UNIX''''' и '''''UNIX-подобных''''' системах, используется д…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''mv''' (от англ. '''m'''o'''v'''e) — утилита в '''''UNIX''''' и '''''UNIX-подобных''''' системах, используется для перемещения или переименования файлов.&lt;br /&gt;
&lt;br /&gt;
Использование:&lt;br /&gt;
* Если в качестве аргументов заданы имена двух файлов, то имя первого файла будет изменено на имя второго.&lt;br /&gt;
 mv file1 file_1       переименовывает файл&lt;br /&gt;
* Если последний аргумент является именем существующего каталога, то &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt; перемещает все заданные файлы в этот каталог.&lt;br /&gt;
&lt;br /&gt;
 mv file ./dir/        перемещает 'file' в 'dir/file' относительно текущего каталога&lt;br /&gt;
&lt;br /&gt;
Если последний аргумент не является каталогом и задано более чем два файла, то будет выдано сообщение об ошибке.&lt;br /&gt;
&lt;br /&gt;
Ключи, использующиеся с &amp;lt;code&amp;gt;mv&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;–f&amp;lt;/code&amp;gt;, не запрашивать подтверждения операций.&lt;br /&gt;
* &amp;lt;code&amp;gt;–i&amp;lt;/code&amp;gt;, выводить запрос на подтверждение операции, когда существует файл, в который происходит переименование или перемещение.&lt;br /&gt;
* &amp;lt;code&amp;gt;––&amp;lt;/code&amp;gt;, завершает список ключей. Применяется для использования с файлами, имена которых начинаются на &amp;lt;code&amp;gt;–&amp;lt;/code&amp;gt;.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Cp_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%B8/%D0%B8%D0%BB%D0%B8_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2</id>
		<title>Cp — Команда копирования файлов и/или каталогов</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Cp_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D0%BA%D0%BE%D0%BF%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%BE%D0%B2_%D0%B8/%D0%B8%D0%BB%D0%B8_%D0%BA%D0%B0%D1%82%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE%D0%B2"/>
				<updated>2017-04-03T10:20:01Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: Новая страница: «'''&amp;lt;tt&amp;gt;cp&amp;lt;/tt&amp;gt;''' — команда '''''Unix''''' в составе '''''GNU Coreutils''''', предназначенная для копирования фай…»&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''&amp;lt;tt&amp;gt;cp&amp;lt;/tt&amp;gt;''' — команда '''''Unix''''' в составе '''''GNU Coreutils''''', предназначенная для копирования файлов из одного в другие каталоги (возможно, с другой файловой системой). Исходный файл остаётся неизменным, имя созданного файла может быть таким же, как у исходного, или изменится.&lt;br /&gt;
&lt;br /&gt;
Последующие примеры использования касаются '''''AIX''''' версии &amp;lt;tt&amp;gt;cp&amp;lt;/tt&amp;gt;. В других операционных системах семейства '''''Unix''''' данная команда может иметь другие ключи. В '''''DOS''''' и '''''Windows''''' аналогом является команда '''''COPY'''''.&lt;br /&gt;
&lt;br /&gt;
== Использование ==&lt;br /&gt;
&lt;br /&gt;
Чтобы скопировать файл&lt;br /&gt;
     cp [ -f ] [ -h ] [ -i ] [ -p ][ -- ] исходный_файл целевой_файл&lt;br /&gt;
&lt;br /&gt;
Чтобы скопировать файл или файлы в другой каталог&lt;br /&gt;
    cp [-R] [-H | -L | -P] [-f | -i] [-pv] исходный_файл ... целевая_директория&lt;br /&gt;
&lt;br /&gt;
Чтобы скопировать каталог в другой каталог (должен быть использован флаг -r или -R)&lt;br /&gt;
     cp [ -f ] [ -h ] [ -i ] [ -p ] [ -- ] { -r | -R } исходная_директория ... целевая_директория&lt;br /&gt;
Чтобы скопировать каталог /media/fff1787/share1/load/ в каталог /media/beac6e58/, с выводом имени копируемого файла, авто пропуском существующих файлов, рекурсивно для вложенных каталогов.&lt;br /&gt;
     cp -invR /media/fff1787/share1/load/ /media/beac6e58/&lt;br /&gt;
&lt;br /&gt;
== Синтаксис команды ==&lt;br /&gt;
* &amp;lt;tt&amp;gt;-R, -r, --recursive&amp;lt;/tt&amp;gt; (recursive) — копировать директории рекурсивно (то есть все поддиректории и все файлы в поддиректориях).&lt;br /&gt;
* &amp;lt;tt&amp;gt;-f&amp;lt;/tt&amp;gt; (force) — разрешает удаление целевого файла, в который производится копирование, если он не может быть открыт для записи.&lt;br /&gt;
* &amp;lt;tt&amp;gt;-H&amp;lt;/tt&amp;gt; — используйте этот ключ, чтобы копировать символические ссылки. По умолчанию команда переходит по символическим ссылкам и копирует файлы, на которые те указывают.&lt;br /&gt;
* &amp;lt;tt&amp;gt;-i&amp;lt;/tt&amp;gt; (interactive) — команда будет запрашивать, следует ли перезаписывать конечный файл, имя которого совпадает с именем исходного, то есть если в параметре ''целевой_каталог'' или ''целевой_файл'' встречается такое же имя файла, какое было задано в параметре ''исходный_файл'' или ''исходная_директория'', то запрашивается подтверждение. Для того, чтобы перезаписать файл, следует ввести '''y''' или его эквивалент для данной локали. Ввод любого другого символа приведёт к отмене перезаписи данного файла.&lt;br /&gt;
* -n, --no-clobber — не перезаписывать существующий файл (отменяет предыдущий параметр -i).&lt;br /&gt;
* -v, --verbose  — выводит имя каждого файла перед его копированием.&lt;br /&gt;
в некоторых системах назначен ''alias'' cp='cp -i', т.е. по умолчанию команда cp будет спрашивать о перезаписи&lt;br /&gt;
* &amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt; (preserve) — повторяет следующие свойства исходного файла или директории у целевого файла или директории:&lt;br /&gt;
** Время последнего изменения и последнего доступа.&lt;br /&gt;
** Идентификатор пользователя и группы.&lt;br /&gt;
** Права доступа и биты SUID и SGID.&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	<entry>
		<id>https://wiki.alex-master.com/index.php/Touch_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F_%D0%BF%D1%83%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%84%D0%B0%D0%B9%D0%BB%D0%B0_%D0%B8_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%B0</id>
		<title>Touch — Команда создания пустого файла и модификации времени последнего изменения файла</title>
		<link rel="alternate" type="text/html" href="https://wiki.alex-master.com/index.php/Touch_%E2%80%94_%D0%9A%D0%BE%D0%BC%D0%B0%D0%BD%D0%B4%D0%B0_%D1%81%D0%BE%D0%B7%D0%B4%D0%B0%D0%BD%D0%B8%D1%8F_%D0%BF%D1%83%D1%81%D1%82%D0%BE%D0%B3%D0%BE_%D1%84%D0%B0%D0%B9%D0%BB%D0%B0_%D0%B8_%D0%BC%D0%BE%D0%B4%D0%B8%D1%84%D0%B8%D0%BA%D0%B0%D1%86%D0%B8%D0%B8_%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8_%D0%BF%D0%BE%D1%81%D0%BB%D0%B5%D0%B4%D0%BD%D0%B5%D0%B3%D0%BE_%D0%B8%D0%B7%D0%BC%D0%B5%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F_%D1%84%D0%B0%D0%B9%D0%BB%D0%B0"/>
				<updated>2017-04-03T10:12:53Z</updated>
		
		<summary type="html">&lt;p&gt;Vaal: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''touch''' — команда Unix, предназначенная для установки времени последнего изменения файла или доступа в текущее время. Также используется для создания пустых файлов.&lt;br /&gt;
&lt;br /&gt;
== История ==&lt;br /&gt;
Утилита &amp;lt;tt&amp;gt;touch&amp;lt;/tt&amp;gt; появилась в операционной системе AT&amp;amp;T UNIX Version 7. Версия утилиты &amp;lt;tt&amp;gt;touch&amp;lt;/tt&amp;gt;, которая идет в комплекте с GNU coreutils, была разработана Полом Рабином, Арнольдом Роббинсом, Джимом Кингдоном, Девидом МакКинзи и Рэнди Смитом.&lt;br /&gt;
&lt;br /&gt;
== Спецификация ==&lt;br /&gt;
Согласно POSIX утилита &amp;lt;tt&amp;gt;touch&amp;lt;/tt&amp;gt; изменяет время последнего изменения файла или время последнего доступа к нему. Имя файла или путь к нему передается в качестве аргумента. Если файл не существует, утилита создает пустой файл с указанным именем и устанавливает время последнего изменения и последнего доступа в значение, переданное в качестве аргумента. Если аргумент времени не задан, используется текущее время.&lt;br /&gt;
&lt;br /&gt;
== Синтаксис команды ==&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
'''touch''' [-acfhm] [-r файл] [-t [[CC]YY]MMDDhhmm.[SS]] файл&amp;lt;/code&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;nbsp;&amp;amp;nbsp;'''-a'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Устанавливает время последнего доступа к файлу. Время последнего изменения не устанавливается, если явно не задан ключ -m&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''-c'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Указывает утилите не создавать файл, если он не существует, при этом никаких сообщений об ошибке показано не будет.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''-f'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Пытается обновить информацию о времени, даже если права доступа файла не позволяют делать.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''-h'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Указывает утилите не изменять данные о файле, если он задан &amp;lt;span style=&amp;quot;color:magenta&amp;quot;&amp;gt;''символической ссылкой''&amp;lt;/span&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''-m'''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Устанавливает время последнего изменения файла.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''-r''' ''file''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Использовать значения времени из файла, заданного аргументом &amp;lt;tt&amp;gt;''file''&amp;lt;/tt&amp;gt;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''-t''' ''time''&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Устанавливает время последнего изменения и доступа в соответствии с указанным форматом ''time''.&lt;br /&gt;
&lt;br /&gt;
Формат даты, указанный в ключе &amp;lt;tt&amp;gt;-t&amp;lt;/tt&amp;gt; задается в соответствии с шаблоном &amp;lt;code&amp;gt;[[СС]YY]MMDDhhmm[.SS]&amp;lt;/code&amp;gt;:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''СС''' — первые две цифры года (век).&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''YY''' — последние две цифры года.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;Если параметр CC не задан и значение YY находится в пределах 69 и 99, то тогда СС устанавливается равным 19,&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;в противном случае используется 20.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''MM''' — двузначный номер месяца.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''DD''' — двузначный номер дня.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''hh''' — значение часов даты.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''mm''' — значение минут даты.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;'''SS''' — значение секунд даты.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В разных UNIX-подобных системах синтаксис команды может отличаться. Например, GNU &amp;lt;tt&amp;gt;touch&amp;lt;/tt&amp;gt; содержит опцию &amp;lt;tt&amp;gt;-d&amp;lt;/tt&amp;gt;, которая позволяет устанавливать дату в форматах, отличающихся от упомянутого выше.&lt;br /&gt;
&lt;br /&gt;
== Примеры ==&lt;br /&gt;
&lt;br /&gt;
Создает файл &amp;lt;tt&amp;gt;myfile.txt&amp;lt;/tt&amp;gt; и устанавливает время последнего изменения и доступа в текущее время в системе; если файл существует — обновляет время последнего изменения и доступа не изменяя при этом содержимого файла:&lt;br /&gt;
 # touch myfile.txt&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Устанавливает дату последнего изменения и доступа в 8:46:26 31 января 2007 г.:&lt;br /&gt;
 # touch -t 200701310846.26 index.html&lt;br /&gt;
 # touch -d '2007-01-31 8:46:26' index.html&lt;br /&gt;
 # touch -d 'Jan 31 2007 8:46:26' index.html&lt;/div&gt;</summary>
		<author><name>Vaal</name></author>	</entry>

	</feed>