diff --git a/app/code/Magento/Cron/Console/Command/CronInstallCommand.php b/app/code/Magento/Cron/Console/Command/CronInstallCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..2835244599d38943fea5b2162814bbd6b9edb32e
--- /dev/null
+++ b/app/code/Magento/Cron/Console/Command/CronInstallCommand.php
@@ -0,0 +1,79 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cron\Console\Command;
+
+use Magento\Framework\Crontab\CrontabManagerInterface;
+use Magento\Framework\Crontab\TasksProviderInterface;
+use Magento\Framework\Exception\LocalizedException;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Magento\Framework\Console\Cli;
+use Symfony\Component\Console\Input\InputOption;
+
+/**
+ * CronInstallCommand installs Magento cron tasks
+ */
+class CronInstallCommand extends Command
+{
+    /**
+     * @var CrontabManagerInterface
+     */
+    private $crontabManager;
+
+    /**
+     * @var TasksProviderInterface
+     */
+    private $tasksProvider;
+
+    /**
+     * @param CrontabManagerInterface $crontabManager
+     * @param TasksProviderInterface $tasksProvider
+     */
+    public function __construct(
+        CrontabManagerInterface $crontabManager,
+        TasksProviderInterface $tasksProvider
+    ) {
+        $this->crontabManager = $crontabManager;
+        $this->tasksProvider = $tasksProvider;
+
+        parent::__construct();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function configure()
+    {
+        $this->setName('cron:install')
+            ->setDescription('Generates and installs crontab for current user')
+            ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force install tasks');
+
+        parent::configure();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        if ($this->crontabManager->getTasks() && !$input->getOption('force')) {
+            $output->writeln('<error>Crontab has already been generated and saved</error>');
+            return Cli::RETURN_FAILURE;
+        }
+
+        try {
+            $this->crontabManager->saveTasks($this->tasksProvider->getTasks());
+        } catch (LocalizedException $e) {
+            $output->writeln('<error>' . $e->getMessage() . '</error>');
+            return Cli::RETURN_FAILURE;
+        }
+
+        $output->writeln('<info>Crontab has been generated and saved</info>');
+
+        return Cli::RETURN_SUCCESS;
+    }
+}
diff --git a/app/code/Magento/Cron/Console/Command/CronRemoveCommand.php b/app/code/Magento/Cron/Console/Command/CronRemoveCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..11c666a556f899e9d7c6358c09291ee9df904998
--- /dev/null
+++ b/app/code/Magento/Cron/Console/Command/CronRemoveCommand.php
@@ -0,0 +1,62 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cron\Console\Command;
+
+use Magento\Framework\Crontab\CrontabManagerInterface;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Output\OutputInterface;
+use Magento\Framework\Console\Cli;
+use Magento\Framework\Exception\LocalizedException;
+
+/**
+ * CronRemoveCommand removes Magento cron tasks
+ */
+class CronRemoveCommand extends Command
+{
+    /**
+     * @var CrontabManagerInterface
+     */
+    private $crontabManager;
+
+    /**
+     * @param CrontabManagerInterface $crontabManager
+     */
+    public function __construct(CrontabManagerInterface $crontabManager)
+    {
+        $this->crontabManager = $crontabManager;
+
+        parent::__construct();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function configure()
+    {
+        $this->setName('cron:remove')
+            ->setDescription('Removes tasks from crontab');
+
+        parent::configure();
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        try {
+            $this->crontabManager->removeTasks();
+        } catch (LocalizedException $e) {
+            $output->writeln('<error>' . $e->getMessage() . '</error>');
+            return Cli::RETURN_FAILURE;
+        }
+
+        $output->writeln('<info>Magento cron tasks have been removed</info>');
+
+        return Cli::RETURN_SUCCESS;
+    }
+}
diff --git a/app/code/Magento/Cron/Test/Unit/Console/Command/CronInstallCommandTest.php b/app/code/Magento/Cron/Test/Unit/Console/Command/CronInstallCommandTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..09949cf78dc8f267fe2bb668d91f2b28032ed8c1
--- /dev/null
+++ b/app/code/Magento/Cron/Test/Unit/Console/Command/CronInstallCommandTest.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cron\Test\Unit\Console\Command;
+
+use Symfony\Component\Console\Tester\CommandTester;
+use Magento\Cron\Console\Command\CronInstallCommand;
+use Magento\Framework\Crontab\CrontabManagerInterface;
+use Magento\Framework\Crontab\TasksProviderInterface;
+use Magento\Framework\Console\Cli;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Phrase;
+
+class CronInstallCommandTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var CrontabManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $crontabManagerMock;
+
+    /**
+     * @var TasksProviderInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $tasksProviderMock;
+
+    /**
+     * @var CommandTester
+     */
+    private $commandTester;
+
+    /**
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->crontabManagerMock = $this->getMockBuilder(CrontabManagerInterface::class)
+            ->getMockForAbstractClass();
+        $this->tasksProviderMock = $this->getMockBuilder(TasksProviderInterface::class)
+            ->getMockForAbstractClass();
+
+        $this->commandTester = new CommandTester(
+            new CronInstallCommand($this->crontabManagerMock, $this->tasksProviderMock)
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecuteAlreadyInstalled()
+    {
+        $this->crontabManagerMock->expects($this->once())
+            ->method('getTasks')
+            ->willReturn([['* * * * * /bin/php /var/run.php']]);
+        $this->tasksProviderMock->expects($this->never())
+            ->method('getTasks');
+
+        $this->commandTester->execute([]);
+        $this->assertEquals(
+            'Crontab has already been generated and saved' . PHP_EOL,
+            $this->commandTester->getDisplay()
+        );
+        $this->assertEquals(Cli::RETURN_FAILURE, $this->commandTester->getStatusCode());
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecuteWithException()
+    {
+        $this->crontabManagerMock->expects($this->once())
+            ->method('getTasks')
+            ->willReturn([]);
+        $this->tasksProviderMock->expects($this->once())
+            ->method('getTasks')
+            ->willReturn([]);
+        $this->crontabManagerMock->expects($this->once())
+            ->method('saveTasks')
+            ->willThrowException(new LocalizedException(new Phrase('Some error')));
+
+        $this->commandTester->execute([]);
+        $this->assertEquals(
+            'Some error' . PHP_EOL,
+            $this->commandTester->getDisplay()
+        );
+        $this->assertEquals(Cli::RETURN_FAILURE, $this->commandTester->getStatusCode());
+    }
+
+    /**
+     * @param array $existingTasks
+     * @param array $options
+     * @return void
+     * @dataProvider executeDataProvider
+     */
+    public function testExecute($existingTasks, $options)
+    {
+        $this->crontabManagerMock->expects($this->once())
+            ->method('getTasks')
+            ->willReturn($existingTasks);
+        $this->tasksProviderMock->expects($this->once())
+            ->method('getTasks')
+            ->willReturn([]);
+        $this->crontabManagerMock->expects($this->once())
+            ->method('saveTasks')
+            ->with([]);
+
+        $this->commandTester->execute($options);
+        $this->assertEquals(
+            'Crontab has been generated and saved' . PHP_EOL,
+            $this->commandTester->getDisplay()
+        );
+        $this->assertEquals(Cli::RETURN_SUCCESS, $this->commandTester->getStatusCode());
+    }
+
+    /**
+     * @return array
+     */
+    public function executeDataProvider()
+    {
+        return [
+            ['existingTasks' => [], 'options' => []],
+            ['existingTasks' => ['* * * * * /bin/php /var/www/run.php'], 'options' => ['-f'=> true]]
+        ];
+    }
+}
diff --git a/app/code/Magento/Cron/Test/Unit/Console/Command/CronRemoveCommandTest.php b/app/code/Magento/Cron/Test/Unit/Console/Command/CronRemoveCommandTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..cd017b26d758578482bffa137a3f221650619bae
--- /dev/null
+++ b/app/code/Magento/Cron/Test/Unit/Console/Command/CronRemoveCommandTest.php
@@ -0,0 +1,72 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Cron\Test\Unit\Console\Command;
+
+use Symfony\Component\Console\Tester\CommandTester;
+use Magento\Cron\Console\Command\CronRemoveCommand;
+use Magento\Framework\Crontab\CrontabManagerInterface;
+use Magento\Framework\Console\Cli;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Phrase;
+
+class CronRemoveCommandTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var CrontabManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $crontabManagerMock;
+
+    /**
+     * @var CommandTester
+     */
+    private $commandTester;
+
+    /**
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->crontabManagerMock = $this->getMockBuilder(CrontabManagerInterface::class)
+            ->getMockForAbstractClass();
+
+        $this->commandTester = new CommandTester(
+            new CronRemoveCommand($this->crontabManagerMock)
+        );
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecute()
+    {
+        $this->crontabManagerMock->expects($this->once())
+            ->method('RemoveTasks');
+
+        $this->commandTester->execute([]);
+        $this->assertEquals(
+            'Magento cron tasks have been removed' . PHP_EOL,
+            $this->commandTester->getDisplay()
+        );
+        $this->assertEquals(Cli::RETURN_SUCCESS, $this->commandTester->getStatusCode());
+    }
+
+    /**
+     * @return void
+     */
+    public function testExecuteFailed()
+    {
+        $this->crontabManagerMock->expects($this->once())
+            ->method('RemoveTasks')
+            ->willThrowException(new LocalizedException(new Phrase('Some error')));
+
+        $this->commandTester->execute([]);
+        $this->assertEquals(
+            'Some error' . PHP_EOL,
+            $this->commandTester->getDisplay()
+        );
+        $this->assertEquals(Cli::RETURN_FAILURE, $this->commandTester->getStatusCode());
+    }
+}
diff --git a/app/code/Magento/Cron/etc/di.xml b/app/code/Magento/Cron/etc/di.xml
index d5624e96765c58bd699eebc29c14c7fe76037b7a..6abc9096f24012309a3b56cb0b84912d3a8d1e26 100644
--- a/app/code/Magento/Cron/etc/di.xml
+++ b/app/code/Magento/Cron/etc/di.xml
@@ -8,6 +8,8 @@
 <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
     <preference for="Magento\Cron\Model\ConfigInterface" type="Magento\Cron\Model\Config" />
     <preference for="Magento\Framework\Shell\CommandRendererInterface" type="Magento\Framework\Shell\CommandRenderer" />
