mirror of
https://codeberg.org/Mo8it/How_To_Linux.git
synced 2024-11-22 05:18:04 +00:00
Done first day tasks
This commit is contained in:
parent
e882f7f49a
commit
dd7f1941fc
12 changed files with 397 additions and 23 deletions
15
cs/Cargo.lock
generated
15
cs/Cargo.lock
generated
|
@ -190,9 +190,9 @@ checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "collective-score-client"
|
name = "collective-score-client"
|
||||||
version = "0.0.2"
|
version = "0.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "18bad7c08c5e9754d1b3a09aab531b2a5112ecb241c8bbf7d52c164db5cfab37"
|
checksum = "d7bf3513f18ebf36b12e0bf91049c2091d5d014a585c65bf54648d19223abe19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -218,6 +218,8 @@ name = "cs"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"collective-score-client",
|
"collective-score-client",
|
||||||
|
"dirs",
|
||||||
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -229,6 +231,15 @@ dependencies = [
|
||||||
"dirs-sys",
|
"dirs-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "5.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
|
|
|
@ -8,4 +8,6 @@ license = "AGPL-3.0"
|
||||||
repository = "https://codeberg.org/mo8it/dev-tools"
|
repository = "https://codeberg.org/mo8it/dev-tools"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
collective-score-client = "0.0.2"
|
collective-score-client = "0.0.5"
|
||||||
|
dirs = "5.0.1"
|
||||||
|
regex = "1.9.3"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use collective_score_client::{
|
use collective_score_client::{
|
||||||
check::{Check, IntoTask, RunnableCheck},
|
check::{Check, IntoTask, Task},
|
||||||
validator::{stdin::Stdin, string_content::StringContent},
|
validator::{stdin::Stdin, string_content::StringContent},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn task() -> (&'static str, Box<dyn RunnableCheck>) {
|
pub fn task() -> Task {
|
||||||
Check::builder()
|
Check::builder()
|
||||||
.description("Checking stdin")
|
.description("Checking stdin")
|
||||||
.validator(Stdin {
|
.validator(Stdin {
|
||||||
|
|
60
cs/src/day1/cowsay.rs
Normal file
60
cs/src/day1/cowsay.rs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{
|
||||||
|
command::{Command, CommandStatus, StdioVariant},
|
||||||
|
file::FileContent,
|
||||||
|
string_content::StringContent,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
let fish_history = dirs::home_dir()
|
||||||
|
.expect("Failed to get the home directory!")
|
||||||
|
.join(".local/share/fish/fish_history");
|
||||||
|
|
||||||
|
[
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that `cowsay` is installed")
|
||||||
|
.validator(
|
||||||
|
CommandStatus::builder()
|
||||||
|
.command(
|
||||||
|
Command::builder()
|
||||||
|
.program("which")
|
||||||
|
.args(vec!["cowsay".into()])
|
||||||
|
.stdout(StdioVariant::Null)
|
||||||
|
.stderr(StdioVariant::Null)
|
||||||
|
.stdin(StdioVariant::Null)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.status_code(0)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.hint("Did you install `cowsay` using the `dnf` package manager?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that you tried to change the eyes")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: fish_history.clone(),
|
||||||
|
expected: StringContent::Regex(
|
||||||
|
Regex::new(r"\n- cmd: cowsay.* -e .+\n").expect("Failed to build a regex"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.hint("Did you read the help message of `cowsay` to find out how to change the eyes?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that you tried to change the tongue")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: fish_history.clone(),
|
||||||
|
expected: StringContent::Regex(
|
||||||
|
Regex::new(r"\n- cmd: cowsay.* -T .+\n").expect("Failed to build a regex"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.hint("Did you read the help message of `cowsay` to find out how to change the tongue?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
]
|
||||||
|
.into_task("cowsay")
|
||||||
|
}
|
61
cs/src/day1/initial_house.rs
Normal file
61
cs/src/day1/initial_house.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{file::FileContent, string_content::StringContent},
|
||||||
|
};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
[
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking the bedroom")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("bedroom/bed.txt"),
|
||||||
|
expected: StringContent::Full(""),
|
||||||
|
})
|
||||||
|
.hint("Did you create the directory `bedroom` containing the empty file `bed.txt`?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking the bathroom")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("bathroom/toilet.txt"),
|
||||||
|
expected: StringContent::Full(""),
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking the living room")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("living_room/couch.txt"),
|
||||||
|
expected: StringContent::Full(""),
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking the kitchen")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("kitchen/fridge.txt"),
|
||||||
|
expected: StringContent::Full(""),
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking the dining room")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("dining_room/chair.txt"),
|
||||||
|
expected: StringContent::Full(""),
|
||||||
|
})
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Looking for Max in the living room")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("living_room/max.txt"),
|
||||||
|
expected: StringContent::Part("beatboxing"),
|
||||||
|
})
|
||||||
|
.hint("Did you add his hobby `beatboxing` to his file?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
]
|
||||||
|
.into_task("initial-house")
|
||||||
|
}
|
60
cs/src/day1/lolcat.rs
Normal file
60
cs/src/day1/lolcat.rs
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{
|
||||||
|
command::{Command, CommandStatus, StdioVariant},
|
||||||
|
file::FileContent,
|
||||||
|
string_content::StringContent,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
let fish_history = dirs::home_dir()
|
||||||
|
.expect("Failed to get the home directory!")
|
||||||
|
.join(".local/share/fish/fish_history");
|
||||||
|
|
||||||
|
[
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that `lolcat` is installed")
|
||||||
|
.validator(
|
||||||
|
CommandStatus::builder()
|
||||||
|
.command(
|
||||||
|
Command::builder()
|
||||||
|
.program("which")
|
||||||
|
.args(vec!["lolcat".into()])
|
||||||
|
.stdout(StdioVariant::Null)
|
||||||
|
.stderr(StdioVariant::Null)
|
||||||
|
.stdin(StdioVariant::Null)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.status_code(0)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.hint("Did you install `lolcat` using the `dnf` package manager?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that you piped `cowsay` into `lolcat`")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: fish_history.clone(),
|
||||||
|
expected: StringContent::Regex(
|
||||||
|
Regex::new(r"\n- cmd: cowsay .+ \| lolcat").expect("Failed to build a regex"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.hint("Did you try the syntax with `|`?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that you tried adding randomness to `lolcat`")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: fish_history.clone(),
|
||||||
|
expected: StringContent::Regex(
|
||||||
|
Regex::new(r"lolcat.* (-r |--random)").expect("Failed to build a regex"),
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.hint("Did you read the help message of `lolcat` to find out how to add randomness to the output colors?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
]
|
||||||
|
.into_task("lolcat")
|
||||||
|
}
|
|
@ -1,7 +1,23 @@
|
||||||
mod collective_score_intro;
|
mod collective_score_intro;
|
||||||
|
mod cowsay;
|
||||||
|
mod initial_house;
|
||||||
|
mod lolcat;
|
||||||
|
mod passwd;
|
||||||
|
mod system_update;
|
||||||
|
mod zombie;
|
||||||
|
mod zombie_nuked;
|
||||||
|
|
||||||
use collective_score_client::check::RunnableCheck;
|
use collective_score_client::check::RunnableCheck;
|
||||||
|
|
||||||
pub fn tasks() -> [(&'static str, Box<dyn RunnableCheck>); 1] {
|
pub fn tasks() -> [(&'static str, Box<dyn RunnableCheck>); 8] {
|
||||||
[collective_score_intro::task()]
|
[
|
||||||
|
collective_score_intro::task(),
|
||||||
|
initial_house::task(),
|
||||||
|
zombie::task(),
|
||||||
|
zombie_nuked::task(),
|
||||||
|
passwd::task(),
|
||||||
|
system_update::task(),
|
||||||
|
cowsay::task(),
|
||||||
|
lolcat::task(),
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
18
cs/src/day1/passwd.rs
Normal file
18
cs/src/day1/passwd.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{file::FileContent, string_content::StringContent},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that you changed your password")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: dirs::home_dir()
|
||||||
|
.expect("Failed to get the home directory!")
|
||||||
|
.join(".local/share/fish/fish_history"),
|
||||||
|
expected: StringContent::Part("- cmd: passwd\n"),
|
||||||
|
})
|
||||||
|
.hint("Did you change your password by running the command `passwd`? Are you in the fish shell?")
|
||||||
|
.build()
|
||||||
|
.into_task("passwd")
|
||||||
|
}
|
18
cs/src/day1/system_update.rs
Normal file
18
cs/src/day1/system_update.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{file::FileContent, string_content::StringContent},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that you tried to update the system")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: dirs::home_dir()
|
||||||
|
.expect("Failed to get the home directory!")
|
||||||
|
.join(".local/share/fish/fish_history"),
|
||||||
|
expected: StringContent::Part("\n- cmd: dnf upgrade"),
|
||||||
|
})
|
||||||
|
.hint("Did you try to update the system? Are you in the fish shell?")
|
||||||
|
.build()
|
||||||
|
.into_task("system-update")
|
||||||
|
}
|
52
cs/src/day1/zombie.rs
Normal file
52
cs/src/day1/zombie.rs
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{
|
||||||
|
command::{Command, CommandStatus, StdioVariant},
|
||||||
|
file::FileContent,
|
||||||
|
string_content::StringContent,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
[
|
||||||
|
Check::builder()
|
||||||
|
.description("Looking for the zombie")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("living_room/zombie.txt"),
|
||||||
|
expected: StringContent::Part("Brainzzz"),
|
||||||
|
})
|
||||||
|
.hint("Did you put a zombie in the living room having `Brainzzz` in his head?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that Max ran away")
|
||||||
|
.validator(
|
||||||
|
CommandStatus::builder()
|
||||||
|
.command(
|
||||||
|
Command::builder()
|
||||||
|
.program("ls")
|
||||||
|
.args(vec!["living_room/max.txt".into()])
|
||||||
|
.stdout(StdioVariant::Null)
|
||||||
|
.stderr(StdioVariant::Null)
|
||||||
|
.stdin(StdioVariant::Null)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.status_code(2)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.hint("Did you move Max away from the living room? Maybe you cloned Max and left one of his copies in the living room 😯")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Looking for Max")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("bedroom/max.txt"),
|
||||||
|
expected: StringContent::Part("beatboxing"),
|
||||||
|
})
|
||||||
|
.hint("Did you move Max into the bedroom? Does he still have his hobby?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
]
|
||||||
|
.into_task("zombie")
|
||||||
|
}
|
43
cs/src/day1/zombie_nuked.rs
Normal file
43
cs/src/day1/zombie_nuked.rs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
use collective_score_client::{
|
||||||
|
check::{Check, IntoTask, Task},
|
||||||
|
validator::{
|
||||||
|
command::{Command, CommandStatus, StdioVariant},
|
||||||
|
file::FileContent,
|
||||||
|
string_content::StringContent,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
pub fn task() -> Task {
|
||||||
|
[
|
||||||
|
Check::builder()
|
||||||
|
.description("Checking that the zombie was nuked")
|
||||||
|
.validator(
|
||||||
|
CommandStatus::builder()
|
||||||
|
.command(
|
||||||
|
Command::builder()
|
||||||
|
.program("ls")
|
||||||
|
.args(vec!["living_room".into()])
|
||||||
|
.stdout(StdioVariant::Null)
|
||||||
|
.stderr(StdioVariant::Null)
|
||||||
|
.stdin(StdioVariant::Null)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.status_code(2)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.hint("Did you destroy the living room with the Zombie in it?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
Check::builder()
|
||||||
|
.description("Looking for Max")
|
||||||
|
.validator(FileContent {
|
||||||
|
file: PathBuf::from("bedroom/max.txt"),
|
||||||
|
expected: StringContent::Part("beatboxing"),
|
||||||
|
})
|
||||||
|
.hint("Is Max in the bedroom? Does he still have his hobby?")
|
||||||
|
.build()
|
||||||
|
.into_box(),
|
||||||
|
]
|
||||||
|
.into_task("zombie-nuked")
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ In general, you will do a task and then run `cs task TASKCODE` to validate your
|
||||||
`TASKCODE` is a code unique to every task/subtask.
|
`TASKCODE` is a code unique to every task/subtask.
|
||||||
For this demo task, the task code is `collective-score-intro`.
|
For this demo task, the task code is `collective-score-intro`.
|
||||||
|
|
||||||
Now, for this demo task to pass the check, run the following command:
|
🟢 Now, for this demo task to pass the check, run the following command:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo "OK" | cs task collective-score-intro
|
echo "OK" | cs task collective-score-intro
|
||||||
|
@ -42,39 +42,66 @@ Congratulations, you have done your first task 🎉
|
||||||
|
|
||||||
To see your progress at any time, run the command **`cs progress show`**.
|
To see your progress at any time, run the command **`cs progress show`**.
|
||||||
|
|
||||||
## Task 1: Building houses
|
## Task 1: Building houses 🏠️
|
||||||
|
|
||||||
In this task, you will build a house with different rooms using (nested) directories.
|
In this task, you will build a house with different rooms using (nested) directories.
|
||||||
|
|
||||||
Start with an empty directory as the house and add directories to it as rooms.
|
Start with an empty directory as the house and add directories to it as rooms.
|
||||||
|
|
||||||
The house should have at least 5 rooms. Give the rooms meaningful names.
|
Rooms (represented by directories) contain objects as text files (ending with `.txt`).
|
||||||
|
The text files for the objects should be empty for now.
|
||||||
|
|
||||||
Place a box as a text file in one of the rooms. Put some content in the box as text lines.
|
The house should have the following 5 rooms:
|
||||||
|
|
||||||
Place some persons as text files in different rooms. You can add some information about the persons like hobbies in their files.
|
- `bedroom` containing `bed.txt`
|
||||||
|
- `bathroom` containing `toilet.txt`
|
||||||
|
- `living_room` containing `couch.txt`
|
||||||
|
- `kitchen` containing `fridge.txt`
|
||||||
|
- `dining_room` containing `chair.txt`
|
||||||
|
|
||||||
Visualise your house structure and content using `tree` and make a screenshot.
|
Place Max in the living room by creating a file `Max.txt` in the living room containing his hobby `beatboxing` as text in his file.
|
||||||
|
|
||||||
Now, clone your whole house and then rename the persons in the new house. Make another screenshot of `tree` afterwards.
|
Example:
|
||||||
|
|
||||||
In the new house, choose a non empty room and move everything within this room into another room. Why? Because zombies are back! They did get in through _windows_...
|
```console
|
||||||
|
$ cat living_room/max.txt
|
||||||
|
He is watching TV.
|
||||||
|
His hobby is beatboxing.
|
||||||
|
```
|
||||||
|
|
||||||
Make a screenshot of `tree`.
|
Run the command `tree` to see the structure of the house.
|
||||||
|
|
||||||
Put some zombies in this room after it is empty, make a screenshot of `tree` and then delete the room with the zombies in it. Make sure to not destroy the whole house!
|
🟢 Run `cs task initial-house` in the house directory.
|
||||||
|
|
||||||
Make a final `tree` screenshot of the rest of the house.
|
Zombies are back!
|
||||||
|
They did get in through _windows_… (You got it?)
|
||||||
|
|
||||||
Take a screenshot of the content of some files. Tipp: 😺
|
Place a zombie in the living room having `Brainzzz` in his file `zombie.txt`.
|
||||||
|
|
||||||
|
Max runs out of the living room!
|
||||||
|
Move him to the bedroom.
|
||||||
|
|
||||||
|
🟢 Run `cs task zombie` in the house directory.
|
||||||
|
|
||||||
|
Now, destroy the whole living room with the zombie in it.
|
||||||
|
|
||||||
|
🟢 Run `cs task zombie-nuked` in the house directory.
|
||||||
|
|
||||||
|
Tipps:
|
||||||
|
|
||||||
- If you get lost, use `pwd`.
|
- If you get lost, use `pwd`.
|
||||||
- If you are looking for an option but you can not remember it, use `--help`.
|
- If you are looking for an option but you can not remember it, use `--help`.
|
||||||
|
|
||||||
## Task 2: Reset your password
|
## Task 2: Reset your password
|
||||||
|
|
||||||
|
⚠️ Launch the [fish shell](https://fishshell.com/) by running the command `fish` and stay in it for all following tasks.
|
||||||
|
If you close the terminal and lauch it later again, you have to run `fish` again.
|
||||||
|
We will learn more about the fish shell later.
|
||||||
|
|
||||||
Use the command `passwd` to reset the password of your user. It is important to have a secure password!
|
Use the command `passwd` to reset the password of your user. It is important to have a secure password!
|
||||||
|
|
||||||
|
🟢 Run `cs task passwd`.
|
||||||
|
|
||||||
## Task 3: Update your system
|
## Task 3: Update your system
|
||||||
|
|
||||||
Find out how to update your system with `dnf` and run the updates.
|
Find out how to update your system with `dnf` and run the updates.
|
||||||
|
@ -83,6 +110,8 @@ Before you confirm, make sure that you read what packages are updated. Make a sc
|
||||||
|
|
||||||
It is possible that you don't find any updates. In this case, you can try it again on another day!
|
It is possible that you don't find any updates. In this case, you can try it again on another day!
|
||||||
|
|
||||||
|
🟢 Run `cs task system-update`.
|
||||||
|
|
||||||
## Task 4: Package installation and usage
|
## Task 4: Package installation and usage
|
||||||
|
|
||||||
Install the package `cowsay` and find out how to use it!
|
Install the package `cowsay` and find out how to use it!
|
||||||
|
@ -91,10 +120,14 @@ Spoiler: You will have to deal with some cows 🐄
|
||||||
|
|
||||||
Find out how to give a fancy tongue and shinny eyes.
|
Find out how to give a fancy tongue and shinny eyes.
|
||||||
|
|
||||||
Make a screenshot of some cow wisdom 🐮
|
🟢 Run `cs task cowsay`.
|
||||||
|
|
||||||
Now install the package `lolcat`.
|
Now, install the package `lolcat`.
|
||||||
|
|
||||||
Let's say the wisdom command you did take the last screenshot of is `cowsay (...)`. Now run `cowsay (...) | lolcat`. Describe what changed. Can you guess how this internally works?
|
Generate some wisdom with `cowsay (…)`. Now, run `cowsay (…) | lolcat`.
|
||||||
|
What did change?
|
||||||
|
Can you guess how this internally works?
|
||||||
|
|
||||||
Now read the help of `lolcat` and find out how to add some randomness. Run the command above again with the option you found and take a screenshot after you are satisfied with the randomness you get.
|
Now, read the help of `lolcat` and find out how to add some randomness.
|
||||||
|
|
||||||
|
🟢 Run `cs task lolcat`.
|
||||||
|
|
Loading…
Reference in a new issue