2021-03-22
Większość terminali, zarówno na Unix, jak i pod Windows obsługują „kody ucieczki” pozwalające na takie sformatowanie napisu wyświetlanego w konsoli poleceniem print, aby wyświetlany tekst otrzymał odpowiedni kolor.
Szczegółowo ten mechanizm jest opisany tutaj:
https://en.wikipedia.org/wiki/ANSI_escape_code#Colors
Jeśli jednak chcesz ominąć czytanie długiej dokumentacji, bo po prostu chcesz wyświetlić coś na kolorowo, to powinno wystarczyć rozumienie poniższej instrukcji:
print('\x1b[38;2;255;0;0m\x1b[48;2;255;255;0m' + 'WWW.MOBILO24.EU!' + '\x1b[0m')
Co tu się dzieje?
- \x1b[ to właśnie znak ucieczki wprowadzający informacje kontrolne dla terminala. Jest to więc coś, co nie jest wyświetlane, tylko interpretuje to sobie terminal. Instrukcja tu zapisana kończy się za literką m. W powyższym przykładzie ta instrukcja występuje aż trzy razy:
- pierwsza wprowadza kolor tekstu (foreground)
- druga wprowadza kolor tła (background)
- a trzecia resetuje terminal do ustawień domyślnych, czyli kasuje informacje o używanych kolorach
- Fragment 38;2;255;0;0 oznacza:
- 38 – określa, że definiujesz kolor tekstu (foreground)
- 2 – określa, że ciąg dalszy jest w formacie RGB
- kolejne 3 liczby definiują kolor RGB – tutaj czerwony
- Fragment 48;2;255;255;0 oznacza:
- 48 – określa, że definiujesz kolor tła (background)
- 2 – określa, że ciąg dalszy jest w formacie RGB
- kolejne 3 liczby definiują kolor RGB – tutaj żółty
- Ostatnia instrukcja to wreszcie reset ustawień terminala, tutaj pomijając znak ucieczki i znak końca instrukcji „m”, istrukcja ta ogranicza się do „0”
- Pośrodku wstawiasz tekst do wyświetlenia
Gotowe!
2021-03-12
W pewnych przypadkach trzeba ustalić jaki adres IPv4 jest przypisany do serwera. Można oczywiście zajrzeć do widoku sys.dm_exec_connections
Niestety ta metoda nie zadziała jeśli połączenie jest nawiązane przez Shared Memory, albo 127.0.0.1 albo (i to mój przypadek) przez IPv6, a tymczasem potrzebowałem IPv4.
Na całe szczęście udało się znaleźć ciekawy pomysł z wykorzystaniem xm_cmdshell i prostego polecenia ipconfig
https://stackoverflow.com/questions/142142/sql-query-to-get-servers-ip-address
Oto delikatnie zmieniona procedura – u mnie działa!
CREATE PROCEDURE #sp_get_ip_address (@ip VARCHAR(40) OUT)
AS
BEGIN
SET NOCOUNT ON
DECLARE @Line varchar(200)
DECLARE @pos int
SET @ip = NULL
CREATE TABLE #temp (line VARCHAR(200))
EXECUTE sp_configure 'show advanced options', 1;
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
INSERT INTO #temp EXEC master..xp_cmdshell 'ipconfig'
EXECUTE sp_configure 'show advanced options', 1;
RECONFIGURE
EXEC sp_configure 'xp_cmdshell', 1
RECONFIGURE
SELECT @Line = line
FROM #temp
WHERE UPPER (line) like '%IPV4%ADDRESS%'
IF (ISNULL (@line,'***') != '***')
BEGIN
SET @pos = CHARINDEX (':',@line,1);
SET @ip = RTRIM(LTRIM(SUBSTRING (@line, @pos + 1, LEN(@line) - @pos)))
END
DROP TABLE #temp
SET NOCOUNT OFF
END
GO
DECLARE @ip VARCHAR(40)
EXEC #sp_get_ip_address @ip OUT
DROP PROCEDURE #sp_get_ip_address
SELECT @ip
2021-02-12
No cóż… zdarza się najlepszym…
Jako tako nie wiem, co się zespuło, ale dałem radę naprawić:
- Panel Sterowania
- Dodaj usuń programy
- Odszukaj pakiet Office (może się różnie nazywać, bo MS dostarcza go w różnych pakietach)
- Klinij modyfikuj
- Wybierz napraw. U mnie były dwie możliwości naprawy – szybka i zaawansowana. Wybrałem szybką i po kawie office działał 🙂
Masz lepszy pomysł? Napisz!
2021-02-10
Coraz częściej pracujemy w środowiskach międzynarodowych. Standardem jest używanie języka angielskiego, ale… jeśli na biurku masz klawiaturę francuską, czy niemiecką, to nic dziwnego, że administratorzy konfigurują do wykorzystania również inne „egzotyczne” układy.
W takim przypadku z pewnością chcemy dodać język angielski. Trzeba to zrobić w kilku miejscach:
- Panel sterowania >> język (language) – dodaj język i wybierz kolejność stosowania języków
- Z boku kliknij na „Advanced” i wypełnij odpowiednio pola
- Kliknij „Apply language settings to the welcome screen”, a potem w oknie Region na zakładce Administrative:
- Wybierz Change system locale i zmień język, tak jak chcesz
- Kliknij też Copy settings
- zaznacz „Welcome screen” i „New user accounts”
- Pozamykaj okna i zrestartuj system
Niestety po wszystkim, nadal może sie okazać, że domyślny język wprowadzania danych na ekranie logowania to np. Francuski. W takim przypadku:
- Uruchom gpedit.msc, przejdź do:
Local Policy >> Computer Configuration >> Administrative Templates >> System >> Locale Services
i zmień wartość w „Disallow copying of user input methods to the system account for Sign-in” na Enabled
W moim przypadku, dopiero to ostatnie ustawienie po restarcie spowodowało wyświetlenie języka angielskiego i angielskiej klawiatury na ekranie logowania
2021-02-08
Python jest fajny, bo jest dynamiczny. Napiszesz sobie funkcję, a potem ni z tego ni z owego można ją wywoływać na wiele sposobów. Popatrz na ten przykład:
def show_args(arg_1, arg_2):
print(arg_1)
print(arg_2)
show_args('one','two')
Proste? No pewnie, że proste! Funkcja ma dwa argumenty i wywołujemy ją z dwoma argumentami i już!
Ale może by tak, mając listę dwóch elementów przekazać ją do tej funkcji? Może funkcja będzie na tyle sprytna, żeby zrozumieć o co chodzi? Niestety będzie błąd:
show_args(['one','two'])
TypeError: show_args() missing 1 required positional argument: 'arg_2'
… ale gdyby tak, przed listą dodać gwiazdkę, to Python „wyłuska z listy jej elementy i przekaże je do funkcji:
show_args(*['one','two'])
one
two
Wow! Dobre!
No a jeśli nie mamy listy argumentów, tylko słownik? I jeśli jeszcze w tym słowniku elementy są „przypadkowo” nazwane tak, jak argumenty testowanej funkcji? Przy pierwszym podejściu – niestety klapa:
show_args({'arg_2':'two', 'arg_1':'one'})
TypeError: show_args() missing 1 required positional argument: 'arg_2'
Ale my już wiemy, jak sobie z tym poradzić:
show_args(*{'arg_2':'two', 'arg_1':'one'})
arg_2
arg_1
Jedna gwiazdka jakoś już pomogła, niestety, pewnie wolelibyśmy nie zobaczyć w wyniku funkcji nazw kluczy, tylko ich wartości! Z pomocą przyjdą dwie gwiazdki, które konwertują słownik na nazwane wartości przekazywane do funkcji:
show_args(**{'arg_2':'two', 'arg_1':'one'})
one
two
I to już działa idealnie. Funkcja domyśliła się, co to jest arg_1 mimo tego, że ta wartość w słowniku była dopiero na drugim miejscu.
Fajnie, ale te „chwyty” można też wykorzystać definiując funkcję:
def clever_function(*args):
for a in args:
print(a)
clever_function(1,2,3)
Kiedy chcesz, aby funkcja mogła przyjąć dowolną liczbę parametrów przekazywanych po prostu przez pozycję, to wystarczy zadeklarować argumenty jako *args. W ciele funkcji można wtedy skorzystać ze zmiennej args, która jest listą. Bardzo to elastyczne!
Jeśli z kolei chcesz, aby funkcja miała przyjmować dowolną liczbę argumentów ze słownika, to argument poprzedź dwoma gwiazdkami. Zazwyczaj ten parametr nazywamy kwargs (key-word argument):
def clever_function(**kwargs):
for k, v in kwargs.items():
print(k,v)
clever_function(a=1,b=2,c=3)
Teraz do funkcji można przekazywać dowolną liczbę nazwanych parametrów, a funkcja w sprytny sposób zobaczy je jako słownik. To użytkownik wywołując funkcję sam decyduje o tym, jak mają się nazywać argumenty widoczne w funkcji.
Obie te metody można zresztą połączyć i zbudować funkcję tak:
def clever_function(*args, **kwargs):
for a in args:
print(a)
for k, v in kwargs.items():
print(k,v)
clever_function('one','two',a=1,b=2,c=3)
print('---')
clever_function(a=1,b=2,c=3)
print('---')
clever_function('one','two')
Jak widać funkcję można teraz wywoływać z argumentami określanymi przez pozycję i nazwę, albo tylko przez nazwę albo tylko przez pozycję.
Oj przyda się na pewno!
2021-01-27
W Pandas, seria danych to po prostu ciąg wartości. Wartość numer 2 to po prostu element prostego typu. Bardzo podobnie na pierwszy rzut oka wygląda jednokolumnowy DataFrame, ale… pewne różnice są:
numbers=[1, 2, 3, 4]
letters=['A', 'B', 'C', 'D']
Tak powstaje seria danych – dla „zmyłki” indeksem jest kolumna numbers:
ds = pd.Series(data=letters, index=numbers)
ds
oto wynik:
Out[45]:
1 A
2 B
3 C
4 D
dtype: object
A tak wygląda to, jeśli utworzymy DataFrame, który ma jedną kolumnę i indeks zdefiniowany w oparciu o numbers:
df = pd.DataFrame(data=letters, index=numbers)
df
wynik jest na pierwszy rzut oka podobny:
0
1 A
2 B
3 C
4 D
Duże różnice pojawią się jednak przy odwołaniu do konkretnej pozycji:
ds.loc[1]
Out[47]: 'A'
a dla DataFrame:
df.loc[1]
Out[48]:
0 A
Name: 1, dtype: object
2021-01-24
Żeby uzyskać dostęp do PostgreSQL, to należy mieć dostęp do tzw. Login role (dawniej user). Jeśli taka rola jest oznaczona jako superuser, to ta rola uzyskuje nieograniczone uprawnienia do serwera bazy danych. Podczas instalacji serwera, taka rola jest tworzona automatycznie i nazywa się postgres. Role mogą też służyć do nadawania uprawnień nie nadając bezpośrednio dostępu do serwera. Role można w sobie zagnieżdżać. Rola, której członkiem są inne role nosi nazwę group role, a jeśli ta rola pozwala też na korzystanie z serwera to jest to group login name. W sumie logiczne 😊
Poniższa komenda tworzy rolę camila z dodatkowym uprawnieniem do tworzenia nowych baz danych
CREATE ROLE camila LOGIN PASSWORD 'Passw0rd’ VALID UNTIL 'infinity’ CREATEDB;
Słowo superuser dodane na końcu polecenia powoduje, że użytkownik staje się pełnoprawnym i „wszechmocnym” administratorem
CREATE ROLE adm_dagmara LOGIN PASSWORD 'P@ssw0rd’ VALID UNTIL '2030-01-01 00:00′ SUPERUSER;
Jeśli rola nie ma służyć do logowania, to należy opuścić słowo LOGIN. Dodane tutaj INHERIT powoduje, że inne role dodane jako członkowie do toli adm_security będą dziedziczyć jej uprawnienia. Ta opcja jest w zasadzie domyślna, więc nie trzeba jej wpisywać jawnie.
CREATE ROLE adm_security INHERIT;
Grant pozwala dodać jedną rolę do innej roli jako członka. W ten sposób camila otrzyma wszystkie przywileje roli adm_security (bez ewentualnego przywileju superuser, bo ten jako jedyny nie podlega dziedziczeniu)
GRANT adm_security TO camila;
Do nadawania przywilejów dla ról należy posłużyć się poleceniem ALTER ROLE
ALTER ROLE adm_security SUPERUSER;
Kiedy użytkownik należy do roli, to może się przełączyć w tą rolę korzystając z SET ROLE
SET ROLE adm_security;
Po wykonaniu takich przełączeń można na bieżąco sprawdzać w jakiej tożsamości w danej chwili się pracuje. Stąd też można odwołać się do zmiennych session_user i current_user. Session_user określa nazwę roli jaka została wykorzystana do początkowego połączenia do serwera, zaś current_user to nazwa tożsamości w jakiej w danej chwili znajduje się użytkownik
SELECT session_user, current_user;
Dodatkowo superuser ma prawo wykonywać polecenie SET SESSION AUTHORIZATION, które zmieni nawet wpis dotyczący roli używanej na początku do zainicjowania połączenia
SET SESSION AUTHORIZATION ROLE adm_security;
Poprzez przełączanie się miedzy rolami może dojść do… przekrętów. Camila będąc członkiem roli adm_security może zmienić swoją rolę na adm_security. Niestety nie dziedziczy w ten sposób przywileju superuser. Jednak rola adm_security ma przywilej superuser, więc może teraz zmienić swoje konto camila nadając mu uprawnienie superuser. Od tej pory może już robić wszystko!