+    <preference for="Magento\Framework\Crontab\CrontabManagerInterface" type="Magento\Framework\Crontab\CrontabManager" />
+    <preference for="Magento\Framework\Crontab\TasksProviderInterface" type="Magento\Framework\Crontab\TasksProvider" />
     <type name="Magento\Config\Model\Config\Structure\Converter">
         <plugin name="cron_backend_config_structure_converter_plugin" type="Magento\Cron\Model\Backend\Config\Structure\Converter" />
     </type>
@@ -28,6 +30,8 @@
         <arguments>
             <argument name="commands" xsi:type="array">
                 <item name="cronCommand" xsi:type="object">Magento\Cron\Console\Command\CronCommand</item>
+                <item name="cronInstall" xsi:type="object">Magento\Cron\Console\Command\CronInstallCommand</item>
+                <item name="cronRemove" xsi:type="object">Magento\Cron\Console\Command\CronRemoveCommand</item>
             </argument>
         </arguments>
     </type>
@@ -38,4 +42,24 @@
             </argument>
         </arguments>
     </type>
+    <type name="Magento\Framework\Crontab\CrontabManager">
+        <arguments>
+            <argument name="shell" xsi:type="object">Magento\Framework\App\Shell</argument>
+        </arguments>
+    </type>
+    <type name="Magento\Framework\Crontab\TasksProviderInterface">
+        <arguments>
+            <argument name="tasks" xsi:type="array">
+                <item name="cronMagento" xsi:type="array">
+                    <item name="command" xsi:type="string">{magentoRoot}bin/magento cron:run | grep -v "Ran jobs by schedule" >> {magentoLog}magento.cron.log</item>
+                </item>
+                <item name="cronUpdate" xsi:type="array">
+                    <item name="command" xsi:type="string">{magentoRoot}update/cron.php >> {magentoLog}update.cron.log</item>
+                </item>
+                <item name="cronSetup" xsi:type="array">
+                    <item name="command" xsi:type="string">{magentoRoot}bin/magento setup:cron:run >> {magentoLog}setup.cron.log</item>
+                </item>
+            </argument>
+        </arguments>
+    </type>
 </config>
diff --git a/lib/internal/Magento/Framework/Crontab/CrontabManager.php b/lib/internal/Magento/Framework/Crontab/CrontabManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..a60bd9d2cb512ac0000941657e76db1f0be20b85
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/CrontabManager.php
@@ -0,0 +1,199 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Crontab;
+
+use Magento\Framework\ShellInterface;
+use Magento\Framework\Phrase;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Filesystem;
+use Magento\Framework\App\Filesystem\DirectoryList;
+
+/**
+ * Manager works with cron tasks
+ */
+class CrontabManager implements CrontabManagerInterface
+{
+    /**
+     * @var ShellInterface
+     */
+    private $shell;
+
+    /**
+     * @var Filesystem
+     */
+    private $filesystem;
+
+    /**
+     * @param ShellInterface $shell
+     * @param Filesystem $filesystem
+     */
+    public function __construct(
+        ShellInterface $shell,
+        Filesystem $filesystem
+    ) {
+        $this->shell = $shell;
+        $this->filesystem = $filesystem;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTasks()
+    {
+        $this->checkSupportedOs();
+        $content = $this->getCrontabContent();
+        $pattern = '!(' . self::TASKS_BLOCK_START . ')(.*?)(' . self::TASKS_BLOCK_END . ')!s';
+
+        if (preg_match($pattern, $content, $matches)) {
+            $tasks = trim($matches[2], PHP_EOL);
+            $tasks = explode(PHP_EOL, $tasks);
+            return $tasks;
+        }
+
+        return [];
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function saveTasks(array $tasks)
+    {
+        $this->checkSupportedOs();
+        $baseDir = $this->filesystem->getDirectoryRead(DirectoryList::ROOT)->getAbsolutePath();
+        $logDir = $this->filesystem->getDirectoryRead(DirectoryList::LOG)->getAbsolutePath();
+
+        if (!$tasks) {
+            throw new LocalizedException(new Phrase('List of tasks is empty'));
+        }
+
+        foreach ($tasks as $key => $task) {
+            if (empty($task['expression'])) {
+                $tasks[$key]['expression'] = '* * * * *';
+            }
+
+            if (empty($task['command'])) {
+                throw new LocalizedException(new Phrase('Command should not be empty'));
+            }
+
+            $tasks[$key]['command'] = str_replace(
+                ['{magentoRoot}', '{magentoLog}'],
+                [$baseDir, $logDir],
+                $task['command']
+            );
+        }
+
+        $content = $this->getCrontabContent();
+        $content = $this->cleanMagentoSection($content);
+        $content = $this->generateSection($content, $tasks);
+
+        $this->save($content);
+    }
+
+    /**
+     * {@inheritdoc}
+     * @throws LocalizedException
+     */
+    public function removeTasks()
+    {
+        $this->checkSupportedOs();
+        $content = $this->getCrontabContent();
+        $content = $this->cleanMagentoSection($content);
+        $this->save($content);
+    }
+
+    /**
+     * Generate Magento Tasks Section
+     *
+     * @param string $content
+     * @param array $tasks
+     * @return string
+     */
+    private function generateSection($content, $tasks = [])
+    {
+        if ($tasks) {
+            $content .= self::TASKS_BLOCK_START . PHP_EOL;
+            foreach ($tasks as $task) {
+                $content .=  $task['expression'] . ' ' . PHP_BINARY . ' '. $task['command'] . PHP_EOL;
+            }
+            $content .= self::TASKS_BLOCK_END . PHP_EOL;
+        }
+
+        return $content;
+    }
+
+    /**
+     * Clean Magento Tasks Section in crontab content
+     *
+     * @param string $content
+     * @return string
+     */
+    private function cleanMagentoSection($content)
+    {
+        $content = preg_replace(
+            '!' . preg_quote(self::TASKS_BLOCK_START) . '.*?' . preg_quote(self::TASKS_BLOCK_END . PHP_EOL) . '!s',
+            '',
+            $content
+        );
+
+        return $content;
+    }
+
+    /**
+     * Get crontab content without Magento Tasks Section
+     *
+     * In case of some exceptions the empty content is returned
+     *
+     * @return string
+     */
+    private function getCrontabContent()
+    {
+        try {
+            $content = (string)$this->shell->execute('crontab -l');
+        } catch (LocalizedException $e) {
+            return '';
+        }
+
+        return $content;
+    }
+
+    /**
+     * Save crontab
+     *
+     * @param string $content
+     * @return void
+     * @throws LocalizedException
+     */
+    private function save($content)
+    {
+        $content = str_replace('%', '%%', $content);
+
+        try {
+            $this->shell->execute('echo "' . $content . '" | crontab -');
+        } catch (LocalizedException $e) {
+            throw new LocalizedException(
+                new Phrase('Error during saving of crontab: %1', [$e->getPrevious()->getMessage()]),
+                $e
+            );
+        }
+    }
+
+    /**
+     * Check that OS is supported
+     *
+     * If OS is not supported then no possibility to work with crontab
+     *
+     * @return void
+     * @throws LocalizedException
+     */
+    private function checkSupportedOs()
+    {
+        if (stripos(PHP_OS, 'WIN') === 0) {
+            throw new LocalizedException(
+                new Phrase('Your operation system is not supported, you cannot work with crontab')
+            );
+        }
+    }
+}
diff --git a/lib/internal/Magento/Framework/Crontab/CrontabManagerInterface.php b/lib/internal/Magento/Framework/Crontab/CrontabManagerInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..c00ab41d8b873a46dc27abbb1af37a23b7e7fd86
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/CrontabManagerInterface.php
@@ -0,0 +1,43 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Crontab;
+
+use Magento\Framework\Exception\LocalizedException;
+
+interface CrontabManagerInterface
+{
+    /**#@+
+     * Constants for wrapping Magento section in crontab
+     */
+    const TASKS_BLOCK_START = '#~ MAGENTO START';
+    const TASKS_BLOCK_END = '#~ MAGENTO END';
+    /**#@-*/
+
+    /**
+     * Get list of Magento Tasks
+     *
+     * @return array
+     * @throws LocalizedException
+     */
+    public function getTasks();
+
+    /**
+     * Save Magento Tasks to crontab
+     *
+     * @param array $tasks
+     * @return void
+     * @throws LocalizedException
+     */
+    public function saveTasks(array $tasks);
+
+    /**
+     * Remove Magento Tasks form crontab
+     *
+     * @return void
+     * @throws LocalizedException
+     */
+    public function removeTasks();
+}
diff --git a/lib/internal/Magento/Framework/Crontab/README.md b/lib/internal/Magento/Framework/Crontab/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..bfbf194715dc8f9f359137ecb79be5a1adbd5c5e
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/README.md
@@ -0,0 +1,12 @@
+Library for working with crontab
+
+The library has the next interfaces:
+* CrontabManagerInterface
+* TasksProviderInterface
+
+*CrontabManagerInterface* provides working with crontab:
+* *getTasks* - get list of Magento cron tasks from crontab
+* *saveTasks* - save Magento cron tasks to crontab
+* *removeTasks* - remove Magento cron tasks from crontab
+
+*TasksProviderInterface* has only one method *getTasks*. This interface provides transportation the list of tasks from DI
\ No newline at end of file
diff --git a/lib/internal/Magento/Framework/Crontab/TasksProvider.php b/lib/internal/Magento/Framework/Crontab/TasksProvider.php
new file mode 100644
index 0000000000000000000000000000000000000000..94524fd2bbd19b4395a8ba36daaa0f43c2b6c648
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/TasksProvider.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Crontab;
+
+/**
+ * TasksProvider collects list of tasks
+ */
+class TasksProvider implements TasksProviderInterface
+{
+    /**
+     * @var array
+     */
+    private $tasks = [];
+
+    /**
+     * @param array $tasks
+     */
+    public function __construct(array $tasks = [])
+    {
+        $this->tasks = $tasks;
+    }
+
+    /**
+     * {@inheritdoc}
+     */
+    public function getTasks()
+    {
+        return $this->tasks;
+    }
+}
diff --git a/lib/internal/Magento/Framework/Crontab/TasksProviderInterface.php b/lib/internal/Magento/Framework/Crontab/TasksProviderInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..bb02c30797be4cbf015c5858ac1c88825bde54a7
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/TasksProviderInterface.php
@@ -0,0 +1,16 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Crontab;
+
+interface TasksProviderInterface
+{
+    /**
+     * Get list of tasks
+     *
+     * @return array
+     */
+    public function getTasks();
+}
diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7cafd386c629a4b48350d5ca4937b58fd49da4b6
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/CrontabManagerTest.php
@@ -0,0 +1,333 @@
+<?php
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Crontab\Test\Unit;
+
+use Magento\Framework\Crontab\CrontabManager;
+use Magento\Framework\Crontab\CrontabManagerInterface;
+use Magento\Framework\ShellInterface;
+use Magento\Framework\Phrase;
+use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Filesystem;
+use Magento\Framework\App\Filesystem\DirectoryList;
+use Magento\Framework\Filesystem\Directory\ReadInterface;
+use Magento\Framework\Filesystem\DriverPool;
+
+class CrontabManagerTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @var ShellInterface|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $shellMock;
+
+    /**
+     * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject
+     */
+    private $filesystemMock;
+
+    /**
+     * @var CrontabManager
+     */
+    private $crontabManager;
+
+    /**
+     * @return void
+     */
+    protected function setUp()
+    {
+        $this->shellMock = $this->getMockBuilder(ShellInterface::class)
+            ->getMockForAbstractClass();
+        $this->filesystemMock = $this->getMockBuilder(Filesystem::class)
+            ->disableOriginalClone()
+            ->disableOriginalConstructor()
+            ->getMock();
+
+        $this->crontabManager = new CrontabManager($this->shellMock, $this->filesystemMock);
+    }
+
+    /**
+     * @return void
+     */
+    public function testGetTasksNoCrontab()
+    {
+        $exception = new \Exception('crontab: no crontab for user');
+        $localizedException = new LocalizedException(new Phrase('Some error'), $exception);
+
+        $this->shellMock->expects($this->once())
+            ->method('execute')
+            ->with('crontab -l', [])
+            ->willThrowException($localizedException);
+
+        $this->assertEquals([], $this->crontabManager->getTasks());
+    }
+
+    /**
+     * @param string $content
+     * @param array $tasks
+     * @return void
+     * @dataProvider getTasksDataProvider
+     */
+    public function testGetTasks($content, $tasks)
+    {
+        $this->shellMock->expects($this->once())
+            ->method('execute')
+            ->with('crontab -l', [])
+            ->willReturn($content);
+
+        $this->assertEquals($tasks, $this->crontabManager->getTasks());
+    }
+
+    /**
+     * @return array
+     */
+    public function getTasksDataProvider()
+    {
+        return [
+            [
+                'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+                'tasks' => ['* * * * * /bin/php /var/www/magento/bin/magento cron:run'],
+            ],
+            [
+                'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
+                    . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+                'tasks' => [
+                    '* * * * * /bin/php /var/www/magento/bin/magento cron:run',
+                    '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run',
+                ],
+            ],
+            [
+                'content' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL,
+                'tasks' => [],
+            ],
+            [
+                'content' => '',
+                'tasks' => [],
+            ],
+        ];
+    }
+
+    /**
+     * @return void
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Shell error
+     */
+    public function testRemoveTasksWithException()
+    {
+        $exception = new \Exception('Shell error');
+        $localizedException = new LocalizedException(new Phrase('Some error'), $exception);
+
+        $this->shellMock->expects($this->at(0))
+            ->method('execute')
+            ->with('crontab -l', [])
+            ->willReturn('');
+
+        $this->shellMock->expects($this->at(1))
+            ->method('execute')
+            ->with('echo "" | crontab -', [])
+            ->willThrowException($localizedException);
+
+        $this->crontabManager->removeTasks();
+    }
+
+    /**
+     * @param string $contentBefore
+     * @param string $contentAfter
+     * @return void
+     * @dataProvider removeTasksDataProvider
+     */
+    public function testRemoveTasks($contentBefore, $contentAfter)
+    {
+        $this->shellMock->expects($this->at(0))
+            ->method('execute')
+            ->with('crontab -l', [])
+            ->willReturn($contentBefore);
+
+        $this->shellMock->expects($this->at(1))
+            ->method('execute')
+            ->with('echo "' . $contentAfter . '" | crontab -', []);
+
+        $this->crontabManager->removeTasks();
+    }
+
+    /**
+     * @return array
+     */
+    public function removeTasksDataProvider()
+    {
+        return [
+            [
+                'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+                'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+            ],
+            [
+                'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
+                    . '* * * * * /bin/php /var/www/magento/bin/magento setup:cron:run' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+                'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+            ],
+            [
+                'contentBefore' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL,
+                'contentAfter' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+            ],
+            [
+                'contentBefore' => '',
+                'contentAfter' => ''
+            ],
+        ];
+    }
+
+    /**
+     * @return void
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage List of tasks is empty
+     */
+    public function testSaveTasksWithEmptyTasksList()
+    {
+        $baseDirMock = $this->getMockBuilder(ReadInterface::class)
+            ->getMockForAbstractClass();
+        $baseDirMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->willReturn('/var/www/magento2/');
+        $logDirMock = $this->getMockBuilder(ReadInterface::class)
+            ->getMockForAbstractClass();
+        $logDirMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->willReturn('/var/www/magento2/var/log/');
+
+        $this->filesystemMock->expects($this->any())
+            ->method('getDirectoryRead')
+            ->willReturnMap([
+                [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock],
+                [DirectoryList::LOG, DriverPool::FILE, $logDirMock],
+            ]);
+
+        $this->crontabManager->saveTasks([]);
+    }
+
+    /**
+     * @return void
+     * @expectedException \Magento\Framework\Exception\LocalizedException
+     * @expectedExceptionMessage Command should not be empty
+     */
+    public function testSaveTasksWithoutCommand()
+    {
+        $baseDirMock = $this->getMockBuilder(ReadInterface::class)
+            ->getMockForAbstractClass();
+        $baseDirMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->willReturn('/var/www/magento2/');
+        $logDirMock = $this->getMockBuilder(ReadInterface::class)
+            ->getMockForAbstractClass();
+        $logDirMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->willReturn('/var/www/magento2/var/log/');
+
+        $this->filesystemMock->expects($this->any())
+            ->method('getDirectoryRead')
+            ->willReturnMap([
+                [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock],
+                [DirectoryList::LOG, DriverPool::FILE, $logDirMock],
+            ]);
+
+        $this->crontabManager->saveTasks([
+            'myCron' => ['expression' => '* * * * *']
+        ]);
+    }
+
+    /**
+     * @param array $tasks
+     * @param string $content
+     * @param string $contentToSave
+     * @return void
+     * @dataProvider saveTasksDataProvider
+     */
+    public function testSaveTasks($tasks, $content, $contentToSave)
+    {
+        $baseDirMock = $this->getMockBuilder(ReadInterface::class)
+            ->getMockForAbstractClass();
+        $baseDirMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->willReturn('/var/www/magento2/');
+        $logDirMock = $this->getMockBuilder(ReadInterface::class)
+            ->getMockForAbstractClass();
+        $logDirMock->expects($this->once())
+            ->method('getAbsolutePath')
+            ->willReturn('/var/www/magento2/var/log/');
+
+        $this->filesystemMock->expects($this->any())
+            ->method('getDirectoryRead')
+            ->willReturnMap([
+                [DirectoryList::ROOT, DriverPool::FILE, $baseDirMock],
+                [DirectoryList::LOG, DriverPool::FILE, $logDirMock],
+            ]);
+
+        $this->shellMock->expects($this->at(0))
+            ->method('execute')
+            ->with('crontab -l', [])
+            ->willReturn($content);
+
+        $this->shellMock->expects($this->at(1))
+            ->method('execute')
+            ->with('echo "' . $contentToSave . '" | crontab -', []);
+
+        $this->crontabManager->saveTasks($tasks);
+    }
+
+    /**
+     * @return array
+     */
+    public function saveTasksDataProvider()
+    {
+        $content = '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+            . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+            . '* * * * * /bin/php /var/www/magento/bin/magento cron:run' . PHP_EOL
+            . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL;
+
+        return [
+            [
+                'tasks' => [
+                    ['expression' => '* * * * *', 'command' => 'run.php']
+                ],
+                'content' => $content,
+                'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '* * * * * ' . PHP_BINARY . ' run.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+            ],
+            [
+                'tasks' => [
+                    ['expression' => '1 2 3 4 5', 'command' => 'run.php']
+                ],
+                'content' => $content,
+                'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '1 2 3 4 5 ' . PHP_BINARY . ' run.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+            ],
+            [
+                'tasks' => [
+                    ['command' => '{magentoRoot}run.php >> {magentoLog}cron.log']
+                ],
+                'content' => $content,
+                'contentToSave' => '* * * * * /bin/php /var/www/cron.php' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_START . PHP_EOL
+                    . '* * * * * ' . PHP_BINARY . ' /var/www/magento2/run.php >>'
+                    . ' /var/www/magento2/var/log/cron.log' . PHP_EOL
+                    . CrontabManagerInterface::TASKS_BLOCK_END . PHP_EOL,
+            ],
+        ];
+    }
+}
diff --git a/lib/internal/Magento/Framework/Crontab/Test/Unit/TasksProviderTest.php b/lib/internal/Magento/Framework/Crontab/Test/Unit/TasksProviderTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..80be47cda5ef4973ad1999968dd636da0bd1757a
--- /dev/null
+++ b/lib/internal/Magento/Framework/Crontab/Test/Unit/TasksProviderTest.php
@@ -0,0 +1,34 @@
+<?php
+
+/**
+ * Copyright © 2016 Magento. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+namespace Magento\Framework\Crontab\Test\Unit;
+
+use Magento\Framework\Crontab\TasksProvider;
+
+class TasksProviderTest extends \PHPUnit_Framework_TestCase
+{
+    /**
+     * @return void
+     */
+    public function testTasksProviderEmpty()
+    {
+        /** @var $tasksProvider $tasksProvider */
+        $tasksProvider = new TasksProvider();
+        $this->assertSame([], $tasksProvider->getTasks());
+    }
+
+    public function testTasksProvider()
+    {
+        $tasks = [
+            'magentoCron' => ['expressin' => '* * * * *', 'command' => 'bin/magento cron:run'],
+            'magentoSetup' => ['command' => 'bin/magento setup:cron:run'],
+        ];
+
+        /** @var $tasksProvider $tasksProvider */
+        $tasksProvider = new TasksProvider($tasks);
+        $this->assertSame($tasks, $tasksProvider->getTasks());
+    }
+}